aboutsummaryrefslogtreecommitdiff
path: root/src/usb/dev.c
diff options
context:
space:
mode:
authorFrançois Cartegnie <281376+fcartegnie@users.noreply.github.com>2024-08-20 13:43:09 +0700
committerGitHub <noreply@github.com>2024-08-20 13:43:09 +0700
commitf5874d607315ff88b27414299089b8528b5bb07c (patch)
tree9db23b8e6cdfb06d8bab77e83224e604f20c4629 /src/usb/dev.c
parentb25d62d1362cfd711e6617a9212e3eddc4e9fddd (diff)
parentc3912e01a2767334103cd139d875d50c834f3f05 (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.c176
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);
+}