diff options
| -rw-r--r-- | executor/common_usb.h | 103 | ||||
| -rw-r--r-- | executor/executor.cc | 20 | ||||
| -rw-r--r-- | pkg/csource/csource.go | 1 | ||||
| -rw-r--r-- | sys/linux/vusb.txt | 258 |
4 files changed, 244 insertions, 138 deletions
diff --git a/executor/common_usb.h b/executor/common_usb.h index 31071fd8c..8fe2b641b 100644 --- a/executor/common_usb.h +++ b/executor/common_usb.h @@ -139,6 +139,7 @@ int usb_fuzzer_vbus_draw(int fd, uint32 power) struct usb_fuzzer_control_event { struct usb_fuzzer_event inner; struct usb_ctrlrequest ctrl; + char data[USB_MAX_PACKET_SIZE]; }; struct usb_fuzzer_ep_io_data { @@ -180,8 +181,10 @@ static bool lookup_connect_response(struct vusb_connect_descriptors* descs, stru return true; case USB_DT_STRING: str_idx = (uint8)ctrl->wValue; - if (str_idx >= descs->strs_len) - return false; + if (str_idx >= descs->strs_len && descs->strs_len > 0) { + // Use the last string if we ran out. + str_idx = descs->strs_len - 1; + } *response_data = descs->strs[str_idx].str; *response_length = descs->strs[str_idx].len; return true; @@ -232,27 +235,35 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil struct usb_device_index index; memset(&index, 0, sizeof(index)); - int rv = false; + int rv = 0; NONFAILING(rv = parse_usb_descriptor(dev, dev_len, &index)); - if (!rv) - return -1; + if (!rv) { + debug("syz_usb_connect: parse_usb_descriptor failed with %d\n", rv); + return rv; + } debug("syz_usb_connect: parsed usb descriptor\n"); int fd = usb_fuzzer_open(); - if (fd < 0) - return -1; + if (fd < 0) { + debug("syz_usb_connect: usb_fuzzer_open failed with %d\n", rv); + return fd; + } debug("syz_usb_connect: usb_fuzzer_open success\n"); char device[32]; sprintf(&device[0], "dummy_udc.%llu", procid); rv = usb_fuzzer_init(fd, speed, "dummy_udc", &device[0]); - if (rv < 0) - return -1; + if (rv < 0) { + debug("syz_usb_connect: usb_fuzzer_init failed with %d\n", rv); + return rv; + } debug("syz_usb_connect: usb_fuzzer_init success\n"); rv = usb_fuzzer_run(fd); - if (rv < 0) - return -1; + if (rv < 0) { + debug("syz_usb_connect: usb_fuzzer_run failed with %d\n", rv); + return rv; + } debug("syz_usb_connect: usb_fuzzer_run success\n"); bool done = false; @@ -261,28 +272,37 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil event.inner.type = 0; event.inner.length = sizeof(event.ctrl); rv = usb_fuzzer_ep0_read(fd, (struct usb_fuzzer_event*)&event); - if (rv < 0) - return -1; + if (rv < 0) { + debug("syz_usb_connect: usb_fuzzer_ep0_read failed with %d\n", rv); + return rv; + } if (event.inner.type != USB_FUZZER_EVENT_CONTROL) continue; - debug("syz_usb_connect: bRequestType: 0x%x, bRequest: 0x%x, wValue: 0x%x, wIndex: 0x%x, wLength: %d\n", - event.ctrl.bRequestType, event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength); + debug("syz_usb_connect: bRequestType: 0x%x (%s), bRequest: 0x%x, wValue: 0x%x, wIndex: 0x%x, wLength: %d\n", + event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT", + event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength); bool response_found = false; char* response_data = NULL; uint32 response_length = 0; NONFAILING(response_found = lookup_connect_response(descs, &index, &event.ctrl, &response_data, &response_length, &done)); - if (!response_found) + if (!response_found) { + debug("syz_usb_connect: no response found\n"); return -1; + } if (done) { - int rv = usb_fuzzer_vbus_draw(fd, index.config->bMaxPower); - if (rv < 0) - return -1; + rv = usb_fuzzer_vbus_draw(fd, index.config->bMaxPower); + if (rv < 0) { + debug("syz_usb_connect: usb_fuzzer_vbus_draw failed with %d\n", rv); + return rv; + } rv = usb_fuzzer_configure(fd); - if (rv < 0) - return -1; + if (rv < 0) { + debug("syz_usb_connect: usb_fuzzer_configure failed with %d\n", rv); + return rv; + } unsigned ep; for (ep = 0; ep < index.eps_num; ep++) { rv = usb_fuzzer_ep_enable(fd, index.eps[ep]); @@ -302,7 +322,11 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil if (event.ctrl.wLength < response.inner.length) response.inner.length = event.ctrl.wLength; debug("syz_usb_connect: reply length = %d\n", response.inner.length); - usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + rv = usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + if (rv < 0) { + debug("syz_usb_connect: usb_fuzzer_ep0_write failed with %d\n", rv); + return rv; + } } sleep_ms(200); @@ -406,22 +430,34 @@ static volatile long syz_usb_control_io(volatile long a0, volatile long a1, vola struct usb_fuzzer_control_event event; event.inner.type = 0; - event.inner.length = sizeof(event.ctrl); + event.inner.length = USB_MAX_PACKET_SIZE; int rv = usb_fuzzer_ep0_read(fd, (struct usb_fuzzer_event*)&event); - if (rv < 0) - return -1; - if (event.inner.type != USB_FUZZER_EVENT_CONTROL) + if (rv < 0) { + debug("syz_usb_control_io: usb_fuzzer_ep0_read failed with %d\n", rv); + return rv; + } + if (event.inner.type != USB_FUZZER_EVENT_CONTROL) { + debug("syz_usb_control_io: wrong event type: %d\n", (int)event.inner.type); return -1; + } - debug("syz_usb_control_io: bRequestType: 0x%x, bRequest: 0x%x, wValue: 0x%x, wIndex: 0x%x, wLength: %d\n", - event.ctrl.bRequestType, event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength); + debug("syz_usb_control_io: bRequestType: 0x%x (%s), bRequest: 0x%x, wValue: 0x%x, wIndex: 0x%x, wLength: %d\n", + event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT", + event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength); + + if (!(event.ctrl.bRequestType & USB_DIR_IN) && event.ctrl.wLength != 0) { + debug("syz_usb_control_io: OUT data:\n"); + debug_dump_data(&event.data[0], event.ctrl.wLength); + } bool response_found = false; char* response_data = NULL; uint32 response_length = 0; NONFAILING(response_found = lookup_control_io_response(descs, resps, &event.ctrl, &response_data, &response_length)); - if (!response_found) + if (!response_found) { + debug("syz_usb_control_io: no response found\n"); return -1; + } struct usb_fuzzer_ep_io_data response; response.inner.ep = 0; @@ -434,7 +470,14 @@ static volatile long syz_usb_control_io(volatile long a0, volatile long a1, vola if (event.ctrl.wLength < response.inner.length) response.inner.length = event.ctrl.wLength; debug("syz_usb_control_io: response length = %d\n", response.inner.length); - usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + debug_dump_data(&response.data[0], response.inner.length); + rv = usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + if (rv < 0) { + debug("syz_usb_control_io: usb_fuzzer_ep0_write failed with %d\n", rv); + return rv; + } + + sleep_ms(200); return 0; } diff --git a/executor/executor.cc b/executor/executor.cc index 2ea588b72..597f6d656 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -601,12 +601,16 @@ retry: prog_extra_cover = true; call_extra_cover = true; } - if (strcmp(syscalls[call_num].name, "syz_usb_connect") == 0) { + if (strncmp(syscalls[call_num].name, "syz_usb_connect", strlen("syz_usb_connect")) == 0) { prog_extra_timeout = 2000; // Must match timeout in pkg/csource/csource.go. call_extra_timeout = 2000; } - if (strcmp(syscalls[call_num].name, "syz_usb_disconnect") == 0) { + if (strncmp(syscalls[call_num].name, "syz_usb_control_io", strlen("syz_usb_control_io")) == 0) { + // Must match timeout in pkg/csource/csource.go. + call_extra_timeout = 200; + } + if (strncmp(syscalls[call_num].name, "syz_usb_disconnect", strlen("syz_usb_disconnect")) == 0) { // Must match timeout in pkg/csource/csource.go. call_extra_timeout = 200; } @@ -723,6 +727,7 @@ retry: timeout_ms = 1000; if (event_timedwait(&th->done, timeout_ms)) handle_completion(th); + // Check if any of previous calls have completed. for (int i = 0; i < kMaxThreads; i++) { th = &threads[i]; @@ -776,9 +781,10 @@ retry: close_fds(); #endif - if (!colliding && !collide && prog_extra_cover) { + if (prog_extra_cover) { sleep_ms(500); - write_extra_output(); + if (!colliding && !collide) + write_extra_output(); } if (flag_collide && !flag_inject_fault && !colliding && !collide) { @@ -1446,10 +1452,12 @@ void debug_dump_data(const char* data, int length) { if (!flag_debug) return; - for (int i = 0; i < length; i++) { + int i; + for (i = 0; i < length; i++) { debug("%02x ", data[i] & 0xff); if (i % 16 == 15) debug("\n"); } - debug("\n"); + if (i % 16 != 0) + debug("\n"); } diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go index de99313d2..2a27ed42d 100644 --- a/pkg/csource/csource.go +++ b/pkg/csource/csource.go @@ -76,6 +76,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { // Must match timeouts in executor/executor.cc. specialCallTimeouts := map[string]int{ "syz_usb_connect": 2000, + "syz_usb_control_io": 200, "syz_usb_disconnect": 200, } timeoutExpr := "45" diff --git a/sys/linux/vusb.txt b/sys/linux/vusb.txt index 5e9177cd6..4eb8040ee 100644 --- a/sys/linux/vusb.txt +++ b/sys/linux/vusb.txt @@ -13,29 +13,34 @@ include <uapi/linux/usb/cdc.h> # This is a special fd for USB fuzzing and should only be used with syz_usb_* syzcalls. # We don't inherit it from the fd resource, to discourage syzkaller calling raw ioctls on it. resource fd_usb[int32]: -1 +resource fd_usb_hid[fd_usb] +# These are generic syzcalls for emulating arbitrary USB devices. +# They are mostly targeted to cover the enumeration process. syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb syz_usb_control_io(fd fd_usb, descs ptr[in, vusb_descriptors], resps ptr[in, vusb_responses]) syz_usb_ep_write(fd fd_usb, ep int16[0:31], len len[data], data buffer[in]) syz_usb_disconnect(fd fd_usb) +# These are syzcalls specifically targeted to the HID device class. +syz_usb_connect$hid(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_hid], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_hid +syz_usb_control_io$hid(fd fd_usb_hid, descs ptr[in, vusb_descriptors_hid], resps ptr[in, vusb_responses_hid]) + usb_device_speed = USB_SPEED_UNKNOWN, USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_WIRELESS, USB_SPEED_SUPER, USB_SPEED_SUPER_PLUS # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# USB device, configuration, interface and endpoint descriptors. - type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] { bLength const[USB_DT_DEVICE_SIZE, int8] bDescriptorType const[USB_DT_DEVICE, int8] - bcdUSB int16 + bcdUSB flags[usb_versions, int16] bDeviceClass const[CLASS, int8] bDeviceSubClass const[SUBCLASS, int8] bDeviceProtocol const[PROTOCOL, int8] - bMaxPacketSize0 int8 + bMaxPacketSize0 flags[usb_max_packet_sizes, int8] idVendor const[VENDOR, int16] idProduct const[PRODUCT, int16] bcdDevice const[DEVICE, int16] @@ -47,14 +52,12 @@ type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, configs CFS } [packed] -# TODO: support more than one configuration. -# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct -# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go. -usb_device_descriptor { - inner usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]] -} [packed] +usb_versions = 0x110, 0x200, 0x201, 0x250, 0x300, 0x310 + +# https://elixir.bootlin.com/linux/v5.1.7/source/drivers/usb/core/hub.c#L4661 +usb_max_packet_sizes = 8, 16, 32, 64 -type usb_config_descriptor_t[IFS] { +type usb_config_descriptor_t[ATTRS, IFS] { bLength const[USB_DT_CONFIG_SIZE, int8] bDescriptorType const[USB_DT_CONFIG, int8] @@ -62,19 +65,12 @@ type usb_config_descriptor_t[IFS] { bNumInterfaces len[interfaces, int8] bConfigurationValue int8 iConfiguration int8 - bmAttributes flags[usb_config_attributes, int8] + bmAttributes ATTRS bMaxPower int8 interfaces IFS } [packed] -# TODO: support more than one interface. -usb_config_descriptor { - inner usb_config_descriptor_t[array[usb_interface_descriptor, 1]] -} [packed] - -usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY - type usb_interface_descriptor_t[CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] { bLength const[USB_DT_INTERFACE_SIZE, int8] bDescriptorType const[USB_DT_INTERFACE, int8] @@ -91,18 +87,12 @@ type usb_interface_descriptor_t[CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] { endpoints EPS } [packed] -# bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol -# are patched by Go code, see sys/linux/init_vusb.go. -usb_interface_descriptor { - inner usb_interface_descriptor_t[0, 0, 0, array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]] -} [packed] - -type usb_endpoint_descriptor_t[EXTRA] { +type usb_endpoint_descriptor_t[ADDR, ATTRS, EXTRA] { bLength const[USB_DT_ENDPOINT_SIZE, int8] bDescriptorType const[USB_DT_ENDPOINT, int8] - bEndpointAddress int8 - bmAttributes flags[usb_endpoint_attributes, int8] + bEndpointAddress ADDR + bmAttributes ATTRS wMaxPacketSize int16 bInterval int8 bRefresh int8 @@ -111,17 +101,39 @@ type usb_endpoint_descriptor_t[EXTRA] { extra EXTRA } [packed] -usb_endpoint_descriptor { - inner usb_endpoint_descriptor_t[array[usb_endpoint_extra_descriptor, 0:2]] -} [packed] - -usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# USB descriptors requested by the kernel before the SET_CONFIGURATION request. +# Generic USB device, configuration, interface and endpoint descriptors. + +# TODO: support more than one configuration. +# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct +# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go. +usb_device_descriptor { + inner usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]] +} [packed] + +# TODO: support more than one interface. +usb_config_descriptor { + inner usb_config_descriptor_t[flags[usb_config_attributes, int8], array[usb_interface_descriptor, 1]] +} [packed] + +usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY + +# bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol +# are patched by Go code, see sys/linux/init_vusb.go. +usb_interface_descriptor { + inner usb_interface_descriptor_t[0, 0, 0, array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]] +} [packed] + +usb_endpoint_descriptor { + inner usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], array[usb_endpoint_extra_descriptor, 0:2]] +} [packed] + +usb_endpoint_addresses = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, USB_DIR_OUT, USB_DIR_IN + +usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK # TODO: consider unifying with vusb_descriptors in case this struct significantly grows. vusb_connect_descriptors { @@ -138,6 +150,113 @@ vusb_connect_string_descriptor { str ptr[in, usb_string_descriptor] } [packed] +vusb_descriptors { + len len[parent, int32] + generic ptr[in, vusb_descriptor_generic] + string ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]] + hid_report ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]] + bos ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]] + hub_hs ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_HUB, usb_hub_descriptor_hs]] + hub_ss ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_SS_HUB, usb_hub_descriptor_ss]] +} [packed] + +vusb_descriptor_generic { + req_type flags[usb_request_types, int8] + desc_type flags[usb_descriptor_types, int8] + len bytesize[data, int32] + data usb_generic_descriptor +} [packed] + +usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR + +type vusb_descriptor_t[CLASS, REQ, DATA] { + type const[CLASS, int8] + req const[REQ, int8] + len bytesize[data, int32] + data DATA +} [packed] + +vusb_responses { + len len[parent, int32] + generic ptr[in, vusb_response_generic] + set_interface ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_SET_INTERFACE, void]] + get_interface ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_INTERFACE, int8]] + set_configuration ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_SET_CONFIGURATION, void]] + get_configuration ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_CONFIGURATION, int8]] + get_status_hub ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]] + get_status_port ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]] + aiptek_get_report ptr[in, vusb_response_t[USB_TYPE_VENDOR, 0x1, array[int8, 3]]] + aiptek_set_report ptr[in, vusb_response_t[USB_TYPE_VENDOR, 0x9, array[int8, 3]]] + cdc_get_ntb_parameters ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]] +} [packed] + +vusb_response_generic { + type flags[usb_request_types, int8] + req flags[usb_requests, int8] + len bytesize[data, int32] + data array[int8] +} [packed] + +usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM + +type vusb_response_t[CLASS, REQ, DATA] { + type const[CLASS, int8] + req const[REQ, int8] + len bytesize[data, int32] + data DATA +} [packed] + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# USB device, configuration, interface and endpoint descriptors for the HID device class. +# Modelled after the Logitech K120 keyboard. + +usb_device_descriptor_hid { + inner usb_device_descriptor_t[0, 0, 0, 0x46d, 0xc31c, 64, array[usb_config_descriptor_hid, 1]] +} [packed] + +usb_config_descriptor_hid { + inner usb_config_descriptor_t[const[USB_CONFIG_HID_ATTRIBUTES, int8], array[usb_interface_descriptor_hid, 1]] +} [packed] + +usb_interface_descriptor_hid { + inner usb_interface_descriptor_t[USB_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_KEYBOARD, hid_descriptor_hid, array[usb_endpoint_descriptor_hid, 1]] +} [packed] + +usb_endpoint_descriptor_hid { + inner usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], array[usb_endpoint_extra_descriptor, 0:2]] +} [packed] + +define USB_CONFIG_HID_ATTRIBUTES (USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_WAKEUP) +define USB_ENDPOINT_HID_ADDRESS (1 | USB_DIR_IN) +define USB_ENDPOINT_HID_ATTRIBUTES (USB_ENDPOINT_XFER_INT) + +# TODO: consider merging with vusb_descriptors. +vusb_descriptors_hid { + len len[parent, int32] + generic ptr[in, vusb_descriptor_generic] + string ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]] + hid_report ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]] + bos ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]] +} [packed] + +# TODO: consider merging with vusb_responses. +vusb_responses_hid { + len len[parent, int32] + generic ptr[in, vusb_response_generic] + set_idle ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_SET_IDLE, void]] + set_report ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_SET_REPORT, void]] + set_protocol ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_SET_PROTOCOL, void]] +} [packed] + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# USB descriptors requested by the kernel before the SET_CONFIGURATION request. + usb_string_descriptor { bLength len[parent, int8] bDescriptorType const[USB_DT_STRING, int8] @@ -152,11 +271,11 @@ usb_qualifier_descriptor { bLength len[parent, int8] bDescriptorType const[USB_DT_DEVICE_QUALIFIER, int8] - bcdUSB int16 + bcdUSB flags[usb_versions, int16] bDeviceClass int8 bDeviceSubClass int8 bDeviceProtocol int8 - bMaxPacketSize0 int8 + bMaxPacketSize0 flags[usb_max_packet_sizes, int8] bNumConfigurations int8 bRESERVED const[0, int8] } [packed] @@ -505,7 +624,6 @@ usb_cdc_mbim_extended_desc { # USB descriptors requested after the SET_CONFIGURATION request. # TODO: define recusively to generate proper structures. - hid_descriptor_report { items array[hid_report_item] } [packed] @@ -623,67 +741,3 @@ usb_cdc_ncm_ntb_parameters { # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - -vusb_descriptors { - len len[parent, int32] - generic ptr[in, vusb_descriptor_generic] - string ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]] - hid_report ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]] - bos ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]] - hub_hs ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_HUB, usb_hub_descriptor_hs]] - hub_ss ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_SS_HUB, usb_hub_descriptor_ss]] -} [packed] - -vusb_descriptor_generic { - req_type flags[usb_request_types, int8] - desc_type flags[usb_descriptor_types, int8] - len bytesize[data, int32] - data usb_generic_descriptor -} [packed] - -usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR - -type vusb_descriptor_t[CLASS, REQ, DATA] { - type const[CLASS, int8] - req const[REQ, int8] - len bytesize[data, int32] - data DATA -} [packed] - -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - -vusb_responses { - len len[parent, int32] - generic ptr[in, vusb_response_generic] - set_interface ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_SET_INTERFACE, void]] - get_interface ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_INTERFACE, int8]] - set_configuration ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_SET_CONFIGURATION, void]] - get_configuration ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_CONFIGURATION, int8]] - get_status_hub ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]] - get_status_port ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]] - aiptek_get_report ptr[in, vusb_response_t[USB_TYPE_VENDOR, 0x1, array[int8, 3]]] - aiptek_set_report ptr[in, vusb_response_t[USB_TYPE_VENDOR, 0x9, array[int8, 3]]] - cdc_get_ntb_parameters ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]] -} [packed] - -vusb_response_generic { - type flags[usb_request_types, int8] - req flags[usb_requests, int8] - len bytesize[data, int32] - data array[int8] -} [packed] - -usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM - -type vusb_response_t[CLASS, REQ, DATA] { - type const[CLASS, int8] - req const[REQ, int8] - len bytesize[data, int32] - data DATA -} [packed] - -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
