825
825
#define USBDEVICE_MAJOR 189
827
/** Deduce the bus that a USB device is plugged into from the device node
828
* number. See drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. */
829
static unsigned usbBusFromDevNum(dev_t devNum)
831
AssertReturn(devNum, 0);
832
AssertReturn(major(devNum) == USBDEVICE_MAJOR, 0);
833
return (minor(devNum) >> 7) + 1;
837
/** Deduce the device number of a USB device on the bus from the device node
838
* number. See drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. */
839
static unsigned usbDeviceFromDevNum(dev_t devNum)
841
AssertReturn(devNum, 0);
842
AssertReturn(major(devNum) == USBDEVICE_MAJOR, 0);
843
return (minor(devNum) & 127) + 1;
827
/** Calculate the bus (a.k.a root hub) number of a USB device from it's sysfs
828
* path. sysfs nodes representing root hubs have file names of the form
829
* usb<n>, where n is the bus number; other devices start with that number.
830
* See [http://www.linux-usb.org/FAQ.html#i6] and
831
* [http://www.kernel.org/doc/Documentation/usb/proc_usb_info.txt] for
832
* equivalent information about usbfs.
833
* @returns a bus number greater than 0 on success or 0 on failure.
835
static unsigned usbGetBusFromSysfsPath(const char *pcszPath)
837
const char *pcszFile = strrchr(pcszPath, '/');
840
unsigned bus = RTStrToUInt32(pcszFile + 1);
842
&& pcszFile[1] == 'u' && pcszFile[2] == 's' && pcszFile[3] == 'b')
843
bus = RTStrToUInt32(pcszFile + 4);
847
/** Calculate the device number of a USB device. See
848
* drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. */
849
static dev_t usbMakeDevNum(unsigned bus, unsigned device)
851
AssertReturn(bus > 0, 0);
852
AssertReturn(((device - 1) & ~127) == 0, 0);
853
AssertReturn(device > 0, 0);
854
return makedev(USBDEVICE_MAJOR, ((bus - 1) << 7) + device - 1);
848
858
* If a file @a pcszNode from /sys/bus/usb/devices is a device rather than an
853
863
VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo)
855
865
const char *pcszFile = strrchr(pcszNode, '/');
867
return VERR_INVALID_PARAMETER;
856
868
if (strchr(pcszFile, ':'))
857
869
return VINF_SUCCESS;
858
dev_t devnum = RTLinuxSysFsReadDevNumFile("%s/dev", pcszNode);
859
/* Sanity test of our static helpers */
860
Assert(usbBusFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 5);
861
Assert(usbDeviceFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 6);
870
unsigned bus = usbGetBusFromSysfsPath(pcszNode);
873
unsigned device = RTLinuxSysFsReadIntFile(10, "%s/devnum", pcszNode);
874
dev_t devnum = usbMakeDevNum(bus, device);
863
876
return VINF_SUCCESS;
864
877
char szDevPath[RTPATH_MAX];
866
879
cchDevPath = RTLinuxFindDevicePath(devnum, RTFS_TYPE_DEV_CHAR,
867
880
szDevPath, sizeof(szDevPath),
870
usbBusFromDevNum(devnum),
871
usbDeviceFromDevNum(devnum));
882
pcszDevicesRoot, bus, device);
872
883
if (cchDevPath < 0)
873
884
return VINF_SUCCESS;
1226
1237
/* Fill in the simple fields */
1227
1238
Dev->enmState = USBDEVICESTATE_UNUSED;
1228
Dev->bBus = RTLinuxSysFsReadIntFile(10, "%s/busnum", pszSysfsPath);
1239
Dev->bBus = usbGetBusFromSysfsPath(pszSysfsPath);
1229
1240
Dev->bDeviceClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceClass", pszSysfsPath);
1230
1241
Dev->bDeviceSubClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceSubClass", pszSysfsPath);
1231
1242
Dev->bDeviceProtocol = RTLinuxSysFsReadIntFile(16, "%s/bDeviceProtocol", pszSysfsPath);