diff --git a/jc/cli.py b/jc/cli.py index f9629b1f..be912f32 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -85,6 +85,7 @@ parsers = [ 'lsblk', 'lsmod', 'lsof', + 'lsusb', 'mount', 'netstat', 'ntpq', diff --git a/jc/parsers/lsusb.py b/jc/parsers/lsusb.py new file mode 100644 index 00000000..776de798 --- /dev/null +++ b/jc/parsers/lsusb.py @@ -0,0 +1,404 @@ +"""jc - JSON CLI output utility `lsusb` command output parser + +<> + +Usage (cli): + + $ lsusb -v | jc --lsusb + + or + + $ jc lsusb -v + +Usage (module): + + import jc.parsers.lsusb + result = jc.parsers.lsusb.parse(lsusb_command_output) + +Schema: + + [ + { + "lsusb": string, + "bar": boolean, + "baz": integer + } + ] + +Examples: + + $ lsusb | jc --lsusb -p + [] + + $ lsusb | jc --lsusb -p -r + [] +""" +import jc.utils +from jc.parsers.universal import sparse_table_parse + + +class info(): + """Provides parser metadata (version, author, etc.)""" + version = '1.0' + description = '`lsusb` command parser' + author = 'Kelly Brazil' + author_email = 'kellyjonbrazil@gmail.com' + # details = 'enter any other details here' + + # compatible options: linux, darwin, cygwin, win32, aix, freebsd + compatible = ['linux'] + magic_commands = ['lsusb'] + + +__version__ = info.version + + +def _process(proc_data): + """ + Final processing to conform to the schema. + + Parameters: + + proc_data: (List of Dictionaries) raw structured data to process + + Returns: + + List of Dictionaries. Structured to conform to the schema. + """ + + # process the data here + # rebuild output for added semantic information + # use helper functions in jc.utils for int, float, bool conversions and timestamps + + return proc_data + + +def _count_indent(line): + indent = 0 + for char in line: + if char == ' ': + indent += 1 + continue + else: + break + return indent + + +def _add_attributes(line): + indent = _count_indent(line) + # section header is formatted with the correct spacing to be used with jc.parsers.universal.sparse_table_parse() + # pad end of string to be at least len of 25 + section_header = 'key val description' + + line_obj = [section_header, line.strip() + (' ' * 25)] + line_obj = sparse_table_parse(line_obj) + line_obj[0].update({'indent': indent}) + + return line_obj[0] + + +def parse(data, raw=False, quiet=False): + """ + Main text parsing function + + Parameters: + + data: (string) text data to parse + raw: (boolean) output preprocessed JSON if True + quiet: (boolean) suppress warning messages if True + + Returns: + + List of Dictionaries. Raw or processed structured data. + """ + if not quiet: + jc.utils.compatibility(__name__, info.compatible) + + raw_output = [] + output_line = {} + section = '' + device_descriptor_list = [] + configuration_descriptor_list = [] + interface_descriptor_list = [] + cdc_header_list = [] + cdc_call_management_list = [] + cdc_acm_list = [] + cdc_union_list = [] + endpoint_descriptor_list = [] + hid_device_descriptor_list = [] + report_descriptors_list = [] + hub_descriptor_list = [] + hub_port_status_list = [] + + if jc.utils.has_data(data): + + for line in data.splitlines(): + # blank line: new object + if not line: + if endpoint_descriptor_list: + interface_descriptor_list.append({'endpoint_descriptor': endpoint_descriptor_list}) + + if report_descriptors_list: + pass + + if output_line: + raw_output.append(output_line) + + output_line = {} + device_descriptor_list = [] + configuration_descriptor_list = [] + interface_descriptor_list = [] + cdc_header_list = [] + cdc_call_management_list = [] + cdc_acm_list = [] + cdc_union_list = [] + endpoint_descriptor_list = [] + hid_device_descriptor_list = [] + report_descriptors_list = [] + hub_descriptor_list = [] + hub_port_status_list = [] + section = '' + continue + + # sections + if line.startswith('Bus '): + if output_line: + raw_output.append(output_line) + + output_line = {} + device_descriptor_list = [] + configuration_descriptor_list = [] + interface_descriptor_list = [] + cdc_header_list = [] + cdc_call_management_list = [] + cdc_acm_list = [] + cdc_union_list = [] + endpoint_descriptor_list = [] + hid_device_descriptor_list = [] + report_descriptors_list = [] + hub_descriptor_list = [] + hub_port_status_list = [] + section = 'bus' + + line_split = line.strip().split(maxsplit=6) + output_line.update( + { + 'bus': line_split[1], + 'device': line_split[3][:-1], + 'id': line_split[5], + 'description': (line_split[6:7] or [None])[0] # way to get a list item or None + } + ) + continue + + if line.startswith('Device Descriptor:'): + section = 'device_descriptor' + device_descriptor_list = [] + configuration_descriptor_list = [] + interface_descriptor_list = [] + cdc_header_list = [] + cdc_call_management_list = [] + cdc_acm_list = [] + cdc_union_list = [] + endpoint_descriptor_list = [] + hid_device_descriptor_list = [] + report_descriptors_list = [] + hub_descriptor_list = [] + hub_port_status_list = [] + continue + + if line.startswith(' Configuration Descriptor:'): + section = 'configuration_descriptor' + configuration_descriptor_list = [] + interface_descriptor_list = [] + continue + + if line.startswith(' Interface Descriptor:'): + section = 'interface_descriptor' + + if cdc_header_list: + interface_descriptor_list.append({'cdc_header': cdc_header_list}) + + if cdc_call_management_list: + interface_descriptor_list.append({'cdc_call_management': cdc_call_management_list}) + + if cdc_acm_list: + interface_descriptor_list.append({'cdc_acm': cdc_acm_list}) + + if cdc_union_list: + interface_descriptor_list.append({'cdc_union': cdc_union_list}) + + if endpoint_descriptor_list: + interface_descriptor_list.append({'endpoint_descriptor': endpoint_descriptor_list}) + + if interface_descriptor_list: + if 'interface_descriptor' not in output_line['device_descriptor']['configuration_descriptor']: + output_line['device_descriptor']['configuration_descriptor']['interface_descriptor'] = [] + output_line['device_descriptor']['configuration_descriptor']['interface_descriptor'].append(interface_descriptor_list) + + cdc_header_list = [] + cdc_call_management_list = [] + cdc_acm_list = [] + cdc_union_list = [] + endpoint_descriptor_list = [] + interface_descriptor_list = [] + continue + + if line.startswith(' CDC Header:'): + section = 'cdc_header' + cdc_header_list = [] + continue + + if line.startswith(' CDC Call Management:'): + section = 'cdc_call_management' + cdc_call_management_list = [] + continue + + if line.startswith(' CDC ACM:'): + section = 'cdc_acm' + cdc_acm_list = [] + continue + + if line.startswith(' CDC Union:'): + section = 'cdc_union' + cdc_union_list = [] + continue + + if line.startswith(' Endpoint Descriptor:'): + section = 'endpoint_descriptor' + if endpoint_descriptor_list: + interface_descriptor_list.append({'endpoint_descriptor': endpoint_descriptor_list}) + endpoint_descriptor_list = [] + continue + + if line.startswith(' HID Device Descriptor:'): + section = 'hid_device_descriptor' + hid_device_descriptor_list = [] + continue + + if line.startswith(' Report Descriptors:'): + section = 'report_descriptors' + report_descriptors_list = [] + continue + + if line.startswith('Hub Descriptor:'): + section = 'hub_descriptor' + hub_descriptor_list = [] + continue + + if line.startswith(' Hub Port Status:'): + section = 'hub_port_status' + hub_port_status_list = [] + continue + + if line.startswith('Device Status:'): + section = 'device_status' + line_split = line.strip().split(':', maxsplit=1) + output_line.update( + { + 'device_status': + { + 'value': line_split[1].strip() + } + } + ) + continue + + # create section lists and schema + if section == 'device_descriptor' and line.startswith(' '): + device_descriptor_list.append(_add_attributes(line)) + if 'device_descriptor' not in output_line: + output_line['device_descriptor'] = {} + output_line['device_descriptor']['attributes'] = device_descriptor_list + continue + + if section == 'configuration_descriptor' and line.startswith(' '): + configuration_descriptor_list.append(_add_attributes(line)) + if 'configuration_descriptor' not in output_line['device_descriptor']: + output_line['device_descriptor']['configuration_descriptor'] = {} + output_line['device_descriptor']['configuration_descriptor']['attributes'] = configuration_descriptor_list + continue + + if section == 'interface_descriptor' and line.startswith(' '): + interface_descriptor_list.append(_add_attributes(line)) + + if cdc_header_list: + interface_descriptor_list.append({'cdc_header': cdc_header_list}) + + if cdc_call_management_list: + interface_descriptor_list.append({'cdc_call_management': cdc_call_management_list}) + + if cdc_acm_list: + interface_descriptor_list.append({'cdc_acm': cdc_acm_list}) + + if cdc_union_list: + interface_descriptor_list.append({'cdc_union': cdc_union_list}) + + if endpoint_descriptor_list: + interface_descriptor_list.append({'endpoint_descriptor': endpoint_descriptor_list}) + + if interface_descriptor_list: + if 'interface_descriptor_list' not in output_line['device_descriptor']['configuration_descriptor']: + output_line['device_descriptor']['configuration_descriptor']['interface_descriptor'] = [] + output_line['device_descriptor']['configuration_descriptor']['interface_descriptor'].append(interface_descriptor_list) + + cdc_header_list = [] + cdc_call_management_list = [] + cdc_acm_list = [] + cdc_union_list = [] + endpoint_descriptor_list = [] + + continue + + if section == 'cdc_header' and line.startswith(' '): + cdc_header_list.append(_add_attributes(line)) + continue + + if section == 'cdc_call_management' and line.startswith(' '): + cdc_call_management_list.append(_add_attributes(line)) + continue + + if section == 'cdc_acm' and line.startswith(' '): + cdc_acm_list.append(_add_attributes(line)) + continue + + if section == 'cdc_union' and line.startswith(' '): + cdc_union_list.append(_add_attributes(line)) + continue + + if section == 'endpoint_descriptor' and line.startswith(' '): + if hid_device_descriptor_list: + endpoint_descriptor_list.append({'hid_device_descriptor': hid_device_descriptor_list}) + + hid_device_descriptor_list = [] + endpoint_descriptor_list.append(_add_attributes(line)) + continue + + if section == 'hid_device_descriptor' and line.startswith(' '): + if report_descriptors_list: + hid_device_descriptor_list.append({'report_descriptors': report_descriptors_list}) + + report_descriptors_list = [] + hid_device_descriptor_list.append(_add_attributes(line)) + continue + + if section == 'report_descriptors' and line.startswith(' '): + report_descriptors_list.append(_add_attributes(line)) + continue + + if section == 'hub_descriptor' and line.startswith(' '): + hub_descriptor_list.append(_add_attributes(line)) + if 'hub_descriptor' not in output_line: + output_line['hub_descriptor'] = {} + output_line['hub_descriptor']['attributes'] = hub_descriptor_list + continue + + if section == 'hub_port_status' and line.startswith(' '): + hub_port_status_list.append(_add_attributes(line)) + output_line['hub_descriptor']['hub_port_status'] = hub_port_status_list + continue + + if output_line: + raw_output.append(output_line) + + return raw_output if raw else _process(raw_output) diff --git a/tests/fixtures/centos-7.7/lsusb-v.out b/tests/fixtures/centos-7.7/lsusb-v.out new file mode 100644 index 00000000..5d4ac6c4 --- /dev/null +++ b/tests/fixtures/centos-7.7/lsusb-v.out @@ -0,0 +1,509 @@ + +Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 9 Hub + bDeviceSubClass 0 Unused + bDeviceProtocol 0 Full speed (or root) hub + bMaxPacketSize0 64 + idVendor 0x1d6b Linux Foundation + idProduct 0x0002 2.0 root hub + bcdDevice 3.10 + iManufacturer 3 Linux 3.10.0-1062.1.2.el7.x86_64 ehci_hcd + iProduct 2 EHCI Host Controller + iSerial 1 0000:02:02.0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xe0 + Self Powered + Remote Wakeup + MaxPower 0mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 9 Hub + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 Full speed (or root) hub + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0004 1x 4 bytes + bInterval 12 +Hub Descriptor: + bLength 9 + bDescriptorType 41 + nNbrPorts 6 + wHubCharacteristic 0x000a + No power switching (usb 1.0) + Per-port overcurrent protection + bPwrOn2PwrGood 10 * 2 milli seconds + bHubContrCurrent 0 milli Ampere + DeviceRemovable 0x00 + PortPwrCtrlMask 0xff + Hub Port Status: + Port 1: 0000.0100 power + Port 2: 0000.0100 power + Port 3: 0000.0100 power + Port 4: 0000.0100 power + Port 5: 0000.0100 power + Port 6: 0000.0100 power +Device Status: 0x0001 + Self Powered + +Bus 002 Device 004: ID 0e0f:0008 VMware, Inc. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 224 Wireless + bDeviceSubClass 1 Radio Frequency + bDeviceProtocol 1 Bluetooth + bMaxPacketSize0 64 + idVendor 0x0e0f VMware, Inc. + idProduct 0x0008 + bcdDevice 1.00 + iManufacturer 1 VMware + iProduct 2 Virtual Bluetooth Adapter + iSerial 3 000650268328 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 177 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 0mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered + +Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 9 Hub + bDeviceSubClass 0 Unused + bDeviceProtocol 0 Full speed (or root) hub + bMaxPacketSize0 8 + idVendor 0x0e0f VMware, Inc. + idProduct 0x0002 Virtual USB Hub + bcdDevice 1.00 + iManufacturer 1 VMware, Inc. + iProduct 2 VMware Virtual USB Hub + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 1 VMware, Inc. + bmAttributes 0xe0 + Self Powered + Remote Wakeup + MaxPower 0mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 9 Hub + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 Full speed (or root) hub + iInterface 1 VMware, Inc. + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0001 1x 1 bytes + bInterval 255 +Hub Descriptor: + bLength 9 + bDescriptorType 41 + nNbrPorts 7 + wHubCharacteristic 0x0009 + Per-port power switching + Per-port overcurrent protection + bPwrOn2PwrGood 50 * 2 milli seconds + bHubContrCurrent 100 milli Ampere + DeviceRemovable 0x00 + PortPwrCtrlMask 0xfe + Hub Port Status: + Port 1: 0000.0103 power enable connect + Port 2: 0000.0100 power + Port 3: 0000.0100 power + Port 4: 0000.0100 power + Port 5: 0000.0100 power + Port 6: 0000.0100 power + Port 7: 0000.0100 power +Device Status: 0x2909 + Self Powered + +Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x0e0f VMware, Inc. + idProduct 0x0003 Virtual Mouse + bcdDevice 1.03 + iManufacturer 1 VMware + iProduct 2 VMware Virtual USB Mouse + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 34 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 1 VMware + bmAttributes 0xc0 + Self Powered + MaxPower 0mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 3 Human Interface Device + bInterfaceSubClass 1 Boot Interface Subclass + bInterfaceProtocol 2 Mouse + iInterface 1 VMware + HID Device Descriptor: + bLength 9 + bDescriptorType 33 + bcdHID 1.10 + bCountryCode 0 Not supported + bNumDescriptors 1 + bDescriptorType 34 Report + wDescriptorLength 46 + Report Descriptors: + ** UNAVAILABLE ** + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0008 1x 8 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered + +Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 9 Hub + bDeviceSubClass 0 Unused + bDeviceProtocol 0 Full speed (or root) hub + bMaxPacketSize0 64 + idVendor 0x1d6b Linux Foundation + idProduct 0x0001 1.1 root hub + bcdDevice 3.10 + iManufacturer 3 Linux 3.10.0-1062.1.2.el7.x86_64 uhci_hcd + iProduct 2 UHCI Host Controller + iSerial 1 0000:02:00.0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xe0 + Self Powered + Remote Wakeup + MaxPower 0mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 9 Hub + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 Full speed (or root) hub + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0002 1x 2 bytes + bInterval 255 +Hub Descriptor: + bLength 9 + bDescriptorType 41 + nNbrPorts 2 + wHubCharacteristic 0x000a + No power switching (usb 1.0) + Per-port overcurrent protection + bPwrOn2PwrGood 1 * 2 milli seconds + bHubContrCurrent 0 milli Ampere + DeviceRemovable 0x00 + PortPwrCtrlMask 0xff + Hub Port Status: + Port 1: 0000.0103 power enable connect + Port 2: 0000.0103 power enable connect +Device Status: 0x0001 + Self Powered diff --git a/tests/fixtures/centos-7.7/lsusb.out b/tests/fixtures/centos-7.7/lsusb.out new file mode 100644 index 00000000..7ae128bd --- /dev/null +++ b/tests/fixtures/centos-7.7/lsusb.out @@ -0,0 +1,5 @@ +Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub +Bus 002 Device 004: ID 0e0f:0008 VMware, Inc. +Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub +Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse +Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub