From a6a5e6ec0cb2e0833b3de101648702a8b36aef90 Mon Sep 17 00:00:00 2001 From: windowsair Date: Thu, 23 Jan 2020 21:55:51 +0800 Subject: [PATCH] feat: USBIP & Standard USB Descriptor Definitions 1. Add Standard USB Descriptor Definitions 2. USBIP stage1 completed --- components/README.md | 3 +- components/USBIP/USB_handle.c | 221 +++++++++++++++++++++++++++++++ components/USBIP/USB_handle.h | 5 + components/USBIP/USBd_config.c | 220 +++++++++++++++++++++++++++++++ components/USBIP/USBd_config.h | 41 ++++++ components/USBIP/usb_defs.h | 6 +- components/USBIP/usbip_defs.h | 2 +- main/main.c | 2 +- main/tcp_server.c | 14 +- main/usbip_server.c | 229 ++++++++++++++++++++++++++++++--- main/usbip_server.h | 2 +- 11 files changed, 713 insertions(+), 32 deletions(-) create mode 100644 components/USBIP/USB_handle.c create mode 100644 components/USBIP/USB_handle.h create mode 100644 components/USBIP/USBd_config.c create mode 100644 components/USBIP/USBd_config.h diff --git a/components/README.md b/components/README.md index 474ac22..e52e5e9 100644 --- a/components/README.md +++ b/components/README.md @@ -1,3 +1,4 @@ # TODO 1. adapt to special hardware -2. USB \ No newline at end of file +2. USB +3. Significant Bit is difficult to judge, may need to dive into the details of usbip \ No newline at end of file diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c new file mode 100644 index 0000000..8b0cd44 --- /dev/null +++ b/components/USBIP/USB_handle.c @@ -0,0 +1,221 @@ +/** + * @file USB_handle.c + * @brief Handle all Standard Device Requests + * @version 0.1 + * @date 2020-01-23 + * + * @copyright Copyright (c) 2020 + * + */ +#include +#include "USB_handle.h" + +// handle functions +static void handleGetDescriptor(usbip_stage2_header *header); +static void handle_get_device_descriptor(usbip_stage2_header *header); + +////TODO: fill this +int handleUSBControlRequest(usbip_stage2_header *header) +{ + // Table 9-3. Standard Device Requests + + switch (header->u.cmd_submit.request.bmRequestType) + { + case 0x00: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_CLEAR_FEATURE: + /* code */ + break; + case USB_REQ_SET_FEATURE: + /* code */ + break; + case USB_REQ_SET_ADDRESS: + /* code */ + break; + case USB_REQ_SET_DESCRIPTOR: + /* code */ + break; + case USB_REQ_SET_CONFIGURATION: + /* code */ + break; + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + case 0x01: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_CLEAR_FEATURE: + /* code */ + break; + case USB_REQ_SET_FEATURE: + /* code */ + break; + case USB_REQ_SET_INTERFACE: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + case 0x02: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_CLEAR_FEATURE: + /* code */ + break; + case USB_REQ_SET_FEATURE: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + + case 0x80: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_GET_CONFIGURATION: + handleGetDescriptor(header); + break; + case USB_REQ_GET_DESCRIPTOR: + /* code */ + break; + case USB_REQ_GET_STATUS: + /* code */ + break; + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + case 0x81: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_GET_INTERFACE: + /* code */ + break; + case USB_REQ_SET_SYNCH_FRAME: + /* code */ + break; + case USB_REQ_GET_STATUS: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + + case 0x82: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_GET_STATUS: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + ///////// + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } +} + +////TODO: fill this +static void handleGetDescriptor(usbip_stage2_header *header) +{ + // 9.4.3 Get Descriptor + switch (header->u.cmd_submit.request.wValue.u8hi) + { + case USB_DT_DEVICE: + handleGetDeviceDescriptor(header); + break; + + case USB_DT_CONFIGURATION: + handleGetConfigurationDescriptor(header); + break; + + case USB_DT_STRING: + handleGetStringDescriptor(header); + break; + + case USB_DT_INTERFACE: + handleGetInterfaceDescriptor(header); + break; + + case USB_DT_ENDPOINT: + handleGetEndpointDescriptor(header); + break; + + case USB_DT_DEVICE_QUALIFIER: + handleGetDeviceQualifierDescriptor(header); + break; + + case USB_DT_OTHER_SPEED_CONFIGURATION: + os_printf("GET 0x07 [UNIMPLEMENTED] USB_DT_OTHER_SPEED_CONFIGURATION"); + break; + + case USB_DT_INTERFACE_POWER: + os_printf("GET 0x08 [UNIMPLEMENTED] USB_DT_INTERFACE_POWER"); + break; + + case USB_DT_REPORT: + handle_get_hid_report_descriptor(header); + break; + + default: + os_printf("USB unknown Get Descriptor requested:%d", header->u.cmd_submit.request.wValue.u8lo); + break; + } +} + +static void handle_get_device_descriptor(usbip_stage2_header *header) +{ + os_printf("* GET 0x01 DEVICE DESCRIPTOR\r\n"); + + usb_device_descriptor desc; + + desc.bLength = USB_DT_DEVICE_SIZE; + desc.bDescriptorType = USB_DT_DEVICE; + + desc.bcdUSB = 0x0110; + + // defined at interface level + desc.bDeviceClass = 0x0; + desc.bDeviceSubClass = 0x0; + desc.bDeviceProtocol = 0x0; + + desc.bMaxPacketSize0 = USB_HID_MAX_PACKET_SIZE; + + desc.idVendor = USB_DEVICE_VENDOR_ID; + desc.idProduct = USB_DEVICE_PRODUCT_ID; + desc.bcdDevice = USB_DEVICE_VERSION; + + desc.iManufacturer = STR_IMANUFACTURER; + desc.iProduct = STR_IPRODUCT; + desc.iSerialNumber = STR_ISERIAL; + + desc.bNumConfigurations = 1; + + send_stage2_submit_data(header, 0, &desc, sizeof(usb_device_descriptor)); +} \ No newline at end of file diff --git a/components/USBIP/USB_handle.h b/components/USBIP/USB_handle.h new file mode 100644 index 0000000..d23789d --- /dev/null +++ b/components/USBIP/USB_handle.h @@ -0,0 +1,5 @@ +#ifndef __USB_HANDLE_H__ +#define __USB_HANDLE_H__ +#include "usbip_defs.h" +int handleUSBControlRequest(usbip_stage2_header *header); +#endif \ No newline at end of file diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c new file mode 100644 index 0000000..c857de3 --- /dev/null +++ b/components/USBIP/USBd_config.c @@ -0,0 +1,220 @@ + ////TODO: refactoring into structure +/** + * @file USBd_config.c + * @brief Standard USB Descriptor Definitions + fix bugs 2020-1-23 + * @version 0.2 + * @date 2020-1-23 + * + * + */ +#include +#include +#include "USBd_config.h" +#include "usb_defs.h" +#include "USBd_config_CustomClass_0.h" + +#define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) + + +/** + * @brief step 1. Build Standard Device Descriptor + * + */ + +// Standard Device Descriptor +const uint8_t kUSBd0DeviceDescriptor[0x12] = +{ + 0x12, // bLength + USB_DT_DEVICE, // bDescriptorType (constant) + USBShort(0x0200), // bcdUSB (2.00) + + // We need to use a device other than the USB-IF standard, set to 0x00 + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + + USBD0_MAX_PACKET0, // Maximum packet size for default pipe. + USBShort(USBD0_DEV_DESC_IDVENDOR), // Vendor ID (VID). + USBShort(USBD0_DEV_DESC_IDPRODUCT), // Product ID (PID). + USBShort(USBD0_DEV_DESC_BCDDEVICE), // Device Version BCD. + 0x01, // Index of Manufacturer string identifier. + 0x02, // Index of Product string identifier. + 0x03 * USBD0_STR_DESC_SER_EN, // Index of Product serial number. + 0x01 // Number of configurations. +}; + + + + +/** + * @brief step 2. Buid Standard Configuration Descriptor + * + */ + + +// Standard Interface Descriptor +const uint8_t kUSBd0InterfaceDescriptor[]= +{ + 0x09, // bLength + USB_DT_INTERFACE, // bDescriptorType + USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber + USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting + 0x03, // bNumEndpoints(we will use three endpoints) + // + USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass + USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass + USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol + 0x00, // iInterface + // Index of string descriptor describing this interface + ////TODO: fix this 0x04 ? + + + // Standard Endpoint Descriptor + + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + USBD_CUSTOM_CLASS0_IF0_EP0_BENDPOINTADDRESS, // bEndpointAddress -> set 0x01 for endpoint 0 + USB_EP_ATTR_BULK, // bmAttributes -> Endpoint is a bulk endpoint. + USBShort(USBD_CUSTOM_CLASS0_IF0_EP0_HS_WMAXPACKETSIZE), + // wMaxPacketSize -> The maximum packet size: 512 bytes + // We assume that it always runs in High Speed. + USBD_CUSTOM_CLASS0_IF0_EP0_HS_BINTERVAL, // bInterval + + + // Endpoint 1: Bulk Out – used for commands received from host PC. + // Endpoint 2: Bulk In – used for responses send to host PC. + // Endpoint 3: Bulk In (optional) – used for streaming SWO trace + + // ATTENTION: + // physical endpoint 1 indeed included two "endpoints": Bulk OUT and Bulk IN + // physical endpoint 1 -> Endpoint 1 & Endpoint 2 + // physical endpoint 2 -> Endpoint 3 + + // See also : + // http://www.keil.com/pack/doc/CMSIS/DAP/html/group__DAP__ConfigUSB__gr.html + + /* Pysical endpoint 1 */ + + // "Endpoint 1: Bulk Out – used for commands received from host PC." PC -> Device + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + 0x01, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(USBD_CUSTOM_CLASS0_IF0_EP1_HS_WMAXPACKETSIZE), // wMaxPacketSize + USBD_CUSTOM_CLASS0_IF0_EP1_HS_BINTERVAL, // bInterval + + /* Pysical endpoint 1 */ + + // "Endpoint 2: Bulk In – used for responses send to host PC." Device -> PC + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + 0x81, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(USBD_CUSTOM_CLASS0_IF0_EP2_HS_WMAXPACKETSIZE), // wMaxPacketSize + USBD_CUSTOM_CLASS0_IF0_EP2_HS_BINTERVAL, // bInterval + + /* Pysical endpoint 2 */ + // "Endpoint 3: Bulk In (optional) – used for streaming SWO trace" Device -> PC + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + 0x82, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(USBD_CUSTOM_CLASS0_IF0_EP3_HS_WMAXPACKETSIZE), // wMaxPacketSize + USBD_CUSTOM_CLASS0_IF0_EP3_HS_BINTERVAL, // bInterval + + +}; + +// Standard Configuration Descriptor +const uint8_t kUSBd0ConfigDescriptor[] = +{ + // Configuration descriptor header. + + 0x09, // bLength -> 0x09?? may be ok... 1-23 + 0x03, // bDescriptorType + // constant, set to 0x03 + + USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (sizeof(kUSBd0ConfigDescriptor))), + // wTotalLength + + 0x01, // bNumInterfaces + // There is only one interface in the CMSIS-DAP project + 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ + 0x00, // iConfiguration: no string to describe this configuration */ + USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes + + USBD0_CFG_DESC_BMAXPOWER, // bMaxPower +}; + + + +/** + * @brief step 3. Build String Descriptor + * + */ + + +const uint8_t kLangDescriptor[] = +{ + 4, + USB_DT_STRING, + USBShort(USB_LANGID_ENGLISH_US) +}; + + +/** + * @brief We will use these string descriptor: + * 1. Manufacturer string -> "KEIL - Tools By ARM" + * 2. Product string -> "LPC-Link-II" + * 3. Serial number string -> "0001A0000000" + * 4. Interface string -> "LPC-Link-II CMSIS-DAP" + * + * + */ + +const uint8_t kManufacturerString[0x28] = +{ + 0x28, // bLength + 0x03, // bDescriptorType + // "KEIL - Tools By ARM" + 'K', 0, 'E', 0, 'I', 0, 'L', 0, ' ', 0, '-', 0, ' ', 0, 'T', 0, 'o', 0, 'o', 0, + 'l', 0, 's', 0, ' ', 0, 'B', 0, 'y', 0, ' ', 0, 'A', 0, 'R', 0, 'M', 0 +}; + +const uint8_t kProductString[0x18] = +{ + 0x18, // bLength + 0x03, // bDescriptorType + // "LPC-Link-II" + 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, + 'I', 0 +}; + +const uint8_t kSerialNumberString[0x1A] = +{ + 0x1A, // bLength + 0x03, // bDescriptorType + // "0001A0000000" + '0', 0, '0', 0, '0', 0, '1', 0, 'A', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, + '0', 0, '0', 0 +}; + +const uint8_t kInterfaceString[0x2C] = +{ + 0x2C, // bLength + 0x03, // bDescriptorType + // "LPC-Link-II CMSIS-DAP" + 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, + 'I', 0, ' ', 0, 'C', 0, 'M', 0, 'S', 0, 'I', 0, 'S', 0, '-', 0, 'D', 0, 'A', 0, + 'P', 0 +}; + +const uint8_t * const kUSBd0StringDescriptorsSet[] = +{ + kLangDescriptor, + kManufacturerString, + kProductString, + kSerialNumberString, + kInterfaceString +}; \ No newline at end of file diff --git a/components/USBIP/USBd_config.h b/components/USBIP/USBd_config.h new file mode 100644 index 0000000..88e213a --- /dev/null +++ b/components/USBIP/USBd_config.h @@ -0,0 +1,41 @@ +#ifndef __USBD_CONFIG_H__ +#define __USBD_CONFIG_H__ + +// Vendor ID assigned by USB-IF (idVendor). +#define USBD0_DEV_DESC_IDVENDOR 0xC251 +// Product ID assigned by manufacturer (idProduct). +#define USBD0_DEV_DESC_IDPRODUCT 0xF00A +// Device Release Number in binary-coded decimal (bcdDevice). +#define USBD0_DEV_DESC_BCDDEVICE 0x0100 + +// Maximum packet size for Endpoint 0 (bMaxPacketSize0). +#define USBD0_MAX_PACKET0 64 + +// If disabled Serial Number String will not be assigned to USB Device. +#define USBD0_STR_DESC_SER_EN 1 + +// bmAttributes +#define USBD0_CFG_DESC_BMATTRIBUTES 0x80 + +// bMaxPower +#define USBD0_CFG_DESC_BMAXPOWER 250 + + +// Interface Number +#define USBD_CUSTOM_CLASS0_IF0_NUM 0 + +// Alternate Setting +#define USBD_CUSTOM_CLASS0_IF0_ALT 0 + +// Class Code +#define USBD_CUSTOM_CLASS0_IF0_CLASS 0xFF // 0xFF: Vendor Specific + +// Subclass Code +#define USBD_CUSTOM_CLASS0_IF0_SUBCLASS 0x00 + +// Protocol Code +#define USBD_CUSTOM_CLASS0_IF0_PROTOCOL 0x00 + + + +#endif \ No newline at end of file diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h index d75f317..995a97e 100644 --- a/components/USBIP/usb_defs.h +++ b/components/USBIP/usb_defs.h @@ -23,10 +23,6 @@ #define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01 - - - - union word_t { struct { uint8_t u8lo; @@ -39,7 +35,7 @@ struct usb_standard_request { uint8_t bmRequestType; uint8_t bRequest; - word_t wValue; + word_t wValue; // 16bit word_t wIndex; word_t wLength; } __attribute__((packed)); diff --git a/components/USBIP/usbip_defs.h b/components/USBIP/usbip_defs.h index 943989a..eb3935c 100644 --- a/components/USBIP/usbip_defs.h +++ b/components/USBIP/usbip_defs.h @@ -165,7 +165,7 @@ struct usbip_stage2_header_cmd_submit { */ struct usbip_stage2_header_ret_submit { int32_t status; - int32_t data_length; + int32_t data_length;//actual_length int32_t start_frame; int32_t number_of_packets; int32_t error_count; diff --git a/main/main.c b/main/main.c index ea82251..03f5354 100644 --- a/main/main.c +++ b/main/main.c @@ -122,7 +122,7 @@ static void wait_for_ip() os_printf("Waiting for AP connection...\r\n"); xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - os_printf("Connected to AP"); + os_printf("Connected to AP\r\n"); } diff --git a/main/tcp_server.c b/main/tcp_server.c index f28213b..7e6f870 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -30,7 +30,7 @@ #include "usbip_server.h" uint8_t state = ACCEPTING; -int sock = -1; +int kSock = -1; void tcp_server_task(void *pvParameters) { char rx_buffer[2048]; @@ -89,8 +89,8 @@ void tcp_server_task(void *pvParameters) struct sockaddr_in sourceAddr; #endif uint32_t addrLen = sizeof(sourceAddr); - sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); - if (sock < 0) + kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); + if (kSock < 0) { os_printf("Unable to accept connection: errno %d\r\n", errno); break; @@ -99,7 +99,7 @@ void tcp_server_task(void *pvParameters) while (1) { - int len = recv(sock, rx_buffer, 2047, 0); + int len = recv(kSock, rx_buffer, 2047, 0); // Error occured during receiving if (len < 0) { @@ -156,11 +156,11 @@ void tcp_server_task(void *pvParameters) } } state = ACCEPTING; - if (sock != -1) + if (kSock != -1) { os_printf("Shutting down socket and restarting...\r\n"); - shutdown(sock, 0); - close(sock); + shutdown(kSock, 0); + close(kSock); shutdown(listen_sock, 0); close(listen_sock); diff --git a/main/usbip_server.c b/main/usbip_server.c index 56b3b06..38faf78 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -8,18 +8,25 @@ #include "usbip_defs.h" #include "usb_defs.h" +// attach helper function static int read_stage1_command(uint8_t *buffer, uint32_t length); static int handle_device_list(uint8_t *buffer, uint32_t length); static int handle_device_attach(uint8_t *buffer, uint32_t length); static void send_stage1_header(uint16_t command, uint32_t status); static void send_device_list(); static void send_device_info(); +static void send_interface_info(); - +// emulate helper function +static void pack(void *data, int size); +static void unpack(void *data, int size); +static int handle_submit(usbip_stage2_header *header); +static int handle_control_request(usbip_stage2_header *header); +static void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length); int attach(uint8_t *buffer, uint32_t length) { - uint32_t command = read_stage1_command(buffer, length); + int command = read_stage1_command(buffer, length); if (command < 0) { return -1; @@ -31,12 +38,12 @@ int attach(uint8_t *buffer, uint32_t length) handle_device_list(buffer, length); break; - case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT - handle_device_attach(buffer, length); + case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT + handle_device_attach(buffer, length); ////TODO: fill this break; default: - os_printf("s1 unknown command: %d\r\n", command); + os_printf("attach Unknown command: %d\r\n", command); break; } } @@ -48,7 +55,7 @@ static int read_stage1_command(uint8_t *buffer, uint32_t length) return -1; } usbip_stage1_header *req = (usbip_stage1_header *)buffer; - return ntohs(req->command) & 0xFF; // 0x80xx low bit + return (ntohs(req->command) & 0xFF); // 0x80xx low bit } static int handle_device_list(uint8_t *buffer, uint32_t length) @@ -60,18 +67,33 @@ static int handle_device_list(uint8_t *buffer, uint32_t length) static int handle_device_attach(uint8_t *buffer, uint32_t length) { - int + os_printf("Handling dev attach request...\r\n"); + + //char bus[USBIP_BUSID_SIZE]; + if (length < sizeof(USBIP_BUSID_SIZE)) + { + return -1; + } + //client.readBytes((uint8_t *)bus, USBIP_BUSID_SIZE); + + send_stage1_header(USBIP_STAGE1_CMD_DEVICE_ATTACH, 0); + + send_device_info(); + + state = EMULATING; } static void send_stage1_header(uint16_t command, uint32_t status) { os_printf("Sending header...\r\n"); usbip_stage1_header header; - header.version = htons(273); // 273??? + header.version = htons(273); ////TODO: 273??? + // may be : https://github.com/Oxalin/usbip_windows/issues/4 + header.command = htons(command); header.status = htonl(status); - send(socket, (uint8_t *)&header, sizeof(usbip_stage1_header), 0); + send(kSock, (uint8_t *)&header, sizeof(usbip_stage1_header), 0); } static void send_device_list() @@ -97,7 +119,7 @@ static void send_device_list() } } -void send_device_info() +static void send_device_info() { //// TODO:fill this os_printf("Sending device info..."); @@ -111,12 +133,11 @@ void send_device_info() device.speed = htonl(2); // what is this??? //// TODO: 0200H for USB2.0 - //// TODO: fill Vendor Product Device-version - device.idVendor = htons(USB_DEVICE_VENDOR_ID); - device.idProduct = htons(USB_DEVICE_PRODUCT_ID); - device.bcdDevice = htons(USB_DEVICE_VERSION); + device.idVendor = htons(USBD0_DEV_DESC_IDVENDOR); + device.idProduct = htons(USBD0_DEV_DESC_IDPRODUCT); + device.bcdDevice = htons(USBD0_DEV_DESC_BCDDEVICE); - device.bDeviceClass = 0x00; // + device.bDeviceClass = 0x00; // We need to use a device other than the USB-IF standard, set to 0x00 device.bDeviceSubClass = 0x00; device.bDeviceProtocol = 0x00; @@ -124,9 +145,185 @@ void send_device_info() device.bNumConfigurations = 1; device.bNumInterfaces = 1; - write(&device, sizeof(usbip_stage1_usb_device)); + send(kSock, (uint8_t *)&device, sizeof(usbip_stage1_usb_device), 0); } +static void send_interface_info() +{ + os_printf("Sending interface info...\r\n"); + usbip_stage1_usb_interface interface; + interface.bInterfaceClass = USBD_CUSTOM_CLASS0_IF0_CLASS; + interface.bInterfaceSubClass = USBD_CUSTOM_CLASS0_IF0_SUBCLASS; + interface.bInterfaceProtocol = USBD_CUSTOM_CLASS0_IF0_PROTOCOL; + interface.padding = 0; // shall be set to zero + + send(kSock, (uint8_t *)&interface, sizeof(usbip_stage1_usb_interface), 0); +} + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + int emulate(uint8_t *buffer, uint32_t length) { + // usbip_stage2_header header; + int command = read_stage2_command((usbip_stage2_header *)buffer); ////TODO: fill this + if (command < 0) + { + return -1; + } + + switch (command) + { + case USBIP_STAGE2_REQ_SUBMIT: + handle_submit((usbip_stage2_header *)buffer); + break; + + case USBIP_STAGE2_REQ_UNLINK: + handle_unlink((usbip_stage2_header *)buffer); + break; + + default: + os_printf("emulate unknown command:%d\r\n", command); + return -1; + } + return 0; +} + +int read_stage2_command(usbip_stage2_header *header, uint32_t length) +{ + if (length < sizeof(usbip_stage2_header)) + { + return -1; + } + + //client.readBytes((uint8_t *)&header, sizeof(usbip_stage2_header)); + unpack((uint32_t *)&header, sizeof(usbip_stage2_header)); + return header->base.command; +} + +/** + * @brief Pack the following packets(Offset 0x00 - 0x28): + * - cmd_submit + * - ret_submit + * - cmd_unlink + * - ret_unlink + * + * @param data Point to packets header + * @param size Packets header size + */ +static void pack(void *data, int size) +{ + + // Ignore the setup field + int size = (size / sizeof(uint32_t)) - 2; + uint32_t *ptr = (uint32_t *)data; + + for (int i = 0; i < size; i++) + { + + ptr[i] = htonl(ptr[i]); + } +} + +/** + * @brief Unack the following packets(Offset 0x00 - 0x28): + * - cmd_submit + * - ret_submit + * - cmd_unlink + * - ret_unlink + * + * @param data Point to packets header + * @param size packets header size + */ +static void unpack(void *data, int size) +{ + + // Ignore the setup field + int size = (size / sizeof(uint32_t)) - 2; + uint32_t *ptr = (uint32_t *)data; + + for (int i = 0; i < size; i++) + { + ptr[i] = ntohl(ptr[i]); + } +} + +////TODO: fill this +/** + * @brief + * + */ +static int handle_submit(usbip_stage2_header *header) +{ + switch (header->base.ep) + { + // control endpoint(endpoint 0) + case 0x00: + handle_control_request(header); + break; + + // data + case 0x01: + if (header->base.direction == 0) + { + // Serial.println("EP 01 DATA FROM HOST"); + handle_data_request(header); + } + else + { + // Serial.println("EP 01 DATA TO HOST"); + handle_data_response(header); + } + break; + + // request to save data to device + case 0x81: + if (header->base.direction == 0) + { + os_printf("*** WARN! EP 81 DATA TX"); + } + else + { + os_printf("*** WARN! EP 81 DATA RX"); + } + return -1; + + default: + os_printf("*** WARN ! UNKNOWN ENDPOINT: "); + os_printf((int)header.base.ep); + return -1; + } + return 0; +} + +static void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length) +{ + + req_header->base.command = USBIP_STAGE2_RSP_SUBMIT; + req_header->base.direction = !req_header->base.direction; + + memset(&req_header->u.ret_submit, 0, sizeof(usbip_stage2_header_ret_submit)); + + req_header->u.ret_submit.status = status; + req_header->u.ret_submit.data_length = data_length; + + pack(&req_header, sizeof(usbip_stage2_header)); + send(kSock, req_header, sizeof(usbip_stage2_header), 0); +} + +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, void *data, int32_t data_length) +{ + + send_stage2_submit(req_header, status, data_length); + + if (data_length) + { + send(kSock, data, data_length, 0); + } } \ No newline at end of file diff --git a/main/usbip_server.h b/main/usbip_server.h index e1c05f3..c085c28 100644 --- a/main/usbip_server.h +++ b/main/usbip_server.h @@ -8,7 +8,7 @@ enum state_t EMULATING }; extern uint32_t state; -extern int socket; +extern int kSock; int attach(uint8_t *buffer, uint32_t length); int emulate(uint8_t *buffer, uint32_t length);