Comment 17 for bug 35004

Just gathering the information for you now, Petr. There's no in-kernel documentation about this, but that's not really unusual because the kernel guys aren't exactly the best documenters in the world. The authorative stance on this is from Greg's book and just general e-mail.

Note that this is not a problem unique to Ubuntu, SuSE Linux 10.1 does not mount /proc/bus/usb either; and I do not believe the current Fedora development branch does. Debian are talking about dropping it in etch+1.

  http://www.helios.de/support/ti.phtml?100
  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=360165

/dev/bus/usb has replaced /proc/bus/usb for the NNN/XXX devices, simply because the latter does not allow any kind of permission control other than at a filesystem level. Because /dev/bus/usb is generated by udev, we have that kind of control.

  http://wiki.linuxfromscratch.org/blfs/ticket/1680

For most software, this is simply a path change from /proc/bus/usb to /dev/bus/usb; the canon way seems to be to check /dev/bus/usb first, and fall back to /proc/bus/usb if the /dev/bus/usb directory does not exist. That way you're compatible with the udev-based distributions and the hotplug/monolothic-based distributions.

Some distributions (like Ubuntu releases) actually include both, however when they do /dev/bus/usb is preferable because the /proc/bus/usb devices can only be written to by the root user. The /dev/bus/usb devices can be written to if the user has permission based on the security settings and their group membership.

Obviously this isn't a complete solution, as /dev/bus/usb does not contain a "devices" file with summary information. If using /dev/bus/usb, you should use an alternate method of detecting USB devices.

To obtain a list of the usb devices, read the /sys/bus/usb/devices directory; which contains a symlink for each known device. The name of the symlink provides the bus id, the target directory contains various files wiht the device information (much easier to parse than the old file).

E.g. to obtain the descriptive name, vendor id and product id of every USB device (in shell):

  for DEVICE in /sys/bus/usb/devices/*; do
    [ -f $DEVICE/product ] && cat $DEVICE/product
    [ -f $DEVICE/idProduct ] && cat $DEVICE/idProduct
    [ -f $DEVICE/idVendor ] && cat $DEVICE/idVendor
  done

Insert and remove notification can also now be done *reliably*, without resorting to polling files or directories and comparing the difference.

Depending how dirty you'd like to get with the system, you can obtain these events using HAL, udev or a kernel netlink socket. HAL is the nice object-oriented, dbus-based way; but that'd introduce a dependency for you. The kernel netlink socket is a bit too low-level perhaps. Given that you know /dev/bus/usb exists, you know that they have udev, so that's probably the right way.

 - Have vmware read from a UNIX domain datagram socket in the abstract namespace, e.g. @/com/vmware/udev/event

 - Install a file named /etc/udev/rules.d/95-vmware.rules that contains the following:

  SUBSYSTEM=="usb_device", RUN+="socket:/com/vmware/udev/event"

Every time a device is added or removed, you will receive a string buffer containing KEY=VALUE environment pairs; here's an example:

  ACTION=add
  DEVPATH=/class/usb_device/usbdev2.1
  SUBSYSTEM=usb_device
  SEQNUM=2327
  PHYSDEVPATH=/devices/pci0000:00/0000:00:02.1/usb2
  PHYSDEVBUS=usb
  PHYSDEVDRIVER=usb
  MAJOR=189
  MINOR=128
  UDEVD_EVENT=1
  USB_BUS=002
  USB_DEV=001
  DEVNAME=/dev/bus/usb/002/001

All the information one could want, for a remove event, ACTION will be remove.

If you don't care about the level of information, you could also just run arbitrary programs on particular events with a rule such as:

  SUBSYSTEM=="usb_device", ACTION=="add", RUN+="vmware_usb_add"
  SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="vmware_usb_remove"

See the udev(8) manpage for more details.