36#ifndef _FREERTOS_DRIVERS_TINYUSB_TINYUSBCDCIMPL_HXX_
37#define _FREERTOS_DRIVERS_TINYUSB_TINYUSBCDCIMPL_HXX_
47#ifndef USBD_STACK_SIZE
48#define USBD_STACK_SIZE 768
52#define USBD_TASK_PRIO 3
55TinyUsbCdc::~TinyUsbCdc()
59void TinyUsbCdc::hw_postinit()
61 usbdThread_.
start(
"tinyusb_device", USBD_TASK_PRIO, USBD_STACK_SIZE);
70 tud_init(BOARD_TUD_RHPORT);
79 tud_cdc_write_flush();
85 unsigned char *data = (
unsigned char *)buf;
95 size_t bytes_read = tud_cdc_read(data, count < 64 ? count : 64);
101 if ((file->
flags & O_NONBLOCK) || result > 0)
110 DeviceBufferBase::block_until_condition(file,
true);
115 result += bytes_read;
119 if (!result && (file->
flags & O_NONBLOCK))
129 const unsigned char *data = (
const unsigned char *)buf;
134 portENTER_CRITICAL();
139 size_t bytes_written = tud_cdc_write(data, count < 64 ? count : 64);
142 if (bytes_written == 0)
145 if ((file->
flags & O_NONBLOCK) || result > 0)
154 DeviceBufferBase::block_until_condition(file,
false);
158 count -= bytes_written;
159 result += bytes_written;
160 data += bytes_written;
163 if (!result && (file->
flags & O_NONBLOCK))
170 tud_cdc_write_flush();
188 portENTER_CRITICAL();
189 if (tud_cdc_available() > 0)
200 portENTER_CRITICAL();
201 if (tud_cdc_write_available() > 0)
219inline void TinyUsbCdc::rx_available()
224inline void TinyUsbCdc::tx_complete()
232void tud_cdc_rx_cb(uint8_t itf)
240void tud_cdc_tx_complete_cb(uint8_t itf)
255#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
257 (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
258 _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4))
260#define USB_VID 0xCAFE
261#define USB_BCD 0x0200
265uint8_t
const *tud_descriptor_device_cb(
void)
267 static tusb_desc_device_t
const desc_device = {
268 .bLength =
sizeof(tusb_desc_device_t),
269 .bDescriptorType = TUSB_DESC_DEVICE,
275 .bDeviceClass = TUSB_CLASS_MISC,
276 .bDeviceSubClass = MISC_SUBCLASS_COMMON,
277 .bDeviceProtocol = MISC_PROTOCOL_IAD,
279 .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
282 .idProduct = USB_PID,
285 .iManufacturer = 0x01,
287 .iSerialNumber = 0x03,
289 .bNumConfigurations = 0x01};
291 return (uint8_t
const *)&desc_device;
301#define EPNUM_CDC_NOTIF 0x81
302#define EPNUM_CDC_OUT 0x02
303#define EPNUM_CDC_IN 0x82
305#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
308uint8_t
const desc_fs_configuration[] = {
311 TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
316 ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
319#if TUD_OPT_HIGH_SPEED
324uint8_t
const desc_hs_configuration[] = {
327 TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
332 ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
336uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
340tusb_desc_device_qualifier_t
const desc_device_qualifier = {
341 .bLength =
sizeof(tusb_desc_device_qualifier_t),
342 .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
345 .bDeviceClass = TUSB_CLASS_MISC,
346 .bDeviceSubClass = MISC_SUBCLASS_COMMON,
347 .bDeviceProtocol = MISC_PROTOCOL_IAD,
349 .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
350 .bNumConfigurations = 0x01,
359uint8_t
const *tud_descriptor_device_qualifier_cb(
void)
361 return (uint8_t
const *)&desc_device_qualifier;
368uint8_t
const *tud_descriptor_other_speed_configuration_cb(uint8_t index)
374 memcpy(desc_other_speed_config,
375 (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration
376 : desc_hs_configuration,
379 desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
381 return desc_other_speed_config;
389uint8_t
const *tud_descriptor_configuration_cb(uint8_t index)
393#if TUD_OPT_HIGH_SPEED
395 return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration
396 : desc_fs_configuration;
398 return desc_fs_configuration;
403char const *string_desc_arr[] = {
404 (
const char[]) {0x09, 0x04},
411static uint16_t _desc_str[32];
416uint16_t
const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
424 memcpy(&_desc_str[1], string_desc_arr[0], 2);
432 if (!(index <
sizeof(string_desc_arr) /
sizeof(string_desc_arr[0])))
435 const char *str = string_desc_arr[index];
438 chr_count = (uint8_t)strlen(str);
443 for (uint8_t i = 0; i < chr_count; i++)
445 _desc_str[1 + i] = str[i];
450 _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
void start(const char *name, int priority, size_t stack_size)
Starts the thread.
void * entry() override
User entry point for the created thread.
ssize_t write(File *file, const void *buf, size_t count) override
Write to a file or device.
bool select(File *file, int mode) override
Device select method.
Device::SelectInfo selectInfoWrite_
Handles the select for outgoing data (write).
ssize_t read(File *file, void *buf, size_t count) override
Read from a file or device.
Device::SelectInfo selectInfoRead_
Handles the select for incoming data (read).
#define FWRITE
Workaround for missing header defines on some newlib versions.
#define FREAD
Workaround for missing header defines on some newlib versions.
static void select_insert(SelectInfo *info)
Add client to list of clients needing woken.
static void select_wakeup(SelectInfo *info)
Wakeup the list of clients needing woken.