#include #include #include #include #include "pico/stdlib.h" #include "bsp/board_api.h" #include "tusb.h" #include "aw410k.h" #include "usb_host.h" #include "usb_server.h" #include "usb_device.h" // reserve space for CDC messages char cdc_buf[64]; uint16_t cdc_len; size_t cdc_count; device_state_t device_state; // reserve space for HID descriptor static uint8_t desc_configuration[DESC_CFG_MAX]; static uint16_t _desc_str[32+1]; // device descriptor static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, // Use Interface Association Descriptor (IAD) for CDC // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = USB_VID, .idProduct = USB_PID, .bcdDevice = 0x0100, .iManufacturer = 0x01, .iProduct = 0x02, .iSerialNumber = 0x03, .bNumConfigurations = 0x01 }; // string labels for device static char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "Raspberry Pi", // 1: Manufacturer "Pico AW410K RGB Controller", // 2: Product NULL, // 3: Serials, should use chip ID "Pico AW410K CDC", // 4: CDC "Pico AWK410K NCM", // 5: NCM NULL, // 6: MAC address for NCM "Pico AW410K HID", // 7: HID }; static void usb_device_init(void); // main task for USB device void usb_device_main(void) { // start ADC for reading LDR startADC(); // initialize the TinyUSB device device_state = DEVICE_INACTIVE; usb_device_init(); // start the web server on USB usb_server_init(); while (true) { switch ( device_state ) { case DEVICE_ACTIVE: if (!tud_mounted()) { device_state = DEVICE_INACTIVE; } break; case DEVICE_INACTIVE: break; case DEVICE_RESTART: if (tud_disconnect()) { device_state = DEVICE_INACTIVE; sleep_ms(10); tud_connect(); } break; default: break; } get_light(); // get the ADC LDR reading tud_task(); tud_cdc_write_flush(); } } // initialize the TinyUSB device static void usb_device_init(void) { // run TinyUSB device tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO, }; tusb_init(BOARD_TUH_RHPORT, &dev_init); } // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void) { return (uint8_t const *) &desc_device; } // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // set configuration descriptor and CDC descriptor memset(desc_configuration, 0, sizeof(desc_configuration)); uint8_t desc_initial[TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+TUD_CDC_NCM_DESC_LEN+1] = { TUD_CONFIG_DESCRIPTOR(1, 4+num_mounted, 0, TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+TUD_CDC_NCM_DESC_LEN+num_mounted*TUD_HID_DESC_LEN, 0x00, 100), TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NCM, 5, 6, EPNUM_NCM_NOTIF, 64, EPNUM_NCM_OUT, EPNUM_NCM_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU) }; memcpy(desc_configuration, desc_initial, TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+TUD_CDC_NCM_DESC_LEN); // add a HID descriptor for each interface mounted on host if ( descriptors != NULL) { struct report_desc *descriptor; for (uint8_t i=0; idev_addr, i); uint8_t hid_desc[TUD_HID_DESC_LEN+1] = { TUD_HID_DESCRIPTOR(ITF_NUM_HID+i, 7, HID_ITF_PROTOCOL_NONE, descriptor->desc_len, EPNUM_HID+i, CFG_TUD_HID_EP_BUFSIZE, 1) }; memcpy(&desc_configuration[TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+TUD_CDC_NCM_DESC_LEN+i*TUD_HID_DESC_LEN], hid_desc, TUD_HID_DESC_LEN); } } return desc_configuration; } // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; uint8_t chr_count; switch (index) { case 0: // langid memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; break; case 3: // serial chr_count = board_usb_get_serial(_desc_str+1, 32); break; case 6: // MAC address: link-local prefix of 02 and last 10 digits from board serial chr_count = board_usb_get_serial(_desc_str+1, 32); if (chr_count > 12) { _desc_str[1] = '0'; _desc_str[2] = '2'; for (uint8_t i=0; i<10; i++) { _desc_str[3+i] = _desc_str[chr_count-9+i]; } chr_count=12; } break; default: // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; char* str = string_desc_arr[index]; // Cap at max char chr_count = (uint8_t) strlen(str); if ( chr_count > 31 ) chr_count = 31; // Convert ASCII string into UTF-16 for(uint8_t i=0; idev_addr, itf); if ( descriptor != NULL ) { return descriptor->descriptor; } } return NULL; } // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // forward to device connected to host if (descriptors != NULL) { tuh_hid_set_report(descriptors->dev_addr, instance, report_id, report_type, buffer, bufsize); } } // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { (void) instance; (void) report_id; (void) report_type; (void) buffer; (void) reqlen; return 0; } // Invoked when device is mounted void tud_mount_cb(void) { device_state = DEVICE_ACTIVE; } // print message to CDC in raw hex void cdc_print_hex(uint8_t const* msg, uint16_t msg_len) { (void) msg; (void) msg_len; for (int i=0; i