diff --git a/sys/include/usb/hid.h b/sys/include/usb/hid.h index d5cbd5370c..2a6beaeedf 100644 --- a/sys/include/usb/hid.h +++ b/sys/include/usb/hid.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Nils Ollrogge + * Copyright (C) 2021 Nils Ollrogge * * This file is subject to the terms and conditions of the GNU Lesser General * Public License v2.1. See the file LICENSE in the top level directory for @@ -16,7 +16,7 @@ * @file * @brief Definition for USB HID interfaces * - * @author Nils Ollrogge + * @author Nils Ollrogge */ #ifndef USB_HID_H diff --git a/sys/include/usb/usbus/hid.h b/sys/include/usb/usbus/hid.h index e99e6931a7..a7672796f4 100644 --- a/sys/include/usb/usbus/hid.h +++ b/sys/include/usb/usbus/hid.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Nils Ollrogge + * Copyright (C) 2021 Nils Ollrogge * * This file is subject to the terms and conditions of the GNU Lesser General * Public License v2.1. See the file LICENSE in the top level directory for @@ -21,7 +21,7 @@ * specific handling. A different module is required to provide * functional handling of the data e.g. UART or STDIO integration. * - * @author Nils Ollrogge + * @author Nils Ollrogge */ #ifndef USB_USBUS_HID_H diff --git a/sys/include/usb/usbus/hid_io.h b/sys/include/usb/usbus/hid_io.h new file mode 100644 index 0000000000..a436343c66 --- /dev/null +++ b/sys/include/usb/usbus/hid_io.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2021 Nils Ollrogge + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for + * more details. + */ + +/** + * @defgroup usbus_hid_io USBUS HID IO + * @ingroup usb_hid + * @brief USBUS HID IO interface module + * + * @{ + * + * @file + * @brief USB HID callback and read/write functions + * + * @author Nils Ollrogge + */ + +#ifndef USB_USBUS_HID_IO_H +#define USB_USBUS_HID_IO_H + +#include +#include + +#include "usb/usbus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief USBUS HID IO RX callback function + */ +typedef void (*usb_hid_io_cb_t)(void *); + +/** + * @brief Set USBUS HID IO RX callback + * + * @param[in] cb callback function to use + * @param[in] arg argument that will be passed to @p cb + */ +void usb_hid_io_set_rx_cb(usb_hid_io_cb_t cb, void *arg); + +/** + * @brief Write data to USB HID IN endpoint buffer + * + * @pre `buffer != NULL` + * + * @param[in] buffer buffer containing data to write + * @param[in] len length of buffer + */ +void usb_hid_io_write(const void *buffer, size_t len); + +/** + * @brief Read data from USB HID OUT endpoint (blocking) + * + * Wrapper for @ref isrpipe_read + * + * @pre `buffer != NULL` + * + * @param[out] buffer buffer to read data into + * @param[in] len length of buffer + * + * @return Number of bytes read + */ +int usb_hid_io_read(void *buffer, size_t len); + +/** + * @brief Read data from USB HID OUT endpoint (with timeout, blocking) + * + * Wrapper for @ref isrpipe_read_timeout + * + * @pre `buffer != NULL` + * + * @param[out] buffer buffer to read data into + * @param[in] len length of buffer + * @param[in] timeout timeout in microseconds + * + * @return Number of bytes read + */ +int usb_hid_io_read_timeout(void *buffer, size_t len, uint32_t timeout); + +/** + * @brief Initialize an USB HID IO interface + * + * @param[in] usbus USBUS context + * @param[in] report_desc USB_HID report descriptor + * @param[in] report_desc_size size of USB_HID report descriptor + */ +void usb_hid_io_init(usbus_t *usbus, const uint8_t *report_desc, size_t report_desc_size); + +#ifdef __cplusplus +} +#endif + +#endif /* USB_USBUS_HID_IO_H */ +/** @} */ diff --git a/sys/usb/usbus/hid/hid.c b/sys/usb/usbus/hid/hid.c index 0e520fc3fa..32ac60f285 100644 --- a/sys/usb/usbus/hid/hid.c +++ b/sys/usb/usbus/hid/hid.c @@ -11,7 +11,7 @@ * @{ * @file * - * @author Nils Ollrogge + * @author Nils Ollrogge * @} */ @@ -107,9 +107,9 @@ static void _init(usbus_t *usbus, usbus_handler_t *handler) hid->hid_descr.arg = hid; /* - Configure Interface as USB_HID interface, choosing NONE for subclass and - protocol in order to represent a generic I/O device - */ + Configure Interface as USB_HID interface, choosing NONE for subclass and + protocol in order to represent a generic I/O device + */ hid->iface.class = USB_CLASS_HID; hid->iface.subclass = USB_HID_SUBCLASS_NONE; hid->iface.protocol = USB_HID_PROTOCOL_NONE; @@ -118,9 +118,9 @@ static void _init(usbus_t *usbus, usbus_handler_t *handler) /* IN endpoint to send data to host */ hid->ep_in = usbus_add_endpoint(usbus, &hid->iface, - USB_EP_TYPE_INTERRUPT, - USB_EP_DIR_IN, - CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); + USB_EP_TYPE_INTERRUPT, + USB_EP_DIR_IN, + CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); /* interrupt endpoint polling rate in ms */ hid->ep_in->interval = 0x05; @@ -129,8 +129,8 @@ static void _init(usbus_t *usbus, usbus_handler_t *handler) /* OUT endpoint to receive data from host */ hid->ep_out = usbus_add_endpoint(usbus, &hid->iface, - USB_EP_TYPE_INTERRUPT, USB_EP_DIR_OUT, - CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); + USB_EP_TYPE_INTERRUPT, USB_EP_DIR_OUT, + CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); /* interrupt endpoint polling rate in ms */ hid->ep_out->interval = 0x05; @@ -150,9 +150,9 @@ static void _event_handler(usbus_t *usbus, usbus_handler_t *handler, (void)handler; switch (event) { - default: - DEBUG("USB HID unhandled event: 0x%x\n", event); - break; + default: + DEBUG("USB HID unhandled event: 0x%x\n", event); + break; } } @@ -167,39 +167,39 @@ static int _control_handler(usbus_t *usbus, usbus_handler_t *handler, /* Requests defined in USB HID 1.11 spec section 7 */ switch (setup->request) { - case USB_SETUP_REQ_GET_DESCRIPTOR: { - uint8_t desc_type = setup->value >> 8; - if (desc_type == USB_HID_DESCR_REPORT) { - usbus_control_slicer_put_bytes(usbus, hid->report_desc, - hid->report_desc_size); - } - else if (desc_type == USB_HID_DESCR_HID) { - _gen_hid_descriptor(usbus, NULL); - } - break; + case USB_SETUP_REQ_GET_DESCRIPTOR: { + uint8_t desc_type = setup->value >> 8; + if (desc_type == USB_HID_DESCR_REPORT) { + usbus_control_slicer_put_bytes(usbus, hid->report_desc, + hid->report_desc_size); } - case USB_HID_REQUEST_GET_REPORT: - break; - case USB_HID_REQUEST_GET_IDLE: - break; - case USB_HID_REQUEST_GET_PROTOCOL: - break; - case USB_HID_REQUEST_SET_REPORT: - if ((state == USBUS_CONTROL_REQUEST_STATE_OUTDATA)) { - size_t size = 0; - uint8_t *data = usbus_control_get_out_data(usbus, &size); - if (size > 0) { - hid->cb(hid, data, size); - } + else if (desc_type == USB_HID_DESCR_HID) { + _gen_hid_descriptor(usbus, NULL); + } + break; + } + case USB_HID_REQUEST_GET_REPORT: + break; + case USB_HID_REQUEST_GET_IDLE: + break; + case USB_HID_REQUEST_GET_PROTOCOL: + break; + case USB_HID_REQUEST_SET_REPORT: + if ((state == USBUS_CONTROL_REQUEST_STATE_OUTDATA)) { + size_t size = 0; + uint8_t *data = usbus_control_get_out_data(usbus, &size); + if (size > 0) { + hid->cb(hid, data, size); } - break; - case USB_HID_REQUEST_SET_IDLE: - break; - case USB_HID_REQUEST_SET_PROTOCOL: - break; - default: - DEBUG("USB_HID: unknown request %d \n", setup->request); - return -1; + } + break; + case USB_HID_REQUEST_SET_IDLE: + break; + case USB_HID_REQUEST_SET_PROTOCOL: + break; + default: + DEBUG("USB_HID: unknown request %d \n", setup->request); + return -1; } return 1; } diff --git a/sys/usb/usbus/hid/hid_io.c b/sys/usb/usbus/hid/hid_io.c index 8e0a34a091..23396c957b 100644 --- a/sys/usb/usbus/hid/hid_io.c +++ b/sys/usb/usbus/hid/hid_io.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Nils Ollrogge + * Copyright (C) 2021 Nils Ollrogge * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -7,12 +7,11 @@ */ /** - * @ingroup usbus_hid + * @ingroup usbus_hid_io * @{ * @file - * @brief This file implements a USB HID callback and read/write functions. * - * @author Nils Ollrogge + * @author Nils Ollrogge * @} */ @@ -25,6 +24,7 @@ #include "usb/usbus.h" #include "usb/usbus/hid.h" +#include "usb/usbus/hid_io.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -32,20 +32,25 @@ static usbus_hid_device_t hid; static uint8_t _hid_rx_buf_mem[CONFIG_USBUS_HID_INTERRUPT_EP_SIZE]; static isrpipe_t _hid_stdio_isrpipe = ISRPIPE_INIT(_hid_rx_buf_mem); +static usb_hid_io_cb_t _rx_cb; +static void *_rx_cb_arg; -int usb_hid_io_read(void *buffer, size_t size) +int usb_hid_io_read(void *buffer, size_t len) { - return isrpipe_read(&_hid_stdio_isrpipe, buffer, size); + assert(buffer); + return isrpipe_read(&_hid_stdio_isrpipe, buffer, len); } -int usb_hid_io_read_timeout(void *buffer, size_t size, uint32_t timeout) +int usb_hid_io_read_timeout(void *buffer, size_t len, uint32_t timeout) { - return isrpipe_read_timeout(&_hid_stdio_isrpipe, buffer, size, timeout); + assert(buffer); + return isrpipe_read_timeout(&_hid_stdio_isrpipe, buffer, len, timeout); } void usb_hid_io_write(const void *buffer, size_t len) { - uint8_t* buffer_ep = hid.ep_in->ep->buf; + assert(buffer); + uint8_t *buffer_ep = hid.ep_in->ep->buf; uint16_t max_size = hid.ep_in->maxpacketsize; size_t offset = 0; @@ -73,10 +78,22 @@ static void _hid_rx_pipe(usbus_hid_device_t *hid, uint8_t *data, size_t len) for (size_t i = 0; i < len; i++) { isrpipe_write_one(&_hid_stdio_isrpipe, data[i]); } + + if (_rx_cb) { + _rx_cb(_rx_cb_arg); + } } -void usb_hid_io_init(usbus_t *usbus, uint8_t *report_desc, +void usb_hid_io_init(usbus_t *usbus, const uint8_t *report_desc, size_t report_desc_size) { + assert(usbus); + assert(report_desc); usbus_hid_init(usbus, &hid, _hid_rx_pipe, report_desc, report_desc_size); } + +void usb_hid_io_set_rx_cb(usb_hid_io_cb_t cb, void *arg) +{ + _rx_cb = cb; + _rx_cb_arg = arg; +} diff --git a/tests/usbus_hid/main.c b/tests/usbus_hid/main.c index 42f262533e..d8c39ffeef 100644 --- a/tests/usbus_hid/main.c +++ b/tests/usbus_hid/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Nils Ollrogge + * Copyright (C) 2021 Nils Ollrogge * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -13,7 +13,7 @@ * * @brief Tests for USB HID * - * @author Nils Ollrogge + * @author Nils Ollrogge */ #include @@ -22,13 +22,14 @@ #include "usb/usbus.h" #include "xtimer.h" #include "usb/usbus/hid.h" +#include "usb/usbus/hid_io.h" /* this descriptor is used, because the basic usb_hid interface was developed in conjunction with FIDO2. Descriptor is taken from CTAP2 specification (version 20190130) section 8.1.8.2 */ -static uint8_t report_desc_ctap[] = { +static const uint8_t report_desc_ctap[] = { 0x06, 0xD0, 0xF1, /* HID_UsagePage ( FIDO_USAGE_PAGE ) */ 0x09, 0x01, /* HID_Usage ( FIDO_USAGE_CTAPHID ) */ 0xA1, 0x01, /* HID_Collection ( HID_Application ) */ @@ -49,19 +50,20 @@ static uint8_t report_desc_ctap[] = { static usbus_t usbus; static char _stack[USBUS_STACKSIZE]; +static char test_arg[] = { "Test argument" }; -void usb_hid_io_init(usbus_t *usbus, uint8_t *report_desc, - size_t report_desc_size); -ssize_t usb_hid_io_read(void *buffer, size_t len); +static void rx_cb(void *arg) +{ + printf("USB_HID rx_cb: %s \n", (char *)arg); +} -void init(void) +static void init(void) { usbdev_t *usbdev = usbdev_get_ctx(0); usbus_init(&usbus, usbdev); - usb_hid_io_init(&usbus, report_desc_ctap, sizeof(report_desc_ctap)); - + usb_hid_io_set_rx_cb(rx_cb, test_arg); usbus_create(_stack, USBUS_STACKSIZE, USBUS_PRIO, USBUS_TNAME, &usbus); } @@ -80,10 +82,10 @@ int main(void) ssize_t len = usb_hid_io_read(buffer, CONFIG_USBUS_HID_INTERRUPT_EP_SIZE); - printf("Msg received via USB HID: "); + puts("Msg received via USB HID: "); for (int i = 0; i < len; i++) { putc(buffer[i], stdout); } - printf("\n"); + puts(""); } }