Skip to content

macOS: ID_VENDOR_ID incorrectly stringified #10

@algofoogle

Description

@algofoogle

ID_VENDOR_ID and ID_MODEL_ID in the device_info dict of the on_connect handler (start_monitoring(on_connect=..., ...)) correctly seems to return a 4-digit hex string on Linux, e.g. '16c0', but for this device on macOS the same field is returned as a stringified base-10 number: '5824'. My USB hardware has other examples where these fields can contain 1 to 5 decimal digits as a string.

If necessary, maybe returning the fields as true Python int types would be fine, but that's not what's happening: They're being returned as a str representation of a base-10 integer.

It appears the reason for the discrepancy is the internal call to ioreg -- if this were to include the -x switch, it will report numerical values in hex instead of decimal.

Beware:

  1. Using -x prefixes the hex values with 0x and does not zero-pad them, so you can end up with raw values like 0xfc9, so they should be cleansed to exactly 4 hex digits before being returned.
  2. There might be existing code out there where macOS users are doing the same as me and just blindly converting these stringified ints, like so: vid = int(device_info['ID_VENDOR_ID']) -- a fix to usb-monitor to make it portable could possibly surprise people who are already working around this on macOS, since there's no definitive way to know what format of string is being returned.

Here's a snippet of ioreg -p IOUSB -w0 -l output for a given device WITHOUT the -x switch; pay attention to idProduct and idVendor (near the bottom):

  | +-o USB Optical Mouse@02100000  <class AppleUSBDevice, id 0x100000553, registered, matched, active, busy 0 (0 ms), retain 11>
  |     {
  |       "sessionID" = 1348795963
  |       "idProduct" = 49271
  |       "iManufacturer" = 1
  |       "bDeviceClass" = 0
  |       "bMaxPacketSize0" = 8
  |       "bcdDevice" = 26368
  |       "iProduct" = 2
  |       "iSerialNumber" = 0
  |       "bNumConfigurations" = 1
  |       "Bus Power Available" = 250
  |       "USB Address" = 2
  |       "Built-In" = No
  |       "locationID" = 34603008
  |       "bDeviceSubClass" = 0
  |       "bcdUSB" = 512
  |       "USB Product Name" = "USB Optical Mouse"
  |       "PortNum" = 1
  |       "non-removable" = "no"
  |       "AppleUSBAlternateServiceRegistryID" = 4294968654
  |       "bDeviceProtocol" = 0
  |       "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"}
  |       "IOPowerManagement" = {"DevicePowerState"=2,"CurrentPowerState"=3,"CapabilityFlags"=65536,"MaxPowerState"=4,"DriverPowerState"=3}
  |       "kUSBCurrentConfiguration" = 1
  |       "Device Speed" = 0
  |       "USB Vendor Name" = "Logitech"
  |       "idVendor" = 1133
  |       "IOGeneralInterest" = "IOCommand is not serializable"
  |       "kUSBProductString" = "USB Optical Mouse"
  |       "kUSBVendorString" = "Logitech"
  |       "IOClassNameOverride" = "IOUSBDevice"
  |     }

Here's an example of the same WITH the -x switch, i.e. ioreg -p IOUSB -w0 -l -x:

  | +-o USB Optical Mouse@02100000  <class AppleUSBDevice, id 0x100000553, registered, matched, active, busy 0 (0 ms), retain 11>
  |     {
  |       "sessionID" = 0x5064fe3b
  |       "idProduct" = 0xc077
  |       "iManufacturer" = 0x1
  |       "bDeviceClass" = 0x0
  |       "bMaxPacketSize0" = 0x8
  |       "bcdDevice" = 0x6700
  |       "iProduct" = 0x2
  |       "iSerialNumber" = 0x0
  |       "bNumConfigurations" = 0x1
  |       "Bus Power Available" = 0xfa
  |       "USB Address" = 0x2
  |       "Built-In" = No
  |       "locationID" = 0x2100000
  |       "bDeviceSubClass" = 0x0
  |       "bcdUSB" = 0x200
  |       "USB Product Name" = "USB Optical Mouse"
  |       "PortNum" = 0x1
  |       "non-removable" = "no"
  |       "AppleUSBAlternateServiceRegistryID" = 0x10000054e
  |       "bDeviceProtocol" = 0x0
  |       "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"}
  |       "IOPowerManagement" = {"DevicePowerState"=0x2,"CurrentPowerState"=0x3,"CapabilityFlags"=0x10000,"MaxPowerState"=0x4,"DriverPowerState"=0x3}
  |       "kUSBCurrentConfiguration" = 0x1
  |       "Device Speed" = 0x0
  |       "USB Vendor Name" = "Logitech"
  |       "idVendor" = 0x46d
  |       "IOGeneralInterest" = "IOCommand is not serializable"
  |       "kUSBProductString" = "USB Optical Mouse"
  |       "kUSBVendorString" = "Logitech"
  |       "IOClassNameOverride" = "IOUSBDevice"
  |     }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions