summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-03-06 15:11:59 +0700
committerhathach <[email protected]>2026-03-06 15:11:59 +0700
commit5838c7f09dda8921fe6f350871211f8bd5a97208 (patch)
treecb2df6d43128316051842860e3ef1468fbbc489c /examples
parent558abb93af64eda51420d5bfe03355c89e4b421a (diff)
update printer class: enhance descriptors, buffer sizes, and callbacks
Diffstat (limited to 'examples')
-rw-r--r--examples/device/CMakeLists.txt1
-rw-r--r--examples/device/printer_to_hid/src/main.c18
-rw-r--r--examples/device/printer_to_hid/src/tusb_config.h10
-rw-r--r--examples/device/printer_to_hid/src/usb_descriptors.c233
-rw-r--r--examples/device/printer_to_hid/src/usb_descriptors.h47
5 files changed, 180 insertions, 129 deletions
diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt
index 660df67cb..dbcb8df6a 100644
--- a/examples/device/CMakeLists.txt
+++ b/examples/device/CMakeLists.txt
@@ -30,6 +30,7 @@ set(EXAMPLE_LIST
msc_dual_lun
mtp
net_lwip_webserver
+ printer_to_hid
uac2_headset
uac2_speaker_fb
usbtmc
diff --git a/examples/device/printer_to_hid/src/main.c b/examples/device/printer_to_hid/src/main.c
index 765d1e653..02b54c7d0 100644
--- a/examples/device/printer_to_hid/src/main.c
+++ b/examples/device/printer_to_hid/src/main.c
@@ -81,7 +81,7 @@ static void hid_tx_task(void) {
return;
}
- if (board_millis() - start_ms < interval_ms) {
+ if (tusb_time_millis_api() - start_ms < interval_ms) {
return; // not enough time
}
start_ms += interval_ms;
@@ -208,6 +208,22 @@ void tud_printer_rx_cb(uint8_t itf, size_t n) {
pending_bytes_on_usb_ep += n; // count pending bytes, counter must decrement when reading from the endpoint buffer
}
+// IEEE 1284 Device ID: first 2 bytes are big-endian total length (including the 2 length bytes).
+// The rest is the Device ID string using standard abbreviated keys.
+static const char printer_device_id[] =
+ "\x00\x34" // total length = 52 = 0x0034 (big-endian)
+ "MFG:TinyUSB;"
+ "MDL:Printer to HID;"
+ "CMD:PS;"
+ "CLS:PRINTER;";
+
+TU_VERIFY_STATIC(sizeof(printer_device_id) - 1 == 52, "device ID length mismatch");
+
+uint8_t const *tud_printer_get_device_id_cb(uint8_t itf) {
+ (void)itf;
+ return (uint8_t const *)printer_device_id;
+}
+
//--------------------------------------------------------------------+
// HID callbacks
diff --git a/examples/device/printer_to_hid/src/tusb_config.h b/examples/device/printer_to_hid/src/tusb_config.h
index a8dbac89d..0988be166 100644
--- a/examples/device/printer_to_hid/src/tusb_config.h
+++ b/examples/device/printer_to_hid/src/tusb_config.h
@@ -34,8 +34,6 @@ extern "C" {
// Board Specific Configuration
//--------------------------------------------------------------------+
-#define BOARD_DEVICE_RHPORT_NUM 3
-
// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
@@ -103,10 +101,10 @@ extern "C" {
// HID buffer size Should be sufficient to hold ID (if any) + Data
#define CFG_TUD_HID_EP_BUFSIZE 16
-// Printer buffer size Should be sufficient to hold data
-#define CFG_TUD_PRINTER_RX_BUFSIZE 16
-#define CFG_TUD_PRINTER_TX_BUFSIZE 16
-#define CFG_TUD_PRINTER_EP_BUFSIZE 16
+// Printer buffer sizes
+#define CFG_TUD_PRINTER_RX_BUFSIZE 512
+#define CFG_TUD_PRINTER_TX_BUFSIZE 512
+#define CFG_TUD_PRINTER_EP_BUFSIZE 512
#ifdef __cplusplus
}
diff --git a/examples/device/printer_to_hid/src/usb_descriptors.c b/examples/device/printer_to_hid/src/usb_descriptors.c
index 9a88cb891..1cbabb02e 100644
--- a/examples/device/printer_to_hid/src/usb_descriptors.c
+++ b/examples/device/printer_to_hid/src/usb_descriptors.c
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2026 Ha Thach (tinyusb.org)
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,117 +28,188 @@
#include "usb_descriptors.h"
+#define USB_VID 0xCafe
+#define USB_PID 0x4004
+#define USB_BCD 0x0200
//--------------------------------------------------------------------+
-// Report definitions
+// Device Descriptors
//--------------------------------------------------------------------+
+static tusb_desc_device_t const desc_device = {
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = USB_BCD,
+ .bDeviceClass = 0x00,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
-// Values of the string descriptors. Order must match the order defined by STRING_DESCRIPTOR_INDICES.
-const char *STRING_DESCRIPTOR_VALUES[] = {
- (const char[]){0x09, 0x04}, // 0: Supported language is English (0x0409)
- "TinyUSB", // 1: Manufacturer
- "TinyUSB Device", // 2: Product
- NULL, // 3: Serial number, will use unique ID from the Pi Pico board hardware
- "Config1", // 4: Configuration
- "Hid1", // 5: HID interface
- "Print1", // 6: Printer interface
+ .idVendor = USB_VID,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+uint8_t const *tud_descriptor_device_cb(void) {
+ return (uint8_t const *) &desc_device;
+}
+
+//--------------------------------------------------------------------+
+// HID Report Descriptor
+//--------------------------------------------------------------------+
+static uint8_t const desc_hid_report[] = {
+ TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD))
};
-uint8_t HID_REPORT_DESCRIPTOR[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD))};
+uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) {
+ (void)instance;
+ return desc_hid_report;
+}
+
+//--------------------------------------------------------------------+
+// Configuration Descriptor
+//--------------------------------------------------------------------+
+
+// Endpoint numbers
+#if defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY)
+ #define EPNUM_HID 0x81
+ #define EPNUM_PRINTER_OUT 0x02
+ #define EPNUM_PRINTER_IN 0x83
+#else
+ #define EPNUM_HID 0x81
+ #define EPNUM_PRINTER_OUT 0x02
+ #define EPNUM_PRINTER_IN 0x82
+#endif
-uint8_t CONFIG_INTERFACE_ENDPOINT_DESCRIPTOR[] = {
+// full speed configuration
+static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
- TUD_CONFIG_DESCRIPTOR(1, ITF_COUNT, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
- // HID:
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
- TUD_HID_DESCRIPTOR(ITF_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(HID_REPORT_DESCRIPTOR), EPADDR_HID,
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID,
CFG_TUD_HID_EP_BUFSIZE, 5),
- // Printer:
// Interface number, string index, EP Bulk Out address, EP Bulk In address, EP size
- TUD_PRINTER_DESCRIPTOR(ITF_PRINTER, 0, EPADDR_PRINTER_OUT, EPADDR_PRINTER_IN, CFG_TUD_PRINTER_EP_BUFSIZE)};
-
-static const tusb_desc_device_t DEVICE_DESCRIPTOR = {
- .bLength = sizeof(tusb_desc_device_t),
- .bDescriptorType = TUSB_DESC_DEVICE,
- .bcdUSB = USB_BCD,
- .bDeviceClass = 0x00, // Define class at interface level
- .bDeviceSubClass = 0x00,
- .bDeviceProtocol = 0x00,
- .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+ TUD_PRINTER_DESCRIPTOR(ITF_NUM_PRINTER, 5, EPNUM_PRINTER_OUT, EPNUM_PRINTER_IN, 64),
+};
- .idVendor = USB_VID,
- .idProduct = USB_PID,
- .bcdDevice = 0x0100,
+#if TUD_OPT_HIGH_SPEED
+// high speed configuration
+static uint8_t const desc_hs_configuration[] = {
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
- .iManufacturer = STR_MANUFACTURER,
- .iProduct = STR_PRODUCT,
- .iSerialNumber = STR_SERIAL,
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID,
+ CFG_TUD_HID_EP_BUFSIZE, 5),
- .bNumConfigurations = 0x01
+ TUD_PRINTER_DESCRIPTOR(ITF_NUM_PRINTER, 5, EPNUM_PRINTER_OUT, EPNUM_PRINTER_IN, 512),
};
+// other speed configuration
+static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
-//--------------------------------------------------------------------+
-// TinyUSB callbacks (descriptor requests)
-//--------------------------------------------------------------------+
+// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
+static tusb_desc_device_qualifier_t const desc_device_qualifier = {
+ .bLength = sizeof(tusb_desc_device_qualifier_t),
+ .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
+ .bcdUSB = USB_BCD,
-// TinyUSB GET HID REPORT DESCRIPTOR callback.
-const uint8_t *tud_hid_descriptor_report_cb(uint8_t instance) {
- (void)instance;
- return HID_REPORT_DESCRIPTOR;
+ .bDeviceClass = 0x00,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+ .bNumConfigurations = 0x01,
+ .bReserved = 0x00
+};
+
+uint8_t const *tud_descriptor_device_qualifier_cb(void) {
+ return (uint8_t const *) &desc_device_qualifier;
}
-// TinyUSB GET CONFIGURATION DESCRIPTOR callback.
-const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
- (void)index;
- return CONFIG_INTERFACE_ENDPOINT_DESCRIPTOR;
+uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) {
+ (void) index;
+
+ // if link speed is high return fullspeed config, and vice versa
+ memcpy(desc_other_speed_config,
+ (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
+ CONFIG_TOTAL_LEN);
+
+ desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
+
+ return desc_other_speed_config;
}
-// TinyUSB GET DEVICE DESCRIPTOR callback.
-const uint8_t *tud_descriptor_device_cb(void) {
- return (const uint8_t *)&DEVICE_DESCRIPTOR;
+#endif // TUD_OPT_HIGH_SPEED
+
+uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
+ (void) index;
+
+#if TUD_OPT_HIGH_SPEED
+ return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
+#else
+ return desc_fs_configuration;
+#endif
}
-// Storage buffer array for string descriptor to be sent to host.
-static uint16_t string_descriptor_buffer[STRING_DESCRIPTOR_MAX_LENGTH + 1];
+//--------------------------------------------------------------------+
+// String Descriptors
+//--------------------------------------------------------------------+
-// TinyUSB GET STRING DESCRIPTOR callback.
-const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
- (void)langid;
- size_t utf16_string_length;
+enum {
+ STRID_LANGID = 0,
+ STRID_MANUFACTURER,
+ STRID_PRODUCT,
+ STRID_SERIAL,
+ STRID_HID,
+ STRID_PRINTER,
+};
- if (index == LANGID) {
- // langid is not a string as in a series of characters: language ID code is binary, 2 bytes
- memcpy(string_descriptor_buffer + 1, STRING_DESCRIPTOR_VALUES[LANGID], 2);
- utf16_string_length = 1; // 2 bytes = 1 UTF16 word
+static char const *string_desc_arr[] = {
+ (const char[]) { 0x09, 0x04 }, // 0: supported language is English (0x0409)
+ "TinyUSB", // 1: Manufacturer
+ "TinyUSB Device", // 2: Product
+ NULL, // 3: Serial, use unique ID if possible
+ "TinyUSB HID", // 4: HID Interface
+ "TinyUSB Printer", // 5: Printer Interface
+};
- } else if (index == STR_SERIAL) {
- // serialnumber is generated from pi pico: see note in STRING_DESCRIPTOR_VALUES definition
- utf16_string_length = board_usb_get_serial(string_descriptor_buffer + 1, STRING_DESCRIPTOR_MAX_LENGTH);
+static uint16_t _desc_str[32 + 1];
- } else if (index < STRING_COUNT) {
- // Get adequate descriptor string
- const char *str = STRING_DESCRIPTOR_VALUES[index];
- utf16_string_length = strlen(str);
- if (utf16_string_length > STRING_DESCRIPTOR_MAX_LENGTH) {
- utf16_string_length = STRING_DESCRIPTOR_MAX_LENGTH;
- }
- // Convert ASCII string from memory (char*) to UTF16 (for buffer),
- // store in buffer with 1 UTF16 word offset (2 bytes, for buffer header)
- for (size_t i = 0; i < utf16_string_length; i++) {
- string_descriptor_buffer[i + 1] = str[i];
- }
+uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
+ (void) langid;
+ size_t chr_count;
- } else {
- return NULL;
- }
+ switch (index) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
- // Set buffer header:
- // byte 1 - buffer length in bytes (including header)
- // byte 0 - string descriptor type (0x03).
- string_descriptor_buffer[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * utf16_string_length + 2));
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
+
+ default:
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { return NULL; }
+
+ const char *str = string_desc_arr[index];
+
+ chr_count = strlen(str);
+ size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1;
+ if (chr_count > max_count) { chr_count = max_count; }
+
+ for (size_t i = 0; i < chr_count; i++) {
+ _desc_str[1 + i] = str[i];
+ }
+ break;
+ }
- return string_descriptor_buffer;
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
+ return _desc_str;
}
diff --git a/examples/device/printer_to_hid/src/usb_descriptors.h b/examples/device/printer_to_hid/src/usb_descriptors.h
index 0d9793a9c..20c34f151 100644
--- a/examples/device/printer_to_hid/src/usb_descriptors.h
+++ b/examples/device/printer_to_hid/src/usb_descriptors.h
@@ -25,52 +25,17 @@
#ifndef USB_DESCRIPTORS_H_
#define USB_DESCRIPTORS_H_
-#include "bsp/board_api.h"
-#include "tusb.h"
-
-#define USB_VID 0xCafe // unassigned vendor id
-#define USB_PID 0x4004 // random product id
-#define USB_BCD 0x0200 // binary coded version: 2.00
-
-// Configuration
-#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_PRINTER_DESC_LEN)
-
-// HID interface endpoints
-#define EPADDR_HID 0x81 // Interrupt In, MSB must be 1
-// Printer interface endpoints
-#define EPADDR_PRINTER_OUT 0x01 // Bulk Out, MSB must be 0
-#define EPADDR_PRINTER_IN 0x82 // Bulk In, MSB must be 1
-
// HID report ID
-#define REPORT_ID_KEYBOARD 1
-
-// The maximum length of the string that will be sent to the host via the STRING DESCRIPTOR. Note that the
-// string descriptor itself is two bytes wider than the string.
-#define STRING_DESCRIPTOR_MAX_LENGTH 32
-
-//--------------------------------------------------------------------+
-// Configuration, interface, endpoint descriptors
-//--------------------------------------------------------------------+
-
enum {
- ITF_HID,
- ITF_PRINTER,
- ITF_COUNT,
+ REPORT_ID_KEYBOARD = 1,
};
-//--------------------------------------------------------------------+
-// String Descriptors
-//--------------------------------------------------------------------+
-
enum {
- LANGID = 0,
- STR_MANUFACTURER,
- STR_PRODUCT,
- STR_SERIAL,
- STR_CONFIGURATION,
- STR_HID_INTERFACE,
- STR_PRINTER_INTERFACE,
- STRING_COUNT,
+ ITF_NUM_HID,
+ ITF_NUM_PRINTER,
+ ITF_NUM_TOTAL,
};
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_PRINTER_DESC_LEN)
+
#endif /* USB_DESCRIPTORS_H_ */