summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-03-06 17:22:38 +0700
committerhathach <[email protected]>2026-03-06 17:22:38 +0700
commit73cd53129529f2dce70072953bfd50ec9dc6b8ea (patch)
treee4fcc75febdc1af7f56973fed061bd2a671f48a2
parent988b18a40a4276eb731c80bc4cec3bf5750523f9 (diff)
replace printer_to_hid example with printer_to_cdc example
fix printer GET_DEVICE_ID request weird wIndex (interface high, alt low)
-rw-r--r--examples/device/CMakeLists.txt2
-rw-r--r--examples/device/printer_to_cdc/CMakeLists.txt (renamed from examples/device/printer_to_hid/CMakeLists.txt)2
-rw-r--r--examples/device/printer_to_cdc/Makefile (renamed from examples/device/printer_to_hid/Makefile)0
-rw-r--r--examples/device/printer_to_cdc/src/main.c115
-rw-r--r--examples/device/printer_to_cdc/src/tusb_config.h (renamed from examples/device/printer_to_hid/src/tusb_config.h)12
-rw-r--r--examples/device/printer_to_cdc/src/usb_descriptors.c (renamed from examples/device/printer_to_hid/src/usb_descriptors.c)59
-rw-r--r--examples/device/printer_to_cdc/src/usb_descriptors.h (renamed from examples/device/printer_to_hid/src/usb_descriptors.h)12
-rw-r--r--examples/device/printer_to_hid/CMakePresets.json6
-rw-r--r--examples/device/printer_to_hid/README.md0
-rw-r--r--examples/device/printer_to_hid/src/main.c175
-rw-r--r--src/class/printer/printer.h6
-rw-r--r--src/class/printer/printer_device.c73
-rw-r--r--src/device/usbd.c24
13 files changed, 222 insertions, 264 deletions
diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt
index dbcb8df6a..7173f455e 100644
--- a/examples/device/CMakeLists.txt
+++ b/examples/device/CMakeLists.txt
@@ -30,7 +30,7 @@ set(EXAMPLE_LIST
msc_dual_lun
mtp
net_lwip_webserver
- printer_to_hid
+ printer_to_cdc
uac2_headset
uac2_speaker_fb
usbtmc
diff --git a/examples/device/printer_to_hid/CMakeLists.txt b/examples/device/printer_to_cdc/CMakeLists.txt
index f58759059..3c8ab3653 100644
--- a/examples/device/printer_to_hid/CMakeLists.txt
+++ b/examples/device/printer_to_cdc/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
-project(printer_to_hid C CXX ASM)
+project(printer_to_cdc C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
diff --git a/examples/device/printer_to_hid/Makefile b/examples/device/printer_to_cdc/Makefile
index 1a4b428dc..1a4b428dc 100644
--- a/examples/device/printer_to_hid/Makefile
+++ b/examples/device/printer_to_cdc/Makefile
diff --git a/examples/device/printer_to_cdc/src/main.c b/examples/device/printer_to_cdc/src/main.c
new file mode 100644
index 000000000..aba79025c
--- /dev/null
+++ b/examples/device/printer_to_cdc/src/main.c
@@ -0,0 +1,115 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2026 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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+/* This example demonstrates a USB Printer + CDC composite device.
+ * Data received on the Printer interface is forwarded to the CDC serial port,
+ * and data received on the CDC serial port is forwarded back to the Printer interface.
+ *
+ * To test:
+ * 1. Flash the device
+ * 2. Open a serial terminal on the CDC port (e.g. /dev/ttyACM0)
+ * 3. Send data to the printer: echo "hello" > /dev/usb/lp0
+ * 4. The data appears on the CDC serial terminal
+ * 5. Type in the serial terminal to send data back through the printer TX
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+#include "usb_descriptors.h"
+
+// -------------------------------------------------------------------+
+// Tasks
+// -------------------------------------------------------------------+
+
+// Forward data from Printer RX to CDC TX
+static void printer_to_cdc_task(void) {
+ if (tud_printer_read_available() == 0 || !tud_cdc_write_available()) {
+ return;
+ }
+
+ uint8_t buf[64];
+ uint32_t count = tud_printer_read(buf, sizeof(buf));
+ if (count > 0) {
+ tud_cdc_write(buf, count);
+ tud_cdc_write_flush();
+ }
+}
+
+// Forward data from CDC RX to Printer TX
+static void cdc_to_printer_task(void) {
+ if (tud_cdc_available() == 0 || !tud_printer_write_available()) {
+ return;
+ }
+
+ uint8_t buf[64];
+ uint32_t count = tud_cdc_read(buf, sizeof(buf));
+ if (count > 0) {
+ tud_printer_write(buf, count);
+ tud_printer_write_flush();
+ }
+}
+
+int main(void) {
+ board_init();
+ // init device stack on configured roothub port
+ tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO};
+ tusb_init(BOARD_TUD_RHPORT, &dev_init);
+ board_init_after_tusb();
+
+ while (1) {
+ tud_task(); // tinyusb device task
+ printer_to_cdc_task(); // forward printer data to CDC
+ cdc_to_printer_task(); // forward CDC data to printer
+ }
+}
+
+//--------------------------------------------------------------------+
+// Printer callbacks
+//--------------------------------------------------------------------+
+
+void tud_printer_rx_cb(uint8_t itf) {
+ (void)itf;
+}
+
+// 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 CDC;"
+ "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;
+}
diff --git a/examples/device/printer_to_hid/src/tusb_config.h b/examples/device/printer_to_cdc/src/tusb_config.h
index 0988be166..50ef41762 100644
--- a/examples/device/printer_to_hid/src/tusb_config.h
+++ b/examples/device/printer_to_cdc/src/tusb_config.h
@@ -91,15 +91,19 @@ extern "C" {
#endif
//------------- CLASS -------------//
-#define CFG_TUD_HID 1
-#define CFG_TUD_CDC 0
+#define CFG_TUD_HID 0
+#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
#define CFG_TUD_PRINTER 1
-// HID buffer size Should be sufficient to hold ID (if any) + Data
-#define CFG_TUD_HID_EP_BUFSIZE 16
+// CDC FIFO size of TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+// CDC Endpoint transfer buffer size
+#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// Printer buffer sizes
#define CFG_TUD_PRINTER_RX_BUFSIZE 512
diff --git a/examples/device/printer_to_hid/src/usb_descriptors.c b/examples/device/printer_to_cdc/src/usb_descriptors.c
index 1cbabb02e..30d309ed4 100644
--- a/examples/device/printer_to_hid/src/usb_descriptors.c
+++ b/examples/device/printer_to_cdc/src/usb_descriptors.c
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ * Copyright (c) 2026 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
@@ -29,7 +29,7 @@
#include "usb_descriptors.h"
#define USB_VID 0xCafe
-#define USB_PID 0x4004
+#define USB_PID 0x4005
#define USB_BCD 0x0200
//--------------------------------------------------------------------+
@@ -39,9 +39,12 @@ 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,
+
+ // Use Interface Association Descriptor (IAD) for CDC
+ // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = USB_VID,
@@ -60,30 +63,22 @@ uint8_t const *tud_descriptor_device_cb(void) {
}
//--------------------------------------------------------------------+
-// HID Report Descriptor
-//--------------------------------------------------------------------+
-static uint8_t const desc_hid_report[] = {
- 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
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x83
+ #define EPNUM_PRINTER_OUT 0x04
+ #define EPNUM_PRINTER_IN 0x85
#else
- #define EPNUM_HID 0x81
- #define EPNUM_PRINTER_OUT 0x02
- #define EPNUM_PRINTER_IN 0x82
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x82
+ #define EPNUM_PRINTER_OUT 0x03
+ #define EPNUM_PRINTER_IN 0x83
#endif
// full speed configuration
@@ -91,9 +86,8 @@ static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
- // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
- TUD_HID_DESCRIPTOR(ITF_NUM_HID, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID,
- CFG_TUD_HID_EP_BUFSIZE, 5),
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
// Interface number, string index, EP Bulk Out address, EP Bulk In address, EP size
TUD_PRINTER_DESCRIPTOR(ITF_NUM_PRINTER, 5, EPNUM_PRINTER_OUT, EPNUM_PRINTER_IN, 64),
@@ -104,8 +98,7 @@ static uint8_t const desc_fs_configuration[] = {
static uint8_t const desc_hs_configuration[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
- TUD_HID_DESCRIPTOR(ITF_NUM_HID, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID,
- CFG_TUD_HID_EP_BUFSIZE, 5),
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
TUD_PRINTER_DESCRIPTOR(ITF_NUM_PRINTER, 5, EPNUM_PRINTER_OUT, EPNUM_PRINTER_IN, 512),
};
@@ -119,9 +112,9 @@ static tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,
- .bDeviceClass = 0x00,
- .bDeviceSubClass = 0x00,
- .bDeviceProtocol = 0x00,
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.bNumConfigurations = 0x01,
@@ -166,7 +159,7 @@ enum {
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
- STRID_HID,
+ STRID_CDC,
STRID_PRINTER,
};
@@ -175,7 +168,7 @@ static char const *string_desc_arr[] = {
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
NULL, // 3: Serial, use unique ID if possible
- "TinyUSB HID", // 4: HID Interface
+ "TinyUSB CDC", // 4: CDC Interface
"TinyUSB Printer", // 5: Printer Interface
};
diff --git a/examples/device/printer_to_hid/src/usb_descriptors.h b/examples/device/printer_to_cdc/src/usb_descriptors.h
index 20c34f151..830593b4d 100644
--- a/examples/device/printer_to_hid/src/usb_descriptors.h
+++ b/examples/device/printer_to_cdc/src/usb_descriptors.h
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ * Copyright (c) 2026 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
@@ -25,17 +25,13 @@
#ifndef USB_DESCRIPTORS_H_
#define USB_DESCRIPTORS_H_
-// HID report ID
enum {
- REPORT_ID_KEYBOARD = 1,
-};
-
-enum {
- ITF_NUM_HID,
+ ITF_NUM_CDC,
+ ITF_NUM_CDC_DATA,
ITF_NUM_PRINTER,
ITF_NUM_TOTAL,
};
-#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_PRINTER_DESC_LEN)
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_PRINTER_DESC_LEN)
#endif /* USB_DESCRIPTORS_H_ */
diff --git a/examples/device/printer_to_hid/CMakePresets.json b/examples/device/printer_to_hid/CMakePresets.json
deleted file mode 100644
index 5cd8971e9..000000000
--- a/examples/device/printer_to_hid/CMakePresets.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "version": 6,
- "include": [
- "../../../hw/bsp/BoardPresets.json"
- ]
-}
diff --git a/examples/device/printer_to_hid/README.md b/examples/device/printer_to_hid/README.md
deleted file mode 100644
index e69de29bb..000000000
--- a/examples/device/printer_to_hid/README.md
+++ /dev/null
diff --git a/examples/device/printer_to_hid/src/main.c b/examples/device/printer_to_hid/src/main.c
deleted file mode 100644
index 0d14147b4..000000000
--- a/examples/device/printer_to_hid/src/main.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2026 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
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "bsp/board_api.h"
-#include "tusb.h"
-
-#include "usb_descriptors.h"
-
-// -------------------------------------------------------------------+
-// Variables
-// -------------------------------------------------------------------+
-
-// next keycode to send on usb/hid
-static uint8_t next_keycode = 0;
-// next key modifiers to send on usb/hid
-static uint8_t next_modifiers = 0;
-// whether the next usb/hid report must be NULL to release the last keystroke
-static bool next_keycode_is_release = false;
-
-
-// -------------------------------------------------------------------+
-// Tasks
-// -------------------------------------------------------------------+
-
-// Every 10ms, we will place HID data in the usb/hid endpoint, ready to
-// sent to the host when required. The tasks will read the keycode in
-// next_keycode and place it in the HID report, then set next_is_null
-// such that the key is released by the next report. This seem to help
-// stroking the same key twice when the character is repeated in the data.
-static void hid_tx_task(void) {
- // Poll every 10ms
- const uint32_t interval_ms = 10;
- static uint32_t start_ms = 0;
-
- if (!tud_hid_ready()) {
- return;
- }
-
- if (tusb_time_millis_api() - start_ms < interval_ms) {
- return; // not enough time
- }
- start_ms += interval_ms;
-
- if (next_keycode_is_release || next_keycode == 0) {
- tud_hid_keyboard_report(1, 0, NULL);
- next_keycode_is_release = false;
- return;
- }
-
- uint8_t keycode_array[6] = {0};
- keycode_array[0] = next_keycode;
- tud_hid_keyboard_report(1, next_modifiers, keycode_array);
- next_keycode_is_release = true;
- next_keycode = 0;
-}
-
-// Read one byte from printer FIFO and translate to HID keycode.
-// Only a-zA-Z0-9 are translated; everything else becomes space.
-static void printer_to_hid_task(void) {
- if (next_keycode != 0) {
- return; // previous key not yet sent
- }
-
- uint8_t ch;
- if (tud_printer_read(&ch, 1) == 0) {
- return; // no data available
- }
-
- uint8_t m = 0;
- if ('a' <= ch && ch <= 'z') {
- ch = (uint8_t)(ch - 'a' + HID_KEY_A);
- } else if ('A' <= ch && ch <= 'Z') {
- ch = (uint8_t)(ch - 'A' + HID_KEY_A);
- m = KEYBOARD_MODIFIER_LEFTSHIFT;
- } else if ('1' <= ch && ch <= '9') {
- ch = (uint8_t)(ch - '1' + HID_KEY_1);
- } else if (ch == '0') {
- ch = HID_KEY_0;
- } else {
- ch = HID_KEY_SPACE;
- }
-
- next_keycode = ch;
- next_modifiers = m;
-}
-
-int main(void) {
- board_init();
- // init device and host stack on configured roothub port
- tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO};
- tusb_init(BOARD_TUD_RHPORT, &dev_init);
- board_init_after_tusb();
-
- while (1) {
- tud_task(); // tinyusb device task
- printer_to_hid_task(); // read printer data and translate to HID keycodes
- hid_tx_task(); // send keycodes to host via HID
- }
-}
-
-
-//--------------------------------------------------------------------+
-// Printer callbacks
-//--------------------------------------------------------------------+
-
-void tud_printer_rx_cb(uint8_t itf) {
- (void)itf;
-}
-
-// 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
-//--------------------------------------------------------------------+
-
-uint16_t tud_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 tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, const uint8_t *buffer,
- uint16_t bufsize) {
- (void)instance;
- (void)report_id;
- (void)report_type;
- (void)buffer;
- (void)bufsize;
- return;
-}
diff --git a/src/class/printer/printer.h b/src/class/printer/printer.h
index b32543077..09d1a8956 100644
--- a/src/class/printer/printer.h
+++ b/src/class/printer/printer.h
@@ -35,9 +35,9 @@ extern "C" {
/// Printer Class Specific Control Request
typedef enum {
- 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_GET_DEVICE_ID = 0x00, ///< Get device ID
+ TUSB_PRINTER_REQUEST_GET_PORT_STATUS = 0x01, ///< Get port status
+ TUSB_PRINTER_REQUEST_SOFT_RESET = 0x02, ///< Soft reset
} tusb_printer_request_type_t;
/// Printer Port Status (returned by GET_PORT_STATUS request)
diff --git a/src/class/printer/printer_device.c b/src/class/printer/printer_device.c
index 05d3f28eb..f5bb33795 100644
--- a/src/class/printer/printer_device.c
+++ b/src/class/printer/printer_device.c
@@ -242,43 +242,54 @@ 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;
+ TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE &&
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
- if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
- if (stage != CONTROL_STAGE_SETUP) {
- return true;
- }
- } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
- // https://www.usb.org/sites/default/files/usbprint11a021811.pdf
- if (stage == CONTROL_STAGE_SETUP) {
- switch (request->bRequest) {
- case TUSB_PRINTER_REQUEST_GET_DEVICE_ID: {
- 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);
- }
+ // GET_DEVICE_ID: wIndex = (interface_number << 8) | alt_setting
+ // GET_PORT_STATUS / SOFT_RESET: wIndex = interface_number
+ uint8_t itf_num;
+ if (TUSB_PRINTER_REQUEST_GET_DEVICE_ID == request->bRequest) {
+ itf_num = tu_u16_high(request->wIndex);
+ } else {
+ itf_num = tu_u16_low(request->wIndex);
+ }
- 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));
- }
+ // Find the printer instance index from the USB interface number
+ uint8_t itf = TUSB_INDEX_INVALID_8;
+ for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
+ if (_printer_itf[i].itf_num == itf_num) {
+ itf = i;
+ break;
+ }
+ }
+ TU_VERIFY(itf < CFG_TUD_PRINTER);
- case TUSB_PRINTER_REQUEST_SOFT_RESET:
- tud_printer_soft_reset_cb(itf_num);
- tud_control_status(rhport, request);
- return true;
+ // https://www.usb.org/sites/default/files/usbprint11a021811.pdf
+ if (stage == CONTROL_STAGE_SETUP) {
+ switch (request->bRequest) {
+ case TUSB_PRINTER_REQUEST_GET_DEVICE_ID: {
+ const uint8_t *device_id = tud_printer_get_device_id_cb(itf);
+ 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);
+ }
- default:
- return false;
+ case TUSB_PRINTER_REQUEST_GET_PORT_STATUS: {
+ static uint8_t port_status;
+ port_status = tud_printer_get_port_status_cb(itf);
+ return tud_control_xfer(rhport, request, &port_status, sizeof(port_status));
}
- } else if (stage == CONTROL_STAGE_ACK) {
- tud_printer_request_complete_cb(itf_num, request);
+
+ case TUSB_PRINTER_REQUEST_SOFT_RESET:
+ tud_printer_soft_reset_cb(itf);
+ tud_control_status(rhport, request);
+ return true;
+
+ default:
+ return false;
}
- } else {
- return false;
+ } else if (stage == CONTROL_STAGE_ACK) {
+ tud_printer_request_complete_cb(itf, request);
}
return true;
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 8d5f94313..42903576c 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -836,7 +836,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) {
TU_LOG_USBD(" %s", tu_str_std_request[p_request->bRequest]);
- if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG_USBD("\r\n");
+ if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) {
+ TU_LOG_USBD("\r\n");
+ }
}
#endif
@@ -972,7 +974,25 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
//------------- Class/Interface Specific Request -------------//
case TUSB_REQ_RCPT_INTERFACE: {
- uint8_t const itf = tu_u16_low(p_request->wIndex);
+ uint8_t itf;
+ #if CFG_TUD_PRINTER
+ // Printer GET_DEVICE_ID has a weird wIndex = interface (high) | alt (low)
+ // attempt to interpret this as a printer request if matched
+ if (TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type &&
+ TUSB_DIR_IN == p_request->bmRequestType_bit.direction &&
+ TUSB_PRINTER_REQUEST_GET_DEVICE_ID == p_request->bRequest) {
+ itf = tu_u16_high(p_request->wIndex);
+ if (itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)) {
+ const usbd_class_driver_t * driver = get_driver(_usbd_dev.itf2drv[itf]);
+ if (driver != NULL && driver->control_xfer_cb == printerd_control_xfer_cb) {
+ if (invoke_class_control(rhport, driver, p_request)) {
+ return true;
+ }
+ }
+ }
+ }
+ #endif
+ itf = tu_u16_low(p_request->wIndex);
TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]);