summaryrefslogtreecommitdiff
path: root/src/class/printer
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 /src/class/printer
parent558abb93af64eda51420d5bfe03355c89e4b421a (diff)
update printer class: enhance descriptors, buffer sizes, and callbacks
Diffstat (limited to 'src/class/printer')
-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
3 files changed, 96 insertions, 60 deletions
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