refactor & cleanup some stuff. tomorrow will be adding all the preexisting interfaces, most likely

This commit is contained in:
Triss 2021-07-01 03:12:51 +02:00
parent b515acabc5
commit 200eee8074
6 changed files with 305 additions and 327 deletions

View File

@ -66,6 +66,7 @@ target_sources(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/modeset.c
${CMAKE_CURRENT_SOURCE_DIR}/src/thread.c
${CMAKE_CURRENT_SOURCE_DIR}/src/tusb_plt.S
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
${CMAKE_CURRENT_SOURCE_DIR}/src/vnd_cfg.c
${CMAKE_CURRENT_SOURCE_DIR}/src/m_default/0def.c
${CMAKE_CURRENT_SOURCE_DIR}/src/m_default2/0def.c

View File

@ -5,9 +5,6 @@
#include "mode.h"
#include "vnd_cfg.h"
#include "protocfg.h"
#include "util.h"
static void enter_cb(void) {
// TODO: init hw
}
@ -32,13 +29,6 @@ static void handle_cmd_cb(uint8_t cmd) {
}
}
#define USB_BCD_BASE 0x8000
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
#define USB_BCD \
(USB_BCD_BASE | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 3) | _PID_MAP(HID, 6) | _PID_MAP(MIDI, 9) | \
_PID_MAP(VENDOR, 12)) \
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
@ -77,34 +67,6 @@ enum {
#define EPNUM_VND_CFG_IN 0x82
// clang-format off
static const tusb_desc_device_t desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0110, // TODO: 0x0200 ?
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = USB_VID,
.idProduct = USB_PID,
.bcdDevice = USB_BCD,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = 0x01
};
static const uint8_t desc_hid_report[] = {
#if CFG_TUD_HID > 0
TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
#else
0
#endif
};
static const uint8_t desc_configuration[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM__TOTAL, STRID_CONFIG, CONFIG_TOTAL_LEN,
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
@ -118,9 +80,10 @@ static const uint8_t desc_configuration[] = {
//#endif
};
static const char* string_desc_arr[] = {
[STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409)
/*[STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "BLAHAJ CTF", // Manufacturer
[STRID_PRODUCT] = "Dragnbus (RP2040 Pico)", // Product
[STRID_PRODUCT] = "Dragnbus (RP2040 Pico)", // Product*/
NULL,
[STRID_CONFIG] = "Configuration descriptor",
// max string length check: |||||||||||||||||||||||||||||||
@ -129,129 +92,20 @@ static const char* string_desc_arr[] = {
};
// clang-format on
// tinyusb callbacks
#if CFG_TUD_HID > 0
// 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
static uint16_t 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;
}
static void hid_set_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t const* RxDataBuffer, uint16_t bufsize) {
static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
uint32_t response_size = TU_MIN(CFG_TUD_HID_EP_BUFSIZE, bufsize);
// This doesn't use multiple report and report ID
(void)instance;
(void)report_id;
(void)report_type;
tud_hid_report(0, TxDataBuffer, response_size);
}
#endif
static void cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
(void)itf;
(void)line_coding;
}
static bool vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr,
tusb_control_request_t const* req) {
(void)rhport;
(void)ep_addr;
(void)req;
return true;
}
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
static const uint8_t* hid_descriptor_report_cb(uint8_t instance) {
(void)instance;
return desc_hid_report;
}
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
static const uint8_t* descriptor_device_cb(void) {
return (const uint8_t*)&desc_device;
}
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
static const uint8_t* descriptor_configuration_cb(uint8_t index) {
(void)index; // for multiple configurations
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
static const uint16_t* descriptor_string_cb(uint8_t index, uint16_t langid) {
static uint16_t _desc_str[32];
(void)langid;
uint8_t chr_count = 0;
if (STRID_LANGID == index) {
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
} else if (STRID_SERIAL == index) {
chr_count = get_unique_id_u16(_desc_str + 1);
} else {
// 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;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = TU_MIN(strlen(str), 31);
// Convert ASCII string into UTF-16
for (int i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; }
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * chr_count + 2);
return _desc_str;
}
extern struct mode m_01_default;
// clang-format off
struct mode m_01_default = {
.name = "Default mode with misc features",
.usb_desc = desc_configuration,
.version = 0x0010,
.n_string_desc = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
.usb_desc = desc_configuration,
.string_desc = string_desc_arr,
.enter = enter_cb,
.leave = leave_cb,
.task = task_cb,
.handle_cmd = handle_cmd_cb,
#if CFG_TUD_HID > 0
.tud_hid_get_report_cb = hid_get_report_cb,
.tud_hid_set_report_cb = hid_set_report_cb,
#endif
.tud_cdc_line_coding_cb = cdc_line_coding_cb,
.tud_vendor_control_xfer_cb = vendor_control_xfer_cb,
.tud_hid_descriptor_report_cb = hid_descriptor_report_cb,
.tud_descriptor_device_cb = descriptor_device_cb,
.tud_descriptor_configuration_cb = descriptor_configuration_cb,
.tud_descriptor_string_cb = descriptor_string_cb,
};
// clang-format on

View File

@ -5,9 +5,6 @@
#include "mode.h"
#include "vnd_cfg.h"
#include "protocfg.h"
#include "util.h"
static void enter_cb(void) {
// TODO: init hw
}
@ -33,13 +30,6 @@ static void handle_cmd_cb(uint8_t cmd) {
}
}
#define USB_BCD_BASE 0x8000
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
#define USB_BCD \
(USB_BCD_BASE | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 3) | _PID_MAP(HID, 6) | _PID_MAP(MIDI, 9) | \
_PID_MAP(VENDOR, 12)) \
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
@ -78,34 +68,6 @@ enum {
#define EPNUM_VND_CFG_IN 0x82
// clang-format off
static const tusb_desc_device_t desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0110, // TODO: 0x0200 ?
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = USB_VID,
.idProduct = USB_PID,
.bcdDevice = USB_BCD,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = 0x01
};
static const uint8_t desc_hid_report[] = {
#if CFG_TUD_HID > 0
TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
#else
0
#endif
};
static const uint8_t desc_configuration[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM__TOTAL, STRID_CONFIG, CONFIG_TOTAL_LEN,
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
@ -119,10 +81,11 @@ static const uint8_t desc_configuration[] = {
//#endif
};
static const char* string_desc_arr[] = {
[STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409)
/*[STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "BLAHAJ CTF", // Manufacturer
[STRID_PRODUCT] = "Dragnbus (hi mum)", // Product
[STRID_PRODUCT] = "Dragnbus (hi mum)", // Product*/
NULL,
[STRID_CONFIG] = "Configuration descriptor",
// max string length check: |||||||||||||||||||||||||||||||
[STRID_IF_VND_CFG ] = "Device cfg/ctl interface",
@ -130,129 +93,20 @@ static const char* string_desc_arr[] = {
};
// clang-format on
// tinyusb callbacks
#if CFG_TUD_HID > 0
// 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
static uint16_t 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;
}
static void hid_set_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t const* RxDataBuffer, uint16_t bufsize) {
static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
uint32_t response_size = TU_MIN(CFG_TUD_HID_EP_BUFSIZE, bufsize);
// This doesn't use multiple report and report ID
(void)instance;
(void)report_id;
(void)report_type;
tud_hid_report(0, TxDataBuffer, response_size);
}
#endif
static void cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
(void)itf;
(void)line_coding;
}
static bool vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr,
tusb_control_request_t const* req) {
(void)rhport;
(void)ep_addr;
(void)req;
return true;
}
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
static const uint8_t* hid_descriptor_report_cb(uint8_t instance) {
(void)instance;
return desc_hid_report;
}
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
static const uint8_t* descriptor_device_cb(void) {
return (const uint8_t*)&desc_device;
}
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
static const uint8_t* descriptor_configuration_cb(uint8_t index) {
(void)index; // for multiple configurations
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
static const uint16_t* descriptor_string_cb(uint8_t index, uint16_t langid) {
static uint16_t _desc_str[32];
(void)langid;
uint8_t chr_count = 0;
if (STRID_LANGID == index) {
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
} else if (STRID_SERIAL == index) {
chr_count = get_unique_id_u16(_desc_str + 1);
} else {
// 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;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = TU_MIN(strlen(str), 31);
// Convert ASCII string into UTF-16
for (int i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; }
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * chr_count + 2);
return _desc_str;
}
extern struct mode m_02_default2;
// clang-format off
struct mode m_02_default2 = {
.name = "Default mode but betterer!",
.usb_desc = desc_configuration,
.version = 0x0020,
.n_string_desc = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
.usb_desc = desc_configuration,
.string_desc = string_desc_arr,
.enter = enter_cb,
.leave = leave_cb,
.task = task_cb,
.handle_cmd = handle_cmd_cb,
#if CFG_TUD_HID > 0
.tud_hid_get_report_cb = hid_get_report_cb,
.tud_hid_set_report_cb = hid_set_report_cb,
#endif
.tud_cdc_line_coding_cb = cdc_line_coding_cb,
.tud_vendor_control_xfer_cb = vendor_control_xfer_cb,
.tud_hid_descriptor_report_cb = hid_descriptor_report_cb,
.tud_descriptor_device_cb = descriptor_device_cb,
.tud_descriptor_configuration_cb = descriptor_configuration_cb,
.tud_descriptor_string_cb = descriptor_string_cb,
};
// clang-format on

View File

@ -13,8 +13,11 @@
struct mode {
const char* name;
const uint8_t* usb_desc;
uint16_t version;
uint16_t n_string_desc;
const uint8_t* usb_desc;
const char** string_desc;
void (*enter)(void); // claim required hardware. no tusb calls here please
void (*leave)(void); // release current in-use hardware. no tusb calls here please
@ -55,5 +58,38 @@ extern const struct mode* mode_list[16];
// clang-format on
#if CFG_TUD_HID > 0
// 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 mode_std_hid_get_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
void mode_std_hid_set_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t const* RxDataBuffer, uint16_t bufsize);
#endif
#if CFG_TUD_CDC > 0
void mode_std_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding);
#endif
#if CFG_TUD_VENDOR > 0
bool mode_std_vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr,
tusb_control_request_t const* req);
#endif
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
const uint8_t* mode_std_hid_descriptor_report_cb(uint8_t instance);
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
const uint8_t* mode_std_descriptor_device_cb(void);
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
const uint8_t* mode_std_descriptor_configuration_cb(uint8_t index);
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to
// complete
const uint16_t* mode_std_descriptor_string_cb(uint8_t index, uint16_t langid);
#endif

