refactor & cleanup some stuff. tomorrow will be adding all the preexisting interfaces, most likely
This commit is contained in:
parent
b515acabc5
commit
200eee8074
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
38
src/mode.h
38
src/mode.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue