replace printer_to_hid example with printer_to_cdc example

fix printer GET_DEVICE_ID request weird wIndex (interface high, alt low)
This commit is contained in:
hathach
2026-03-06 17:22:38 +07:00
parent 988b18a40a
commit 73cd531295
13 changed files with 226 additions and 268 deletions

View File

@ -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

View File

@ -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})

View File

@ -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;
}

View File

@ -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

View File

@ -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,
@ -59,31 +62,23 @@ 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 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
};

View File

@ -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_ */

View File

@ -1,6 +0,0 @@
{
"version": 6,
"include": [
"../../../hw/bsp/BoardPresets.json"
]
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}
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));
}
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);
}
// 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 {
return false;
itf_num = tu_u16_low(request->wIndex);
}
// 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);
// 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);
}
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));
}
case TUSB_PRINTER_REQUEST_SOFT_RESET:
tud_printer_soft_reset_cb(itf);
tud_control_status(rhport, request);
return true;
default:
return false;
}
} else if (stage == CONTROL_STAGE_ACK) {
tud_printer_request_complete_cb(itf, request);
}
return true;

View File

@ -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]);