View File

@ -30,39 +30,54 @@ enum tusbgot_index {
tusbgot_descriptor_string
};
#define ORDEF(a,b) ((a != NULL) ? a : b)
void modes_init(void) {
// switch to the default mode, but without doing a USB reboot thing
mode_current_id = &mode_default - mode_list;
mode_next_id = -1;
if (!mode_default) return;
if (!mode_default) return; // TODO: panic here
// clang-format off
#if CFG_TUD_HID > 0
tusb_got[tusbgot_hid_get_report ] = mode_default->tud_hid_get_report_cb;
tusb_got[tusbgot_hid_set_report ] = mode_default->tud_hid_set_report_cb;
tusb_got[tusbgot_hid_get_report ] =
ORDEF(mode_default->tud_hid_get_report_cb, mode_std_hid_get_report_cb);
tusb_got[tusbgot_hid_set_report ] =
ORDEF(mode_default->tud_hid_set_report_cb, mode_std_hid_set_report_cb);
#else
tusb_got[tusbgot_hid_get_report ] = NULL;
tusb_got[tusbgot_hid_set_report ] = NULL;
#endif
#if CFG_TUD_CDC > 0
tusb_got[tusbgot_cdc_line_coding ] = mode_default->tud_cdc_line_coding_cb;
tusb_got[tusbgot_cdc_line_coding ] =
ORDEF(mode_default->tud_cdc_line_coding_cb, mode_std_cdc_line_coding_cb);
#else
tusb_got[tusbgot_cdc_line_coding ] = NULL;
#endif
#if CFG_TUD_VENDOR > 0
tusb_got[tusbgot_vendor_control_xfer] = mode_default->tud_vendor_control_xfer_cb;
tusb_got[tusbgot_vendor_control_xfer] =
ORDEF(mode_default->tud_vendor_control_xfer_cb, mode_std_vendor_control_xfer_cb);
#else
tusb_got[tusbgot_vendor_control_xfer] = NULL;
#endif
tusb_got[tusbgot_hid_descriptor_report ] = mode_default->tud_hid_descriptor_report_cb;
tusb_got[tusbgot_descriptor_device ] = mode_default->tud_descriptor_device_cb;
tusb_got[tusbgot_descriptor_configuration] = mode_default->tud_descriptor_configuration_cb;
tusb_got[tusbgot_descriptor_string ] = mode_default->tud_descriptor_string_cb;
tusb_got[tusbgot_hid_descriptor_report ] =
ORDEF(mode_default->tud_hid_descriptor_report_cb, mode_std_hid_descriptor_report_cb);
tusb_got[tusbgot_descriptor_device ] =
ORDEF(mode_default->tud_descriptor_device_cb, mode_std_descriptor_device_cb);
tusb_got[tusbgot_descriptor_configuration] =
ORDEF(mode_default->tud_descriptor_configuration_cb, mode_std_descriptor_configuration_cb);
tusb_got[tusbgot_descriptor_string ] =
ORDEF(mode_default->tud_descriptor_string_cb, mode_std_descriptor_string_cb);
// clang-format on
}
void modes_switch(uint8_t newmode) {
for (size_t i = 0; i < 500/20; ++i) {
tud_task(); // flush ongoing stuff
sleep_ms(10);
}
if (mode_current) mode_current->leave();
// to force a reconfig from the device, we basically have to kill the USB
@ -70,7 +85,7 @@ void modes_switch(uint8_t newmode) {
tud_disconnect();
// maybe wait a second or so for the host to notice this
sleep_ms(750);
sleep_ms(500/2);
// now apply the new tusb settings
mode_current_id = (newmode >= 16 || newmode == 0) ? (-1) : newmode;
@ -78,35 +93,66 @@ void modes_switch(uint8_t newmode) {
if (mode_current) {
// clang-format off
#if CFG_TUD_HID > 0
tusb_got[tusbgot_hid_get_report ] = mode_current->tud_hid_get_report_cb;
tusb_got[tusbgot_hid_set_report ] = mode_current->tud_hid_set_report_cb;
tusb_got[tusbgot_hid_get_report ] =
ORDEF(mode_current->tud_hid_get_report_cb, mode_std_hid_get_report_cb);
tusb_got[tusbgot_hid_set_report ] =
ORDEF(mode_current->tud_hid_set_report_cb, mode_std_hid_set_report_cb);
#else
tusb_got[tusbgot_hid_get_report ] = NULL;
tusb_got[tusbgot_hid_set_report ] = NULL;
#endif
#if CFG_TUD_CDC > 0
tusb_got[tusbgot_cdc_line_coding ] = mode_current->tud_cdc_line_coding_cb;
tusb_got[tusbgot_cdc_line_coding ] =
ORDEF(mode_current->tud_cdc_line_coding_cb, mode_std_cdc_line_coding_cb);
#else
tusb_got[tusbgot_cdc_line_coding ] = NULL;
#endif
#if CFG_TUD_VENDOR > 0
tusb_got[tusbgot_vendor_control_xfer] = mode_current->tud_vendor_control_xfer_cb;
tusb_got[tusbgot_vendor_control_xfer] =
ORDEF(mode_current->tud_vendor_control_xfer_cb, mode_std_vendor_control_xfer_cb);
#else
tusb_got[tusbgot_vendor_control_xfer] = NULL;
#endif
tusb_got[tusbgot_hid_descriptor_report ] = mode_current->tud_hid_descriptor_report_cb;
tusb_got[tusbgot_descriptor_device ] = mode_current->tud_descriptor_device_cb;
tusb_got[tusbgot_descriptor_configuration] = mode_current->tud_descriptor_configuration_cb;
tusb_got[tusbgot_descriptor_string ] = mode_current->tud_descriptor_string_cb;
tusb_got[tusbgot_hid_descriptor_report ] =
ORDEF(mode_current->tud_hid_descriptor_report_cb, mode_std_hid_descriptor_report_cb);
tusb_got[tusbgot_descriptor_device ] =
ORDEF(mode_current->tud_descriptor_device_cb, mode_std_descriptor_device_cb);
tusb_got[tusbgot_descriptor_configuration] =
ORDEF(mode_current->tud_descriptor_configuration_cb, mode_std_descriptor_configuration_cb);
tusb_got[tusbgot_descriptor_string ] =
ORDEF(mode_current->tud_descriptor_string_cb, mode_std_descriptor_string_cb);
// clang-format on
} else {
// TODO: invalid mode???
// clang-format off
#if CFG_TUD_HID > 0
tusb_got[tusbgot_hid_get_report ] = mode_std_hid_get_report_cb;
tusb_got[tusbgot_hid_set_report ] = mode_std_hid_set_report_cb;
#else
tusb_got[tusbgot_hid_get_report ] = NULL;
tusb_got[tusbgot_hid_set_report ] = NULL;
#endif
#if CFG_TUD_CDC > 0
tusb_got[tusbgot_cdc_line_coding ] = mode_std_cdc_line_coding_cb;
#else
tusb_got[tusbgot_cdc_line_coding ] = NULL;
#endif
#if CFG_TUD_VENDOR > 0
tusb_got[tusbgot_vendor_control_xfer] = mode_std_vendor_control_xfer_cb;
#else
tusb_got[tusbgot_vendor_control_xfer] = NULL;
#endif
tusb_got[tusbgot_hid_descriptor_report ] = mode_std_hid_descriptor_report_cb;
tusb_got[tusbgot_descriptor_device ] = mode_std_descriptor_device_cb;
tusb_got[tusbgot_descriptor_configuration] = mode_std_descriptor_configuration_cb;
tusb_got[tusbgot_descriptor_string ] = mode_std_descriptor_string_cb;
// clang-format on
}
// and reconnect
tud_connect();
sleep_ms(750);
sleep_ms(500/2);
//while (!tud_mounted()) sleep_ms(5);
if (mode_current) mode_current->enter();

187
src/usb_descriptors.c Normal file
View File

@ -0,0 +1,187 @@
// vim: set et:
#include "tusb_config.h"
#include <tusb.h>
#include "mode.h"
#include "protocfg.h"
#include "util.h"
#define USB_BCD_BASE 0x8000
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
#define USB_BCD \
(USB_BCD_BASE | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 3) | _PID_MAP(HID, 6) | _PID_MAP(MIDI, 9) | \
_PID_MAP(VENDOR, 12)) \
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
STRID_CONFIG,
STRID_IF_VND_CFG,
};
enum {
ITF_NUM_VND_CFG,
ITF_NUM__TOTAL
};
enum {
CONFIG_TOTAL_LEN
= TUD_CONFIG_DESC_LEN
+ TUD_VENDOR_DESC_LEN
};
#define EPNUM_VND_CFG_OUT 0x02
#define EPNUM_VND_CFG_IN 0x82
// clang-format off
static const tusb_desc_device_t desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0110, // TODO: 0x0200 ?
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = USB_VID,
.idProduct = USB_PID,
.bcdDevice = USB_BCD,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = 0x01
};
static const uint8_t desc_hid_report[] = {
#if CFG_TUD_HID > 0
TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
#else
0
#endif
};
// this is a default fallback descriptor
static const uint8_t desc_configuration[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM__TOTAL, STRID_CONFIG, CONFIG_TOTAL_LEN,
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
TUD_VENDOR_DESCRIPTOR(ITF_NUM_VND_CFG, STRID_IF_VND_CFG, EPNUM_VND_CFG_OUT,
EPNUM_VND_CFG_IN, 64),
};
static const char* string_desc_arr[] = {
[STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "BLAHAJ CTF", // Manufacturer
[STRID_PRODUCT] = "Dragnbus (RP2040 Pico)", // Product
[STRID_CONFIG] = "Configuration descriptor",
[STRID_IF_VND_CFG] = "Device cfg/ctl interface",
};
// clang-format on
#if CFG_TUD_HID > 0
uint16_t mode_std_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;
}
void mode_std_hid_set_report_cb(uint8_t instance, uint8_t report_id,
hid_report_type_t report_type, uint8_t const* rx_data_buffer, uint16_t bufsize) {
static uint8_t tx_data_buffer[CFG_TUD_HID_EP_BUFSIZE];
uint32_t response_size = TU_MIN(CFG_TUD_HID_EP_BUFSIZE, bufsize);
// This doesn't use multiple report and report ID
(void)instance;
(void)report_id;
(void)report_type;
tud_hid_report(0, tx_data_buffer, response_size);
}
#endif
#if CFG_TUD_CDC > 0
void mode_std_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
(void)itf;
(void)line_coding;
}
#endif
#if CFG_TUD_VENDOR > 0
bool mode_std_vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr,
tusb_control_request_t const* req) {
(void)rhport;
(void)ep_addr;
(void)req;
return true;
}
#endif
const uint8_t* mode_std_hid_descriptor_report_cb(uint8_t instance) {
(void)instance;
return desc_hid_report;
}
const uint8_t* mode_std_descriptor_device_cb(void) {
return (const uint8_t*)&desc_device;
}
const uint8_t* mode_std_descriptor_configuration_cb(uint8_t index) {
(void)index; // for multiple configurations
if (mode_current != NULL && mode_current->usb_desc != NULL) {
return mode_current->usb_desc;
}
return desc_configuration;
}
const uint16_t* mode_std_descriptor_string_cb(uint8_t index, uint16_t langid) {
static uint16_t _desc_str[32];
(void)langid;
uint8_t chr_count = 0;
if (index == STRID_LANGID) {
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
} else if (index == STRID_SERIAL) {
chr_count = get_unique_id_u16(_desc_str + 1);
} else if (index > STRID_CONFIG && mode_current != NULL && mode_current->string_desc != NULL) {
if (index >= mode_current->n_string_desc) return NULL;
const char* str = mode_current->string_desc[index];
chr_count = TU_MIN(strlen(str), 31);
for (int i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; }
} else {
// 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;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = TU_MIN(strlen(str), 31);
// Convert ASCII string into UTF-16
for (int i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; }
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * chr_count + 2);
return _desc_str;
}