summaryrefslogtreecommitdiff
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
parent558abb93af64eda51420d5bfe03355c89e4b421a (diff)
update printer class: enhance descriptors, buffer sizes, and callbacks
-rw-r--r--AGENTS.md3
-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
-rw-r--r--src/class/printer/printer.h29
-rw-r--r--src/class/printer/printer_device.c105
-rw-r--r--src/class/printer/printer_device.h22
-rw-r--r--src/device/usbd.h15
-rw-r--r--src/tusb.h4
11 files changed, 279 insertions, 208 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 34fc57cb8..bbbd7c36d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -332,6 +332,9 @@ take 2-5 minutes. NEVER CANCEL. Set timeout to 20+ minutes.
- `examples/device/cdc_msc/`: Most commonly used example for testing
- `test/unit-test/project.yml`: Ceedling test configuration
+#### MCU Reference Manuals and Datasheets
+- Look in `$HOME/Documents/Calibre Library` for all MCU reference manuals, datasheets and board schematics.
+
#### Debugging Build Issues
- **Missing compiler**: Install `gcc-arm-none-eabi` package
- **Missing dependencies**: Run `python3 tools/get_deps.py FAMILY`
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_ */
diff --git a/src/class/printer/printer.h b/src/class/printer/printer.h
index c9ed3cebc..b32543077 100644
--- a/src/class/printer/printer.h
+++ b/src/class/printer/printer.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_PRINTER_H_
-#define _TUSB_PRINTER_H_
+#ifndef TUSB_PRINTER_H_
+#define TUSB_PRINTER_H_
#include "common/tusb_common.h"
@@ -35,13 +35,28 @@ extern "C" {
/// Printer Class Specific Control Request
typedef enum {
- PRINTER_REQ_CONTROL_GET_DEVICE_ID = 0x01, ///< Get device ID
- PRINTER_REQ_CONTROL_GET_PORT_STATUS = 0x02, ///< Get port status
- PRINTER_REQ_CONTROL_SOFT_RESET = 0x03, ///< Soft reset
-} printer_request_enum_t;
+ TUSB_PRINTER_REQUEST_GET_DEVICE_ID = 0x01, ///< Get device ID
+ TUSB_PRINTER_REQUEST_GET_PORT_STATUS = 0x02, ///< Get port status
+ TUSB_PRINTER_REQUEST_SOFT_RESET = 0x03, ///< Soft reset
+} tusb_printer_request_type_t;
+
+/// Printer Port Status (returned by GET_PORT_STATUS request)
+/// USB Printer Class spec 1.1, Section 4.2
+typedef union TU_ATTR_PACKED {
+ uint8_t status;
+ struct TU_ATTR_PACKED {
+ uint8_t reserved0 : 3; ///< Reserved (bits 0-2)
+ uint8_t not_error : 1; ///< 1 = no error, 0 = error
+ uint8_t selected : 1; ///< 1 = selected (online), 0 = not selected
+ uint8_t paper_empty : 1; ///< 1 = paper empty, 0 = paper not empty
+ uint8_t reserved6 : 2; ///< Reserved (bits 6-7)
+ } status_bm;
+} tusb_printer_port_status_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_printer_port_status_t) == 1, "size is not correct");
#ifdef __cplusplus
}
#endif
-#endif /* _TUSB_PRINTER_H__ */
+#endif
diff --git a/src/class/printer/printer_device.c b/src/class/printer/printer_device.c
index aaea4c988..d288014a1 100644
--- a/src/class/printer/printer_device.c
+++ b/src/class/printer/printer_device.c
@@ -28,13 +28,13 @@
#if (CFG_TUD_ENABLED && CFG_TUD_PRINTER)
- //--------------------------------------------------------------------+
- // INCLUDE
- //--------------------------------------------------------------------+
- #include "device/usbd.h"
- #include "device/usbd_pvt.h"
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "device/usbd.h"
+#include "device/usbd_pvt.h"
- #include "printer_device.h"
+#include "printer_device.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
@@ -63,6 +63,8 @@ typedef struct {
TUD_EPBUF_DEF(epin, CFG_TUD_PRINTER_EP_BUFSIZE);
} printer_epbuf_t;
+#define ITF_MEM_RESET_SIZE offsetof(printer_interface_t, rx_ff)
+
static printer_interface_t _printer_itf[CFG_TUD_PRINTER];
CFG_TUD_MEM_SECTION static printer_epbuf_t _printer_epbuf[CFG_TUD_PRINTER];
@@ -70,9 +72,6 @@ CFG_TUD_MEM_SECTION static printer_epbuf_t _printer_epbuf[CFG_TUD_PRINTER];
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-
-static tud_printer_configure_fifo_t _printer_fifo_cfg;
-
static bool _prep_out_transaction(uint8_t itf) {
const uint8_t rhport = 0;
printer_interface_t *p_printer = &_printer_itf[itf];
@@ -112,6 +111,25 @@ TU_ATTR_WEAK void tud_printer_rx_cb(uint8_t itf, size_t n) {
(void)n;
}
+TU_ATTR_WEAK void tud_printer_request_complete_cb(uint8_t itf, tusb_control_request_t const *request) {
+ (void)itf;
+ (void)request;
+}
+
+TU_ATTR_WEAK uint8_t const *tud_printer_get_device_id_cb(uint8_t itf) {
+ (void)itf;
+ return NULL;
+}
+
+TU_ATTR_WEAK uint8_t tud_printer_get_port_status_cb(uint8_t itf) {
+ (void)itf;
+ return 0x18; // not error, selected, paper not empty
+}
+
+TU_ATTR_WEAK void tud_printer_soft_reset_cb(uint8_t itf) {
+ (void)itf;
+}
+
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
@@ -142,7 +160,6 @@ void tud_printer_n_read_flush(uint8_t itf) {
//--------------------------------------------------------------------+
void printerd_init(void) {
tu_memclr(_printer_itf, sizeof(_printer_itf));
- tu_memclr(&_printer_fifo_cfg, sizeof(_printer_fifo_cfg));
for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
printer_interface_t *p_printer = &_printer_itf[i];
@@ -166,7 +183,7 @@ bool printerd_deinit(void) {
for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
printer_interface_t *p_printer = &_printer_itf[i];
osal_mutex_t mutex_rd = p_printer->rx_ff.mutex_rd;
- osal_mutex_t mutex_wr = p_printer->tx_ff.mutex_rd;
+ osal_mutex_t mutex_wr = p_printer->tx_ff.mutex_wr;
if (mutex_rd) {
osal_mutex_delete(mutex_rd);
@@ -189,15 +206,9 @@ void printerd_reset(uint8_t rhport) {
for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
printer_interface_t *p_printer = &_printer_itf[i];
- tu_memclr(p_printer, sizeof(&p_printer));
- if (!_printer_fifo_cfg.rx_persistent) {
- tu_fifo_clear(&p_printer->rx_ff);
- }
- if (!_printer_fifo_cfg.tx_persistent) {
- tu_fifo_clear(&p_printer->tx_ff);
- }
- // tu_fifo_set_overwritable(&p_printer->rx_ff, true);
- tu_fifo_set_overwritable(&p_printer->tx_ff, true);
+ tu_memclr(p_printer, ITF_MEM_RESET_SIZE);
+ tu_fifo_clear(&p_printer->rx_ff);
+ tu_fifo_clear(&p_printer->tx_ff);
}
}
@@ -222,7 +233,7 @@ uint16_t printerd_open(uint8_t rhport, const tusb_desc_interface_t *itf_desc, ui
//------------- Endpoints -------------//
TU_ASSERT(itf_desc->bNumEndpoints == 2);
drv_len += 2 * sizeof(tusb_desc_endpoint_t);
- p_printer->itf_num = 2;
+ p_printer->itf_num = itf_desc->bInterfaceNumber;
const uint8_t *p_desc = tu_desc_next(itf_desc);
TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_printer->ep_out, &p_printer->ep_in), 0);
@@ -233,6 +244,7 @@ uint16_t printerd_open(uint8_t rhport, const tusb_desc_interface_t *itf_desc, ui
bool printerd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t *request) {
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
+ uint8_t const itf_num = (uint8_t)request->wIndex;
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
//------------- STD Request -------------//
@@ -240,39 +252,38 @@ bool printerd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_
return true;
}
} else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
- switch (request->bRequest) {
- // https://www.usb.org/sites/default/files/usbprint11a021811.pdf
- case PRINTER_REQ_CONTROL_GET_DEVICE_ID:
- if (stage == CONTROL_STAGE_SETUP) {
- const char deviceId[] = "MANUFACTURER:ACME Manufacturing;"
- "MODEL:LaserBeam 9;"
- "COMMAND SET:PS;"
- "COMMENT:Anything you like;"
- "ACTIVE COMMAND SET:PS;";
- char buffer[256];
- strcpy(buffer + 2, deviceId);
- buffer[0] = 0x00;
- buffer[1] = strlen(deviceId);
- return tud_control_xfer(rhport, request, buffer, strlen(deviceId) + 2);
+ // https://www.usb.org/sites/default/files/usbprint11a021811.pdf
+ if (stage == CONTROL_STAGE_SETUP) {
+ switch (request->bRequest) {
+ case TUSB_PRINTER_REQUEST_GET_DEVICE_ID: {
+ // App provides buffer with IEEE 1284 format (first 2 bytes = big-endian length)
+ const uint8_t *device_id = tud_printer_get_device_id_cb(itf_num);
+ TU_VERIFY(device_id);
+ const uint16_t total_len = (uint16_t)((device_id[0] << 8) | device_id[1]);
+ return tud_control_xfer(rhport, request, (void *)(uintptr_t)device_id, total_len);
}
- break;
- case PRINTER_REQ_CONTROL_GET_PORT_STATUS:
- if (stage == CONTROL_STAGE_SETUP) {
- static uint8_t port_status = 0b00011000; // paper not empty, selected, no error
+
+ case TUSB_PRINTER_REQUEST_GET_PORT_STATUS: {
+ static uint8_t port_status;
+ port_status = tud_printer_get_port_status_cb(itf_num);
return tud_control_xfer(rhport, request, &port_status, sizeof(port_status));
}
- break;
- case PRINTER_REQ_CONTROL_SOFT_RESET:
- if (stage == CONTROL_STAGE_SETUP) {
- return false; // TODO: reset buffers, reset Bulk In and Out endpoints, clear stall conditions
- }
- break;
- default:
- return false;
+
+ case TUSB_PRINTER_REQUEST_SOFT_RESET:
+ tud_printer_soft_reset_cb(itf_num);
+ tud_control_status(rhport, request);
+ return true;
+
+ default:
+ return false;
+ }
+ } else if (stage == CONTROL_STAGE_ACK) {
+ tud_printer_request_complete_cb(itf_num, request);
}
} else {
return false;
}
+
return true;
}
diff --git a/src/class/printer/printer_device.h b/src/class/printer/printer_device.h
index 8c21e39ce..aeff1ffc5 100644
--- a/src/class/printer/printer_device.h
+++ b/src/class/printer/printer_device.h
@@ -33,11 +33,6 @@
extern "C" {
#endif
-typedef struct TU_ATTR_PACKED {
- uint8_t rx_persistent : 1; // keep rx fifo on bus reset or disconnect
- uint8_t tx_persistent : 1; // keep tx fifo on bus reset or disconnect
-} tud_printer_configure_fifo_t;
-
//--------------------------------------------------------------------+
// Application API (Multiple Ports) i.e. CFG_TUD_PRINTER > 1
//--------------------------------------------------------------------+
@@ -59,7 +54,22 @@ bool tud_printer_n_peek(uint8_t itf, uint8_t *ui8);
//--------------------------------------------------------------------+
// Invoked when received new data
-TU_ATTR_WEAK void tud_printer_rx_cb(uint8_t itf, size_t n);
+void tud_printer_rx_cb(uint8_t itf, size_t n);
+
+// Invoked when host requests device ID string (IEEE 1284).
+// Application returns pointer to device ID buffer (must remain valid until transfer completes).
+// First 2 bytes of returned buffer must contain big-endian length (including the 2 length bytes).
+const uint8_t *tud_printer_get_device_id_cb(uint8_t itf);
+
+// Invoked when host requests port status.
+uint8_t tud_printer_get_port_status_cb(uint8_t itf);
+
+// Invoked when host requests soft reset.
+void tud_printer_soft_reset_cb(uint8_t itf);
+
+// Invoked when a control request is completed (GET_DEVICE_ID, GET_PORT_STATUS, etc.)
+void tud_printer_request_complete_cb(uint8_t itf, tusb_control_request_t const *request);
+
//--------------------------------------------------------------------+
// Internal Class Driver API
diff --git a/src/device/usbd.h b/src/device/usbd.h
index c6e7d31c8..d3a6dccbb 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -331,21 +331,6 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
//--------------------------------------------------------------------+
-// Printer Descriptor Templates
-//--------------------------------------------------------------------+
-
-#define TUD_PRINTER_DESC_LEN (9 + 7 + 7) // one interface, two endpoints
-
-#define TUD_PRINTER_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \
- /* Interface */\
- 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_PRINTER, 1, 2, _stridx,\
- /* Endpoint Out */\
- 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
- /* Endpoint In */\
- 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
-
-
-//--------------------------------------------------------------------+
// HID Descriptor Templates
//--------------------------------------------------------------------+
diff --git a/src/tusb.h b/src/tusb.h
index 4f76397cc..c80c8433c 100644
--- a/src/tusb.h
+++ b/src/tusb.h
@@ -96,10 +96,6 @@
#include "class/mtp/mtp_device.h"
#endif
- #if CFG_TUD_PRINTER
- #include "class/printer/printer_device.h"
- #endif
-
#if CFG_TUD_AUDIO
#include "class/audio/audio_device.h"
#endif