summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-03-06 16:06:42 +0700
committerhathach <[email protected]>2026-03-06 16:06:42 +0700
commit988b18a40a4276eb731c80bc4cec3bf5750523f9 (patch)
treedfe79c7d7504a18dcb7ee95d1b3792e5f5b24931
parent5838c7f09dda8921fe6f350871211f8bd5a97208 (diff)
add full read/write() API, use edpt stream for printer class
-rw-r--r--examples/device/printer_to_hid/src/main.c137
-rw-r--r--src/class/printer/printer_device.c246
-rw-r--r--src/class/printer/printer_device.h55
3 files changed, 206 insertions, 232 deletions
diff --git a/examples/device/printer_to_hid/src/main.c b/examples/device/printer_to_hid/src/main.c
index 02b54c7d0..0d14147b4 100644
--- a/examples/device/printer_to_hid/src/main.c
+++ b/examples/device/printer_to_hid/src/main.c
@@ -33,34 +33,15 @@
#include "usb_descriptors.h"
// -------------------------------------------------------------------+
-// Variables controlled with USB endpoint callbacks
+// Variables
// -------------------------------------------------------------------+
-// usb interface pointer
-uint8_t printer_itf = 0;
-// pendings bytes in usb endpoint buffer ; must process these bytes
-size_t pending_bytes_on_usb_ep = 0;
-
-
-// -------------------------------------------------------------------+
-// Variables controlled locally
-// -------------------------------------------------------------------+
-
-// local data buffer (copy data from usb endpoint into this buffer) ; acts as fifo
-uint8_t data_buffer[16] = {0};
-// write offset for usb/printer incoming data to data_buffer
-size_t data_rx_offset = 0;
-// read offset for usb/hid outgoing data from data_buffer
-size_t data_tx_offset = 0;
-// available space in data_buffer
-size_t data_available = sizeof(data_buffer);
-
// next keycode to send on usb/hid
-uint8_t next_keycode = 0;
+static uint8_t next_keycode = 0;
// next key modifiers to send on usb/hid
-uint8_t next_modifiers = 0;
+static uint8_t next_modifiers = 0;
// whether the next usb/hid report must be NULL to release the last keystroke
-uint8_t next_keycode_is_release = false;
+static bool next_keycode_is_release = false;
// -------------------------------------------------------------------+
@@ -99,83 +80,34 @@ static void hid_tx_task(void) {
next_keycode = 0;
}
-// Whenever there are pendings bytes on the USB endpoint, we will pull them from the
-// endpoint buffer and write then in the local data buffer. We must take care to not
-// overwrite local data that is not processed yet, so we use data_buffer as a fifo.
-// We do not have to take care of reading correctly from the endpoint buffer, as all
-// is done well by tud_printer_n_read().
-static void printer_rx_task(void) {
-
- if (pending_bytes_on_usb_ep == 0) {
- return;
+// 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
}
- size_t len1 = data_available;
- size_t len2 = 0;
- if (data_rx_offset + len1 > sizeof(data_buffer)) {
- len2 = len1 - (sizeof(data_buffer) - data_rx_offset);
- len1 = sizeof(data_buffer) - data_rx_offset;
- }
- uint32_t count = tud_printer_n_read(printer_itf, data_buffer + data_rx_offset, len1);
- if (len2 > 0) {
- count += tud_printer_n_read(printer_itf, data_buffer, len2);
+ uint8_t ch;
+ if (tud_printer_read(&ch, 1) == 0) {
+ return; // no data available
}
- if (count == 0) {
- return;
+ 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;
}
- data_available -= count;
- pending_bytes_on_usb_ep -= count;
- data_rx_offset = (data_rx_offset + count) % sizeof(data_buffer);
-}
-
-// The HID keycodes are not binary mapped like UTF8 codes. If we want to send the
-// data received as a usb/printer, we have to translate the binary data for the
-// usb/hid interface. Note that the simple mapping below will be valid only for
-// hosts expecting hid data from a QWERTY keyboard. Also note that only a-zA-Z0-9
-// characters are converted, for simplicity of the example. Other characters are
-// converted to spaces.
-static void translation_task(void) {
- if (data_tx_offset != data_rx_offset || data_available == 0) {
- // If data_tx_offset and data_rx_offset have different values, then we
- // can proceed: translate, prepare for TX, and advance data_tx_offset.
- //
- // If the buffer is full (data_available == 0), then we must also
- // translate data and prepare it for TX. But the data_tx_offset and
- // data_rx_offset will have the same value, since RX caught up to TX.
- // Hence the OR.
-
- // Translate UTF8 to HID keystroke
- char c = data_buffer[data_tx_offset];
- uint8_t m = 0;
- if ('a' <= c && c <= 'z') {
- c -= 'a';
- c += HID_KEY_A;
- } else if ('A' <= c && c <= 'Z') {
- c -= 'A';
- c += HID_KEY_A;
- m = KEYBOARD_MODIFIER_LEFTSHIFT;
- } else if ('1' <= c && c <= '9') {
- c -= '1';
- c += HID_KEY_1;
- } else if (c == '0') {
- c = HID_KEY_0;
- } else {
- c = HID_KEY_SPACE;
- }
-
- // Proceed only if there are no characters pending for TX
- if (next_keycode == 0) {
- // Prepare next keystroke with translated data
- next_keycode = c;
- next_modifiers = m;
- // Increment read offset
- data_tx_offset += 1;
- data_tx_offset %= sizeof(data_buffer);
- data_available += 1;
- }
- }
+ next_keycode = ch;
+ next_modifiers = m;
}
int main(void) {
@@ -186,15 +118,9 @@ int main(void) {
board_init_after_tusb();
while (1) {
- tud_task(); // tinyusb device task
- printer_rx_task(); // read data sent by host on our printer interface
- translation_task(); // translate printer's UTF8 to HID keycodes
- hid_tx_task(); // send data to host with our HID interface
- if (pending_bytes_on_usb_ep > 0) {
- board_led_on();
- } else {
- board_led_off();
- }
+ 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
}
}
@@ -203,9 +129,8 @@ int main(void) {
// Printer callbacks
//--------------------------------------------------------------------+
-void tud_printer_rx_cb(uint8_t itf, size_t n) {
- printer_itf = itf; // get interface from which to read endpoint buffer
- pending_bytes_on_usb_ep += n; // count pending bytes, counter must decrement when reading from the endpoint buffer
+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).
diff --git a/src/class/printer/printer_device.c b/src/class/printer/printer_device.c
index d288014a1..05d3f28eb 100644
--- a/src/class/printer/printer_device.c
+++ b/src/class/printer/printer_device.c
@@ -28,9 +28,6 @@
#if (CFG_TUD_ENABLED && CFG_TUD_PRINTER)
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
#include "device/usbd.h"
#include "device/usbd_pvt.h"
@@ -42,73 +39,52 @@
typedef struct {
uint8_t itf_num;
- uint8_t ep_out; // Bulk Out endpoint
- uint8_t ep_in; // optional Bulk In endpoint
/*------------- From this point, data is not cleared by bus reset -------------*/
- // FIFO
- tu_fifo_t rx_ff;
- tu_fifo_t tx_ff;
+ tu_edpt_stream_t rx_stream;
+ tu_edpt_stream_t tx_stream;
uint8_t rx_ff_buf[CFG_TUD_PRINTER_RX_BUFSIZE];
uint8_t tx_ff_buf[CFG_TUD_PRINTER_TX_BUFSIZE];
-
- OSAL_MUTEX_DEF(rx_ff_mutex);
- OSAL_MUTEX_DEF(tx_ff_mutex);
} printer_interface_t;
+#define ITF_MEM_RESET_SIZE offsetof(printer_interface_t, rx_stream)
+
+#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0
typedef struct {
TUD_EPBUF_DEF(epout, CFG_TUD_PRINTER_EP_BUFSIZE);
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];
+#endif
+static printer_interface_t _printer_itf[CFG_TUD_PRINTER];
//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
+// INTERNAL HELPERS
//--------------------------------------------------------------------+
-static bool _prep_out_transaction(uint8_t itf) {
- const uint8_t rhport = 0;
- printer_interface_t *p_printer = &_printer_itf[itf];
- printer_epbuf_t *p_epbuf = &_printer_epbuf[itf];
-
- // Skip if usb is not ready yet
- TU_VERIFY(tud_ready() && p_printer->ep_out);
- uint16_t available = tu_fifo_remaining(&p_printer->rx_ff);
-
- // Prepare for incoming data but only allow what we can store in the ring buffer.
- // TODO Actually we can still carry out the transfer, keeping count of received bytes
- // and slowly move it to the FIFO when read().
- // This pre-check reduces endpoint claiming
- TU_VERIFY(available >= CFG_TUD_PRINTER_EP_BUFSIZE);
-
- // claim endpoint
- TU_VERIFY(usbd_edpt_claim(rhport, p_printer->ep_out));
-
- // fifo can be changed before endpoint is claimed
- available = tu_fifo_remaining(&p_printer->rx_ff);
-
- if (available >= CFG_TUD_PRINTER_EP_BUFSIZE) {
- return usbd_edpt_xfer(rhport, p_printer->ep_out, p_epbuf->epout, CFG_TUD_PRINTER_EP_BUFSIZE, false);
- } else {
- // Release endpoint since we don't make any transfer
- usbd_edpt_release(rhport, p_printer->ep_out);
- return false;
+TU_ATTR_ALWAYS_INLINE static inline uint8_t _find_itf(uint8_t ep_addr) {
+ for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
+ const printer_interface_t *p = &_printer_itf[i];
+ if (ep_addr == p->rx_stream.ep_addr || ep_addr == p->tx_stream.ep_addr) {
+ return i;
+ }
}
+ return TUSB_INDEX_INVALID_8;
}
//--------------------------------------------------------------------+
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
-TU_ATTR_WEAK void tud_printer_rx_cb(uint8_t itf, size_t n) {
+TU_ATTR_WEAK void tud_printer_rx_cb(uint8_t itf) {
+ (void)itf;
+}
+
+TU_ATTR_WEAK void tud_printer_tx_complete_cb(uint8_t itf) {
(void)itf;
- (void)n;
}
TU_ATTR_WEAK void tud_printer_request_complete_cb(uint8_t itf, tusb_control_request_t const *request) {
@@ -131,29 +107,53 @@ TU_ATTR_WEAK void tud_printer_soft_reset_cb(uint8_t itf) {
}
//--------------------------------------------------------------------+
-// APPLICATION API
+// READ API
//--------------------------------------------------------------------+
-uint32_t tud_printer_n_available(uint8_t itf) {
- return tu_fifo_count(&_printer_itf[itf].rx_ff);
+uint32_t tud_printer_n_read_available(uint8_t itf) {
+ TU_VERIFY(itf < CFG_TUD_PRINTER, 0);
+ return tu_edpt_stream_read_available(&_printer_itf[itf].rx_stream);
}
uint32_t tud_printer_n_read(uint8_t itf, void *buffer, uint32_t bufsize) {
- printer_interface_t *p_printer = &_printer_itf[itf];
- uint32_t num_read = tu_fifo_read_n(&p_printer->rx_ff, buffer, (uint16_t)TU_MIN(bufsize, UINT16_MAX));
- _prep_out_transaction(itf);
- return num_read;
+ TU_VERIFY(itf < CFG_TUD_PRINTER, 0);
+ return tu_edpt_stream_read(&_printer_itf[itf].rx_stream, buffer, bufsize);
}
bool tud_printer_n_peek(uint8_t itf, uint8_t *chr) {
- return tu_fifo_peek(&_printer_itf[itf].rx_ff, chr);
+ TU_VERIFY(itf < CFG_TUD_PRINTER);
+ return tu_edpt_stream_peek(&_printer_itf[itf].rx_stream, chr);
}
void tud_printer_n_read_flush(uint8_t itf) {
- printer_interface_t *p_printer = &_printer_itf[itf];
- tu_fifo_clear(&p_printer->rx_ff);
- _prep_out_transaction(itf);
+ TU_VERIFY(itf < CFG_TUD_PRINTER, );
+ printer_interface_t *p = &_printer_itf[itf];
+ tu_edpt_stream_clear(&p->rx_stream);
+ tu_edpt_stream_read_xfer(&p->rx_stream);
}
+//--------------------------------------------------------------------+
+// WRITE API
+//--------------------------------------------------------------------+
+uint32_t tud_printer_n_write(uint8_t itf, const void *buffer, uint32_t bufsize) {
+ TU_VERIFY(itf < CFG_TUD_PRINTER, 0);
+ return tu_edpt_stream_write(&_printer_itf[itf].tx_stream, buffer, bufsize);
+}
+
+uint32_t tud_printer_n_write_flush(uint8_t itf) {
+ TU_VERIFY(itf < CFG_TUD_PRINTER, 0);
+ return tu_edpt_stream_write_xfer(&_printer_itf[itf].tx_stream);
+}
+
+uint32_t tud_printer_n_write_available(uint8_t itf) {
+ TU_VERIFY(itf < CFG_TUD_PRINTER, 0);
+ return tu_edpt_stream_write_available(&_printer_itf[itf].tx_stream);
+}
+
+bool tud_printer_n_write_clear(uint8_t itf) {
+ TU_VERIFY(itf < CFG_TUD_PRINTER);
+ tu_edpt_stream_clear(&_printer_itf[itf].tx_stream);
+ return true;
+}
//--------------------------------------------------------------------+
// USBD-CLASS API
@@ -162,41 +162,32 @@ void printerd_init(void) {
tu_memclr(_printer_itf, sizeof(_printer_itf));
for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
- printer_interface_t *p_printer = &_printer_itf[i];
+ printer_interface_t *p = &_printer_itf[i];
- tu_fifo_config(&p_printer->rx_ff, p_printer->rx_ff_buf, TU_ARRAY_SIZE(p_printer->rx_ff_buf), false);
- tu_fifo_config(&p_printer->tx_ff, p_printer->tx_ff_buf, TU_ARRAY_SIZE(p_printer->tx_ff_buf), true);
+ #if CFG_TUD_EDPT_DEDICATED_HWFIFO
+ uint8_t *epout_buf = NULL;
+ uint8_t *epin_buf = NULL;
+ #else
+ uint8_t *epout_buf = _printer_epbuf[i].epout;
+ uint8_t *epin_buf = _printer_epbuf[i].epin;
+ #endif
- #if OSAL_MUTEX_REQUIRED
- osal_mutex_t mutex_rd = osal_mutex_create(&p_printer->rx_ff_mutex);
- osal_mutex_t mutex_wr = osal_mutex_create(&p_printer->tx_ff_mutex);
- TU_ASSERT(mutex_rd != NULL && mutex_wr != NULL, );
+ tu_edpt_stream_init(&p->rx_stream, false, false, false,
+ p->rx_ff_buf, CFG_TUD_PRINTER_RX_BUFSIZE,
+ epout_buf, CFG_TUD_PRINTER_EP_BUFSIZE);
- tu_fifo_config_mutex(&p_printer->rx_ff, NULL, mutex_rd);
- tu_fifo_config_mutex(&p_printer->tx_ff, mutex_wr, NULL);
- #endif
+ tu_edpt_stream_init(&p->tx_stream, false, true, true,
+ p->tx_ff_buf, CFG_TUD_PRINTER_TX_BUFSIZE,
+ epin_buf, CFG_TUD_PRINTER_EP_BUFSIZE);
}
}
bool printerd_deinit(void) {
- #if OSAL_MUTEX_REQUIRED
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_wr;
-
- if (mutex_rd) {
- osal_mutex_delete(mutex_rd);
- tu_fifo_config_mutex(&p_printer->rx_ff, NULL, NULL);
- }
-
- if (mutex_wr) {
- osal_mutex_delete(mutex_wr);
- tu_fifo_config_mutex(&p_printer->tx_ff, NULL, NULL);
- }
+ printer_interface_t *p = &_printer_itf[i];
+ tu_edpt_stream_deinit(&p->rx_stream);
+ tu_edpt_stream_deinit(&p->tx_stream);
}
- #endif
-
return true;
}
@@ -204,40 +195,48 @@ void printerd_reset(uint8_t rhport) {
(void)rhport;
for (uint8_t i = 0; i < CFG_TUD_PRINTER; i++) {
- printer_interface_t *p_printer = &_printer_itf[i];
-
- tu_memclr(p_printer, ITF_MEM_RESET_SIZE);
- tu_fifo_clear(&p_printer->rx_ff);
- tu_fifo_clear(&p_printer->tx_ff);
+ printer_interface_t *p = &_printer_itf[i];
+ tu_memclr(p, ITF_MEM_RESET_SIZE);
+ tu_edpt_stream_close(&p->rx_stream);
+ tu_edpt_stream_close(&p->tx_stream);
}
}
uint16_t printerd_open(uint8_t rhport, const tusb_desc_interface_t *itf_desc, uint16_t max_len) {
- (void)max_len;
TU_VERIFY(TUSB_CLASS_PRINTER == itf_desc->bInterfaceClass, 0);
- // Identify available interface to open
- printer_interface_t *p_printer;
- uint8_t printer_id;
- for (printer_id = 0; printer_id < CFG_TUD_PRINTER; printer_id++) {
- p_printer = &_printer_itf[printer_id];
- if (p_printer->ep_out == 0) {
- break;
- }
- }
- TU_ASSERT(printer_id < CFG_TUD_PRINTER);
+ // Find available interface slot
+ uint8_t const printer_id = _find_itf(0);
+ TU_ASSERT(printer_id < CFG_TUD_PRINTER, 0);
+ printer_interface_t *p = &_printer_itf[printer_id];
- //------------- Interface -------------//
- uint16_t drv_len = sizeof(tusb_desc_interface_t);
+ p->itf_num = itf_desc->bInterfaceNumber;
//------------- Endpoints -------------//
- TU_ASSERT(itf_desc->bNumEndpoints == 2);
- drv_len += 2 * sizeof(tusb_desc_endpoint_t);
- 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);
+ const uint8_t *p_desc = (const uint8_t *)itf_desc;
+ const uint8_t *desc_end = p_desc + max_len;
+ uint16_t drv_len = sizeof(tusb_desc_interface_t);
- _prep_out_transaction(printer_id);
+ p_desc = tu_desc_next(itf_desc);
+ for (uint8_t e = 0; e < itf_desc->bNumEndpoints; e++) {
+ TU_VERIFY(tu_desc_in_bounds(p_desc, desc_end), 0);
+ const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc;
+ TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0);
+
+ TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
+
+ if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
+ tu_edpt_stream_open(&p->tx_stream, rhport, desc_ep);
+ tu_edpt_stream_clear(&p->tx_stream);
+ } else {
+ tu_edpt_stream_open(&p->rx_stream, rhport, desc_ep);
+ tu_edpt_stream_clear(&p->rx_stream);
+ TU_ASSERT(tu_edpt_stream_read_xfer(&p->rx_stream) > 0, 0);
+ }
+
+ drv_len += sizeof(tusb_desc_endpoint_t);
+ p_desc = tu_desc_next(p_desc);
+ }
return drv_len;
}
@@ -247,7 +246,6 @@ bool printerd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_
uint8_t const itf_num = (uint8_t)request->wIndex;
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
- //------------- STD Request -------------//
if (stage != CONTROL_STAGE_SETUP) {
return true;
}
@@ -256,7 +254,6 @@ bool printerd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_
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]);
@@ -290,28 +287,29 @@ bool printerd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_
bool printerd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void)rhport;
(void)result;
- uint8_t itf;
- printer_interface_t *p_printer;
- // Identify which interface to use
- for (itf = 0; itf < CFG_TUD_PRINTER; itf++) {
- p_printer = &_printer_itf[itf];
- if (ep_addr == p_printer->ep_out) {
- break;
- }
- }
+ uint8_t const itf = _find_itf(ep_addr);
TU_ASSERT(itf < CFG_TUD_PRINTER);
- printer_epbuf_t *p_epbuf = &_printer_epbuf[itf];
+ printer_interface_t *p = &_printer_itf[itf];
// Received new data
- if (ep_addr == p_printer->ep_out) {
- tu_fifo_write_n(&p_printer->rx_ff, p_epbuf->epout, (uint16_t)xferred_bytes);
- // invoke receive callback (if there is still data)
- if (!tu_fifo_empty(&p_printer->rx_ff)) {
- tud_printer_rx_cb(itf, xferred_bytes);
+ if (ep_addr == p->rx_stream.ep_addr) {
+ tu_edpt_stream_read_xfer_complete(&p->rx_stream, xferred_bytes);
+
+ if (!tu_edpt_stream_empty(&p->rx_stream)) {
+ tud_printer_rx_cb(itf);
+ }
+
+ tu_edpt_stream_read_xfer(&p->rx_stream);
+ }
+
+ // Data sent to host
+ if (ep_addr == p->tx_stream.ep_addr) {
+ tud_printer_tx_complete_cb(itf);
+
+ if (0 == tu_edpt_stream_write_xfer(&p->tx_stream)) {
+ tu_edpt_stream_write_zlp_if_needed(&p->tx_stream, xferred_bytes);
}
- // prepare for OUT transaction
- _prep_out_transaction(itf);
}
return true;
diff --git a/src/class/printer/printer_device.h b/src/class/printer/printer_device.h
index aeff1ffc5..a6b7052cb 100644
--- a/src/class/printer/printer_device.h
+++ b/src/class/printer/printer_device.h
@@ -38,23 +38,74 @@ extern "C" {
//--------------------------------------------------------------------+
// Get the number of bytes available for reading
-uint32_t tud_printer_n_available(uint8_t itf);
+uint32_t tud_printer_n_read_available(uint8_t itf);
// Read received bytes
uint32_t tud_printer_n_read(uint8_t itf, void *buffer, uint32_t bufsize);
+// Get the number of bytes available for writing
+uint32_t tud_printer_n_write_available(uint8_t itf);
+
// Clear the received FIFO
void tud_printer_n_read_flush(uint8_t itf);
// Get a byte from FIFO without removing it
bool tud_printer_n_peek(uint8_t itf, uint8_t *ui8);
+// Write data to host
+uint32_t tud_printer_n_write(uint8_t itf, const void *buffer, uint32_t bufsize);
+
+// Force sending data in the TX FIFO
+uint32_t tud_printer_n_write_flush(uint8_t itf);
+
+// Clear the transmit FIFO
+bool tud_printer_n_write_clear(uint8_t itf);
+
+//--------------------------------------------------------------------+
+// Application API (Single Port)
+//--------------------------------------------------------------------+
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_printer_read_available(void) {
+ return tud_printer_n_read_available(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_printer_write_available(void) {
+ return tud_printer_n_write_available(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_printer_read(void *buffer, uint32_t bufsize) {
+ return tud_printer_n_read(0, buffer, bufsize);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void tud_printer_read_flush(void) {
+ tud_printer_n_read_flush(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_printer_peek(uint8_t *ui8) {
+ return tud_printer_n_peek(0, ui8);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_printer_write(const void *buffer, uint32_t bufsize) {
+ return tud_printer_n_write(0, buffer, bufsize);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_printer_write_flush(void) {
+ return tud_printer_n_write_flush(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_printer_write_clear(void) {
+ return tud_printer_n_write_clear(0);
+}
+
//--------------------------------------------------------------------+
// Application Callback API (weak is optional)
//--------------------------------------------------------------------+
// Invoked when received new data
-void tud_printer_rx_cb(uint8_t itf, size_t n);
+void tud_printer_rx_cb(uint8_t itf);
+
+// Invoked when last write transfer is completed
+void tud_printer_tx_complete_cb(uint8_t itf);
// Invoked when host requests device ID string (IEEE 1284).
// Application returns pointer to device ID buffer (must remain valid until transfer completes).