diff options
| author | François Cartegnie <281376+fcartegnie@users.noreply.github.com> | 2024-08-20 13:43:09 +0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-20 13:43:09 +0700 |
| commit | f5874d607315ff88b27414299089b8528b5bb07c (patch) | |
| tree | 9db23b8e6cdfb06d8bab77e83224e604f20c4629 /src/usb/dev.c | |
| parent | b25d62d1362cfd711e6617a9212e3eddc4e9fddd (diff) | |
| parent | c3912e01a2767334103cd139d875d50c834f3f05 (diff) | |
Merge pull request #35 from kienvo/usb
feat: Receive data over USB
Diffstat (limited to 'src/usb/dev.c')
| -rw-r--r-- | src/usb/dev.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/usb/dev.c b/src/usb/dev.c new file mode 100644 index 0000000..fb28e43 --- /dev/null +++ b/src/usb/dev.c @@ -0,0 +1,176 @@ +#include "CH58x_common.h" + +#include "utils.h" +#include "debug.h" + +extern uint8_t *cfg_desc; + +void usb_set_address(uint8_t ad); + +USB_DEV_DESCR dev_desc = { + .bLength = sizeof(USB_DEV_DESCR), + .bDescriptorType = 0x01, + .bcdUSB = 0x0110, + + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + + .bMaxPacketSize0 = MAX_PACKET_SIZE, + + .idVendor = 0x0416, + .idProduct = 0x5020, + .bcdDevice = 0x0000, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 0x01 +}; + +/* String Descriptor Zero, Specifying Languages Supported by the Device */ +static uint8_t lang_desc[] = { + 0x04, /* bLength */ + 0x03, /* bDescriptorType */ + 0x09, 0x04 /* wLANGID - en-US */ +}; + +static uint16_t vendor_info[] = { + 36 | /* bLength */ + 0x03 << 8, /* bDescriptorType */ + + /* bString */ + 'F', 'O', 'S', 'S', 'A', 'S', 'I', 'A', ' ', + 'W', 'A', 'S', ' ', 'H', 'E', 'R', 'E' +}; + +static uint16_t product_info[] = { + 32 | /* bLength */ + 0x03 << 8, /* bDescriptorType */ + + /* bString */ + 'L', 'E', 'D', ' ', + 'B', 'a', 'd', 'g', 'e', ' ', + 'M', 'a', 'g', 'i', 'c' +}; + +// TODO: auto update firmware version by CI here +static uint16_t serial_number[] = { + 47 * 2 | /* bLength */ + 0x03 << 8, /* bDescriptorType */ + + /* bString */ + 'N', 'o', 't', ' ', 'y', 'e', 't', ' ', + 'i', 'm', 'p', 'l', 'e', 'm', 'e', 'n', 't', 'e', 'd', '\n', + 'P', 'R', 'E', 'S', 'S', ' ', 'A', 'L', 'T', '+', 'F', '4', ' ', + 'T', 'O', ' ', 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'E', '.' +}; + +static void desc_dev(USB_SETUP_REQ *request) +{ + ctrl_start_load_block(&dev_desc, dev_desc.bLength); +} + +static void desc_config(USB_SETUP_REQ *request) +{ + ctrl_start_load_block(cfg_desc, request->wLength); +} + +static void desc_string(USB_SETUP_REQ *request) +{ + uint8_t *string_index[32] = { + lang_desc, + vendor_info, + product_info, + serial_number + }; + uint8_t index = request->wValue & 0xff; + if (index <= sizeof(string_index)) + ctrl_start_load_block(string_index[index], string_index[index][0]); +} + +static void dev_getDesc(USB_SETUP_REQ *request) +{ + _TRACE(); + uint8_t type = request->wValue >> 8; + + PRINT("Descriptor type: 0x%02x\n", type); + + static const void (*desc_type_handlers[4])(USB_SETUP_REQ *request) = { + NULL, + desc_dev, + desc_config, + desc_string + }; + if (type <= 3 && desc_type_handlers[type]) + desc_type_handlers[type](request); +} + +static void dev_getStatus(USB_SETUP_REQ *request) +{ + _TRACE(); + // Remote Wakeup disabled | Bus powered, hardcoded for now + uint8_t buf[] = {0, 0}; + ctrl_start_load_block(buf, 2); +} + +static void dev_clearFeature(USB_SETUP_REQ *request) +{ + _TRACE(); + // DEVICE_REMOTE_WAKEUP and TEST_MODE are not available, ignore. +} + +static void dev_setFeature(USB_SETUP_REQ *request) +{ + _TRACE(); + // DEVICE_REMOTE_WAKEUP and TEST_MODE are not available, ignore. +} + +static void dev_setAddress(USB_SETUP_REQ *request) +{ + _TRACE(); + /* new address will be loadled in the next IN poll, + so here just sending a ACK */ + usb_set_address(request->wValue & 0xff); + ctrl_ack(); +} + +// For now, multiple configuration is not supported +static uint8_t devcfg; + +static void dev_getConfig(USB_SETUP_REQ *request) +{ + _TRACE(); + ctrl_start_load_block(&devcfg, 1); +} + +static void dev_setConfig(USB_SETUP_REQ *request) +{ + _TRACE(); + devcfg = (request->wValue) & 0xff; + ctrl_ack(); +} + +void handle_devreq(USB_SETUP_REQ *request) +{ + _TRACE(); + + static const void (*dev_req_handlers[13])(USB_SETUP_REQ *request) = { + dev_getStatus, + dev_clearFeature, + NULL, // Reserved + dev_setFeature, + NULL, // Reserved + dev_setAddress, + dev_getDesc, + NULL, // set desc + dev_getConfig, + dev_setConfig, + NULL, // get interface + NULL, // set interface + NULL, // sync frame + }; + + uint8_t req = request->bRequest; + if (req <= 12 && dev_req_handlers[req]) + dev_req_handlers[req](request); +} |