[Nut-upsdev] Fun and games with newhidups, udev rules and permissions

Lincoln Turner l.turner at aip.org.au
Thu Apr 20 01:57:39 UTC 2006


Thought I would write some notes about how I got an APC BackUPS XS
1500 working with newhidups under Gentoo 2006.0. The specific issue
here is the permissions on the device files used that libusb uses to
access the USB hardware. 

I followed Peter Selinger's instructions at 
http://www.mscs.dal.ca/~selinger/ups/backups.html
on getting newhidups going with an APC device. The sticking point for
me was setting these permissions. Basically, I could run

  newhidups -DD -u root /dev/whatever 

(when I say 'whatever', I mean it - newhidups doesn't seem to care)
and see all the variables from the UPS scroll up the screen. But
running without the '-u root' results in:

[snip] 
Bus: 004
Trying to match device
Device matches
failed to claim USB device, trying 2 more time(s)...
detaching kernel driver from USB device...
failed to detach kernel driver from USB device...
trying again to claim USB device...
failed to claim USB device, trying 1 more time(s)...
detaching kernel driver from USB device...
failed to detach kernel driver from USB device...
trying again to claim USB device...
failed to claim USB device, trying 0 more time(s)...
detaching kernel driver from USB device...
failed to detach kernel driver from USB device...
trying again to claim USB device...
Unable to get HID descriptor (error sending control message: Operation not permitted)

Doing a manual 

  chgrp ups /proc/bus/usb/002/002 

allows newhidups to work without '-u root'. But the chgrp setting
unsurprisingly evaporates on reboot. The older hotplug systems seem to
work by re-chowning/chmoding things in /proc/bus/usb, but I don't have
this apparatus on my system. 

Peter's instructions cover the older 'hotplug' method of handling
permissions. The hardware abstraction seems to have changed quite
rapidly in recent kernels, and as of 2.6.15 I believe that
/proc/bus/usb is obsolete and the recommended method of setting
permissions on USB devices is with udev rules.  Also, recent udev rule
sets implement a replica of /proc/bus/usb under /dev/bus/usb -
although the former is handled by 'usbfs' and the latter by a single
elaborate (and rather hackish) rule in /etc/udev/rules.d (or wherever
your distro stores your udev rules). It _seems_ that the two bus/usb
heirarchies are equivalent as far as libusb is concerned.  Gentoo and
probably other systems will implement both heirarchies as a
transitional step.

It also seems that recent versions of libusb (and I have read
conflicting reports on when this was implemented) are capable of
looking at either /dev/bus/usb or /proc/bus/usb. 

So the first step is getting udev to set the appropriate ownership in
/dev/bus/usb, and the second step is getting libusb (and ergo
newhidups) to recognise /dev/bus/usb.

To get ownership and permissions set correctly in /dev/bus/usb, I
added a file named 60-nut-usbups.rules to my /etc/udev/rules.d
directory. It contains the two lines:

BUS=="usb", SYSFS{idVendor}=="051d", SYSFS{idProduct}=="0002", \
  ACTION=="add", NAME="%k", GROUP="ups", MODE="0660"
SUBSYSTEM=="usb_device", SYSFS{idVendor}=="051d", \
  SYSFS{idProduct}=="0002", ACTION=="add", GROUP="ups", MODE="0660"

The first matches an APC ups (051d/0002) and then creates a
default-named hiddev device, which appears on my system as
/dev/hiddev0. It sets the permissions root:ups 0660. Although this
device appears as expected as a char device with maj,min = 180,96, it
seems that newhidups takes no notice of this. Running

  newhidups -DD /dev/hiddev0

proceeds to scan the USB as always and fails as above.

The second line somehow manages to interact with the
dev/bus/usb-populating rule (on my system in 50-udev.rules) to get the
permissions set on the appropriate file, in my case
/dev/bus/usb/002/002. 

Running newhidups still doesn't work at this point, as it is still
looking by default at /proc/bus/usb. I've read that libusb-0.1.12 will
search /dev/bus/usb first then /proc/bus/usb. But it's not in gentoo's
portage yet so I haven't tried it.

I have libusb-0.1.11, and it appears that if I do an 

  export USB_DEVFS_PATH=/dev/bus/usb

then I can run

  newhidups -DD /dev/whatever

and get a successful spew of all the UPS variables. So this seems to
work, although I'm not quite sure how I got there. Any advice on udev
rule improvements would be very welcome. Also, it appears odd that
newhidups insists on scanning the bus nomatter what is fed to it as
the mandatory command-line device filename.

Finally, a disclaimer - I only just got this going. I thought I had
the bugs out last night, but they all came back after a reboot. I've
rebooted, restarted udev with udevstart, unplugged and replugged the
UPS into different USB ports etc. And it still seems to be OK. But no
guarantees I'm not missing something here!

Hope this might be useful to someone.

Lincoln









More information about the Nut-upsdev mailing list