0
0
Fork 0

feat: USBIP & Standard USB Descriptor Definitions

1. Add Standard USB Descriptor Definitions
2. USBIP stage1 completed
This commit is contained in:
windowsair 2020-01-23 21:55:51 +08:00
parent a15f873744
commit a6a5e6ec0c
11 changed files with 713 additions and 32 deletions

View File

@ -1,3 +1,4 @@
# TODO # TODO
1. adapt to special hardware 1. adapt to special hardware
2. USB 2. USB
3. Significant Bit is difficult to judge, may need to dive into the details of usbip

View File

@ -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 <stdint.h>
#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));
}

View File

@ -0,0 +1,5 @@
#ifndef __USB_HANDLE_H__
#define __USB_HANDLE_H__
#include "usbip_defs.h"
int handleUSBControlRequest(usbip_stage2_header *header);
#endif

View File

@ -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 <stdint.h>
#include <stdbool.h>
#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
};

View File

@ -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

View File

@ -23,10 +23,6 @@
#define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01 #define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01
union word_t { union word_t {
struct { struct {
uint8_t u8lo; uint8_t u8lo;
@ -39,7 +35,7 @@ struct usb_standard_request
{ {
uint8_t bmRequestType; uint8_t bmRequestType;
uint8_t bRequest; uint8_t bRequest;
word_t wValue; word_t wValue; // 16bit
word_t wIndex; word_t wIndex;
word_t wLength; word_t wLength;
} __attribute__((packed)); } __attribute__((packed));

View File

@ -165,7 +165,7 @@ struct usbip_stage2_header_cmd_submit {
*/ */
struct usbip_stage2_header_ret_submit { struct usbip_stage2_header_ret_submit {
int32_t status; int32_t status;
int32_t data_length; int32_t data_length;//actual_length
int32_t start_frame; int32_t start_frame;
int32_t number_of_packets; int32_t number_of_packets;
int32_t error_count; int32_t error_count;

View File

@ -122,7 +122,7 @@ static void wait_for_ip()
os_printf("Waiting for AP connection...\r\n"); os_printf("Waiting for AP connection...\r\n");
xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY);
os_printf("Connected to AP"); os_printf("Connected to AP\r\n");
} }

View File

@ -30,7 +30,7 @@
#include "usbip_server.h" #include "usbip_server.h"
uint8_t state = ACCEPTING; uint8_t state = ACCEPTING;
int sock = -1; int kSock = -1;
void tcp_server_task(void *pvParameters) void tcp_server_task(void *pvParameters)
{ {
char rx_buffer[2048]; char rx_buffer[2048];
@ -89,8 +89,8 @@ void tcp_server_task(void *pvParameters)
struct sockaddr_in sourceAddr; struct sockaddr_in sourceAddr;
#endif #endif
uint32_t addrLen = sizeof(sourceAddr); uint32_t addrLen = sizeof(sourceAddr);
sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (sock < 0) if (kSock < 0)
{ {
os_printf("Unable to accept connection: errno %d\r\n", errno); os_printf("Unable to accept connection: errno %d\r\n", errno);
break; break;
@ -99,7 +99,7 @@ void tcp_server_task(void *pvParameters)
while (1) while (1)
{ {
int len = recv(sock, rx_buffer, 2047, 0); int len = recv(kSock, rx_buffer, 2047, 0);
// Error occured during receiving // Error occured during receiving
if (len < 0) if (len < 0)
{ {
@ -156,11 +156,11 @@ void tcp_server_task(void *pvParameters)
} }
} }
state = ACCEPTING; state = ACCEPTING;
if (sock != -1) if (kSock != -1)
{ {
os_printf("Shutting down socket and restarting...\r\n"); os_printf("Shutting down socket and restarting...\r\n");
shutdown(sock, 0); shutdown(kSock, 0);
close(sock); close(kSock);
shutdown(listen_sock, 0); shutdown(listen_sock, 0);
close(listen_sock); close(listen_sock);

View File

@ -8,18 +8,25 @@
#include "usbip_defs.h" #include "usbip_defs.h"
#include "usb_defs.h" #include "usb_defs.h"
// attach helper function
static int read_stage1_command(uint8_t *buffer, uint32_t length); 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_list(uint8_t *buffer, uint32_t length);
static int handle_device_attach(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_stage1_header(uint16_t command, uint32_t status);
static void send_device_list(); static void send_device_list();
static void send_device_info(); 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) 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) if (command < 0)
{ {
return -1; return -1;
@ -31,12 +38,12 @@ int attach(uint8_t *buffer, uint32_t length)
handle_device_list(buffer, length); handle_device_list(buffer, length);
break; break;
case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT
handle_device_attach(buffer, length); handle_device_attach(buffer, length); ////TODO: fill this
break; break;
default: default:
os_printf("s1 unknown command: %d\r\n", command); os_printf("attach Unknown command: %d\r\n", command);
break; break;
} }
} }
@ -48,7 +55,7 @@ static int read_stage1_command(uint8_t *buffer, uint32_t length)
return -1; return -1;
} }
usbip_stage1_header *req = (usbip_stage1_header *)buffer; 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) 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) 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) static void send_stage1_header(uint16_t command, uint32_t status)
{ {
os_printf("Sending header...\r\n"); os_printf("Sending header...\r\n");
usbip_stage1_header header; 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.command = htons(command);
header.status = htonl(status); 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() 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 //// TODO:fill this
os_printf("Sending device info..."); os_printf("Sending device info...");
@ -111,12 +133,11 @@ void send_device_info()
device.speed = htonl(2); // what is this??? device.speed = htonl(2); // what is this???
//// TODO: 0200H for USB2.0 //// TODO: 0200H for USB2.0
//// TODO: fill Vendor Product Device-version device.idVendor = htons(USBD0_DEV_DESC_IDVENDOR);
device.idVendor = htons(USB_DEVICE_VENDOR_ID); device.idProduct = htons(USBD0_DEV_DESC_IDPRODUCT);
device.idProduct = htons(USB_DEVICE_PRODUCT_ID); device.bcdDevice = htons(USBD0_DEV_DESC_BCDDEVICE);
device.bcdDevice = htons(USB_DEVICE_VERSION);
device.bDeviceClass = 0x00; // <defined at interface level> device.bDeviceClass = 0x00; // We need to use a device other than the USB-IF standard, set to 0x00
device.bDeviceSubClass = 0x00; device.bDeviceSubClass = 0x00;
device.bDeviceProtocol = 0x00; device.bDeviceProtocol = 0x00;
@ -124,9 +145,185 @@ void send_device_info()
device.bNumConfigurations = 1; device.bNumConfigurations = 1;
device.bNumInterfaces = 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) 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);
}
} }

View File

@ -8,7 +8,7 @@ enum state_t
EMULATING EMULATING
}; };
extern uint32_t state; extern uint32_t state;
extern int socket; extern int kSock;
int attach(uint8_t *buffer, uint32_t length); int attach(uint8_t *buffer, uint32_t length);
int emulate(uint8_t *buffer, uint32_t length); int emulate(uint8_t *buffer, uint32_t length);