Locking USB Serial Device to Specific Com port

dweimer dweimer at dweimer.net
Sun Jan 27 16:01:27 UTC 2013


On 2013-01-27 08:48, dweimer wrote:
> On 2013-01-26 16:40, Shane Ambler wrote:
>> On 27/01/2013 08:15, dweimer wrote:
>>
>>> I would like to lock down the USB serial port adapter used on the 
>>> UPS to
>>> /dev/cuaU0, to make sure the UPS is always monitored and I will get 
>>> a
>>> clean shutdown in event of a power failure.
>>>
>>> I believe that this requires setting a hint line of some sort in 
>>> the
>>> /boot/loader.conf file, but I am having trouble tracking down what 
>>> this
>>> should be, or maybe I am on the wrong track.  Here is the current
>>> information from the adpapters, the UPS adapter was connected at 
>>> boot,
>>> is on /dev/cuaU0, the other one was plugged in after boot, and is 
>>> on
>>> /dev/cuaU1.
>>
>> start with man devd.conf
>>
>> You can add your own devd files in /usr/local/etc/devd/
>> Something along the lines of -
>>
>> attach 200 {
>> device-name "cuaU[0-9]+";
>> match "vendor" "0x067b";
>> match "product" "0x2303";
>> action "sleep 2; cd /dev; ln -s ${device-name} upsmonitor";
>> };
>>
>> use usbconfig to get info. I am thinking with the similarity of the 
>> two
>> you may need to rely on bus and hubaddr or devaddr to keep each 
>> device
>> identified by usb port location.
>
> OK, so I was looking in the wrong direction, which might explain why
> my searching wasn't finding anything.
>
> However I might still be out of luck, after doing some checking, and
> a reboot the only difference I can find is below.
>
> dev.uplcom.0.%location: bus=1 hubaddr=1 port=0 devaddr=2 interface=0
> dev.uplcom.1.%location: bus=1 hubaddr=3 port=0 devaddr=3 interface=0
>
> The devices have switch at this point, all info from usbconfig,
> dmesg, looks identical, these two lines from the sysctl -a | grep
> "uplcom" output is all that changed, the hubaddr=1 and hubaddr=3 have
> switched, however the man devd.conf has a variable list, to use, and
> doesn't seem to have an option to match agains that hubaddr variable.
>
>  Variable      Description
>      bus           Device name of parent bus.
>      cdev          Device node path if one is created by the devfs(5) 
> filesys-
>                    tem.
>      cisproduct    CIS-product.
>      cisvendor     CIS-vendor.
>      class         Device class.
>      device        Device ID.
>      devclass      Device Class (USB)
>      devsubclass   Device Sub-class (USB)
>      device-name   Name of attached/detached device.
>      endpoints     Endpoint count (USB)
>      function      Card functions.
>      interface     Interface ID (USB)
>      intclass      Interface Class (USB)
>      intprotocol   Interface Protocol  (USB)
>      intsubclass   Interface Sub-class (USB)
>      manufacturer  Manufacturer ID (pccard).
>      mode          Peripheral mode (USB)
>      notify        Match the value of the ``notify'' variable.
>      parent        Parent device
>      port          Hub port number (USB)
>      product       Product ID (pccard/USB).
>      release       Hardware revision (USB)
>      sernum        Serial Number (USB).
>      slot          Card slot.
>      subvendor     Sub-vendor ID.
>      subdevice     Sub-device ID.
>      subsystem     Matches a subsystem of a system, see below.
>      system        Matches a system type, see below.
>      type          Type of notification, see below.
>      vendor        Vendor ID.
>
>
> But the action line above does give me an idea though, I should be
> able to write a script to run at startup to find the line, and create
> the link to the device.  The only one I care about is the UPS 
> monitor,
> as the other is only occasionally used, and I can easily check which
> com port its on before connecting to it.

This probably wouldn't work for anyone else, but here is my solution in 
case it does help someone else.

Created a new script in /usr/local/etc/rc.d/nutusblink
#!/bin/sh

# PROVIDE: NUTUSBLINK
# REQUIRE: NETWORKING
# BEFORE: nut
# KEYWORD: shutdown

. /etc/rc.subr

name="nutusblink"
start_cmd="nutusblink_start"
stop_cmd="nutusblink_stop"
rcvar="nutusblink_enable"


find_comport() {
   grepstring='uplcom.*hubaddr='${nutusblink_hubaddr}
   comnum=`sysctl -a | grep ${grepstring} | awk '{print $1}' | awk -F . 
'{print $3}'`
}

nutusblink_start() {
   find_comport
   echo ""
   echo "...Creating USB Serial Adapter Comport Link for NUT UPS 
Monitoring..."
   ln -s /dev/cuaU${comnum} /dev/${nutusblink_link}
   echo "   /dev/${nutusblink_link} Linked to /dev/cuaU${comnum}"
   echo ""
}

nutusblink_stop() {
   find_comport
   echo ""
   echo "...Removing USB Serial Adapter Comport Link for NUT UPS 
Monitoring..."
   rm /dev/${nutusblink_link}
   echo "   /dev/${nutusblink_link} No longer linked to 
/dev/cuaU${comnum}"
   echo ""
}

load_rc_config $name

: ${nutusblink_enable="NO"}
: ${nutusblink_hubaddr=""}
: ${nutusblink_link=""}

run_rc_command "$1"


Added these lines to /etc/rc.conf
# Create NUT USB Link
nutusblink_enable="YES"
nutusblink_hubaddr="3"
nutusblink_link="nutusblink"

End Result,
I now have a link /dev/nutusblink pointed at /dev/cuaU#, where # is the 
correct port number.  I have tested on a couple of reboots, and 
configured NUT to use the link instead of the actual com port.  Using 
the BEFORE: nut in the script ensures that it gets ran before the NUT 
process starts at boot.

Downside is that if I do unplug the USB serial port adapter, I have to 
make sure you put it in the same port, and if its unplugged at boot, I 
will need to run the script manually after plugging it in.  I also 
didn't bother with making sure it found a com port number before 
creating the link, so if its not there, it will error, rather than 
display a warning message, and not try to create a link.

-- 
Thanks,
    Dean E. Weimer
    http://www.dweimer.net/


More information about the freebsd-questions mailing list