From 33c715bdd060c4c2bbc89da3ccc62f10b3faba09 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 4 Jan 2020 13:59:20 -0600 Subject: CDC device: fix behavior for transfers that are a whole multiple of endpoint buffer --- src/class/cdc/cdc_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 3ff72b00c..a4c42863a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -402,10 +402,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Data sent to host, we could continue to fetch data tx fifo to send. // But it will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! -// if ( ep_addr == p_cdc->ep_in ) -// { -// -// } + if ( ep_addr == p_cdc->ep_in ) + { + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + } // nothing to do with notif endpoint for now -- cgit v1.3.1 From 53732805b76882b3e0eba561ce854e0a95dd6dfe Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 11 Jan 2020 15:31:42 -0600 Subject: CDC device: help ensure code is consistent with the size of the buffers it operates on --- src/class/cdc/cdc_device.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a4c42863a..015c1c6fd 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -82,9 +82,9 @@ static void _prep_out_transaction (uint8_t itf) // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= CFG_TUD_CDC_EPSIZE ) + if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE); + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf)); } } @@ -162,7 +162,7 @@ bool tud_cdc_n_write_flush (uint8_t itf) cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, CFG_TUD_CDC_EPSIZE); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected @@ -198,8 +198,8 @@ void cdcd_init(void) p_cdc->line_coding.data_bits = 8; // config fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, false); - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, 1, false); + tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); -- cgit v1.3.1 From 73228a67efd122915e43ed445ddaec8285786d28 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 16 Jan 2020 10:06:52 +0100 Subject: MIDI: Add packet interface This changes the internal buffering to the raw 4-byte messages. The conversion of the messages to a byte-stream moved to the read/write methods. It adds a raw packet interface to send and retrieve the raw 4-byte USB MIDI message: static inline bool tud_midi_receive (uint8_t packet[4]); static inline bool tud_midi_send (uint8_t const packet[4]); MIDI USB packets carry virtual cable/wire/plug data in the packet header, which cannot be exported in the byte-stream interface. The raw packet interface allows to send and and receive the complete USB message. --- src/class/midi/midi_device.c | 145 +++++++++++++++++++++++++++---------------- src/class/midi/midi_device.h | 15 +++++ 2 files changed, 106 insertions(+), 54 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 312405621..82ceba87f 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -56,11 +56,15 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif - // We need to pack messages into words before queueing their transmission so buffer across write - // calls. - uint8_t message_buffer[4]; - uint8_t message_buffer_length; - uint8_t message_target_length; + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + uint8_t write_buffer[4]; + uint8_t write_buffer_length; + uint8_t write_target_length; + + uint8_t read_buffer[4]; + uint8_t read_buffer_length; + uint8_t read_target_length; // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE]; @@ -93,24 +97,14 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id) uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize) { (void) jack_id; - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, buffer, bufsize); -} - -void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) -{ - (void) jack_id; - tu_fifo_clear(&_midid_itf[itf].rx_ff); -} + midid_interface_t* midi = &_midid_itf[itf]; -void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { - if (bufsize % 4 != 0) { - return; - } + // Fill empty buffer + if (midi->read_buffer_length == 0) { + if (!tud_midi_n_receive(itf, midi->read_buffer)) + return 0; - for(uint32_t i=0; i> 4; - uint8_t code_index = header & 0x0f; + uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. uint8_t count = 1; // Ignore subsequent bytes based on the code. @@ -120,10 +114,40 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu count = 3; } } - tu_fifo_write_n(&midi->rx_ff, &buffer[i + 1], count); + + midi->read_buffer_length = count; + } + + uint32_t n = midi->read_buffer_length - midi->read_target_length; + if (bufsize < n) + n = bufsize; + + // Skip the header in the buffer + memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); + midi->read_target_length += n; + + if (midi->read_target_length == midi->read_buffer_length) { + midi->read_buffer_length = 0; + midi->read_target_length = 0; } + + return n; +} + +void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) +{ + (void) jack_id; + tu_fifo_clear(&_midid_itf[itf].rx_ff); +} + +bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) +{ + return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); } +void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { + tu_fifo_write_n(&midi->rx_ff, buffer, bufsize); +} //--------------------------------------------------------------------+ // WRITE API @@ -154,62 +178,59 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u uint32_t i = 0; while (i < bufsize) { uint8_t data = buffer[i]; - if (midi->message_buffer_length == 0) { + if (midi->write_buffer_length == 0) { uint8_t msg = data >> 4; - midi->message_buffer[1] = data; - midi->message_buffer_length = 2; + midi->write_buffer[1] = data; + midi->write_buffer_length = 2; // Check to see if we're still in a SysEx transmit. - if (midi->message_buffer[0] == 0x4) { + if (midi->write_buffer[0] == 0x4) { if (data == 0xf7) { - midi->message_buffer[0] = 0x5; + midi->write_buffer[0] = 0x5; } else { - midi->message_buffer_length = 4; + midi->write_buffer_length = 4; } } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->message_buffer[0] = jack_id << 4 | msg; - midi->message_target_length = 4; - } else if (msg == 0xC || msg == 0xD) { - midi->message_buffer[0] = jack_id << 4 | msg; - midi->message_target_length = 3; + midi->write_buffer[0] = jack_id << 4 | msg; + midi->write_target_length = 4; } else if (msg == 0xf) { if (data == 0xf0) { - midi->message_buffer[0] = 0x4; - midi->message_target_length = 4; + midi->write_buffer[0] = 0x4; + midi->write_target_length = 4; } else if (data == 0xf1 || data == 0xf3) { - midi->message_buffer[0] = 0x2; - midi->message_target_length = 3; + midi->write_buffer[0] = 0x2; + midi->write_target_length = 3; } else if (data == 0xf2) { - midi->message_buffer[0] = 0x3; - midi->message_target_length = 4; + midi->write_buffer[0] = 0x3; + midi->write_target_length = 4; } else { - midi->message_buffer[0] = 0x5; - midi->message_target_length = 2; + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; } } else { // Pack individual bytes if we don't support packing them into words. - midi->message_buffer[0] = jack_id << 4 | 0xf; - midi->message_buffer[2] = 0; - midi->message_buffer[3] = 0; - midi->message_buffer_length = 2; - midi->message_target_length = 2; + midi->write_buffer[0] = jack_id << 4 | 0xf; + midi->write_buffer[2] = 0; + midi->write_buffer[3] = 0; + midi->write_buffer_length = 2; + midi->write_target_length = 2; } } else { - midi->message_buffer[midi->message_buffer_length] = data; - midi->message_buffer_length += 1; + midi->write_buffer[midi->write_buffer_length] = data; + midi->write_buffer_length += 1; // See if this byte ends a SysEx. - if (midi->message_buffer[0] == 0x4 && data == 0xf7) { - midi->message_buffer[0] = 0x4 + (midi->message_buffer_length - 1); - midi->message_target_length = midi->message_buffer_length; + if (midi->write_buffer[0] == 0x4 && data == 0xf7) { + midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_target_length = midi->write_buffer_length; } } - if (midi->message_buffer_length == midi->message_target_length) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->message_buffer, 4); + if (midi->write_buffer_length == midi->write_target_length) { + uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); if (written < 4) { TU_ASSERT( written == 0 ); break; } - midi->message_buffer_length = 0; + midi->write_buffer_length = 0; } i++; } @@ -218,6 +239,22 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u return i; } +bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) +{ + midid_interface_t* midi = &_midid_itf[itf]; + if (midi->itf_num == 0) { + return 0; + } + + if (tu_fifo_remaining(&midi->tx_ff) < 4) + return false; + + tu_fifo_write_n(&midi->tx_ff, packet, 4); + maybe_transmit(midi, itf); + + return true; +} + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index fbf4bce0b..e4d4f9d51 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -62,6 +62,9 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buf static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); +bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); + //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ @@ -71,6 +74,8 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +static inline bool tud_midi_receive (uint8_t packet[4]); +static inline bool tud_midi_send (uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -118,6 +123,16 @@ static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b return tud_midi_write(jack_id, msg, 3); } +static inline bool tud_midi_receive (uint8_t packet[4]) +{ + return tud_midi_n_receive(0, packet); +} + +static inline bool tud_midi_send (uint8_t const packet[4]) +{ + return tud_midi_n_send(0, packet); +} + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From b6b9fe42af1828c2ed8f794a930999ecb4da2902 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2020 16:43:44 +0700 Subject: more log for debugging --- src/class/cdc/cdc_device.c | 11 ++++++++++- src/device/usbd_control.c | 14 +++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index c0de0cadd..f63418dae 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -335,25 +335,34 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: + TU_LOG2(" Set Line Coding\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_GET_LINE_CODING: + TU_LOG2(" Get Line Coding\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: + { // CDC PSTN v1.2 section 6.3.12 // Bit 0: Indicates if DTE is present or not. // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) // Bit 1: Carrier control for half-duplex modems. // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); + p_cdc->line_state = (uint8_t) request->wValue; + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts); + tud_control_status(rhport, request); // Invoke callback - if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, tu_bit_test(request->wValue, 0), tu_bit_test(request->wValue, 1)); + if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts); + } break; default: return false; // stall unsupported request diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index e6d1caf4b..5a0ba412f 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -51,8 +51,8 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ // Application API @@ -60,8 +60,14 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_EN static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) { + // Opposite to endpoint in Data Phase + uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; + + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", ep_addr, 0); + // status direction is reversed to one in the setup packet - return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); + // Note: Status must always be DATA1 + return dcd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase @@ -106,6 +112,8 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // Data stage TU_ASSERT( _data_stage_xact(rhport) ); + + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); }else { // Status stage -- cgit v1.3.1 From fee79d746604f671483f5872337ea366f2d2c1a2 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:15:01 -0600 Subject: add CDC-ECM/RNDIS/CDC-EEM network device class with example --- .gitmodules | 5 +- examples/device/lwip_webserver/Makefile | 57 ++++ examples/device/lwip_webserver/src/arch/cc.h | 75 +++++ examples/device/lwip_webserver/src/lwipopts.h | 57 ++++ examples/device/lwip_webserver/src/main.c | 214 +++++++++++++ examples/device/lwip_webserver/src/tusb_config.h | 90 ++++++ .../device/lwip_webserver/src/usb_descriptors.c | 199 ++++++++++++ .../device/lwip_webserver/src/usb_descriptors.h | 28 ++ examples/rules.mk | 1 + lib/lwip | 1 + lib/networking/dhserver.c | 347 +++++++++++++++++++++ lib/networking/dhserver.h | 63 ++++ lib/networking/dnserver.c | 200 ++++++++++++ lib/networking/dnserver.h | 47 +++ lib/networking/ndis.h | 266 ++++++++++++++++ lib/networking/rndis_protocol.h | 307 ++++++++++++++++++ lib/networking/rndis_reports.c | 303 ++++++++++++++++++ src/class/net/net_device.c | 345 ++++++++++++++++++++ src/class/net/net_device.h | 84 +++++ src/device/usbd.c | 18 ++ src/device/usbd.h | 84 +++++ src/tusb.h | 4 + src/tusb_option.h | 12 + 23 files changed, 2806 insertions(+), 1 deletion(-) create mode 100644 examples/device/lwip_webserver/Makefile create mode 100644 examples/device/lwip_webserver/src/arch/cc.h create mode 100644 examples/device/lwip_webserver/src/lwipopts.h create mode 100644 examples/device/lwip_webserver/src/main.c create mode 100644 examples/device/lwip_webserver/src/tusb_config.h create mode 100644 examples/device/lwip_webserver/src/usb_descriptors.c create mode 100644 examples/device/lwip_webserver/src/usb_descriptors.h create mode 160000 lib/lwip create mode 100644 lib/networking/dhserver.c create mode 100644 lib/networking/dhserver.h create mode 100644 lib/networking/dnserver.c create mode 100644 lib/networking/dnserver.h create mode 100644 lib/networking/ndis.h create mode 100644 lib/networking/rndis_protocol.h create mode 100644 lib/networking/rndis_reports.c create mode 100644 src/class/net/net_device.c create mode 100644 src/class/net/net_device.h (limited to 'src/class') diff --git a/.gitmodules b/.gitmodules index 18b627bcf..0dda17d64 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,4 +21,7 @@ url = https://github.com/hathach/microchip_driver.git [submodule "hw/mcu/nuvoton"] path = hw/mcu/nuvoton - url = https://github.com/majbthrd/nuc_driver.git \ No newline at end of file + url = https://github.com/majbthrd/nuc_driver.git +[submodule "lib/lwip"] + path = lib/lwip + url = https://git.savannah.nongnu.org/git/lwip.git diff --git a/examples/device/lwip_webserver/Makefile b/examples/device/lwip_webserver/Makefile new file mode 100644 index 000000000..a153c30be --- /dev/null +++ b/examples/device/lwip_webserver/Makefile @@ -0,0 +1,57 @@ +include ../../../tools/top.mk +include ../../make.mk + +CFLAGS += \ + -DPBUF_POOL_SIZE=2 \ + -DTCP_WND=2*TCP_MSS \ + -DHTTPD_USE_CUSTOM_FSDATA=0 + +INC += \ + src \ + $(TOP)/hw \ + $(TOP)/lib/lwip/src/include \ + $(TOP)/lib/lwip/src/include/ipv4 \ + $(TOP)/lib/lwip/src/include/lwip/apps \ + $(TOP)/lib/networking + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += \ + lib/lwip/src/core/altcp.c \ + lib/lwip/src/core/altcp_alloc.c \ + lib/lwip/src/core/altcp_tcp.c \ + lib/lwip/src/core/def.c \ + lib/lwip/src/core/dns.c \ + lib/lwip/src/core/inet_chksum.c \ + lib/lwip/src/core/init.c \ + lib/lwip/src/core/ip.c \ + lib/lwip/src/core/mem.c \ + lib/lwip/src/core/memp.c \ + lib/lwip/src/core/netif.c \ + lib/lwip/src/core/pbuf.c \ + lib/lwip/src/core/raw.c \ + lib/lwip/src/core/stats.c \ + lib/lwip/src/core/sys.c \ + lib/lwip/src/core/tcp.c \ + lib/lwip/src/core/tcp_in.c \ + lib/lwip/src/core/tcp_out.c \ + lib/lwip/src/core/timeouts.c \ + lib/lwip/src/core/udp.c \ + lib/lwip/src/core/ipv4/autoip.c \ + lib/lwip/src/core/ipv4/dhcp.c \ + lib/lwip/src/core/ipv4/etharp.c \ + lib/lwip/src/core/ipv4/icmp.c \ + lib/lwip/src/core/ipv4/igmp.c \ + lib/lwip/src/core/ipv4/ip4.c \ + lib/lwip/src/core/ipv4/ip4_addr.c \ + lib/lwip/src/core/ipv4/ip4_frag.c \ + lib/lwip/src/netif/ethernet.c \ + lib/lwip/src/netif/slipif.c \ + lib/lwip/src/apps/http/httpd.c \ + lib/lwip/src/apps/http/fs.c \ + lib/networking/dhserver.c \ + lib/networking/dnserver.c \ + lib/networking/rndis_reports.c + +include ../../rules.mk diff --git a/examples/device/lwip_webserver/src/arch/cc.h b/examples/device/lwip_webserver/src/arch/cc.h new file mode 100644 index 000000000..56a0cacf7 --- /dev/null +++ b/examples/device/lwip_webserver/src/arch/cc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +//#include "cpu.h" + +typedef int sys_prot_t; + + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/examples/device/lwip_webserver/src/lwipopts.h b/examples/device/lwip_webserver/src/lwipopts.h new file mode 100644 index 000000000..23319592d --- /dev/null +++ b/examples/device/lwip_webserver/src/lwipopts.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 1 +#define MEM_ALIGNMENT 4 +#define LWIP_RAW 1 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define LWIP_DHCP 0 +#define LWIP_ICMP 1 +#define LWIP_UDP 1 +#define LWIP_TCP 1 +#define ETH_PAD_SIZE 0 +#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) + +#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) +#define TCP_SND_BUF (2 * TCP_MSS) + +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 + +#define LWIP_HTTPD_CGI 0 +#define LWIP_HTTPD_SSI 0 +#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 + +#endif /* __LWIPOPTS_H__ */ diff --git a/examples/device/lwip_webserver/src/main.c b/examples/device/lwip_webserver/src/main.c new file mode 100644 index 000000000..364a26788 --- /dev/null +++ b/examples/device/lwip_webserver/src/main.c @@ -0,0 +1,214 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * + * influenced by lrndis https://github.com/fetisov/lrndis + * + * 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. + * + */ + +/* +depending on the value of CFG_TUD_NET (tusb_config.h), this can be a CDC-ECM, RNDIS, or CDC-EEM USB virtual network adapter + +CDC-ECM should be valid on Linux and MacOS hosts +RNDIS should be valid on Linux and Windows hosts +CDC-EEM should be valid on Linux hosts + +You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network adapters to emulate. + +The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. +*/ + +#include "bsp/board.h" +#include "tusb.h" + +#include "dhserver.h" +#include "dnserver.h" +#include "lwip/init.h" +#include "httpd.h" + +/* lwip context */ +static struct netif netif_data; + +/* shared between network_recv_callback() and service_traffic() */ +static struct pbuf *received_frame; + +/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ +/* ideally speaking, this should be generated from the hardware's unique ID (if available) */ +const uint8_t network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; + +/* network parameters of this MCU */ +static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); +static const ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); +static const ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); + +/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ +static dhcp_entry_t entries[] = +{ + /* mac ip address subnet mask lease time */ + { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, + { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, + { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } +}; + +/* DHCP configuration parameters, leveraging "entries" above */ +static const dhcp_config_t dhcp_config = +{ + {192, 168, 7, 1}, 67, /* server address (self), port */ + {192, 168, 7, 1}, /* dns server (self) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* number of entries */ + entries /* pointer to entries */ +}; + +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +{ + (void)netif; + + for (;;) + { + /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ + if (!tud_ready()) + return ERR_USE; + + /* if the network driver can accept another packet, we make it happen */ + if (network_can_xmit()) + { + network_xmit(p); + return ERR_OK; + } + + /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ + tud_task(); + } +} + +static err_t output_fn(struct netif *netif, struct pbuf *p, const ip_addr_t *addr) +{ + return etharp_output(netif, p, addr); +} + +static err_t netif_init_cb(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + netif->mtu = CFG_TUD_NET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->linkoutput = linkoutput_fn; + netif->output = output_fn; + return ERR_OK; +} + +static void init_lwip(void) +{ + struct netif *netif = &netif_data; + + lwip_init(); + netif->hwaddr_len = sizeof(network_mac_address); + memcpy(netif->hwaddr, network_mac_address, sizeof(network_mac_address)); + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif_set_default(netif); +} + +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip_addr_t *addr) +{ + if (0 == strcmp(name, "tiny.usb")) + { + *addr = ipaddr; + return true; + } + return false; +} + +bool network_recv_callback(struct pbuf *p) +{ + /* this shouldn't happen, but if we get another packet before + parsing the previous, we must signal our inability to accept it */ + if (received_frame) return false; + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + return true; +} + +static void service_traffic(void) +{ + /* handle any packet received by network_recv_callback() */ + if (received_frame) + { + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + network_recv_renew(); + } +} + +void network_init_callback(void) +{ + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) + { + pbuf_free(received_frame); + received_frame = NULL; + } +} + +int main(void) +{ + /* initialize TinyUSB */ + board_init(); + tusb_init(); + + /* initialize lwip, dhcp-server, dns-server, and http */ + init_lwip(); + while (!netif_is_up(&netif_data)); + while (dhserv_init(&dhcp_config) != ERR_OK); + while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); + httpd_init(); + + while (1) + { + tud_task(); + service_traffic(); + } + + return 0; +} + +/* lwip has provision for using a mutex, when applicable */ +sys_prot_t sys_arch_protect(void) +{ + return 0; +} +void sys_arch_unprotect(sys_prot_t pval) +{ + (void)pval; +} + +/* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ +uint32_t sys_now(void) +{ + return board_millis(); +} diff --git a/examples/device/lwip_webserver/src/tusb_config.h b/examples/device/lwip_webserver/src/tusb_config.h new file mode 100644 index 000000000..329fc80b9 --- /dev/null +++ b/examples/device/lwip_webserver/src/tusb_config.h @@ -0,0 +1,90 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#endif + +#define CFG_TUSB_OS OPT_OS_NONE + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 +//#define CFG_TUD_NET OPT_NET_ECM +#define CFG_TUD_NET OPT_NET_RNDIS +//#define CFG_TUD_NET OPT_NET_EEM + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/lwip_webserver/src/usb_descriptors.c b/examples/device/lwip_webserver/src/usb_descriptors.c new file mode 100644 index 000000000..803c99c02 --- /dev/null +++ b/examples/device/lwip_webserver/src/usb_descriptors.c @@ -0,0 +1,199 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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 "tusb.h" +#include "usb_descriptors.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] NET1:NET0 | VENDOR | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(NET, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + .bDeviceClass = TUSB_CLASS_UNSPECIFIED, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_TOTAL +}; + +enum +{ + STR_LANGID = 0, + STR_MANUFACTURER, + STR_PRODUCT, + STR_ITFNAME, + STR_MAC, +}; + +#if CFG_TUD_NET == OPT_NET_ECM +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) +#elif CFG_TUD_NET == OPT_NET_RNDIS +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) +#elif CFG_TUD_NET == OPT_NET_EEM +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_CDC 2 +#else + #define EPNUM_CDC 2 +#endif + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + +#if CFG_TUD_NET == OPT_NET_ECM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STR_ITFNAME, STR_MAC, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +#elif CFG_TUD_NET == OPT_NET_RNDIS + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STR_ITFNAME, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#elif CFG_TUD_NET == OPT_NET_EEM + // Interface number, description string index, EP data address (out, in) and size. + TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STR_ITFNAME, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#endif +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + [STR_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) + [STR_MANUFACTURER] = "TinyUSB", // Manufacturer + [STR_PRODUCT] = "TinyUSB Device", // Product + [STR_ITFNAME] = // CDC-ECM Interface +#if CFG_TUD_NET == OPT_NET_ECM + "TinyUSB CDC-ECM", +#elif CFG_TUD_NET == OPT_NET_RNDIS + "TinyUSB RNDIS", +#elif CFG_TUD_NET == OPT_NET_EEM + "TinyUSB CDC-EEM", +#endif +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void)langid; + + unsigned chr_count = 0; + + if (STR_LANGID == index) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + else if (STR_MAC == index) + { + // Convert MAC address into UTF-16 + + for (unsigned i=0; i> 4) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(network_mac_address[i] >> 0) & 0xf]; + } + } + else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1; + + for (unsigned i=0; i + * + * 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 "dhserver.h" + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/* DHCP options */ +enum DHCP_OPTIONS +{ + DHCP_PAD = 0, + DHCP_SUBNETMASK = 1, + DHCP_ROUTER = 3, + DHCP_DNSSERVER = 6, + DHCP_HOSTNAME = 12, + DHCP_DNSDOMAIN = 15, + DHCP_MTU = 26, + DHCP_BROADCAST = 28, + DHCP_PERFORMROUTERDISC = 31, + DHCP_STATICROUTE = 33, + DHCP_NISDOMAIN = 40, + DHCP_NISSERVER = 41, + DHCP_NTPSERVER = 42, + DHCP_VENDOR = 43, + DHCP_IPADDRESS = 50, + DHCP_LEASETIME = 51, + DHCP_OPTIONSOVERLOADED = 52, + DHCP_MESSAGETYPE = 53, + DHCP_SERVERID = 54, + DHCP_PARAMETERREQUESTLIST = 55, + DHCP_MESSAGE = 56, + DHCP_MAXMESSAGESIZE = 57, + DHCP_RENEWALTIME = 58, + DHCP_REBINDTIME = 59, + DHCP_CLASSID = 60, + DHCP_CLIENTID = 61, + DHCP_USERCLASS = 77, /* RFC 3004 */ + DHCP_FQDN = 81, + DHCP_DNSSEARCH = 119, /* RFC 3397 */ + DHCP_CSR = 121, /* RFC 3442 */ + DHCP_MSCSR = 249, /* MS code for RFC 3442 */ + DHCP_END = 255 +}; + +typedef struct +{ + uint8_t dp_op; /* packet opcode type */ + uint8_t dp_htype; /* hardware addr type */ + uint8_t dp_hlen; /* hardware addr length */ + uint8_t dp_hops; /* gateway hops */ + uint32_t dp_xid; /* transaction ID */ + uint16_t dp_secs; /* seconds since boot began */ + uint16_t dp_flags; + uint8_t dp_ciaddr[4]; /* client IP address */ + uint8_t dp_yiaddr[4]; /* 'your' IP address */ + uint8_t dp_siaddr[4]; /* server IP address */ + uint8_t dp_giaddr[4]; /* gateway IP address */ + uint8_t dp_chaddr[16]; /* client hardware address */ + uint8_t dp_legacy[192]; + uint8_t dp_magic[4]; + uint8_t dp_options[275]; /* options area */ +} DHCP_TYPE; + +DHCP_TYPE dhcp_data; +static struct udp_pcb *pcb = NULL; +static const dhcp_config_t *config = NULL; + +char magic_cookie[] = {0x63,0x82,0x53,0x63}; + +static uint32_t get_ip(const uint8_t *pnt) +{ + uint32_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static void set_ip(uint8_t *pnt, uint32_t value) +{ + memcpy(pnt, &value, sizeof(value)); +} + +static dhcp_entry_t *entry_by_ip(uint32_t ip) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (get_ip(config->entries[i].addr) == ip) + return &config->entries[i]; + return NULL; +} + +static dhcp_entry_t *entry_by_mac(uint8_t *mac) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (memcmp(config->entries[i].mac, mac, 6) == 0) + return &config->entries[i]; + return NULL; +} + +static __inline bool is_vacant(dhcp_entry_t *entry) +{ + return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; +} + +static dhcp_entry_t *vacant_address(void) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (is_vacant(config->entries + i)) + return config->entries + i; + return NULL; +} + +static __inline void free_entry(dhcp_entry_t *entry) +{ + memset(entry->mac, 0, 6); +} + +uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) +{ + int i = 0; + while ((i + 1) < size) + { + int next = i + attrs[i + 1] + 2; + if (next > size) return NULL; + if (attrs[i] == attr) + return attrs + i; + i = next; + } + return NULL; +} + +int fill_options(void *dest, + uint8_t msg_type, + const char *domain, + uint32_t dns, + int lease_time, + uint32_t serverid, + uint32_t router, + uint32_t subnet) +{ + uint8_t *ptr = (uint8_t *)dest; + /* ACK message type */ + *ptr++ = 53; + *ptr++ = 1; + *ptr++ = msg_type; + + /* dhcp server identifier */ + *ptr++ = DHCP_SERVERID; + *ptr++ = 4; + set_ip(ptr, serverid); + ptr += 4; + + /* lease time */ + *ptr++ = DHCP_LEASETIME; + *ptr++ = 4; + *ptr++ = (lease_time >> 24) & 0xFF; + *ptr++ = (lease_time >> 16) & 0xFF; + *ptr++ = (lease_time >> 8) & 0xFF; + *ptr++ = (lease_time >> 0) & 0xFF; + + /* subnet mask */ + *ptr++ = DHCP_SUBNETMASK; + *ptr++ = 4; + set_ip(ptr, subnet); + ptr += 4; + + /* router */ + if (router != 0) + { + *ptr++ = DHCP_ROUTER; + *ptr++ = 4; + set_ip(ptr, router); + ptr += 4; + } + + /* domain name */ + if (domain != NULL) + { + int len = strlen(domain); + *ptr++ = DHCP_DNSDOMAIN; + *ptr++ = len; + memcpy(ptr, domain, len); + ptr += len; + } + + /* domain name server (DNS) */ + if (dns != 0) + { + *ptr++ = DHCP_DNSSERVER; + *ptr++ = 4; + set_ip(ptr, dns); + ptr += 4; + } + + /* end */ + *ptr++ = DHCP_END; + return ptr - (uint8_t *)dest; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + uint8_t *ptr; + dhcp_entry_t *entry; + struct pbuf *pp; + + (void)arg; + (void)addr; + + unsigned n = p->len; + if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); + memcpy(&dhcp_data, p->payload, n); + switch (dhcp_data.dp_options[2]) + { + case DHCP_DISCOVER: + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry == NULL) entry = vacant_address(); + if (entry == NULL) break; + + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + set_ip(dhcp_data.dp_yiaddr, get_ip(entry->addr)); + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_OFFER, + config->domain, + get_ip(config->dns), + entry->lease, + get_ip(config->addr), + get_ip(config->addr), + get_ip(entry->subnet)); + + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + case DHCP_REQUEST: + /* 1. find requested ipaddr in option list */ + ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); + if (ptr == NULL) break; + if (ptr[1] != 4) break; + ptr += 2; + + /* 2. does hw-address registered? */ + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry != NULL) free_entry(entry); + + /* 3. find requested ipaddr */ + entry = entry_by_ip(get_ip(ptr)); + if (entry == NULL) break; + if (!is_vacant(entry)) break; + + /* 4. fill struct fields */ + memcpy(dhcp_data.dp_yiaddr, ptr, 4); + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + /* 5. fill options */ + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_ACK, + config->domain, + get_ip(config->dns), + entry->lease, + get_ip(config->addr), + get_ip(config->addr), + get_ip(entry->subnet)); + + /* 6. send ACK */ + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(entry->mac, dhcp_data.dp_chaddr, 6); + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + default: + break; + } + pbuf_free(p); +} + +err_t dhserv_init(const dhcp_config_t *c) +{ + err_t err; + udp_init(); + dhserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, IP_ADDR_ANY, c->port); + if (err != ERR_OK) + { + dhserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + config = c; + return ERR_OK; +} + +void dhserv_free(void) +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/lib/networking/dhserver.h b/lib/networking/dhserver.h new file mode 100644 index 000000000..901f6e351 --- /dev/null +++ b/lib/networking/dhserver.h @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dhcp ipv4 server using lwip (pcb) + * ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html + */ + +#ifndef DHSERVER_H +#define DHSERVER_H + +#include +#include +#include +#include +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef struct dhcp_entry +{ + uint8_t mac[6]; + uint8_t addr[4]; + uint8_t subnet[4]; + uint32_t lease; +} dhcp_entry_t; + +typedef struct dhcp_config +{ + uint8_t addr[4]; + uint16_t port; + uint8_t dns[4]; + const char *domain; + int num_entry; + dhcp_entry_t *entries; +} dhcp_config_t; + +err_t dhserv_init(const dhcp_config_t *config); +void dhserv_free(void); + +#endif /* DHSERVER_H */ diff --git a/lib/networking/dnserver.c b/lib/networking/dnserver.c new file mode 100644 index 000000000..6df0bd0c4 --- /dev/null +++ b/lib/networking/dnserver.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#include "dnserver.h" + +#define DNS_MAX_HOST_NAME_LEN 128 + +static struct udp_pcb *pcb = NULL; +dns_query_proc_t query_proc = NULL; + +#pragma pack(push, 1) +typedef struct +{ +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t rd: 1, /* Recursion Desired */ + tc: 1, /* Truncation Flag */ + aa: 1, /* Authoritative Answer Flag */ + opcode: 4, /* Operation code */ + qr: 1; /* Query/Response Flag */ + uint8_t rcode: 4, /* Response Code */ + z: 3, /* Zero */ + ra: 1; /* Recursion Available */ +#else + uint8_t qr: 1, /* Query/Response Flag */ + opcode: 4, /* Operation code */ + aa: 1, /* Authoritative Answer Flag */ + tc: 1, /* Truncation Flag */ + rd: 1; /* Recursion Desired */ + uint8_t ra: 1, /* Recursion Available */ + z: 3, /* Zero */ + rcode: 4; /* Response Code */ +#endif +} dns_header_flags_t; + +typedef struct +{ + uint16_t id; + dns_header_flags_t flags; + uint16_t n_record[4]; +} dns_header_t; + +typedef struct dns_answer +{ + uint16_t name; + uint16_t type; + uint16_t Class; + uint32_t ttl; + uint16_t len; + uint32_t addr; +} dns_answer_t; +#pragma pack(pop) + +typedef struct dns_query +{ + char name[DNS_MAX_HOST_NAME_LEN]; + uint16_t type; + uint16_t Class; +} dns_query_t; + +static uint16_t get_uint16(const uint8_t *pnt) +{ + uint16_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static int parse_next_query(void *data, int size, dns_query_t *query) +{ + int len; + int lables; + uint8_t *ptr; + + len = 0; + lables = 0; + ptr = (uint8_t *)data; + + while (true) + { + uint8_t lable_len; + if (size <= 0) return -1; + lable_len = *ptr++; + size--; + if (lable_len == 0) break; + if (lables > 0) + { + if (len == DNS_MAX_HOST_NAME_LEN) return -2; + query->name[len++] = '.'; + } + if (lable_len > size) return -1; + if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2; + memcpy(&query->name[len], ptr, lable_len); + len += lable_len; + ptr += lable_len; + size -= lable_len; + lables++; + } + + if (size < 4) return -1; + query->name[len] = 0; + query->type = get_uint16(ptr); + ptr += 2; + query->Class = get_uint16(ptr); + ptr += 2; + return ptr - (uint8_t *)data; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + int len; + dns_header_t *header; + static dns_query_t query; + struct pbuf *out; + ip_addr_t host_addr; + dns_answer_t *answer; + + (void)arg; + + if (p->len <= sizeof(dns_header_t)) goto error; + header = (dns_header_t *)p->payload; + if (header->flags.qr != 0) goto error; + if (ntohs(header->n_record[0]) != 1) goto error; + + len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query); + if (len < 0) goto error; + if (!query_proc(query.name, &host_addr)) goto error; + + len += sizeof(dns_header_t); + out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL); + if (out == NULL) goto error; + + memcpy(out->payload, p->payload, len); + header = (dns_header_t *)out->payload; + header->flags.qr = 1; + header->n_record[1] = htons(1); + answer = (struct dns_answer *)((uint8_t *)out->payload + len); + answer->name = htons(0xC00C); + answer->type = htons(1); + answer->Class = htons(1); + answer->ttl = htonl(32); + answer->len = htons(4); + answer->addr = host_addr.addr; + + udp_sendto(upcb, out, addr, port); + pbuf_free(out); + +error: + pbuf_free(p); +} + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp) +{ + err_t err; + udp_init(); + dnserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, bind, port); + if (err != ERR_OK) + { + dnserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + query_proc = qp; + return ERR_OK; +} + +void dnserv_free() +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/lib/networking/dnserver.h b/lib/networking/dnserver.h new file mode 100644 index 000000000..130991f5f --- /dev/null +++ b/lib/networking/dnserver.h @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#ifndef DNSERVER +#define DNSERVER + +#include +#include +#include +#include +#include "lwip/def.h" +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef bool (*dns_query_proc_t)(const char *name, ip_addr_t *addr); + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); +void dnserv_free(void); + +#endif diff --git a/lib/networking/ndis.h b/lib/networking/ndis.h new file mode 100644 index 000000000..1c737574c --- /dev/null +++ b/lib/networking/ndis.h @@ -0,0 +1,266 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ndis.h *************************************************************** + * + * \brief + * This file contains the possible external configuration of the USB. + * + * \addtogroup usbstick + * + * + ******************************************************************************/ + +/** + \ingroup usbstick + \defgroup RNDIS RNDIS Support + @{ + */ + +/* + * ndis.h + * + * Modified by Colin O'Flynn + * ntddndis.h modified by Benedikt Spranger + * + * Thanks to the cygwin development team, + * espacially to Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef _LINUX_NDIS_H +#define _LINUX_NDIS_H + + +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B + +/* from drivers/net/sk98lin/h/skgepnmi.h */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + +/* NDIS_PNP_CAPABILITIES.Flags constants */ +#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +/* +struct NDIS_PNP_CAPABILITIES { + __le32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + __le32 Priority; + __le32 Reserved; + __le32 MaskSize; + __le32 PatternOffset; + __le32 PatternSize; + __le32 PatternFlags; +}; +*/ + +/* Required Object IDs (OIDs) */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional statistics OIDs */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 +#define OID_GEN_INIT_TIME_MS 0x00020213 +#define OID_GEN_RESET_COUNTS 0x00020214 +#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 +#define OID_GEN_FRIENDLY_NAME 0x00020216 +#define OID_GEN_MINIPORT_INFO 0x00020217 +#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 + +/* IEEE 802.3 (Ethernet) OIDs */ +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* Wireless LAN OIDs */ +/* Mandatory */ +#define OID_802_11_BSSID 0x0D010101 /* Q S */ +#define OID_802_11_SSID 0x0D010102 /* Q S */ +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ +#define OID_802_11_RSSI 0x0D010206 /* Q I */ +#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ +#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ +#define OID_802_11_ADD_WEP 0x0D010113 /* S */ +#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ +#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ +#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ + + + +/* OID_GEN_MINIPORT_INFO constants */ +#define NDIS_MINIPORT_BUS_MASTER 0x00000001 +#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 +#define NDIS_MINIPORT_SG_LIST 0x00000004 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 +#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 +#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 +#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 +#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 +#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 +#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 +#define NDIS_MINIPORT_IS_CO 0x00000400 +#define NDIS_MINIPORT_DESERIALIZE 0x00000800 +#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 +#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 +#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 +#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 +#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 +#define NDIS_MINIPORT_HIDDEN 0x00040000 +#define NDIS_MINIPORT_SWENUM 0x00080000 +#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 +#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 +#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 +#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 +#define NDIS_MINIPORT_64BITS_DMA 0x01000000 + +#define NDIS_MEDIUM_802_3 0x00000000 +#define NDIS_MEDIUM_802_5 0x00000001 +#define NDIS_MEDIUM_FDDI 0x00000002 +#define NDIS_MEDIUM_WAN 0x00000003 +#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 +#define NDIS_MEDIUM_DIX 0x00000005 +#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 +#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 +#define NDIS_MEDIUM_ATM 0x00000008 +#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 +#define NDIS_MEDIUM_IRDA 0x0000000A +#define NDIS_MEDIUM_BPC 0x0000000B +#define NDIS_MEDIUM_CO_WAN 0x0000000C +#define NDIS_MEDIUM_1394 0x0000000D + +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00000100 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 + +#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 +#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#endif /* _LINUX_NDIS_H */ + +/** @} */ diff --git a/lib/networking/rndis_protocol.h b/lib/networking/rndis_protocol.h new file mode 100644 index 000000000..b45860eeb --- /dev/null +++ b/lib/networking/rndis_protocol.h @@ -0,0 +1,307 @@ +/** + * \file rndis_protocol.h + * RNDIS Defines + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 Colin O'Flynn + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _RNDIS_H +#define _RNDIS_H + +/** + \addtogroup RNDIS + @{ + */ + +#include + +#define RNDIS_MAJOR_VERSION 1 +#define RNDIS_MINOR_VERSION 0 + +#define RNDIS_STATUS_SUCCESS 0X00000000 +#define RNDIS_STATUS_FAILURE 0XC0000001 +#define RNDIS_STATUS_INVALID_DATA 0XC0010015 +#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB +#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B +#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C + + +/* Message set for Connectionless (802.3) Devices */ +#define REMOTE_NDIS_PACKET_MSG 0x00000001 +#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 +#define REMOTE_NDIS_HALT_MSG 0X00000003 +#define REMOTE_NDIS_QUERY_MSG 0X00000004 +#define REMOTE_NDIS_SET_MSG 0X00000005 +#define REMOTE_NDIS_RESET_MSG 0X00000006 +#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 +#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 +#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 +#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 +#define REMOTE_NDIS_SET_CMPLT 0X80000005 +#define REMOTE_NDIS_RESET_CMPLT 0X80000006 +#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 + +typedef uint32_t rndis_MessageType_t; +typedef uint32_t rndis_MessageLength_t; +typedef uint32_t rndis_RequestId_t; +typedef uint32_t rndis_MajorVersion_t; +typedef uint32_t rndis_MinorVersion_t; +typedef uint32_t rndis_MaxTransferSize_t; +typedef uint32_t rndis_Status_t; + + +/* Device Flags */ +#define RNDIS_DF_CONNECTIONLESS 0x00000001 +#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +typedef uint32_t rndis_DeviceFlags_t; + +/* Mediums */ +#define RNDIS_MEDIUM_802_3 0x00000000 +typedef uint32_t rndis_Medium_t; + + +typedef uint32_t rndis_MaxPacketsPerTransfer_t; +typedef uint32_t rndis_PacketAlignmentFactor_t; +typedef uint32_t rndis_AfListOffset_t; +typedef uint32_t rndis_AfListSize_t; + +/*** Remote NDIS Generic Message type ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + } rndis_generic_msg_t; + + +/*** Remote NDIS Initialize Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_MaxTransferSize_t MaxTransferSize; + } rndis_initialize_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_DeviceFlags_t DeviceFlags; + rndis_Medium_t Medium; + rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; + rndis_MaxTransferSize_t MaxTransferSize; + rndis_PacketAlignmentFactor_t PacketAlignmentFactor; + rndis_AfListOffset_t AfListOffset; + rndis_AfListSize_t AfListSize; + } rndis_initialize_cmplt_t; + + +/*** Remote NDIS Halt Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + } rndis_halt_msg_t; + +typedef uint32_t rndis_Oid_t; +typedef uint32_t rndis_InformationBufferLength_t; +typedef uint32_t rndis_InformationBufferOffset_t; +typedef uint32_t rndis_DeviceVcHandle_t; + +/*** Remote NDIS Query Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_query_msg_t; + +/* Response: */ + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + } rndis_query_cmplt_t; + +/*** Remote NDIS Set Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_set_msg_t; + +/* Response */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_set_cmplt_t; + +/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ +typedef uint32_t rndis_ParameterNameOffset_t; +typedef uint32_t rndis_ParameterNameLength_t; +typedef uint32_t rndis_ParameterType_t; +typedef uint32_t rndis_ParameterValueOffset_t; +typedef uint32_t rndis_ParameterValueLength_t; + +#define PARAMETER_TYPE_STRING 2 +#define PARAMETER_TYPE_NUMERICAL 0 + +typedef struct{ + rndis_ParameterNameOffset_t ParameterNameOffset; + rndis_ParameterNameLength_t ParameterNameLength; + rndis_ParameterType_t ParameterType; + rndis_ParameterValueOffset_t ParameterValueOffset; + rndis_ParameterValueLength_t ParameterValueLength; + }rndis_config_parameter_t; + +typedef uint32_t rndis_Reserved_t; + +/*** Remote NDIS Soft Reset Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Reserved_t Reserved; + } rndis_reset_msg_t; + +typedef uint32_t rndis_AddressingReset_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_AddressingReset_t AddressingReset; + } rndis_reset_cmplt_t; + +/*** Remote NDIS Indicate Status Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_Status_t StatusBufferLength; + rndis_Status_t StatusBufferOffset; + } rndis_indicate_status_t; + +typedef uint32_t rndis_DiagStatus_t; +typedef uint32_t rndis_ErrorOffset_t; + +typedef struct { + rndis_DiagStatus_t DiagStatus; + rndis_ErrorOffset_t ErrorOffset; + }rndis_diagnostic_info_t; + +/*** Remote NDIS Keepalive Message */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + }rndis_keepalive_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_keepalive_cmplt_t; + +/*** Remote NDIS Data Packet ***/ + +typedef uint32_t rndis_DataOffset_t; +typedef uint32_t rndis_DataLength_t; +typedef uint32_t rndis_OOBDataOffset_t; +typedef uint32_t rndis_OOBDataLength_t; +typedef uint32_t rndis_NumOOBDataElements_t; +typedef uint32_t rndis_PerPacketInfoOffset_t; +typedef uint32_t rndis_PerPacketInfoLength_t; + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_DataOffset_t DataOffset; + rndis_DataLength_t DataLength; + rndis_OOBDataOffset_t OOBDataOffset; + rndis_OOBDataLength_t OOBDataLength; + rndis_NumOOBDataElements_t NumOOBDataElements; + rndis_PerPacketInfoOffset_t PerPacketInfoOffset; + rndis_PerPacketInfoLength_t PerPacketInfoLength; + rndis_DeviceVcHandle_t DeviceVcHandle; + rndis_Reserved_t Reserved; + }rndis_data_packet_t; + +typedef uint32_t rndis_ClassInformationOffset_t; +typedef uint32_t rndis_Size_t; +typedef uint32_t rndis_Type_t; + +typedef struct{ + rndis_Size_t Size; + rndis_Type_t Type; + rndis_ClassInformationOffset_t ClassInformationType; + }rndis_OOB_packet_t; + +#include "ndis.h" + +typedef enum rnids_state_e { + rndis_uninitialized, + rndis_initialized, + rndis_data_initialized + } rndis_state_t; + +typedef struct { + uint32_t txok; + uint32_t rxok; + uint32_t txbad; + uint32_t rxbad; +} usb_eth_stat_t; + +#endif /* _RNDIS_H */ + +/** @} */ diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c new file mode 100644 index 000000000..535bdf851 --- /dev/null +++ b/lib/networking/rndis_reports.c @@ -0,0 +1,303 @@ +/* + The original version of this code was lrndis/usbd_rndis_core.c from https://github.com/fetisov/lrndis + It has since been overhauled to suit this application +*/ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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 +#include +#include "class/net/net_device.h" +#include "rndis_protocol.h" +#include "netif/ethernet.h" + +#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ +#define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ + +static const uint8_t *const station_hwaddr = network_mac_address; +static const uint8_t *const permanent_hwaddr = network_mac_address; + +static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; +static uint32_t oid_packet_filter = 0x0000000; +static rndis_state_t rndis_state; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + +static const uint32_t OIDSupportedList[] = +{ + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_MAC_OPTIONS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_MAC_OPTIONS +}; + +#define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) +#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) + +static uint8_t *encapsulated_buffer; + +static void rndis_report(void) +{ + netd_report(ndis_report, sizeof(ndis_report)); +} + +static void rndis_query_cmplt32(int status, uint32_t data) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + 4; + c->InformationBufferLength = 4; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, &data, sizeof(data)); + rndis_report(); +} + +static void rndis_query_cmplt(int status, const void *data, int size) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + size; + c->InformationBufferLength = size; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, data, size); + rndis_report(); +} + +#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ + NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \ + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ + NDIS_MAC_OPTION_NO_LOOPBACK + +static const char *rndis_vendor = RNDIS_VENDOR; + +static void rndis_query(void) +{ + switch (((rndis_query_msg_t *)encapsulated_buffer)->Oid) + { + case OID_GEN_SUPPORTED_LIST: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return; + case OID_GEN_VENDOR_DRIVER_VERSION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00001000); return; + case OID_802_3_CURRENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, &station_hwaddr, 6); return; + case OID_802_3_PERMANENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, &permanent_hwaddr, 6); return; + case OID_GEN_MEDIA_SUPPORTED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_MEDIA_IN_USE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_PHYSICAL_MEDIUM: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_HARDWARE_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_LINK_SPEED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return; + case OID_GEN_VENDOR_ID: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return; + case OID_GEN_VENDOR_DESCRIPTION: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return; + case OID_GEN_CURRENT_PACKET_FILTER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, oid_packet_filter); return; + case OID_GEN_MAXIMUM_FRAME_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU - SIZEOF_ETH_HDR); return; + case OID_GEN_MAXIMUM_TOTAL_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_TRANSMIT_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_RECEIVE_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_MEDIA_CONNECT_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIA_STATE_CONNECTED); return; + case OID_GEN_RNDIS_CONFIG_PARAMETER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_MAXIMUM_LIST_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 1); return; + case OID_802_3_MULTICAST_LIST: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_802_3_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_GEN_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, /*MAC_OPT*/ 0); return; + case OID_802_3_RCV_ERROR_ALIGNMENT: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_ONE_COLLISION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_MORE_COLLISIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_XMIT_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txok); return; + case OID_GEN_RCV_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxok); return; + case OID_GEN_RCV_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxbad); return; + case OID_GEN_XMIT_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txbad); return; + case OID_GEN_RCV_NO_BUFFER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + default: rndis_query_cmplt(RNDIS_STATUS_FAILURE, NULL, 0); return; + } +} + +#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) + +static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) +{ + (void)data; + (void)keyoffset; + (void)valoffset; + (void)keylen; + (void)vallen; +} + +static void rndis_packetFilter(uint32_t newfilter) +{ + (void)newfilter; +} + +static void rndis_handle_set_msg(void) +{ + rndis_set_cmplt_t *c; + rndis_set_msg_t *m; + rndis_Oid_t oid; + + c = (rndis_set_cmplt_t *)encapsulated_buffer; + m = (rndis_set_msg_t *)encapsulated_buffer; + + oid = m->Oid; + c->MessageType = REMOTE_NDIS_SET_CMPLT; + c->MessageLength = sizeof(rndis_set_cmplt_t); + c->Status = RNDIS_STATUS_SUCCESS; + + switch (oid) + { + /* Parameters set up in 'Advanced' tab */ + case OID_GEN_RNDIS_CONFIG_PARAMETER: + { + rndis_config_parameter_t *p; + char *ptr = (char *)m; + ptr += sizeof(rndis_generic_msg_t); + ptr += m->InformationBufferOffset; + p = (rndis_config_parameter_t *)ptr; + rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); + } + break; + + /* Mandatory general OIDs */ + case OID_GEN_CURRENT_PACKET_FILTER: + oid_packet_filter = *INFBUF; + if (oid_packet_filter) + { + rndis_packetFilter(oid_packet_filter); + rndis_state = rndis_data_initialized; + } + else + { + rndis_state = rndis_initialized; + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + break; + + case OID_GEN_PROTOCOL_OPTIONS: + break; + + /* Mandatory 802_3 OIDs */ + case OID_802_3_MULTICAST_LIST: + break; + + /* Power Managment: fails for now */ + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ENABLE_WAKE_UP: + default: + c->Status = RNDIS_STATUS_FAILURE; + break; + } + + /* c->MessageID is same as before */ + rndis_report(); + return; +} + +void rndis_class_set_handler(uint8_t *data, int size) +{ + encapsulated_buffer = data; + (void)size; + + switch (((rndis_generic_msg_t *)data)->MessageType) + { + case REMOTE_NDIS_INITIALIZE_MSG: + { + rndis_initialize_cmplt_t *m; + m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); + /* m->MessageID is same as before */ + m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + m->MessageLength = sizeof(rndis_initialize_cmplt_t); + m->MajorVersion = RNDIS_MAJOR_VERSION; + m->MinorVersion = RNDIS_MINOR_VERSION; + m->Status = RNDIS_STATUS_SUCCESS; + m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; + m->Medium = RNDIS_MEDIUM_802_3; + m->MaxPacketsPerTransfer = 1; + m->MaxTransferSize = CFG_TUD_NET_MTU + sizeof(rndis_data_packet_t); + m->PacketAlignmentFactor = 0; + m->AfListOffset = 0; + m->AfListSize = 0; + rndis_state = rndis_initialized; + rndis_report(); + } + break; + + case REMOTE_NDIS_QUERY_MSG: + rndis_query(); + break; + + case REMOTE_NDIS_SET_MSG: + rndis_handle_set_msg(); + break; + + case REMOTE_NDIS_RESET_MSG: + { + rndis_reset_cmplt_t * m; + m = ((rndis_reset_cmplt_t *)encapsulated_buffer); + rndis_state = rndis_uninitialized; + m->MessageType = REMOTE_NDIS_RESET_CMPLT; + m->MessageLength = sizeof(rndis_reset_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + m->AddressingReset = 1; /* Make it look like we did something */ + /* m->AddressingReset = 0; - Windows halts if set to 1 for some reason */ + rndis_report(); + } + break; + + case REMOTE_NDIS_KEEPALIVE_MSG: + { + rndis_keepalive_cmplt_t * m; + m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; + m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + m->MessageLength = sizeof(rndis_keepalive_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + } + /* We have data to send back */ + rndis_report(); + break; + + default: + break; + } +} diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c new file mode 100644 index 000000000..422d435c6 --- /dev/null +++ b/src/class/net/net_device.c @@ -0,0 +1,345 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) ) + +#include "net_device.h" +#include "device/usbd_pvt.h" +#include "rndis_protocol.h" + +void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; +} netd_interface_t; + +#if CFG_TUD_NET == OPT_NET_ECM + #define CFG_TUD_NET_PACKET_PREFIX_LEN 0 + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 + #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL +#elif CFG_TUD_NET == OPT_NET_RNDIS + #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 + #define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS +#elif CFG_TUD_NET == OPT_NET_EEM + #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 + #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL +#endif + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; + +#if CFG_TUD_NET == OPT_NET_RNDIS + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[128]; +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; + +static bool can_xmit; + +void network_recv_renew(void) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); +} + +static void do_in_xfer(uint8_t *buf, uint16_t len) +{ + can_xmit = false; + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len); +} + +void netd_report(uint8_t *buf, uint16_t len) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void netd_init(void) +{ + tu_memclr(&_netd_itf, sizeof(_netd_itf)); +} + +void netd_reset(uint8_t rhport) +{ + (void) rhport; + + netd_init(); +} + +bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + // sanity check the descriptor + TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass); + + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_in); + + //------------- first Interface -------------// + _netd_itf.itf_num = itf_desc->bInterfaceNumber; + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + (*p_length) = sizeof(tusb_desc_interface_t); + +#if CFG_TUD_NET != OPT_NET_EEM + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + { + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // notification endpoint (if any) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + + _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + (*p_length) += p_desc[DESC_OFFSET_LEN]; + p_desc = tu_desc_next(p_desc); + } + + //------------- second Interface -------------// + if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + { + // next to endpoint descriptor + p_desc = tu_desc_next(p_desc); + (*p_length) += sizeof(tusb_desc_interface_t); + } +#endif + + if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + { + // Open endpoint pair + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + (*p_length) += 2*sizeof(tusb_desc_endpoint_t); + } + + network_init_callback(); + + // we are ready to transmit a packet + can_xmit = true; + + // prepare for incoming packets + network_recv_renew(); + + return true; +} + +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send nonsense DATA) +bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + // Handle class request only + TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + +#if CFG_TUD_NET == OPT_NET_RNDIS + if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + rndis_class_set_handler(rndis_buf, request->wLength); + } +#endif + + return true; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) +{ + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + +#if CFG_TUD_NET == OPT_NET_RNDIS + tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); +#else + (void)rhport; +#endif + + return true; +} + +struct cdc_eem_packet_header +{ + uint16_t length:14; + uint16_t bmCRC:1; + uint16_t bmType:1; +}; + +static void handle_incoming_packet(uint32_t len) +{ + uint8_t *pnt = received; + uint32_t size = 0; + +#if CFG_TUD_NET == OPT_NET_ECM + size = len; +#elif CFG_TUD_NET == OPT_NET_RNDIS + rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + if (len >= sizeof(rndis_data_packet_t)) + if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) + if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) + { + pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; + size = r->DataLength; + } +#elif CFG_TUD_NET == OPT_NET_EEM + struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; + + (void)len; + + if (hdr->bmType) + { + /* EEM Control Packet: discard it */ + network_recv_renew(); + } + else + { + /* EEM Data Packet */ + pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; + size = hdr->length - 4; /* discard the unused CRC-32 */ + } +#endif + + if (size) + { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + bool accepted = true; + + if (p) + { + memcpy(p->payload, pnt, size); + p->len = size; + accepted = network_recv_callback(p); + } + + if (!p || !accepted) + { + /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ + network_recv_renew(); + } + } +} + +bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + /* new packet received */ + if ( ep_addr == _netd_itf.ep_out ) + { + handle_incoming_packet(xferred_bytes); + } + + /* data transmission finished */ + if ( ep_addr == _netd_itf.ep_in ) + { + /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ + + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) + { + do_in_xfer(NULL, 0); /* a ZLP is needed */ + } + else + { + /* we're finally finished */ + can_xmit = true; + } + } + + return true; +} + +bool network_can_xmit(void) +{ + return can_xmit; +} + +void network_xmit(struct pbuf *p) +{ + struct pbuf *q; + uint8_t *data; + uint16_t len; + + if (!can_xmit) + return; + + len = CFG_TUD_NET_PACKET_PREFIX_LEN; + data = transmitted + len; + + for(q = p; q != NULL; q = q->next) + { + memcpy(data, (char *)q->payload, q->len); + data += q->len; + len += q->len; + } + +#if CFG_TUD_NET == OPT_NET_RNDIS + rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); + hdr->DataLength = len - sizeof(rndis_data_packet_t); +#elif CFG_TUD_NET == OPT_NET_EEM + struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; + /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ + data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; + /* adjust length to reflect added fake CRC-32 */ + len += 4; + hdr->bmType = 0; /* EEM Data Packet */ + hdr->length = len - sizeof(struct cdc_eem_packet_header); + hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ +#endif + + do_in_xfer(transmitted, len); +} + +#endif diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h new file mode 100644 index 000000000..c61efc86c --- /dev/null +++ b/src/class/net/net_device.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_NET_DEVICE_H_ +#define _TUSB_NET_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "class/cdc/cdc.h" +#include "lwip/pbuf.h" +#include "netif/ethernet.h" + +/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ +#define CFG_TUD_NET_ENDPOINT_SIZE ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) + +/* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ +#define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// client must provide this: initialize any network state back to the beginning +void network_init_callback(void); + +// client must provide this: return false if the packet buffer was not accepted +bool network_recv_callback(struct pbuf *p); + +// client must provide this: 48-bit MAC address +extern const uint8_t network_mac_address[6]; + +// indicate to network driver that client has finished with the packet provided to network_recv_callback() +void network_recv_renew(void); + +// poll network driver for its ability to accept another packet to transmit +bool network_can_xmit(void); + +// if network_can_xmit() returns true, network_xmit() can be called once +void network_xmit(struct pbuf *p); + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void netd_init (void); +void netd_reset (uint8_t rhport); +bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 68c5c5160..32a89889e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -181,6 +181,24 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL }, #endif + + #if CFG_TUD_NET + { + .class_code = +#if CFG_TUD_NET == OPT_NET_RNDIS + TUD_RNDIS_ITF_CLASS, +#else + TUSB_CLASS_CDC, +#endif + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_request = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index d80abf17c..07163a013 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -326,6 +326,90 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +//------------- CDC-ECM -------------// + +// Length of template descriptor: 62 bytes +#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7) + +// CDC-ECM Descriptor Template +// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. +#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-ECM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + +//------------- RNDIS -------------// + +#if 0 + /* Windows XP */ + #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC + #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL + #define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS +#else + /* Windows 7+ */ + #define TUD_RNDIS_ITF_CLASS 0xE0 + #define TUD_RNDIS_ITF_SUBCLASS 0x01 + #define TUD_RNDIS_ITF_PROTOCOL 0x03 +#endif + +// Length of template descriptor: 66 bytes +#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7) + +// RNDIS Descriptor Template +// Interface number, string index, EP notification address and size, EP data address (out, in) and size. +#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + +//------------- CDC-EEM -------------// + +// Length of template descriptor: 23 bytes +#define TUD_CDC_EEM_DESC_LEN (9+7+7) + +// CDC-EEM Descriptor Template +// Interface number, description string index, EP data address (out, in) and size. +#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + /* EEM Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + #ifdef __cplusplus } #endif diff --git a/src/tusb.h b/src/tusb.h index 7dcddf645..55c105121 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -91,6 +91,10 @@ #if CFG_TUD_DFU_RT #include "class/dfu/dfu_rt_device.h" #endif + + #if CFG_TUD_NET + #include "class/net/net_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 97f14532f..00d4a39dc 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -117,6 +117,15 @@ #define OPT_MODE_HIGH_SPEED 0x10 ///< High speed /** @} */ +/** \defgroup group_supported_netif Supported Network Interface + * \ref CFG_TUD_NET must be defined to one of these + * @{ */ +#define OPT_NET_NONE 0 ///< No network interface +#define OPT_NET_ECM 1 ///< CDC-ECM +#define OPT_NET_RNDIS 2 ///< RNDIS +#define OPT_NET_EEM 3 ///< CDC-EEM +/** @} */ + #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif @@ -204,6 +213,9 @@ #define CFG_TUD_DFU_RT 0 #endif +#ifndef CFG_TUD_NET + #define CFG_TUD_NET 0 +#endif //-------------------------------------------------------------------- // HOST OPTIONS -- cgit v1.3.1 From 4a4682a80a2bd3d6d607d5a960443656de32955d Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 3 Mar 2020 10:31:46 -0600 Subject: update net class to follow API naming convention --- examples/device/lwip_webserver/src/main.c | 20 ++++++++++---------- examples/device/lwip_webserver/src/usb_descriptors.c | 6 +++--- lib/networking/rndis_reports.c | 4 ++-- src/class/net/net_device.c | 16 ++++++++-------- src/class/net/net_device.h | 14 +++++++------- 5 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src/class') diff --git a/examples/device/lwip_webserver/src/main.c b/examples/device/lwip_webserver/src/main.c index 364a26788..c193aeb0f 100644 --- a/examples/device/lwip_webserver/src/main.c +++ b/examples/device/lwip_webserver/src/main.c @@ -48,12 +48,12 @@ The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP serve /* lwip context */ static struct netif netif_data; -/* shared between network_recv_callback() and service_traffic() */ +/* shared between tud_network_recv_cb() and service_traffic() */ static struct pbuf *received_frame; /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ -const uint8_t network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; +const uint8_t tud_network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; /* network parameters of this MCU */ static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); @@ -90,9 +90,9 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) return ERR_USE; /* if the network driver can accept another packet, we make it happen */ - if (network_can_xmit()) + if (tud_network_can_xmit()) { - network_xmit(p); + tud_network_xmit(p); return ERR_OK; } @@ -124,8 +124,8 @@ static void init_lwip(void) struct netif *netif = &netif_data; lwip_init(); - netif->hwaddr_len = sizeof(network_mac_address); - memcpy(netif->hwaddr, network_mac_address, sizeof(network_mac_address)); + netif->hwaddr_len = sizeof(tud_network_mac_address); + memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); netif_set_default(netif); @@ -142,7 +142,7 @@ bool dns_query_proc(const char *name, ip_addr_t *addr) return false; } -bool network_recv_callback(struct pbuf *p) +bool tud_network_recv_cb(struct pbuf *p) { /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ @@ -155,17 +155,17 @@ bool network_recv_callback(struct pbuf *p) static void service_traffic(void) { - /* handle any packet received by network_recv_callback() */ + /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); received_frame = NULL; - network_recv_renew(); + tud_network_recv_renew(); } } -void network_init_callback(void) +void tud_network_init_cb(void) { /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ if (received_frame) diff --git a/examples/device/lwip_webserver/src/usb_descriptors.c b/examples/device/lwip_webserver/src/usb_descriptors.c index 803c99c02..26f8aeba6 100644 --- a/examples/device/lwip_webserver/src/usb_descriptors.c +++ b/examples/device/lwip_webserver/src/usb_descriptors.c @@ -168,10 +168,10 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Convert MAC address into UTF-16 - for (unsigned i=0; i> 4) & 0xf]; - _desc_str[1+chr_count++] = "0123456789ABCDEF"[(network_mac_address[i] >> 0) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; } } else diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c index 535bdf851..9c470b621 100644 --- a/lib/networking/rndis_reports.c +++ b/lib/networking/rndis_reports.c @@ -36,8 +36,8 @@ #define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ #define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ -static const uint8_t *const station_hwaddr = network_mac_address; -static const uint8_t *const permanent_hwaddr = network_mac_address; +static const uint8_t *const station_hwaddr = tud_network_mac_address; +static const uint8_t *const permanent_hwaddr = tud_network_mac_address; static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; static uint32_t oid_packet_filter = 0x0000000; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 422d435c6..c918e5874 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -74,7 +74,7 @@ CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; static bool can_xmit; -void network_recv_renew(void) +void tud_network_recv_renew(void) { usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); } @@ -156,13 +156,13 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t (*p_length) += 2*sizeof(tusb_desc_endpoint_t); } - network_init_callback(); + tud_network_init_cb(); // we are ready to transmit a packet can_xmit = true; // prepare for incoming packets - network_recv_renew(); + tud_network_recv_renew(); return true; } @@ -237,7 +237,7 @@ static void handle_incoming_packet(uint32_t len) if (hdr->bmType) { /* EEM Control Packet: discard it */ - network_recv_renew(); + tud_network_recv_renew(); } else { @@ -256,13 +256,13 @@ static void handle_incoming_packet(uint32_t len) { memcpy(p->payload, pnt, size); p->len = size; - accepted = network_recv_callback(p); + accepted = tud_network_recv_cb(p); } if (!p || !accepted) { /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ - network_recv_renew(); + tud_network_recv_renew(); } } } @@ -297,12 +297,12 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } -bool network_can_xmit(void) +bool tud_network_can_xmit(void) { return can_xmit; } -void network_xmit(struct pbuf *p) +void tud_network_xmit(struct pbuf *p) { struct pbuf *q; uint8_t *data; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index c61efc86c..fee54163f 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -49,22 +49,22 @@ //--------------------------------------------------------------------+ // client must provide this: initialize any network state back to the beginning -void network_init_callback(void); +void tud_network_init_cb(void); // client must provide this: return false if the packet buffer was not accepted -bool network_recv_callback(struct pbuf *p); +bool tud_network_recv_cb(struct pbuf *p); // client must provide this: 48-bit MAC address -extern const uint8_t network_mac_address[6]; +extern const uint8_t tud_network_mac_address[6]; -// indicate to network driver that client has finished with the packet provided to network_recv_callback() -void network_recv_renew(void); +// indicate to network driver that client has finished with the packet provided to network_recv_cb() +void tud_network_recv_renew(void); // poll network driver for its ability to accept another packet to transmit -bool network_can_xmit(void); +bool tud_network_can_xmit(void); // if network_can_xmit() returns true, network_xmit() can be called once -void network_xmit(struct pbuf *p); +void tud_network_xmit(struct pbuf *p); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API -- cgit v1.3.1 From d74facfd0aede63da35c067ae8b8f3e4ed29ac6f Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Wed, 4 Mar 2020 17:54:11 -0600 Subject: usbnet RNDIS correction --- src/class/net/net_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index c918e5874..d0d32e909 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -64,7 +64,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACK CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; #if CFG_TUD_NET == OPT_NET_RNDIS - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[128]; + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120]; #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 85a3315a998ce7c625796177a665e6f4cd373e73 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 9 Mar 2020 15:51:29 +0700 Subject: Adding lwip_webserver to ci - buil_al.py skip specific MCU if .skip.MCU_ exists - reduce stm32f070 heap & stack size to compile webserver --- examples/device/lwip_webserver/.skip.MCU_LPC11UXX | 0 examples/device/lwip_webserver/.skip.MCU_LPC13XX | 0 examples/device/lwip_webserver/.skip.MCU_NUC121 | 0 examples/device/lwip_webserver/.skip.MCU_STM32L0 | 0 hw/bsp/samg55xplained/samg55xplained.c | 3 +- hw/bsp/spresense/board.mk | 4 +- hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld | 4 +- src/class/net/net_device.h | 2 + tools/build_all.py | 56 ++++++++++++++++------- tools/build_success.sh | 10 ---- 10 files changed, 48 insertions(+), 31 deletions(-) create mode 100644 examples/device/lwip_webserver/.skip.MCU_LPC11UXX create mode 100644 examples/device/lwip_webserver/.skip.MCU_LPC13XX create mode 100644 examples/device/lwip_webserver/.skip.MCU_NUC121 create mode 100644 examples/device/lwip_webserver/.skip.MCU_STM32L0 delete mode 100644 tools/build_success.sh (limited to 'src/class') diff --git a/examples/device/lwip_webserver/.skip.MCU_LPC11UXX b/examples/device/lwip_webserver/.skip.MCU_LPC11UXX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/lwip_webserver/.skip.MCU_LPC13XX b/examples/device/lwip_webserver/.skip.MCU_LPC13XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/lwip_webserver/.skip.MCU_NUC121 b/examples/device/lwip_webserver/.skip.MCU_NUC121 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/lwip_webserver/.skip.MCU_STM32L0 b/examples/device/lwip_webserver/.skip.MCU_STM32L0 new file mode 100644 index 000000000..e69de29bb diff --git a/hw/bsp/samg55xplained/samg55xplained.c b/hw/bsp/samg55xplained/samg55xplained.c index a5e145734..66a3d137f 100644 --- a/hw/bsp/samg55xplained/samg55xplained.c +++ b/hw/bsp/samg55xplained/samg55xplained.c @@ -24,13 +24,14 @@ */ #include "sam.h" +#include "bsp/board.h" + #include "peripheral_clk_config.h" #include "hal/include/hal_init.h" #include "hal/include/hpl_usart_sync.h" #include "hpl/pmc/hpl_pmc.h" #include "hal/include/hal_gpio.h" -#include "bsp/board.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk index 2e88cf994..c6b5ce12a 100644 --- a/hw/bsp/spresense/board.mk +++ b/hw/bsp/spresense/board.mk @@ -1,5 +1,4 @@ CFLAGS += \ - -DCONFIG_WCHAR_BUILTIN \ -DCONFIG_HAVE_DOUBLE \ -Dmain=spresense_main \ -pipe \ @@ -14,6 +13,9 @@ CFLAGS += \ -fomit-frame-pointer \ -DCFG_TUSB_MCU=OPT_MCU_CXD56 \ +# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration +CFLAGS += -Wno-error=shadow + SPRESENSE_SDK = $(TOP)/hw/mcu/sony/cxd56/spresense-exported-sdk INC += \ diff --git a/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld b/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld index 7ae8e5960..59e18f375 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld +++ b/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld @@ -55,8 +55,8 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20004000; /* end of "RAM" Ram type memory */ -_Min_Heap_Size = 0x400; /* required amount of heap */ -_Min_Stack_Size = 0x600; /* required amount of stack */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ /* Memories definition */ MEMORY diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index fee54163f..71483364d 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -31,6 +31,8 @@ #include "common/tusb_common.h" #include "device/usbd.h" #include "class/cdc/cdc.h" + +// TODO should not include external files #include "lwip/pbuf.h" #include "netif/ethernet.h" diff --git a/tools/build_all.py b/tools/build_all.py index 97294a9a3..45ae8d4d5 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -1,5 +1,5 @@ import os -import shutil +import glob import sys import subprocess import time @@ -10,9 +10,8 @@ exit_status = 0 total_time = time.monotonic() +# 1st Argument is Example, build all examples if not existed all_examples = [] - -# build all example if input not existed if len(sys.argv) > 1: all_examples.append(sys.argv[1]) else: @@ -22,11 +21,17 @@ else: # TODO update freeRTOS example to work with all boards (only nrf52840 now) all_examples.remove("cdc_msc_hid_freertos") +all_examples.sort() +# 2nd Argument is Board, build all boards if not existed all_boards = [] -for entry in os.scandir("hw/bsp"): - if entry.is_dir(): - all_boards.append(entry.name) +if len(sys.argv) > 2: + all_boards.append(sys.argv[2]) +else: + for entry in os.scandir("hw/bsp"): + if entry.is_dir(): + all_boards.append(entry.name) +all_boards.sort() def build_example(example, board): @@ -35,6 +40,16 @@ def build_example(example, board): return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +def skip_example(example, board): + ex_dir = 'examples/device/' + example + board_mk = 'hw/bsp/{}/board.mk'.format(board) + for skip_file in glob.iglob(ex_dir + '/.skip.MCU_*'): + mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(skip_file).split('.')[2] + with open(board_mk) as mk: + if mcu_cflag in mk.read(): + return 1 + + return 0 build_format = '| {:30} | {:30} | {:9} ' build_separator = '-' * 87 @@ -44,20 +59,27 @@ for example in all_examples: print(build_separator) for board in all_boards: start_time = time.monotonic() - build_result = build_example(example, board) - build_duration = time.monotonic() - start_time - if build_result.returncode == 0: - success = "\033[32msucceeded\033[0m" - success_count += 1 + # Check if board is skipped + if skip_example(example, board): + success = "\033[33mskipped\033[0m " + print((build_format + '| {:.2f}s |').format(example, board, success, 0)) else: - exit_status = build_result.returncode - success = "\033[31mfailed\033[0m " - fail_count += 1 + build_result = build_example(example, board) + + if build_result.returncode == 0: + success = "\033[32msucceeded\033[0m" + success_count += 1 + else: + exit_status = build_result.returncode + success = "\033[31mfailed\033[0m " + fail_count += 1 + + build_duration = time.monotonic() - start_time + print((build_format + '| {:.2f}s |').format(example, board, success, build_duration)) - print((build_format + '| {:.2f}s |').format(example, board, success, build_duration)) - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) + if build_result.returncode != 0: + print(build_result.stdout.decode("utf-8")) # FreeRTOS example # example = 'cdc_msc_hid_freertos' diff --git a/tools/build_success.sh b/tools/build_success.sh deleted file mode 100644 index df725bdce..000000000 --- a/tools/build_success.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Trigger mynewt-tinyusb-example repo each push -curl -s -X POST \ - -H "Content-Type: application/json" \ - -H "Accept: application/json" \ - -H "Travis-API-Version: 3" \ - -H "Authorization: token $TRAVIS_TOKEN" \ - -d '{ "request": { "branch":"master" }}' \ - https://api.travis-ci.com/repo/hathach%2Fmynewt-tinyusb-example/requests \ No newline at end of file -- cgit v1.3.1 From 7f6316dbe1c98d2f00ded0913176a85e871353fa Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Mar 2020 14:22:08 -0400 Subject: Use CRLF on UART. --- examples/device/board_test/src/main.c | 2 +- src/class/cdc/cdc_device.c | 6 +++--- src/class/msc/msc_device.c | 6 +++--- src/common/tusb_common.h | 2 +- src/common/tusb_verify.h | 4 ++-- src/device/usbd_control.c | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/class') diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index 865821745..584ff799d 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -42,7 +42,7 @@ enum { BLINK_UNPRESSED = 1000 }; -#define HELLO_STR "Hello from TinyUSB\n" +#define HELLO_STR "Hello from TinyUSB\r\n" int main(void) { diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f63418dae..14b9a3153 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -335,12 +335,12 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: - TU_LOG2(" Set Line Coding\n"); + TU_LOG2(" Set Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_GET_LINE_CODING: - TU_LOG2(" Get Line Coding\n"); + TU_LOG2(" Get Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; @@ -356,7 +356,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts); + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); tud_control_status(rhport, request); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3ff0eba92..06cc9dbb6 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -407,7 +407,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + TU_LOG2(" SCSI Command: %s\r\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; @@ -480,7 +480,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: - TU_LOG2(" SCSI Data\n"); + TU_LOG2(" SCSI Data\r\n"); //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); // OUT transfer, invoke callback if needed @@ -577,7 +577,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" SCSI Status: %u\n", p_csw->status); + TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); // TU_LOG2_MEM(p_csw, xferred_bytes, 2); // Move to default CMD stage diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 5e6a8bb10..ef232a593 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -222,7 +222,7 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); // Log with debug level 1 #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem -#define TU_LOG1_LOCATION() tu_printf("%s: %d:\n", __PRETTY_FUNCTION__, __LINE__) +#define TU_LOG1_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) // Log with debug level 2 #if CFG_TUSB_DEBUG > 1 diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 1ad6d3fb0..74150d6c5 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -76,8 +76,8 @@ #if CFG_TUSB_DEBUG #include - #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() printf("%s %d: assert failed\n", __func__, __LINE__) + #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) + #define _MESS_FAILED() printf("%s %d: assert failed\r\n", __func__, __LINE__) #else #define _MESS_ERR(_err) #define _MESS_FAILED() diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f0a4cf84a..7c35fe768 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -63,7 +63,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", ep_addr, 0); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, 0); // status direction is reversed to one in the setup packet // Note: Status must always be DATA1 @@ -96,7 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\n", ep_addr, xact_len); + TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\r\n", ep_addr, xact_len); return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -112,7 +112,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo { TU_ASSERT(buffer); - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); -- cgit v1.3.1 From 5e8ff1f7c2887abb5459b0d9d6812e2da437d4d0 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 15 Mar 2020 16:05:45 -0500 Subject: usb RNDIS revision on @pigrew suggestions --- src/class/net/net_device.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index d0d32e909..7bb11d57c 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -198,7 +198,17 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); #if CFG_TUD_NET == OPT_NET_RNDIS - tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)rndis_buf; + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(rndis_buf)); + tud_control_xfer(rhport, request, rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); + } #else (void)rhport; #endif -- cgit v1.3.1 From aafddfe637cf2dadf82075b59b18aad6a722caaa Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 15 Mar 2020 18:32:02 -0500 Subject: following suggestion by @kasjer --- src/class/cdc/cdc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 73eafab07..51c69423e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -413,7 +413,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) && (0 == p_cdc->tx_ff.count) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } // nothing to do with notif endpoint for now -- cgit v1.3.1 From 8a22eba7b4104e037fb10d86edfd9dd97421b156 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Mar 2020 15:24:30 +0700 Subject: add TODO note to remove tud_network_mac_address --- src/class/net/net_device.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/class') diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 71483364d..67cd99933 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -57,6 +57,7 @@ void tud_network_init_cb(void); bool tud_network_recv_cb(struct pbuf *p); // client must provide this: 48-bit MAC address +// TODO removed later since it is not part of tinyusb stack extern const uint8_t tud_network_mac_address[6]; // indicate to network driver that client has finished with the packet provided to network_recv_cb() -- cgit v1.3.1 From 622a6c77a10b3b9278f78c9b597bdfd4efd1dd68 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Fri, 27 Mar 2020 20:30:57 -0500 Subject: usbnet: tweak CDC-ECM after MacOS testing --- examples/device/net_lwip_webserver/src/main.c | 6 +++++- .../device/net_lwip_webserver/src/usb_descriptors.c | 2 +- src/class/net/net_device.c | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index c193aeb0f..fe904e8e8 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -53,7 +53,8 @@ static struct pbuf *received_frame; /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ -const uint8_t tud_network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; +/* it is suggested that the first two bytes are 0x02,0x02 to indicate a link-local address */ +const uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; /* network parameters of this MCU */ static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); @@ -124,8 +125,11 @@ static void init_lwip(void) struct netif *netif = &netif_data; lwip_init(); + + /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ netif->hwaddr_len = sizeof(tud_network_mac_address); memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); + netif->hwaddr[5] ^= 0x01; netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); netif_set_default(netif); diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index c7a8cc767..a4eba205f 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -112,7 +112,7 @@ uint8_t const desc_configuration[] = #if CFG_TUD_NET == OPT_NET_ECM // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), #elif CFG_TUD_NET == OPT_NET_RNDIS // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 7bb11d57c..68520625a 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -63,7 +63,15 @@ typedef struct CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; -#if CFG_TUD_NET == OPT_NET_RNDIS +#if CFG_TUD_NET == OPT_NET_ECM + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static tusb_control_request_t notify = + { + .bmRequestType = 0x21, + .bRequest = 0 /* NETWORK_CONNECTION */, + .wValue = 1 /* Connected */, + .wLength = 0, + }; +#elif CFG_TUD_NET == OPT_NET_RNDIS CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120]; #endif @@ -197,7 +205,15 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_RNDIS +#if CFG_TUD_NET == OPT_NET_ECM + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + notify.wIndex = request->wIndex; + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, (uint8_t *)¬ify, sizeof(notify)); + } +#elif CFG_TUD_NET == OPT_NET_RNDIS if (request->bmRequestType_bit.direction == TUSB_DIR_IN) { rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)rndis_buf; -- cgit v1.3.1 From 55fd9fe392d9aa63c27ba39275c9fd7e5dd37049 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 2 Apr 2020 23:16:28 -0400 Subject: Typo of usbtmc. --- examples/device/usbtmc/src/usbtmc_app.c | 2 +- src/class/usbtmc/usbtmc_device.c | 2 +- src/class/usbtmc/usbtmc_device.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 0e39b4227..8f87a6dca 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -303,7 +303,7 @@ bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) void tud_usbtmc_bulkIn_clearFeature_cb(void) { } -void tud_usmtmc_bulkOut_clearFeature_cb(void) +void tud_usbtmc_bulkOut_clearFeature_cb(void) { tud_usbtmc_start_bus_read(); } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 916422752..92d8d34ef 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -590,7 +590,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - tud_usmtmc_bulkOut_clearFeature_cb(); + tud_usbtmc_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 4c52989c2..e231dd72d 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -69,7 +69,7 @@ void tud_usbtmc_open_cb(uint8_t interface_id); bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usmtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); bool tud_usbtmc_msgBulkIn_complete_cb(void); -- cgit v1.3.1 From bb3bbcc00bfa641d285b28931ceb8bd04c3f7651 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 12 Apr 2020 15:41:18 -0500 Subject: usbnet: OS-agnostic (Windows/Linux/macOS) network driver --- examples/device/net_lwip_webserver/src/main.c | 11 +- .../device/net_lwip_webserver/src/tusb_config.h | 3 +- .../net_lwip_webserver/src/usb_descriptors.c | 61 ++++-- src/class/net/net_device.c | 218 ++++++++++++++------- src/class/net/net_device.h | 2 + src/device/usbd.c | 38 +++- src/device/usbd.h | 12 +- src/tusb_option.h | 5 +- 8 files changed, 237 insertions(+), 113 deletions(-) (limited to 'src/class') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index fe904e8e8..c6af96ea8 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,13 +26,14 @@ */ /* -depending on the value of CFG_TUD_NET (tusb_config.h), this can be a CDC-ECM, RNDIS, or CDC-EEM USB virtual network adapter +depending on the value of CFG_TUD_NET (tusb_config.h), this can be a RNDIS+CDC-ECM or CDC-EEM USB virtual network adapter -CDC-ECM should be valid on Linux and MacOS hosts -RNDIS should be valid on Linux and Windows hosts -CDC-EEM should be valid on Linux hosts +OPT_NET_RNDIS_ECM : RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and MacOS hosts +OPT_NET_EEM : CDC-EEM should be valid on Linux hosts -You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network adapters to emulate. +OPT_NET_RNDIS_ECM should be the best choice, as it makes for a hopefully universal solution. + +You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network option. The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. */ diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 0b40fefab..d8c750d5c 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -79,8 +79,7 @@ #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -//#define CFG_TUD_NET OPT_NET_ECM -#define CFG_TUD_NET OPT_NET_RNDIS +#define CFG_TUD_NET OPT_NET_RNDIS_ECM //#define CFG_TUD_NET OPT_NET_EEM #ifdef __cplusplus diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 6ce36cfef..39c542eca 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -63,13 +63,17 @@ tusb_desc_device_t const desc_device = .idVendor = 0xCafe, .idProduct = USB_PID, - .bcdDevice = 0x0100, + .bcdDevice = 0x0101, .iManufacturer = STRID_MANUFACTURER, .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, +#if CFG_TUD_NET == OPT_NET_EEM .bNumConfigurations = 0x01 +#else + .bNumConfigurations = 0x02 +#endif }; // Invoked when received GET DEVICE DESCRIPTOR @@ -85,16 +89,23 @@ uint8_t const * tud_descriptor_device_cb(void) enum { ITF_NUM_CDC = 0, +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM ITF_NUM_CDC_DATA, +#endif ITF_NUM_TOTAL }; -#if CFG_TUD_NET == OPT_NET_ECM - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) -#elif CFG_TUD_NET == OPT_NET_RNDIS - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) -#elif CFG_TUD_NET == OPT_NET_EEM - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +enum +{ + CONFIG_NUM_DEFAULT = 1, + CONFIG_NUM_ALTERNATE = 2, +}; + +#if CFG_TUD_NET == OPT_NET_EEM + #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +#else + #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) + #define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) #endif #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX @@ -105,30 +116,42 @@ enum #define EPNUM_CDC 2 #endif -uint8_t const desc_configuration[] = +static uint8_t const main_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_DEFAULT, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), -#if CFG_TUD_NET == OPT_NET_ECM - // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), -#elif CFG_TUD_NET == OPT_NET_RNDIS - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM // Interface number, description string index, EP data address (out, in) and size. TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#else + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), #endif }; +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM +static uint8_t const alt_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_ALTERNATE, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), + + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { +#if CFG_TUD_NET == OPT_NET_EEM (void) index; // for multiple configurations - return desc_configuration; + return main_configuration; +#else + return (0 == index) ? main_configuration : alt_configuration; +#endif } //--------------------------------------------------------------------+ @@ -141,8 +164,8 @@ static char const* string_desc_arr [] = [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer [STRID_PRODUCT] = "TinyUSB Device", // Product - [STRID_SERIAL] = "123456", // Serials - [STRID_INTERFACE] = "TinyUSB Network Interface" // CDC-ECM Interface + [STRID_SERIAL] = "123456", // Serial + [STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description // STRID_MAC index is handled separately }; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 68520625a..19bc5d2d6 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -41,39 +41,57 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ typedef struct { uint8_t itf_num; +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM uint8_t ep_notif; + bool ecm_mode; +#endif uint8_t ep_in; uint8_t ep_out; } netd_interface_t; -#if CFG_TUD_NET == OPT_NET_ECM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 0 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL -#elif CFG_TUD_NET == OPT_NET_RNDIS - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - #define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 - #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL +#else + #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 #endif CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; -#if CFG_TUD_NET == OPT_NET_ECM - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static tusb_control_request_t notify = - { - .bmRequestType = 0x21, - .bRequest = 0 /* NETWORK_CONNECTION */, +struct ecm_notify_struct +{ + tusb_control_request_t header; + uint32_t downlink, uplink; +}; + +static const struct ecm_notify_struct ecm_notify_nc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, .wValue = 1 /* Connected */, .wLength = 0, - }; -#elif CFG_TUD_NET == OPT_NET_RNDIS - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120]; -#endif + }, +}; + +static const struct ecm_notify_struct ecm_notify_csc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, + .wLength = 8, + }, + .downlink = 9728000, + .uplink = 9728000, +}; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union +{ + uint8_t rndis_buf[120]; + struct ecm_notify_struct ecm_buf; +} notify; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -95,7 +113,9 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +#endif } //--------------------------------------------------------------------+ @@ -106,6 +126,10 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } +void netd_init_data(void) +{ +} + void netd_reset(uint8_t rhport) { (void) rhport; @@ -113,21 +137,26 @@ void netd_reset(uint8_t rhport) netd_init(); } +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // sanity check the descriptor - TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass); +#if CFG_TUD_NET == OPT_NET_EEM + TU_VERIFY (CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL == itf_desc->bInterfaceSubClass); +#else + _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); +#endif // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); + TU_ASSERT(0 == _netd_itf.ep_notif); - //------------- first Interface -------------// + //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); -#if CFG_TUD_NET != OPT_NET_EEM // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) { @@ -143,18 +172,28 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = tu_desc_next(p_desc); } - //------------- second Interface -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + return true; +} +#endif + +bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_in); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + (*p_length) = sizeof(tusb_desc_interface_t); + + //------------- Data Interface -------------// + while ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor p_desc = tu_desc_next(p_desc); (*p_length) += sizeof(tusb_desc_interface_t); } -#endif if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { @@ -184,18 +223,25 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques // Handle class request only TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) + if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) { - rndis_class_set_handler(rndis_buf, request->wLength); + rndis_class_set_handler(notify.rndis_buf, request->wLength); } #endif return true; } +static void ecm_report(bool nc) +{ + notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; + notify.ecm_buf.header.wIndex = _netd_itf.itf_num; + netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); +} + // Handle class control request // return false to stall control endpoint (e.g unsupported request) bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) @@ -205,28 +251,32 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_ECM - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - notify.wIndex = request->wIndex; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, (uint8_t *)¬ify, sizeof(notify)); - } -#elif CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) +#if CFG_TUD_NET == OPT_NET_EEM + (void)rhport; +#else + if (_netd_itf.ecm_mode) { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)rndis_buf; - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(rndis_buf)); - tud_control_xfer(rhport, request, rndis_buf, msglen); + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } } else { - tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } } -#else - (void)rhport; #endif return true; @@ -244,18 +294,7 @@ static void handle_incoming_packet(uint32_t len) uint8_t *pnt = received; uint32_t size = 0; -#if CFG_TUD_NET == OPT_NET_ECM - size = len; -#elif CFG_TUD_NET == OPT_NET_RNDIS - rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; (void)len; @@ -271,26 +310,45 @@ static void handle_incoming_packet(uint32_t len) pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; size = hdr->length - 4; /* discard the unused CRC-32 */ } +#else + if (_netd_itf.ecm_mode) + { + size = len; + } + else + { + rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + if (len >= sizeof(rndis_data_packet_t)) + if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) + if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) + { + pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; + size = r->DataLength; + } + } #endif + bool accepted = false; + if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - bool accepted = true; if (p) { memcpy(p->payload, pnt, size); p->len = size; accepted = tud_network_recv_cb(p); - } - if (!p || !accepted) - { - /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ - tud_network_recv_renew(); + if (!accepted) pbuf_free(p); } } + + if (!accepted) + { + /* if a buffer was never handled by user code, we must renew on the user's behalf */ + tud_network_recv_renew(); + } } bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -320,6 +378,13 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM + if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) + { + if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); + } +#endif + return true; } @@ -337,7 +402,11 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; +#if CFG_TUD_NET == OPT_NET_EEM len = CFG_TUD_NET_PACKET_PREFIX_LEN; +#else + len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; +#endif data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -347,14 +416,7 @@ void tud_network_xmit(struct pbuf *p) len += q->len; } -#if CFG_TUD_NET == OPT_NET_RNDIS - rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); -#elif CFG_TUD_NET == OPT_NET_EEM +#if CFG_TUD_NET == OPT_NET_EEM struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; @@ -363,6 +425,16 @@ void tud_network_xmit(struct pbuf *p) hdr->bmType = 0; /* EEM Data Packet */ hdr->length = len - sizeof(struct cdc_eem_packet_header); hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ +#else + if (!_netd_itf.ecm_mode) + { + rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); + hdr->DataLength = len - sizeof(rndis_data_packet_t); + } #endif do_in_xfer(transmitted, len); diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..6914ed050 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,8 +73,10 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); +void netd_init_data (void); void netd_reset (uint8_t rhport); bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool netd_open_data (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 2adac429c..9d15ea4a4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -184,21 +184,47 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET +#if CFG_TUD_NET != OPT_NET_EEM + /* RNDIS management interface */ { - .class_code = -#if CFG_TUD_NET == OPT_NET_RNDIS - TUD_RNDIS_ITF_CLASS, -#else - TUSB_CLASS_CDC, + .class_code = TUD_RNDIS_ITF_CLASS, + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_request = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, #endif + /* CDC-ECM management interface; CDC-EEM data interface */ + { + .class_code = TUSB_CLASS_CDC, .init = netd_init, .reset = netd_reset, +#if CFG_TUD_NET == OPT_NET_EEM + .open = netd_open_data, +#else .open = netd_open, +#endif .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, - .sof = NULL + .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ +#if CFG_TUD_NET != OPT_NET_EEM + { + .class_code = TUSB_CLASS_CDC_DATA, + .init = netd_init_data, + .reset = NULL, + .open = netd_open_data, + .control_request = NULL, + .control_complete = NULL, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, +#endif #endif }; diff --git a/src/device/usbd.h b/src/device/usbd.h index 817af20e3..756f5b161 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -342,8 +342,8 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- CDC-ECM -------------// -// Length of template descriptor: 62 bytes -#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7) +// Length of template descriptor: 71 bytes +#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+9+7+7) // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. @@ -358,8 +358,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ /* Endpoint Notification */\ 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ /* Endpoint Out */\ @@ -372,7 +374,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Windows XP */ #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL - #define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS + #define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else /* Windows 7+ */ #define TUD_RNDIS_ITF_CLASS 0xE0 diff --git a/src/tusb_option.h b/src/tusb_option.h index 6e2a2f125..c2394880f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -128,9 +128,8 @@ * \ref CFG_TUD_NET must be defined to one of these * @{ */ #define OPT_NET_NONE 0 ///< No network interface -#define OPT_NET_ECM 1 ///< CDC-ECM -#define OPT_NET_RNDIS 2 ///< RNDIS -#define OPT_NET_EEM 3 ///< CDC-EEM +#define OPT_NET_RNDIS_ECM 1 ///< RNDIS+CDC-ECM +#define OPT_NET_EEM 2 ///< CDC-EEM /** @} */ #ifndef CFG_TUSB_RHPORT0_MODE -- cgit v1.3.1 From 3ef6e33533c533ef52336fae66e784b7d85e612f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 00:59:56 +0700 Subject: use class driver open() for interface support detection tested with dfu_runtime --- examples/device/dfu_rt/src/main.h | 5 -- examples/device/dfu_rt/src/usb_descriptors.c | 71 +--------------------------- src/class/dfu/dfu_rt_device.c | 4 +- src/class/dfu/dfu_rt_device.h | 2 +- src/device/usbd.c | 37 +++++++++++++-- 5 files changed, 38 insertions(+), 81 deletions(-) delete mode 100644 examples/device/dfu_rt/src/main.h (limited to 'src/class') diff --git a/examples/device/dfu_rt/src/main.h b/examples/device/dfu_rt/src/main.h deleted file mode 100644 index 673247ec7..000000000 --- a/examples/device/dfu_rt/src/main.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H -void led_indicator_pulse(void); - -#endif diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index 5cd661b2b..3d900efd9 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -77,92 +77,25 @@ uint8_t const * tud_descriptor_device_cb(void) return (uint8_t const *) &desc_device; } -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ -#if CFG_TUD_HID - -uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) -}; - -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void) -{ - return desc_hid_report; -} - -#endif - //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ enum { -#if CFG_TUD_CDC - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, -#endif - -#if CFG_TUD_MSC - ITF_NUM_MSC, -#endif - -#if CFG_TUD_HID - ITF_NUM_HID, -#endif - -#if CFG_TUD_DFU_RT ITF_NUM_DFU_RT, -#endif - ITF_NUM_TOTAL }; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + \ - CFG_TUD_HID*TUD_HID_DESC_LEN + (CFG_TUD_DFU_RT)*TUD_DFU_RT_DESC_LEN) - -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force - // endpoint number for MSC to 5 - #define EPNUM_MSC 0x05 -#else - #define EPNUM_MSC 0x03 -#endif - +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_RT_DESC_LEN) uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), -#if CFG_TUD_CDC - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 1, 0x81, 8, 0x02, 0x82, 64), -#endif - -#if CFG_TUD_MSC - // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), -#endif - -#if CFG_TUD_HID - // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10), -#endif - -#if CFG_TUD_DFU_RT // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 7, 0x0d, 1000, 4096), -#endif + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), }; diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index ad1871dad..0ef5fe63f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -61,8 +61,8 @@ bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 (void) rhport; // Ensure this is DFU Runtime - TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); - TU_ASSERT(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); + TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 4348a0f3a..294d993e3 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -58,7 +58,7 @@ typedef enum //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); +TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.c b/src/device/usbd.c index c1ef482e2..eea344c3b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -76,8 +76,8 @@ enum { DRVID_INVALID = 0xFFu }; typedef struct { uint8_t class_code; - uint8_t subclass; // 0xFF support all values of subclass - uint8_t protocol; // 0xFF support all values of protocol + uint8_t subclass; + uint8_t protocol; struct TU_ATTR_PACKED { @@ -299,7 +299,7 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); -static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); +//static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); @@ -346,6 +346,9 @@ static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] = #if CFG_TUD_VENDOR "Vendor", #endif + #if CFG_TUD_DFU_RT + "DFU Runtime", + #endif #if CFG_TUD_USBTMC "USBTMC" #endif @@ -823,6 +826,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; +#if 0 // Find driver id for the interface uint8_t drv_id = find_driver_id(desc_itf); TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); @@ -835,8 +839,31 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_LOG2(" %s open\r\n", _usbd_driver_str[drv_id]); TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); +#else + uint8_t drv_id; + uint16_t itf_len; + + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + itf_len = 0; + if ( driver->open(rhport, desc_itf, &itf_len) ) + { + // Interface number must not be used already TODO alternate interface + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); + TU_LOG2(" itf_len = %d \r\n", itf_len); + break; + } + } + + // Assert if cannot find a driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && itf_len >= sizeof(tusb_desc_interface_t) ); +#endif + + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); // TODO refactor p_desc += itf_len; // next interface } @@ -848,6 +875,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } +#if 0 // Helper to find class driver id for an interface // return 0xFF if not found static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) @@ -865,6 +893,7 @@ static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) return DRVID_INVALID; } +#endif // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -- cgit v1.3.1 From 8614dcece7792aab34431156c499f778baafa7c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 01:01:07 +0700 Subject: tested with hid --- src/class/hid/hid_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 7cb35f1ce..ca00cb942 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -160,6 +160,8 @@ void hidd_reset(uint8_t rhport) bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len) { + TU_VERIFY(desc_itf->bInterfaceClass == TUSB_CLASS_HID); + uint8_t const *p_desc = (uint8_t const *) desc_itf; // Find available interface -- cgit v1.3.1 From 7fa8d872916789fc5876c2e6bfae0d5a4d6fe379 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 14 Apr 2020 21:10:43 -0500 Subject: usbnet: remove CDC-EEM --- examples/device/net_lwip_webserver/src/main.c | 9 +-- .../device/net_lwip_webserver/src/tusb_config.h | 3 +- .../net_lwip_webserver/src/usb_descriptors.c | 28 +-------- src/class/net/net_device.c | 69 +--------------------- src/device/usbd.c | 10 +--- src/tusb_option.h | 8 --- 6 files changed, 10 insertions(+), 117 deletions(-) (limited to 'src/class') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 26c6401e6..b672ca3bb 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,14 +26,9 @@ */ /* -depending on the value of CFG_TUD_NET (tusb_config.h), this can be a RNDIS+CDC-ECM or CDC-EEM USB virtual network adapter +this appears as either a RNDIS or CDC-ECM USB virtual network adapter; the OS picks its preference -OPT_NET_RNDIS_ECM : RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and MacOS hosts -OPT_NET_EEM : CDC-EEM should be valid on Linux hosts - -OPT_NET_RNDIS_ECM should be the best choice, as it makes for a hopefully universal solution. - -You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network option. +RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and macOS hosts The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. */ diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index d8c750d5c..a959968bc 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -79,8 +79,7 @@ #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -#define CFG_TUD_NET OPT_NET_RNDIS_ECM -//#define CFG_TUD_NET OPT_NET_EEM +#define CFG_TUD_NET 1 #ifdef __cplusplus } diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 39c542eca..3e61112e2 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -30,7 +30,7 @@ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. * * Auto ProductID layout's Bitmap: - * [MSB] NET1:NET0 | VENDOR | MIDI | HID | MSC | CDC [LSB] + * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] */ #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ @@ -69,11 +69,7 @@ tusb_desc_device_t const desc_device = .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, -#if CFG_TUD_NET == OPT_NET_EEM - .bNumConfigurations = 0x01 -#else .bNumConfigurations = 0x02 -#endif }; // Invoked when received GET DEVICE DESCRIPTOR @@ -89,9 +85,7 @@ uint8_t const * tud_descriptor_device_cb(void) enum { ITF_NUM_CDC = 0, -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM ITF_NUM_CDC_DATA, -#endif ITF_NUM_TOTAL }; @@ -101,12 +95,8 @@ enum CONFIG_NUM_ALTERNATE = 2, }; -#if CFG_TUD_NET == OPT_NET_EEM - #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) -#else - #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) - #define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) -#endif +#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) +#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -121,16 +111,10 @@ static uint8_t const main_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_DEFAULT, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), -#if CFG_TUD_NET == OPT_NET_EEM - // Interface number, description string index, EP data address (out, in) and size. - TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#else // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#endif }; -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM static uint8_t const alt_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA @@ -139,19 +123,13 @@ static uint8_t const alt_configuration[] = // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), }; -#endif // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { -#if CFG_TUD_NET == OPT_NET_EEM - (void) index; // for multiple configurations - return main_configuration; -#else return (0 == index) ? main_configuration : alt_configuration; -#endif } //--------------------------------------------------------------------+ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 19bc5d2d6..777d0da98 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) ) +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) #include "net_device.h" #include "device/usbd_pvt.h" @@ -41,21 +41,14 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ typedef struct { uint8_t itf_num; -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM uint8_t ep_notif; bool ecm_mode; -#endif uint8_t ep_in; uint8_t ep_out; } netd_interface_t; -#if CFG_TUD_NET == OPT_NET_EEM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 -#else - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 -#endif +#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) +#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; @@ -113,9 +106,7 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); -#endif } //--------------------------------------------------------------------+ @@ -137,16 +128,11 @@ void netd_reset(uint8_t rhport) netd_init(); } -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // sanity check the descriptor -#if CFG_TUD_NET == OPT_NET_EEM - TU_VERIFY (CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL == itf_desc->bInterfaceSubClass); -#else _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); -#endif // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_notif); @@ -176,7 +162,6 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t return true; } -#endif bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { @@ -223,14 +208,12 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques // Handle class request only TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM TU_VERIFY (_netd_itf.itf_num == request->wIndex); if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) { rndis_class_set_handler(notify.rndis_buf, request->wLength); } -#endif return true; } @@ -251,9 +234,6 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_EEM - (void)rhport; -#else if (_netd_itf.ecm_mode) { /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ @@ -277,40 +257,15 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); } } -#endif return true; } -struct cdc_eem_packet_header -{ - uint16_t length:14; - uint16_t bmCRC:1; - uint16_t bmType:1; -}; - static void handle_incoming_packet(uint32_t len) { uint8_t *pnt = received; uint32_t size = 0; -#if CFG_TUD_NET == OPT_NET_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; - - (void)len; - - if (hdr->bmType) - { - /* EEM Control Packet: discard it */ - tud_network_recv_renew(); - } - else - { - /* EEM Data Packet */ - pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; - size = hdr->length - 4; /* discard the unused CRC-32 */ - } -#else if (_netd_itf.ecm_mode) { size = len; @@ -326,7 +281,6 @@ static void handle_incoming_packet(uint32_t len) size = r->DataLength; } } -#endif bool accepted = false; @@ -378,12 +332,10 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) { if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); } -#endif return true; } @@ -402,11 +354,7 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; -#if CFG_TUD_NET == OPT_NET_EEM - len = CFG_TUD_NET_PACKET_PREFIX_LEN; -#else len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; -#endif data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -416,16 +364,6 @@ void tud_network_xmit(struct pbuf *p) len += q->len; } -#if CFG_TUD_NET == OPT_NET_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; - /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ - data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; - /* adjust length to reflect added fake CRC-32 */ - len += 4; - hdr->bmType = 0; /* EEM Data Packet */ - hdr->length = len - sizeof(struct cdc_eem_packet_header); - hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ -#else if (!_netd_itf.ecm_mode) { rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; @@ -435,7 +373,6 @@ void tud_network_xmit(struct pbuf *p) hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); hdr->DataLength = len - sizeof(rndis_data_packet_t); } -#endif do_in_xfer(transmitted, len); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 9d15ea4a4..651cbbc7d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -184,7 +184,6 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET -#if CFG_TUD_NET != OPT_NET_EEM /* RNDIS management interface */ { .class_code = TUD_RNDIS_ITF_CLASS, @@ -196,24 +195,18 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif - /* CDC-ECM management interface; CDC-EEM data interface */ + /* CDC-ECM management interface */ { .class_code = TUSB_CLASS_CDC, .init = netd_init, .reset = netd_reset, -#if CFG_TUD_NET == OPT_NET_EEM - .open = netd_open_data, -#else .open = netd_open, -#endif .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, .sof = NULL, }, /* RNDIS/CDC-ECM data interface */ -#if CFG_TUD_NET != OPT_NET_EEM { .class_code = TUSB_CLASS_CDC_DATA, .init = netd_init_data, @@ -224,7 +217,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif #endif }; diff --git a/src/tusb_option.h b/src/tusb_option.h index c2394880f..0826a5aab 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -124,14 +124,6 @@ #define OPT_MODE_HIGH_SPEED 0x10 ///< High speed /** @} */ -/** \defgroup group_supported_netif Supported Network Interface - * \ref CFG_TUD_NET must be defined to one of these - * @{ */ -#define OPT_NET_NONE 0 ///< No network interface -#define OPT_NET_RNDIS_ECM 1 ///< RNDIS+CDC-ECM -#define OPT_NET_EEM 2 ///< CDC-EEM -/** @} */ - #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif -- cgit v1.3.1 From bae570f7c7ab16fcd727dde7e41bd182ade18d71 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 01:01:31 +0700 Subject: tested with midi --- src/class/midi/midi_device.c | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index ae6e3afe1..6eb522380 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -253,21 +253,31 @@ void midid_reset(uint8_t rhport) } } -bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length) +bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length) { - // For now handle the audio control interface as well. - if ( AUDIO_SUBCLASS_CONTROL == p_interface_desc->bInterfaceSubClass) { - uint8_t const * p_desc = tu_desc_next ( (uint8_t const *) p_interface_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); - // Skip over the class specific descriptor. - (*p_length) += tu_desc_len(p_desc); + // 1st Interface is Audio Control v1 + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol); + + uint16_t drv_len = tu_desc_len(desc_itf); + uint8_t const * p_desc = tu_desc_next(desc_itf); + + // Skip Class Specific descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + { + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - return true; } - TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == p_interface_desc->bInterfaceSubClass && - AUDIO_PROTOCOL_V1 == p_interface_desc->bInterfaceProtocol ); + // 2nd Interface is MIDI Streaming + TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; + + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol ); // Find available interface midid_interface_t * p_midi = NULL; @@ -280,13 +290,15 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, } } - p_midi->itf_num = p_interface_desc->bInterfaceNumber; + p_midi->itf_num = desc_midi->bInterfaceNumber; - uint8_t const * p_desc = tu_desc_next( (uint8_t const *) p_interface_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + // next descriptor + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + // Find and open endpoint descriptors uint8_t found_endpoints = 0; - while (found_endpoints < p_interface_desc->bNumEndpoints) + while (found_endpoints < desc_midi->bNumEndpoints) { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { @@ -298,14 +310,16 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, p_midi->ep_out = ep_addr; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += p_desc[DESC_OFFSET_LEN]; p_desc = tu_desc_next(p_desc); found_endpoints += 1; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += p_desc[DESC_OFFSET_LEN]; p_desc = tu_desc_next(p_desc); } + *p_length = drv_len; + // Prepare for incoming data TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); -- cgit v1.3.1 From e713b534fa563509cad81807fbe11937dfcca8fb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 10:30:34 +0700 Subject: test ok with cdc and msc --- src/class/cdc/cdc_device.c | 8 ++++---- src/class/hid/hid_device.c | 2 +- src/class/msc/msc_device.c | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 14b9a3153..04c73da78 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -223,11 +223,11 @@ void cdcd_reset(uint8_t rhport) bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // Only support ACM subclass - TU_ASSERT ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); - // Only support AT commands, no protocol and vendor specific commands. - TU_ASSERT(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - itf_desc->bInterfaceProtocol == 0xff); + // Note: 0xFF can be used with RNDIS + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA)); // Find available interface cdcd_interface_t * p_cdc = NULL; diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ca00cb942..cbdc5bece 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -160,7 +160,7 @@ void hidd_reset(uint8_t rhport) bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len) { - TU_VERIFY(desc_itf->bInterfaceClass == TUSB_CLASS_HID); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); uint8_t const *p_desc = (uint8_t const *) desc_itf; diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 06cc9dbb6..68f5587fd 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -157,7 +157,8 @@ void mscd_reset(uint8_t rhport) bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) { // only support SCSI's BOT protocol - TU_ASSERT(MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && + TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && + MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); mscd_interface_t * p_msc = &_mscd_itf; -- cgit v1.3.1 From c1c9ca5629270e545c54d5e2983b77a5c3821a4e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 10:37:31 +0700 Subject: test with tmc --- src/class/usbtmc/usbtmc_device.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 92d8d34ef..abe26ced3 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -263,17 +263,19 @@ void usbtmcd_init_cb(void) bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { (void)rhport; - TU_ASSERT(usbtmc_state.state == STATE_CLOSED); uint8_t const * p_desc; uint8_t found_endpoints = 0; + TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); + #ifndef NDEBUG - TU_ASSERT(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); - TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); // Only 2 or 3 endpoints are allowed for USBTMC. TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); #endif + TU_ASSERT(usbtmc_state.state == STATE_CLOSED); + // Interface (*p_length) = 0u; p_desc = (uint8_t const *) itf_desc; -- cgit v1.3.1 From 490771a094baaa9ead60c7ea2e7c4a594d322825 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 10:39:01 +0700 Subject: test vendor --- src/class/vendor/vendor_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/class') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8db5005f4..7f2fe9793 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -168,6 +168,8 @@ void vendord_reset(uint8_t rhport) bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) { + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass); + // Find available interface vendord_interface_t* p_vendor = NULL; for(uint8_t i=0; i Date: Wed, 15 Apr 2020 11:41:26 +0700 Subject: tested usbnet, completely remove class code --- src/class/net/net_device.c | 17 ++++++++++++++--- src/device/usbd.c | 18 ++---------------- 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 777d0da98..8d0cb5d37 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -130,13 +130,22 @@ void netd_reset(uint8_t rhport) bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { - // sanity check the descriptor - _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); - TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); + bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && + TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); + + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); + + TU_VERIFY ( is_rndis || is_ecm ); // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_notif); + // sanity check the descriptor + _netd_itf.ecm_mode = is_ecm; + //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; @@ -165,6 +174,8 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { + TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); + // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_in); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4db6cd671..0f60117ee 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,11 +190,6 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_NET /* RNDIS management interface */ { -// .class_code = TUD_RNDIS_ITF_CLASS, -// .subclass = TUD_RNDIS_ITF_SUBCLASS, -// .protocol = TUD_RNDIS_ITF_PROTOCOL, -// .all_subclass = 0, -// .all_protocol = 0, DRIVER_NAME("RNDIS") .init = netd_init, .reset = netd_reset, @@ -204,14 +199,9 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* CDC-ECM management interface */ { -// .class_code = TUSB_CLASS_CDC, -// .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, -// .protocol = 0x00, -// .all_subclass = 0, -// .all_protocol = 0, - DRIVER_NAME("CDC-ECM") .init = netd_init, .reset = netd_reset, @@ -221,13 +211,9 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ { -// .class_code = TUSB_CLASS_CDC_DATA, -// .subclass = 0x00, -// .protocol = 0x00, -// .all_subclass = 0, -// .all_protocol = 0, DRIVER_NAME("CDC-DATA") .init = netd_init_data, .reset = NULL, -- cgit v1.3.1 From b03b9eb93991c561610a01c379154e7db55e9f4b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 15:14:26 +0700 Subject: change cdc template protocol to None --- src/class/cdc/cdc_host.c | 2 +- src/device/usbd.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 595e7fd62..5e45e8f6b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -86,7 +86,7 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) { // TODO consider all AT Command as serial candidate return tuh_cdc_mounted(dev_addr) && - (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) && + (CDC_COMM_PROTOCOL_NONE <= cdch_data[dev_addr-1].itf_protocol) && (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); } diff --git a/src/device/usbd.h b/src/device/usbd.h index 7b04ef9a7..acefb6943 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -183,9 +183,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, 0,\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ /* CDC Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC Call */\ -- cgit v1.3.1 From d315393fbb39ab6a70ea2c636d28305d9777ff97 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 16:18:24 +0700 Subject: use IAD to assign itf2drv mapping correctly merge net_data back into net driver --- src/class/cdc/cdc_device.c | 4 +- src/class/net/net_device.c | 30 ++++----------- src/class/net/net_device.h | 2 - src/device/usbd.c | 92 ++++++++++++++++++++++------------------------ 4 files changed, 53 insertions(+), 75 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 04c73da78..95b14ba54 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -262,12 +262,12 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8d0cb5d37..8bbce2305 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -117,10 +117,6 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } -void netd_init_data(void) -{ -} - void netd_reset(uint8_t rhport) { (void) rhport; @@ -166,32 +162,21 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } - return true; -} - -bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) -{ - TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); - //------------- Data Interface -------------// - while ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // TODO extract Alt Interface 0 & 1 + while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - (*p_length) += sizeof(tusb_desc_interface_t); } - if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); @@ -207,6 +192,7 @@ bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint // prepare for incoming packets tud_network_recv_renew(); + return true; } diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 6914ed050..67cd99933 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,10 +73,8 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); -void netd_init_data (void); void netd_reset (uint8_t rhport); bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool netd_open_data (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4587a2cc7..ad5a32f92 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -188,9 +188,8 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET - /* RNDIS management interface */ { - DRIVER_NAME("RNDIS") + DRIVER_NAME("NET") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -199,30 +198,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, - - /* CDC-ECM management interface */ - { - DRIVER_NAME("CDC-ECM") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_request = netd_control_request, - .control_complete = netd_control_complete, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - - /* RNDIS/CDC-ECM data interface */ - { - DRIVER_NAME("CDC-DATA") - .init = netd_init_data, - .reset = NULL, - .open = netd_open_data, - .control_request = NULL, - .control_complete = NULL, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, #endif }; @@ -611,9 +586,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_SET_INTERFACE: { uint8_t const alternate = (uint8_t) p_request->wValue; + (void) alternate; // TODO not support alternate interface yet - TU_ASSERT(alternate == 0); +// TU_ASSERT(alternate == 0); tud_control_status(rhport, p_request); } break; @@ -727,41 +703,59 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - // Each interface always starts with Interface or Association descriptor + tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + + // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - p_desc = tu_desc_next(p_desc); // ignore Interface Association - }else - { - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to Interface + } - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - uint8_t drv_id; - uint16_t drv_len; + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint8_t drv_id; + uint16_t drv_len; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + drv_len = 0; + if ( driver->open(rhport, desc_itf, &drv_len) ) { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + // If IAD exist, assign all interfaces to the same driver + if (desc_itf_assoc) { - // Interface number must not be used already TODO alternate interface - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - break; + // IAD's first interface number and class/subclass/protocol should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && + desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && + desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + + for(uint8_t i=1; ibInterfaceCount; i++) + { + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; + } } + + break; } + } - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + // Assert if cannot find supported driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor - p_desc += drv_len; // next interface - } + p_desc += drv_len; // next interface } // invoke callback -- cgit v1.3.1 From caa1dceed97d841ca4176d96e324de976948f327 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 17:51:02 +0700 Subject: implement alternate setInterface() request mostly forward these request (recipient = interface) to class driver. --- src/class/net/net_device.c | 158 +++++++++++++++++++++++++++++++++------------ src/device/usbd.c | 37 +---------- 2 files changed, 118 insertions(+), 77 deletions(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8bbce2305..575a15edd 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -40,11 +40,20 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_num; + uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface + uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active + uint8_t ep_notif; - bool ecm_mode; uint8_t ep_in; uint8_t ep_out; + + bool ecm_mode; + + // Endpoint descriptor use to open/close when receving SetInterface + // TODO since configuration descriptor may not be long-lived memory, we should + // keep a copy of endpoint attribute instead + uint8_t const * ecm_desc_epdata; + } netd_interface_t; #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) @@ -145,8 +154,8 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; - uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) @@ -167,31 +176,44 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t } //------------- Data Interface -------------// - // TODO extract Alt Interface 0 & 1 - while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // - RNDIS Data followed immediately by a pair of endpoints + // - CDC-ECM data interface has 2 alternate settings + // - 0 : zero endpoints for inactive (default) + // - 1 : IN & OUT endpoints for active networking + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + + do { - // next to endpoint descriptor + tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass); + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - } + }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) ); - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) + // Pair of endpoints + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); + + if ( _netd_itf.ecm_mode ) + { + // ECM by default is in-active, save the endpoint attribute + // to open later when received setInterface + _netd_itf.ecm_desc_epdata = p_desc; + }else { - // Open endpoint pair + // Open endpoint pair for RNDIS TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - (*p_length) += 2*sizeof(tusb_desc_endpoint_t); - } + tud_network_init_cb(); - tud_network_init_cb(); + // we are ready to transmit a packet + can_xmit = true; - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); + // prepare for incoming packets + tud_network_recv_renew(); + } + (*p_length) += 2*sizeof(tusb_desc_endpoint_t); return true; } @@ -226,33 +248,83 @@ static void ecm_report(bool nc) // return false to stall control endpoint (e.g unsupported request) bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) + { + case TUSB_REQ_GET_INTERFACE: + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + break; + + case TUSB_REQ_SET_INTERFACE: + { + // Request to enable/disable network activities on ACM-ECM only + TU_ASSERT(_netd_itf.ecm_mode); + + _netd_itf.itf_data_alt = (uint8_t) request->wValue; + + if ( _netd_itf.itf_data_alt ) + { + // TODO since we don't actually close endpoint + // hack here to not re-open it + if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + { + TU_ASSERT(_netd_itf.ecm_desc_epdata); + TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + // TODO should have opposite callback for application to disable network !! + tud_network_init_cb(); + can_xmit = true; // we are ready to transmit a packet + tud_network_recv_renew(); // prepare for incoming packets + } + }else + { + // TODO close the endpoint pair + // For now pretend that we did, this should have no harm since host won't try to + // communicate with the endpoints again + // _netd_itf.ep_in = _netd_itf.ep_out = 0 + } + + tud_control_status(rhport, request); + } + break; - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + // unsupported request + default: return false; + } + break; - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, msglen); - } - else - { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); - } + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + + if (_netd_itf.ecm_mode) + { + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } + } + else + { + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } + } + break; + + // unsupported request + default: return false; } return true; diff --git a/src/device/usbd.c b/src/device/usbd.c index ad5a32f92..1df850165 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -571,40 +571,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const drvid = _usbd_dev.itf2drv[itf]; TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - // TODO not support alternate interface yet - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const alternate = (uint8_t) p_request->wValue; - (void) alternate; - - // TODO not support alternate interface yet -// TU_ASSERT(alternate == 0); - tud_control_status(rhport, p_request); - } - break; - - default: - // forward to class driver: "STD request to Interface" - // GET HID REPORT DESCRIPTOR falls into this case - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); - break; - } - }else - { - // forward to class driver: "non-STD request to Interface" - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); - } + // all requests to Interface (STD or Class) is forwarded to class driver. + // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE + TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); } break; -- cgit v1.3.1 From 86ff5651ad94b6134aca0805b48d255da4786eef Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 23:10:52 +0700 Subject: correct usbnet control complete response don't return false with STD request get/setInterface() or targeted Data Interface (itfnum +1) --- src/class/net/net_device.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 575a15edd..8cb2e2e0b 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -224,14 +224,15 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques { (void) rhport; - // Handle class request only - TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - TU_VERIFY (_netd_itf.itf_num == request->wIndex); - - if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) + // Handle RNDIS class control OUT only + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.direction == TUSB_DIR_OUT && + _netd_itf.itf_num == request->wIndex) { - rndis_class_set_handler(notify.rndis_buf, request->wLength); + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } } return true; @@ -259,9 +260,14 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request case TUSB_REQ_SET_INTERFACE: { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + // Request to enable/disable network activities on ACM-ECM only TU_ASSERT(_netd_itf.ecm_mode); + // Only valid for Data Interface + TU_ASSERT(_netd_itf.itf_num+1 == req_itfnum); + _netd_itf.itf_data_alt = (uint8_t) request->wValue; if ( _netd_itf.itf_data_alt ) @@ -273,7 +279,8 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_ASSERT(_netd_itf.ecm_desc_epdata); TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - // TODO should have opposite callback for application to disable network !! + // TODO should be merge with RNDIS's after endpoint opened + // Also should have opposite callback for application to disable network !! tud_network_init_cb(); can_xmit = true; // we are ready to transmit a packet tud_network_recv_renew(); // prepare for incoming packets -- cgit v1.3.1 From 2eed58d0962849014ab3166d4a3f0d3677d32c01 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 11:13:54 +0700 Subject: per review --- src/class/net/net_device.c | 16 +++++++++++----- src/device/usbd.c | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8cb2e2e0b..0f2ccbd44 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -255,20 +255,26 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } break; case TUSB_REQ_SET_INTERFACE: { uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; - // Request to enable/disable network activities on ACM-ECM only - TU_ASSERT(_netd_itf.ecm_mode); + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - // Only valid for Data Interface - TU_ASSERT(_netd_itf.itf_num+1 == req_itfnum); + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); - _netd_itf.itf_data_alt = (uint8_t) request->wValue; + _netd_itf.itf_data_alt = req_alt; if ( _netd_itf.itf_data_alt ) { diff --git a/src/device/usbd.c b/src/device/usbd.c index cf16b28c8..29845ff36 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -575,8 +575,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE if ( !invoke_class_control(rhport, drvid, p_request) ) { - // For STD GET_INTERFACE even if class driver doesn't support alternate setting - // It is still mandatory to response with value of zero + // For GET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings. TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && TUSB_REQ_GET_INTERFACE == p_request->bRequest); -- cgit v1.3.1 From 4571ce0d29398089cf6615515190a70ff9be2361 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 15:54:20 +0700 Subject: add a bit of document for cdc device API. also improve cdc write flush when complete. --- changelog.md | 4 ++++ src/class/cdc/cdc_device.c | 34 ++++++++++++++++++++++------------ src/class/cdc/cdc_device.h | 46 ++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 20 deletions(-) (limited to 'src/class') diff --git a/changelog.md b/changelog.md index 807b4dc3a..59af2ea74 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,10 @@ - All default IRQ Handler is renamed to `dcd_int_handler()` +### Others + +- tud_cdc_n_write_flush() return number of bytes forced to transfer instead of bool + ## 0.6.0 - 2019.03.30 Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to [Nathan Conrad](https://github.com/pigrew), [Peter Lawrence](https://github.com/majbthrd) and [William D. Jones](https://github.com/cr1901) and others for spending their precious time to add lots of features and ports for this release. diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f669cfa51..c03c714ce 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -157,10 +157,12 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) return ret; } -bool tud_cdc_n_write_flush (uint8_t itf) +uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete + + // skip if previous transfer not complete yet + TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); if ( count ) @@ -169,7 +171,7 @@ bool tud_cdc_n_write_flush (uint8_t itf) TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) ); } - return true; + return count; } uint32_t tud_cdc_n_write_available (uint8_t itf) @@ -376,16 +378,16 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ (void) rhport; (void) result; - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; + uint8_t itf; + cdcd_interface_t* p_cdc; // Identify which interface to use - for ( ; ; itf++, p_cdc++) + for (itf = 0; itf < CFG_TUD_CDC; itf++) { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - + p_cdc = &_cdcd_itf[itf]; if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; } + TU_ASSERT(itf < CFG_TUD_CDC); // Received new data if ( ep_addr == p_cdc->ep_out ) @@ -408,12 +410,20 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ _prep_out_transaction(itf); } - // Data sent to host, we could continue to fetch data tx fifo to send. - // But it will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! + // Data sent to host, we continue to fetch from tx fifo to send. + // Note: This will cause incorrect baudrate set in line coding. + // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) && (0 == p_cdc->tx_ff.count) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + if ( 0 == tud_cdc_n_write_flush(itf) ) + { + // There is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + } + } } // nothing to do with notif endpoint for now diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 969ec7f99..1db196c7b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -48,28 +48,58 @@ * @{ */ //--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) +// Application API (Multiple Ports) // CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ + + +// Check if terminal is connected to this port bool tud_cdc_n_connected (uint8_t itf); + +// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) uint8_t tud_cdc_n_get_line_state (uint8_t itf); + +// Get current line encoding: bit rate, stop bits parity etc .. void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); + +// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); +// Get the number of bytes available for reading uint32_t tud_cdc_n_available (uint8_t itf); + +// Read received bytes uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); + +// Read a byte, return -1 if there is none +static inline +int32_t tud_cdc_n_read_char (uint8_t itf); + +// Clear the received FIFO void tud_cdc_n_read_flush (uint8_t itf); + +// Get a byte from FIFO at the specified position without revmoing it bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); -static inline int32_t tud_cdc_n_read_char (uint8_t itf); +// Write bytes to TX FIFO, data may remain in the FIFO for a while uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -bool tud_cdc_n_write_flush (uint8_t itf); + +// Write a byte +static inline +uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); + +// Write a nul-terminated string +static inline +uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); + +// Force sending data if possible, return number of forced bytes +uint32_t tud_cdc_n_write_flush (uint8_t itf); + +// Return number of characters available for writing uint32_t tud_cdc_n_write_available (uint8_t itf); -static inline uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); -static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); //--------------------------------------------------------------------+ -// Application API (Interface0) +// Application API (Single Port) //--------------------------------------------------------------------+ static inline bool tud_cdc_connected (void); static inline uint8_t tud_cdc_get_line_state (void); @@ -85,7 +115,7 @@ static inline bool tud_cdc_peek (int pos, uint8_t* u8); static inline uint32_t tud_cdc_write_char (char ch); static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_cdc_write_str (char const* str); -static inline bool tud_cdc_write_flush (void); +static inline uint32_t tud_cdc_write_flush (void); static inline uint32_t tud_cdc_write_available (void); //--------------------------------------------------------------------+ @@ -183,7 +213,7 @@ static inline uint32_t tud_cdc_write_str (char const* str) return tud_cdc_n_write_str(0, str); } -static inline bool tud_cdc_write_flush (void) +static inline uint32_t tud_cdc_write_flush (void) { return tud_cdc_n_write_flush(0); } -- cgit v1.3.1 From 464b1e8e890866984c85505782540bd32e877581 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 15:57:24 +0700 Subject: correct return for write flush --- src/class/cdc/cdc_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index c03c714ce..3c7118f13 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -167,8 +167,8 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); if ( count ) { - TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) ); + TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected + TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); } return count; -- cgit v1.3.1 From ce6a81e74d806844f3a705c137dd5c4febbf891a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 22:10:31 +0700 Subject: fix typo --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 1db196c7b..69542a3b3 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -78,7 +78,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf); // Clear the received FIFO void tud_cdc_n_read_flush (uint8_t itf); -// Get a byte from FIFO at the specified position without revmoing it +// Get a byte from FIFO at the specified position without removing it bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); // Write bytes to TX FIFO, data may remain in the FIFO for a while -- cgit v1.3.1 From a0598ef3699c1b502a499d76c26bd48d48355384 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 19 Apr 2020 11:44:15 +0200 Subject: MIDI - Add flow control to incoming packet stream Larger SysEx transfers get corrupted by incoming packets. This changes the FIFOs not to overwrite their data. MIDI should not be a transport that drops packets. A potentially blocking device is easier to detect and handle than a device that silently corrupts the packet stream at random overflows, especially when SysEx messages are involved. --- src/class/midi/midi_device.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 56a27fbce..589d0123f 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -85,6 +85,18 @@ bool tud_midi_n_mounted (uint8_t itf) return midi->ep_in && midi->ep_out; } +static void _prep_out_transaction (midid_interface_t* p_midi) +{ + // skip if previous transfer not complete + if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) + return; + + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t max_read = tu_fifo_remaining(&p_midi->rx_ff); + if ( max_read >= CFG_TUD_MIDI_EPSIZE ) + usbd_edpt_xfer(TUD_OPT_RHPORT, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE); +} + //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -138,11 +150,17 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) { (void) jack_id; tu_fifo_clear(&_midid_itf[itf].rx_ff); + + if (tud_ready() && &_midid_itf[itf].ep_out != 0) + _prep_out_transaction(&_midid_itf[itf]); } bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) { - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); + if (tud_ready() && &_midid_itf[itf].ep_out != 0) + _prep_out_transaction(&_midid_itf[itf]); + + return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4) == 4; } void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { @@ -267,8 +285,8 @@ void midid_init(void) midid_interface_t* midi = &_midid_itf[i]; // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); + tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); @@ -358,7 +376,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length = drv_len; // Prepare for incoming data - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); + _prep_out_transaction(p_midi); return true; } @@ -381,6 +399,7 @@ bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_requ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) rhport; (void) result; uint8_t itf = 0; @@ -399,7 +418,8 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); + _prep_out_transaction(p_midi); + } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } -- cgit v1.3.1 From d57312602dd9aadc47ae8eae943f51b585e0a228 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 Apr 2020 16:09:17 +0700 Subject: add extra comma to HID_REPORT_ID this make the template with Report ID look less weird to the user --- examples/device/hid_composite/src/usb_descriptors.c | 4 ++-- src/class/hid/hid.h | 4 ++-- src/class/hid/hid_device.h | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 6bde2ff7a..02cbc17f6 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -73,8 +73,8 @@ uint8_t const * tud_descriptor_device_cb(void) uint8_t const desc_hid_report[] = { - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) + TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD) ), + TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE) ) }; // Invoked when received GET HID REPORT DESCRIPTOR diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 848274037..8803e4b66 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -413,8 +413,8 @@ enum { #define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1) #define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n) -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n) +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n), #define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1) #define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f5e29d8a2..efdde9569 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -93,17 +93,17 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); * HID Report Descriptor Template * * Convenient for declaring popular HID device (keyboard, mouse, consumer, - * gamepad etc...). Templates take "HID_REPORT_ID(n)," as input, leave + * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave * empty if multiple reports is not used * * - Only 1 report: no parameter * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; * - * - Multiple Reports: "HID_REPORT_ID(ID)," must be passed to template + * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template * uint8_t const report_desc[] = * { - * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1), ) , - * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2), ) + * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , + * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) * }; *--------------------------------------------------------------------*/ -- cgit v1.3.1 From 3b83813f017dfd08e19a7a3bc2dc575779b1eadd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Apr 2020 00:25:08 +0700 Subject: clean up --- .github/ISSUE_TEMPLATE/bug_report.md | 13 ++++++++----- .github/ISSUE_TEMPLATE/feature_request.md | 7 +++++-- .github/ISSUE_TEMPLATE/question.md | 2 +- README.md | 4 ---- src/class/midi/midi_device.c | 5 +++-- 5 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c4d2757d2..5c70569d0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,17 +7,20 @@ assignees: '' --- -**Set up (mandatory):** -Provide details of your setup help us to reproduce the issue as quick as possible +**Set up** +[Mandatory] Provide details of your setup help us to reproduce the issue as quick as possible - **PC OS** : Ubuntu 18.04 / Windows 10/ macOS 10.15 - **Board** : Feather nRF52840 Express - **Firmware**: examples/device/cdc_msc -**Bug Description** -Describe what the bug is. +**Describe the bug** +A clear and concise description of what the bug is. -**Reproduce** +**To reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. See error + +**Log & screenshots** +If applicable, add screenshots and TinyUSB's log to help explain your problem. To enable logging, add `LOG=2` to your make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index cb211eeb4..f34ff49ed 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,5 +7,8 @@ assignees: '' --- -**Feature Description** -Describe your feature +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 3a9fd205c..d12c9785d 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -7,4 +7,4 @@ assignees: '' --- -**Question Description** +**Describe what the question is** diff --git a/README.md b/README.md index a8a533fd4..a7551155d 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,6 @@ TinyUSB is completely thread-safe by pushing all ISR events into a central queue - **FreeRTOS** - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example) -## Compiler & IDE - -The stack is developed with GCC compiler and should be compilable with others. The `examples` folder provides Makefile and Segger Embedded Studio build support. [Here are example build instructions](examples/readme.md). - ## Getting Started [Here are the details for getting started](docs/getting_started.md) with the stack. diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 589d0123f..f8db63b73 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -88,13 +88,14 @@ bool tud_midi_n_mounted (uint8_t itf) static void _prep_out_transaction (midid_interface_t* p_midi) { // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) - return; + if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) return; // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_midi->rx_ff); if ( max_read >= CFG_TUD_MIDI_EPSIZE ) + { usbd_edpt_xfer(TUD_OPT_RHPORT, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE); + } } //--------------------------------------------------------------------+ -- cgit v1.3.1 From 10e035241f0ea4bf8604fab2556fd65be16137b9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Apr 2020 23:04:21 +0700 Subject: house keeping --- examples/readme.md | 4 ++-- src/class/msc/msc_device.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/examples/readme.md b/examples/readme.md index 8d3d2e415..1c85214e9 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -52,8 +52,8 @@ By default log message is printed via on-board UART which is slow and take lots - Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package. - `LOGGER=swo`: Use dedicated SWO pin of ARM Cortex SWD debug header. - Cons: only work with ARM Cortex MCUs minus M0 - - Pros: even faster than RTT, and should be compatible with hardware and software debugger that support SWO. - - Software viewer is JLink SWO Viewer which is also bundled with JLink driver package. + - Pros: should be compatible with more debugger that support SWO. + - Software viewer should be provided along with your debugger driver. ``` $ make LOG=2 LOGGER=rtt BOARD=feather_nrf52840_express all diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 68f5587fd..70ba956aa 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -605,6 +605,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t else { // Invoke complete callback if defined + // Note: There is racing issue with samd51 + qspi flash testing with arduino + // if complete_cb() is invoked after queuing the status. switch(p_cbw->command[0]) { case SCSI_CMD_READ_10: -- cgit v1.3.1 From c59fa774274b13790a3ae0fc19d9651eeba560ab Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Apr 2020 23:25:20 +0700 Subject: Revert "Merge pull request #359 from versioduo/midi-flow-control" This reverts commit 1d33aa9b6f7940f9eac07ce684515856940175da, reversing changes made to 718db7e5369df57b0f49a563737e6e0446fd4c4d. --- src/class/midi/midi_device.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index f8db63b73..56a27fbce 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -85,19 +85,6 @@ bool tud_midi_n_mounted (uint8_t itf) return midi->ep_in && midi->ep_out; } -static void _prep_out_transaction (midid_interface_t* p_midi) -{ - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) return; - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_midi->rx_ff); - if ( max_read >= CFG_TUD_MIDI_EPSIZE ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE); - } -} - //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -151,17 +138,11 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) { (void) jack_id; tu_fifo_clear(&_midid_itf[itf].rx_ff); - - if (tud_ready() && &_midid_itf[itf].ep_out != 0) - _prep_out_transaction(&_midid_itf[itf]); } bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) { - if (tud_ready() && &_midid_itf[itf].ep_out != 0) - _prep_out_transaction(&_midid_itf[itf]); - - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4) == 4; + return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); } void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { @@ -286,8 +267,8 @@ void midid_init(void) midid_interface_t* midi = &_midid_itf[i]; // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); + tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); @@ -377,7 +358,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length = drv_len; // Prepare for incoming data - _prep_out_transaction(p_midi); + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); return true; } @@ -400,7 +381,6 @@ bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_requ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) rhport; (void) result; uint8_t itf = 0; @@ -419,8 +399,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next - _prep_out_transaction(p_midi); - + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } -- cgit v1.3.1 From 017c95037f3173455fa09efae6093d56fd3f3d1a Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 14:51:44 +0700 Subject: add usbd edpt open - RTT mode is blocking to prevent log lost - Improve logging message --- examples/make.mk | 2 +- src/class/cdc/cdc_device.c | 2 +- src/class/midi/midi_device.c | 2 +- src/class/net/net_device.c | 2 +- src/class/usbtmc/usbtmc_device.c | 2 +- src/common/tusb_common.h | 12 ++++++++++-- src/common/tusb_verify.h | 6 +++--- src/device/usbd.c | 38 ++++++++++++++++++++++++++++++-------- src/device/usbd_control.c | 6 +++--- src/device/usbd_pvt.h | 5 ++++- src/tusb.c | 8 +++++--- test/test/support/tusb_config.h | 2 ++ 12 files changed, 62 insertions(+), 25 deletions(-) (limited to 'src/class') diff --git a/examples/make.mk b/examples/make.mk index 319ceece8..449dc899d 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -84,7 +84,7 @@ endif ifeq ($(LOGGER),rtt) RTT_SRC = lib/SEGGER_RTT - CFLAGS += -DLOGGER_RTT + CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL INC += $(TOP)/$(RTT_SRC)/RTT SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT_printf.c SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 3c7118f13..2d8f986ae 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -260,7 +260,7 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 56a27fbce..7bc8cef84 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -339,7 +339,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { p_midi->ep_in = ep_addr; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 0f2ccbd44..ad1d66fca 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -167,7 +167,7 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t // notification endpoint (if any) if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index abe26ced3..b14135146 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -309,7 +309,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin default: TU_ASSERT(false); } - TU_VERIFY( dcd_edpt_open(rhport, ep_desc)); + TU_VERIFY( usbd_edpt_open(rhport, ep_desc)); found_endpoints++; } (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2d80f8210..fcb22cde1 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -219,17 +219,25 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); #define tu_printf printf #endif +static inline +void tu_print_var(uint8_t const* buf, uint32_t bufsize) +{ + for(uint32_t i=0; i 1 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2_VAR TU_LOG1_VAR #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index fee291df6..406f5e6ee 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -90,13 +90,13 @@ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -#else -#if defined(__riscv) + +#elif defined(__riscv) #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) + #else #define TU_BREAKPOINT() do {} while (0) #endif -#endif /*------------------------------------------------------------------*/ /* Macro Generator diff --git a/src/device/usbd.c b/src/device/usbd.c index 219dd23be..f0b7fcefc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -356,7 +356,8 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD: event %s\r\n", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("USBD: %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); switch ( event.event_id ) { @@ -372,7 +373,8 @@ void tud_task (void) break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG2_MEM(&event.setup_received, 8, 2); + TU_LOG2_VAR(&event.setup_received); + TU_LOG2("\r\n"); // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set @@ -395,7 +397,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; @@ -472,10 +474,11 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return tud_vendor_control_request_cb(rhport, p_request); } -#if CFG_TUSB_DEBUG > 1 +#if CFG_TUSB_DEBUG >= 2 if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) { - TU_LOG2(" %s\r\n", _tusb_std_request_str[p_request->bRequest]); + TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); + if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); } #endif @@ -702,7 +705,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Interface number must not be used already TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -767,6 +770,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { case TUSB_DESC_DEVICE: { + TU_LOG2(" Device\r\n"); + uint16_t len = sizeof(tusb_desc_device_t); // Only send up to EP0 Packet Size if not addressed @@ -785,6 +790,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_BOS: { + TU_LOG2(" BOS\r\n"); + // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; @@ -798,6 +805,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { + TU_LOG2(" Configuration[%u]\r\n", desc_index); + tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); @@ -809,6 +818,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_STRING: + TU_LOG2(" String[%u]\r\n", desc_index); + // String Descriptor always uses the desc set from user if ( desc_index == 0xEE ) { @@ -827,6 +838,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_DEVICE_QUALIFIER: + TU_LOG2(" Device Qualifier\r\n"); + // TODO If not highspeed capable stall this request otherwise // return the descriptor that could work in highspeed return false; @@ -920,7 +933,7 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); - TU_ASSERT(dcd_edpt_open(rhport, desc_ep)); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { @@ -955,15 +968,24 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) // USBD Endpoint API //--------------------------------------------------------------------+ +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) +{ + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + + return dcd_edpt_open(rhport, desc_ep); +} + bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); _usbd_dev.ep_status[epnum][dir].busy = true; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, total_bytes); + TU_LOG2("OK\r\n"); return true; } diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index c61606f18..b0ae85e3b 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -63,7 +63,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, 0); + TU_LOG2(" Queue EP %02X with zlp Status\r\n", ep_addr); // status direction is reversed to one in the setup packet // Note: Status must always be DATA1 @@ -96,7 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\r\n", ep_addr, xact_len); + TU_LOG2(" Queue EP %02X with %u bytes\r\n", ep_addr, xact_len); return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -118,7 +118,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo TU_ASSERT(buffer); } - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); +// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 26b9700e8..48188ec99 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -37,7 +37,10 @@ // USBD Endpoint API //--------------------------------------------------------------------+ -//bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +// Open an endpoint +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + +// Close an endpoint void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer diff --git a/src/tusb.c b/src/tusb.c index 8f234455f..1bc134dba 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -78,9 +78,11 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) } } -// size : item size in bytes -// count : number of item -// print offet or not (handfy for dumping large memory) +/* Print out memory contents + * - size : item size in bytes + * - count : number of item + * - indent: prefix spaces on every line + */ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent) { uint8_t const size = 1; // fixed 1 byte for now diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 5e7b70e0d..5258513ec 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -52,7 +52,9 @@ #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build +#ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 +#endif /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put -- cgit v1.3.1 From 83353dd93f2c24b87b9d22e3543e91420d758513 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 22:03:05 +0700 Subject: add TODO for usbnet clean up --- src/class/net/net_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index ad1d66fca..e3faa0187 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -89,7 +89,8 @@ static const struct ecm_notify_struct ecm_notify_csc = .uplink = 9728000, }; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union +// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static union { uint8_t rndis_buf[120]; struct ecm_notify_struct ecm_buf; @@ -98,6 +99,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +// TODO remove CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; static bool can_xmit; -- cgit v1.3.1 From d0487088ac094eaaff54c04241d8018ffc729b36 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 23:04:17 +0700 Subject: revert a change to net driver --- src/class/net/net_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index e3faa0187..fedd4db99 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -90,7 +90,7 @@ static const struct ecm_notify_struct ecm_notify_csc = }; // TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static union +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union { uint8_t rndis_buf[120]; struct ecm_notify_struct ecm_buf; -- cgit v1.3.1 From 4a3a44834048006b05d82d32e1f69be856554d4d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 00:29:52 +0700 Subject: clean up things, add makefile for host example --- examples/host/cdc_msc_hid/Makefile | 22 +++++++ .../host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 21 +++--- .../host/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject | 19 ++++-- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 15 +---- hw/bsp/ea4357/ea4357.c | 15 +++-- hw/bsp/mcb1800/mcb1800.c | 77 +++++++++++----------- src/class/cdc/cdc_host.c | 1 - src/host/ehci/ehci.c | 6 +- test/test/support/tusb_config.h | 10 +-- 10 files changed, 107 insertions(+), 81 deletions(-) create mode 100644 examples/host/cdc_msc_hid/Makefile (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile new file mode 100644 index 000000000..20cd7ba69 --- /dev/null +++ b/examples/host/cdc_msc_hid/Makefile @@ -0,0 +1,22 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + + +# TinyUSB Host Stack source +SRC_C += \ + src/host/usbh.c \ + src/host/hub.c \ + src/host/ehci/ehci.c \ + src/class/cdc/cdc_host.c \ + src/host/ehci/ehci.c \ + src/portable/nxp/lpc18_43/hcd_lpc18_43.c + +include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2dd7de552..2b68bfa23 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -17,8 +17,8 @@ arm_target_debug_interface_type="ADIv5" arm_target_device_name="LPC1857" arm_target_interface_type="SWD" - c_preprocessor_definitions="LPC18xx;__LPC1800_FAMILY;__LPC185x_SUBFAMILY;ARM_MATH_CM3;FLASH_PLACEMENT=1;CORE_M3;BOARD_MCB1800;CFG_TUSB_MCU=OPT_MCU_LPC18XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")))" - c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)//inc;$(lpcDir)//inc/config_18xx" + c_preprocessor_definitions="LPC18xx;__LPC1800_FAMILY;__LPC185x_SUBFAMILY;ARM_MATH_CM3;FLASH_PLACEMENT=1;CORE_M3;BOARD_MCB1800;CFG_TUSB_MCU=OPT_MCU_LPC18XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")));CFG_TUSB_DEBUG=2" + c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)//inc;$(lpcDir)//inc/config_18xx;$(rootDir)/lib/SEGGER_RTT/RTT" debug_register_definition_file="$(ProjectDir)/LPC18xx_Registers.xml" debug_target_connection="J-Link" gcc_entry_point="Reset_Handler" @@ -101,12 +101,6 @@ - + + + + + + + + + + + - + + + + + + + + + + + diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 0fbbd4534..6f5df1250 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -193,7 +193,7 @@ void print_greeting(void) printf("- issue at https://github.com/hathach/tinyusb\n"); printf("--------------------------------------------------------------------\n\n"); - printf("This Host demo is configured to support:"); + printf("This Host demo is configured to support:\r\n"); printf(" - RTOS = %s\n", rtos_name[CFG_TUSB_OS]); // if (CFG_TUH_CDC ) puts(" - Communication Device Class"); // if (CFG_TUH_MSC ) puts(" - Mass Storage"); diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index aa259dafd..235402180 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -75,23 +75,10 @@ #define CFG_TUH_HID_MOUSE 0 #define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) #define CFG_TUH_MSC 0 +#define CFG_TUH_VENDOR 0 #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports -//------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 0 -#define CFG_TUD_VENDOR 0 - -// CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 - -// MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - - #ifdef __cplusplus } #endif diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 30d899f69..193e19831 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -63,7 +63,7 @@ const uint32_t ExtRateIn = 0; static const PINMUX_GRP_T pinmuxing[] = { - // Button + // Button ( Joystick down ) {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, // UART @@ -139,21 +139,26 @@ void board_init(void) USBMODE_VBUS_HIGH = 1 }; - /* USB0 - * For USB0 Device operation: - * - insert jumpers in position 1-2 in JP17/JP18/JP19. + /* From EA4357 user manual + * + * USB0 Device operation: + * - Insert jumpers in position 1-2 in JP17/JP18/JP19. * - GPIO28 controls USB connect functionality * - LED32 lights when the USB Device is connected. SJ4 has pads 1-2 shorted by default. * - LED33 is controlled by GPIO27 and signals USB-up state. GPIO54 is used for VBUS * sensing. * - * For USB0 Host operation: + * USB0 Host operation: * - insert jumpers in position 2-3 in JP17/JP18/JP19. * - USB Host power is controlled via distribution switch U20 (found in schematic page 11). * - Signal GPIO26 is active low and enables +5V on VBUS2. * - LED35 light whenever +5V is present on VBUS2. * - GPIO55 is connected to status feedback from the distribution switch. * - GPIO54 is used for VBUS sensing. 15Kohm pull-down resistors are always active + * + * Note: + * - Insert jumpers in position 2-3 in JP17/JP18/JP19 + * - Insert jumpers in JP31 (OTG) */ #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 075210c85..fdbe389a3 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -76,30 +76,27 @@ const uint32_t ExtRateIn = 0; static const PINMUX_GRP_T pinmuxing[] = { - // LEDs - {0xD, 10, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4)}, - {0xD, 11, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0xD, 12, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0xD, 13, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0xD, 14, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0x9, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN)}, - {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN)}, - {0x9, 2, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN)}, - - // Button - {0x4, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, - - // UART - {UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC2 }, - {UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, - - /* I2S */ - {0x3, 0, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, - {0x6, 0, (SCU_PINIO_FAST | SCU_MODE_FUNC4)}, - {0x7, 2, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, - {0x6, 2, (SCU_PINIO_FAST | SCU_MODE_FUNC3)}, - {0x7, 1, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, - {0x6, 1, (SCU_PINIO_FAST | SCU_MODE_FUNC3)}, + // LEDs + { 0xD, 10, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4) }, + { 0xD, 11, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0xD, 12, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0xD, 13, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0xD, 14, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0x9, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 2, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + + // Button + { 0x4, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP) }, + + // UART + { UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC2 }, + { UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, + + // USB + { 0x9, 5, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC2 }, // P9_5 USB1_VBUS_EN, USB1 VBus function + { 0x2, 5, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, // P2_5 USB1_VBUS, MUST CONFIGURE THIS SIGNAL FOR USB1 NORMAL OPERATION */ + { 0x6, 3, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC1 } // P6_3 USB0_PWR_EN, USB0 VBus function }; /* Pin clock mux values, re-used structure, value in first index is meaningless */ @@ -147,10 +144,10 @@ void board_init(void) Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN); //------------- UART -------------// - Chip_UART_Init(UART_DEV); - Chip_UART_SetBaud(UART_DEV, CFG_BOARD_UART_BAUDRATE); - Chip_UART_ConfigData(UART_DEV, UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS); - Chip_UART_TXEnable(UART_DEV); + Chip_UART_Init(UART_DEV); + Chip_UART_SetBaud(UART_DEV, CFG_BOARD_UART_BAUDRATE); + Chip_UART_ConfigData(UART_DEV, UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS); + Chip_UART_TXEnable(UART_DEV); //------------- USB -------------// enum { @@ -167,17 +164,19 @@ void board_init(void) #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); -// // Reset controller -// LPC_USB0->USBCMD_D |= 0x02; -// while( LPC_USB0->USBCMD_D & 0x02 ) {} -// -// // Set mode -// #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST -// LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); -// #else // TODO OTG -// LPC_USB0->USBMODE_D = USBMODE_DEVICE; -// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; -// #endif + // Host/Device mode can only be set right after controller reset + LPC_USB0->USBCMD_D |= 0x02; + while( LPC_USB0->USBCMD_D & 0x02 ) {} + + // Set mode + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); + + LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging + #else // TODO OTG + LPC_USB0->USBMODE_D = USBMODE_DEVICE; + LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; + #endif #endif // USB1 diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 5e45e8f6b..6b36ea94d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -86,7 +86,6 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) { // TODO consider all AT Command as serial candidate return tuh_cdc_mounted(dev_addr) && - (CDC_COMM_PROTOCOL_NONE <= cdch_data[dev_addr-1].itf_protocol) && (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); } diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 9ddffaf2c..bbad072bf 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -358,7 +358,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const if ( dev_addr == 0 ) return true; // Insert to list - ehci_link_t * list_head; + ehci_link_t * list_head = NULL; switch (ep_desc->bmAttributes.xfer) { @@ -378,8 +378,10 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const default: break; } + TU_ASSERT(list_head); + // TODO might need to disable async/period list - list_insert( list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); + list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); return true; } diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 5258513ec..578c4126f 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -43,10 +43,12 @@ #define CFG_TUSB_MCU OPT_MCU_NRF5X #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) -#else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#ifndef CFG_TUSB_RHPORT0_MODE + #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) + #else + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #endif #endif #define CFG_TUSB_OS OPT_OS_NONE -- cgit v1.3.1 From 81b1f97ef7510a12a2d2ee3e8c806d4824e8a720 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 May 2020 13:23:40 +0700 Subject: suppress cast-align warnings for net device driver --- examples/device/net_lwip_webserver/Makefile | 3 --- lib/networking/rndis_reports.c | 10 +++++----- src/class/net/net_device.c | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'src/class') diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 5279c49e2..fa93cf87f 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -6,9 +6,6 @@ CFLAGS += \ -DTCP_WND=2*TCP_MSS \ -DHTTPD_USE_CUSTOM_FSDATA=0 -# TODO rndis_reports.c and net_device cause cast algin warnings -CFLAGS += -Wno-error=cast-align - INC += \ src \ $(TOP)/hw \ diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c index 6e24c57e9..ee611c883 100644 --- a/lib/networking/rndis_reports.c +++ b/lib/networking/rndis_reports.c @@ -74,7 +74,7 @@ static const uint32_t OIDSupportedList[] = #define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) #define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) -static uint8_t *encapsulated_buffer; +static void *encapsulated_buffer; static void rndis_report(void) { @@ -152,7 +152,7 @@ static void rndis_query(void) } } -#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) +#define INFBUF ((uint8_t *)&(m->RequestId) + m->InformationBufferOffset) static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) { @@ -191,14 +191,14 @@ static void rndis_handle_set_msg(void) char *ptr = (char *)m; ptr += sizeof(rndis_generic_msg_t); ptr += m->InformationBufferOffset; - p = (rndis_config_parameter_t *)ptr; + p = (rndis_config_parameter_t *) ((void*) ptr); rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); } break; /* Mandatory general OIDs */ case OID_GEN_CURRENT_PACKET_FILTER: - oid_packet_filter = *INFBUF; + memcpy(&oid_packet_filter, INFBUF, 4); if (oid_packet_filter) { rndis_packetFilter(oid_packet_filter); @@ -239,7 +239,7 @@ void rndis_class_set_handler(uint8_t *data, int size) encapsulated_buffer = data; (void)size; - switch (((rndis_generic_msg_t *)data)->MessageType) + switch (((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) { case REMOTE_NDIS_INITIALIZE_MSG: { diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index fedd4db99..cbd662b10 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -326,7 +326,7 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request { if (request->bmRequestType_bit.direction == TUSB_DIR_IN) { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); tud_control_xfer(rhport, request, notify.rndis_buf, msglen); @@ -356,7 +356,7 @@ static void handle_incoming_packet(uint32_t len) } else { - rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt); if (len >= sizeof(rndis_data_packet_t)) if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) @@ -450,7 +450,7 @@ void tud_network_xmit(struct pbuf *p) if (!_netd_itf.ecm_mode) { - rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); memset(hdr, 0, sizeof(rndis_data_packet_t)); hdr->MessageType = REMOTE_NDIS_PACKET_MSG; hdr->MessageLength = len; -- cgit v1.3.1 From 58cedf4c061fbf9f95cd88cafb6e581fc04549ff Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 19 May 2020 00:55:43 +0700 Subject: usb0 host on mcb1800 work with fullspeed mode. use usbh_edpt_open() to correctly map ep2drv[] --- examples/host/cdc_msc_hid/Makefile | 3 +- .../host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 4 ++ examples/host/cdc_msc_hid/src/main.c | 15 +++-- examples/host/cdc_msc_hid/src/msc_app.c | 36 ++++++------ examples/host/cdc_msc_hid/src/tusb_config.h | 6 +- hw/bsp/ea4357/board.mk | 2 +- hw/bsp/mcb1800/board.mk | 4 +- hw/bsp/mcb1800/mcb1800.c | 3 +- src/class/cdc/cdc_host.c | 4 +- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/class/vendor/vendor_host.c | 2 +- src/host/ehci/ehci.c | 21 ++++++- src/host/ehci/ehci.h | 4 ++ src/host/hcd.h | 1 + src/host/hub.c | 2 +- src/host/usbh.c | 68 +++++++++++++--------- src/host/usbh.h | 2 + 18 files changed, 115 insertions(+), 66 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 20cd7ba69..373dbbf9e 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -15,8 +15,9 @@ SRC_C += \ src/host/usbh.c \ src/host/hub.c \ src/host/ehci/ehci.c \ - src/class/cdc/cdc_host.c \ src/host/ehci/ehci.c \ + src/class/cdc/cdc_host.c \ + src/class/msc/msc_host.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2b68bfa23..e0a2f6f97 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -124,6 +124,10 @@ + USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); - -// LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging + LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging #else // TODO OTG LPC_USB0->USBMODE_D = USBMODE_DEVICE; LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6b36ea94d..e62f47b72 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -158,7 +158,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it // notification endpoint tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( hcd_edpt_open(rhport, dev_addr, ep_desc) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) ); p_cdc->ep_notif = ep_desc->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; @@ -179,7 +179,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 69c49b012..8abb3cd22 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) { - p_hid->pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); + p_hid->pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->interface_number = interface_number; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e20969f57..98c71eb70 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -293,7 +293,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 3e8dac0f6..0524cb981 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -107,7 +107,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); + *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); p_desc = tu_desc_next(p_desc); diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 048affb1e..e2ead7b08 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -120,10 +120,27 @@ void hcd_port_reset(uint8_t rhport) ehci_registers_t* regs = ehci_data.regs; - regs->portsc_bm.port_enabled = 0; // disable port before reset - regs->portsc_bm.port_reset = 1; +// regs->portsc_bm.port_enabled = 0; // disable port before reset +// regs->portsc_bm.port_reset = 1; + + uint32_t portsc = regs->portsc; + + portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); + portsc |= EHCI_PORTSC_MASK_PORT_RESET; + + regs->portsc = portsc; } +#if 0 +void hcd_port_reset_end(uint8_t rhport) +{ + (void) rhport; + + ehci_registers_t* regs = ehci_data.regs; + regs->portsc_bm.port_reset = 0; +} +#endif + bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index f11c4536a..a6342b2d2 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -311,10 +311,14 @@ enum ehci_usbcmd_pos_ { }; enum ehci_portsc_change_mask_{ + EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), + EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + EHCI_PORTSC_MASK_ALL = EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | diff --git a/src/host/hcd.h b/src/host/hcd.h index d9307ca09..f2ca0a1d6 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -104,6 +104,7 @@ static inline uint32_t hcd_frame_number(uint8_t rhport) /// return the current connect status of roothub port bool hcd_port_connect_status(uint8_t hostid); void hcd_port_reset(uint8_t hostid); +void hcd_port_reset_end(uint8_t rhport); tusb_speed_t hcd_port_speed_get(uint8_t hostid); // HCD closes all opened endpoints belong to this device diff --git a/src/host/hub.c b/src/host/hub.c index 00450b704..eb85dfa42 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -154,7 +154,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_status = ep_desc->bEndpointAddress; diff --git a/src/host/usbh.c b/src/host/usbh.c index 7171f6bab..8536cec0a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -116,7 +116,6 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_H //------------- Helper Function Prototypes -------------// static inline uint8_t get_new_address(void); static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc); -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) @@ -225,6 +224,30 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return TUSB_ERROR_NONE; } +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + bool ret = hcd_edpt_open(rhport, dev_addr, ep_desc); + + if (ret) + { + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + // new endpoints belongs to latest interface (last valid value) + uint8_t drvid = 0xff; + for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) + { + if ( dev->itf2drv[i] == 0xff ) break; + drvid = dev->itf2drv[i]; + } + TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); + + uint8_t const ep_addr = ep_desc->bEndpointAddress; + dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; + } + + return ret; +} + //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ @@ -358,6 +381,8 @@ bool enum_task(hcd_event_t* event) { if( hcd_port_connect_status(dev0->rhport) ) { + TU_LOG2("Connect \r\n"); + // connection event osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get @@ -371,6 +396,8 @@ bool enum_task(hcd_event_t* event) } else { + TU_LOG2("Disconnect \r\n"); + // disconnection event usbh_device_unplugged(dev0->rhport, 0, 0); return true; // restart task @@ -424,6 +451,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + TU_LOG2("Get 8 byte of Device Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -434,12 +462,16 @@ bool enum_task(hcd_event_t* event) bool is_ok = usbh_control_xfer(0, &request, _usbh_ctrl_buf); //------------- Reset device again before Set Address -------------// + TU_LOG2("Port reset \r\n"); + if (dev0->hub_addr == 0) { // connected directly to roothub TU_ASSERT(is_ok); // TODO some slow device is observed to fail the very fist controller xfer, can try more times hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor osal_task_delay(RESET_DELAY); +// hcd_port_reset_end(dev0->rhport); +// osal_task_delay(RESET_DELAY); } #if CFG_TUH_HUB else @@ -458,6 +490,7 @@ bool enum_task(hcd_event_t* event) #endif //------------- Set new address -------------// + TU_LOG2("Set Address \r\n"); uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices @@ -484,6 +517,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); //------------- Get full device descriptor -------------// + TU_LOG2("Get Device Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -502,6 +536,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// + TU_LOG2("Get 9 bytes of Configuration Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -515,6 +550,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); //------------- Get full configuration descriptor -------------// + TU_LOG2("Get full Configuration Descriptor \r\n"); request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); @@ -522,6 +558,7 @@ bool enum_task(hcd_event_t* event) new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; //------------- Set Configure -------------// + TU_LOG2("Set Configuration Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_CONFIGURATION, @@ -577,11 +614,7 @@ bool enum_task(hcd_event_t* event) { uint16_t itf_len = 0; - if ( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ) - { - mark_interface_endpoint(new_dev->ep2drv, p_desc, itf_len, drv_id); - } - + TU_ASSERT( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; } @@ -597,7 +630,7 @@ bool enum_task(hcd_event_t* event) /* USB Host Driver task * This top level thread manages all host controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. - * + *_usbh_devices[dev_addr]. @code int main(void) { @@ -661,25 +694,4 @@ static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_de return config_num; } -// Helper marking endpoint of interface belongs to class driver -// TODO merge with usbd -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -{ - uint16_t len = 0; - - while( len < desc_len ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - ep2drv[ tu_edpt_number(ep_addr) ][ tu_edpt_dir(ep_addr) ] = driver_id; - } - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } -} - - #endif diff --git a/src/host/usbh.h b/src/host/usbh.h index 42a2bd095..bc0abcccc 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -94,6 +94,8 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 9be2f1bf3dc2c89bc23eed1e95c06de41ebb0946 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 22 May 2020 12:09:34 +0200 Subject: Add basic UAC2 structure - untested --- src/class/audio/audio.h | 466 ++++++++++++++-- src/class/audio/audio_device.c | 1193 ++++++++++++++++++++++++++++++++++++++++ src/class/audio/audio_device.h | 304 ++++++++++ src/device/usbd.c | 13 + src/device/usbd.h | 37 ++ src/tusb.h | 4 + 6 files changed, 1982 insertions(+), 35 deletions(-) create mode 100644 src/class/audio/audio_device.c create mode 100644 src/class/audio/audio_device.h (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 5bec14d88..f4f460c22 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -35,64 +35,460 @@ #include "common/tusb_common.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + /// Audio Interface Subclass Codes typedef enum { - AUDIO_SUBCLASS_CONTROL = 0x01 , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming + AUDIO_SUBCLASS_UNDEFINED = 0x00, + AUDIO_SUBCLASS_CONTROL , ///< Audio Control + AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; /// Audio Protocol Codes typedef enum { - AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 - AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 - AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 + AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 + AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 + AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 } audio_protocol_type_t; /// Audio Function Category Codes typedef enum { - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C + AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO_FUNC_HOME_THEATER = 0x02, + AUDIO_FUNC_MICROPHONE = 0x03, + AUDIO_FUNC_HEADSET = 0x04, + AUDIO_FUNC_TELEPHONE = 0x05, + AUDIO_FUNC_CONVERTER = 0x06, + AUDIO_FUNC_SOUND_RECODER = 0x07, + AUDIO_FUNC_IO_BOX = 0x08, + AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO_FUNC_PRO_AUDIO = 0x0A, + AUDIO_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO_FUNC_CONTROL_PANEL = 0x0C, } audio_function_t; -/// Audio Class-Specific AC Interface Descriptor Subtypes +/// Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio_cs_ac_interface_subtype_t; + +/// Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO_CS_AS_INTERFACE_DECODER = 0x04, +} audio_cs_as_interface_subtype_t; + +/// Audio Class-Control Values UAC2 +typedef enum +{ + AUDIO_CTRL_NONE = 0x00, ///< No Host access + AUDIO_CTRL_R = 0x01, ///< Host read access only + AUDIO_CTRL_RW = 0x03, ///< Host read write access +} audio_control_t; + +/// Audio Class-Specific AC Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio_cs_ac_interface_control_pos_t; + +/// Audio Class-Specific AS Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio_cs_as_interface_control_pos_t; + +/// Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_DESCRIPTOR_UNDEFINED = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio_cs_as_iso_data_ep_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Clock Source Attributes UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio_clock_source_attribute_t; + +/// Audio Class-Clock Source Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio_clock_source_control_pos_t; + +/// Audio Class-Clock Selector Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, +} audio_clock_selector_control_pos_t; + +/// Audio Class-Clock Multiplier Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio_clock_multiplier_control_pos_t; + +/// Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// Audio Class-Input Terminal Controls UAC2 +typedef enum +{ + AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio_terminal_input_control_pos_t; + +/// Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Audio Class-Output Terminal Controls UAC2 +typedef enum +{ + AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio_terminal_output_control_pos_t; + +/// Audio Class-Feature Unit Controls UAC2 typedef enum { - AUDIO_CS_INTERFACE_HEADER = 0x01, - AUDIO_CS_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_interface_subtype_t; + AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio_feature_unit_control_pos_t; + +/// Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = 0x00000000, + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = 0x00000001, + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x00000002, + AUDIO_DATA_FORMAT_TYPE_I_ALAW = 0x00000003, + AUDIO_DATA_FORMAT_TYPE_I_MULAW = 0x00000004, +} audio_data_format_type_I_t; + +/// Audio Class-Audio Channel Configuration UAC2 +typedef enum +{ + AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, +} audio_channel_config_t; + +/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. +} audio_desc_cs_ac_interface_t; + +/// AUDIO Clock Source Descriptor (4.7.2.1) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio_desc_clock_source_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio_desc_clock_selector_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins +#define audio_desc_clock_selector_n_t(source_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bClockID ; \ + uint8_t bNrInPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ + } + +/// AUDIO Clock Multiplier Descriptor (4.7.2.3) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio_desc_clock_multiplier_t; + +/// AUDIO Input Terminal Descriptor(4.7.2.4) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. +} audio_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor(4.7.2.5) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. +} audio_desc_output_terminal_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. +} audio_desc_feature_unit_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels +#define audio_desc_feature_unit_n_t(ch_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; /* 6+(ch_num+1)*4 */\ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ + } + +/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. +} audio_desc_cs_as_interface_t; + +/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. +} audio_desc_type_I_format_t; + +/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. +} audio_desc_cs_as_iso_data_ep_t; + /** @} */ #ifdef __cplusplus - } +} #endif #endif diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c new file mode 100644 index 000000000..fbd412564 --- /dev/null +++ b/src/class/audio/audio_device.c @@ -0,0 +1,1193 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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 file is part of the TinyUSB stack. + */ + +/* + * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! + * It supports multiple TX and RX channels. + * + * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. + * + * */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "audio_device.h" +#include "class/audio/audio.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + +#if CFG_TUD_AUDIO_EPSIZE_IN + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint8_t ep_fb; // Feedback EP. +#endif + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + uint8_t ep_int_ctr; // Audio control interrupt EP. +#endif + +#if CFG_TUD_AUDIO_N_AS_INT + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; +#endif + /*------------- From this point, data is not cleared by bus reset -------------*/ + // FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; +#endif +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; +#endif +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t int_ctr_ff_mutex; +#endif +#endif + + // Endpoint Transfer buffers +#if CFG_TUD_AUDIO_EPSIZE_OUT + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + + // TODO: required? + //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // uint16_t fb_val; // Feedback value for asynchronous mode! + //#endif + +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; +#endif + +} audiod_interface_t; + +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) +#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) +#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) +#elif CFG_TUD_AUDIO_EPSIZE_OUT +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) +#elif CFG_TUD_AUDIO_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) +#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; + +extern const uint16_t tud_audio_desc_lengths[]; + +#if CFG_TUD_AUDIO_EPSIZE_OUT +static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN +static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +#endif + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); + +static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); + +bool tud_audio_n_mounted(uint8_t itf) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + +#if CFG_TUD_AUDIO_EPSIZE_OUT + if (audio->ep_out == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + if (audio->ep_in == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + if (audio->ep_int_ctr == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (audio->ep_fb == 0) + { + return false; + } +#endif + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO + +uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); +} + +uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); +} + +void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); +} + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + +uint16_t tud_audio_int_ctr_n_available(uint8_t itf) +{ + return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); +} + +uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +{ + return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); +} + +void tud_audio_int_ctr_n_read_flush (uint8_t itf) +{ + tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); +} + +#endif + +// This function is called once something is received by USB and is responsible for decoding received stream into audio channels. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_RX_FIFO = 0. + +#if CFG_TUD_AUDIO_EPSIZE_OUT + +static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) +{ + switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + +#if CFG_TUD_AUDIO_USE_RX_FIFO + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); +#else +#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! +#endif + break; + + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed RX was completed + TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; +} + +#endif //CFG_TUD_AUDIO_EPSIZE_OUT + +// The following functions are used in case CFG_TUD_AUDIO_USE_RX_FIFO == 1 +#if CFG_TUD_AUDIO_USE_RX_FIFO +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) +{ + (void) rhport; + + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + return false; + } + + uint8_t chId = 0; + uint16_t cnt; +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 + uint8_t sample = 0; +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 + uint16_t sample = 0; +#else + uint32_t sample = 0; +#endif + + for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) + { + // Let alignment problems be handled by memcpy + memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); + if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) + { + // Buffer overflow + return false; + } + + if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) + { + chId = 0; + } + } +} } +#endif //CFG_TUD_AUDIO_USE_RX_FIFO + + +#if CFG_TUD_AUDIO_EPSIZE_OUT +TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) +{ + (void) rhport; + (void) buffer; + (void) bufsize; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_rx_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 + +uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->itf_num == 0) { + return 0; + } + + return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); +} + +#endif + + +// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_TX_FIFO = 0. +#if CFG_TUD_AUDIO_EPSIZE_IN +static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + +#if CFG_TUD_AUDIO_USE_TX_FIFO + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); +#else +#error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! +#endif + break; + + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed TX was completed + TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); + return true; +} + +#endif //CFG_TUD_AUDIO_EPSIZE_IN + +#if CFG_TUD_AUDIO_USE_TX_FIFO +static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint8_t cntChannel; + + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + { + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + } + } + + // Check if there is enough + if (nSamplesPerChannelToSend == 0) + { + *n_bytes_copied = 0; + return true; + } + + // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! + if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) + { + nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + + // Encode + uint16_t cntSample; + uint8_t * pBuff = audio->epin_buf; +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 + uint8_t sample; +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 + uint16_t sample; +#else + uint32_t sample; +#endif + + // TODO: Big endianess handling + for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + { + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + // Get sample from buffer + tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + + // Put it into EP's buffer - Let alignment problems be handled by memcpy + memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + + // Advance pointer + pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + } + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); + *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + return true; +} + +#endif //CFG_TUD_AUDIO_USE_TX_FIFO + +// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +{ + (void) rhport; + (void) audio; + + // Here we need to return the feedback value +#error RETURN YOUR FEEDBACK VALUE HERE! + + TU_VERIFY(tud_audio_fb_done_cb(rhport)); + return 0; +} + +#endif + +// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); + + // TODO: Big endianess handling + uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); + + if (cnt > 0) + { + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); + } + + *n_bytes_copied = cnt; + + TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); + + return true; +} +#endif + +// Callback functions +// Currently the return value has to effect so far. The return value finally is discarded in tud_task(void) in usbd.c - we just incorporate that for later use + +#if CFG_TUD_AUDIO_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) +{ + (void) rhport; + (void) n_bytes_copied; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_tx_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport) +{ + (void) rhport; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_fb_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) +{ + (void) rhport; + (void) n_bytes_copied; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_int_ctr_done_cb could be implemented in the user file + */ + + return true; +} + +#endif + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void audiod_init(void) +{ + uint8_t cnt; + tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + + for(uint8_t i=0; i 0 && CFG_TUD_AUDIO_USE_TX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_BUFSIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); +#endif + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_BUFSIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); +#endif + } +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 + tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); +#endif +#endif + } +} + +void audiod_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; i 0 && CFG_TUD_AUDIO_USE_TX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_clear(&audio->tx_ff[cnt]); + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_clear(&audio->rx_ff[cnt]); + } +#endif + } +} + +bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + + // Verify version is correct - this check can be omitted + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); + + // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted + if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed + { + TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); + } + + // Alternate setting MUST be zero - this check can be omitted + TU_VERIFY(itf_desc->bAlternateSetting == 0); + + // Find available audio driver interface + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + break; + } + } + + // Verify we found a free one + TU_ASSERT( i < CFG_TUD_AUDIO ); + + // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) + + // Notify caller we read complete descriptor + (*p_length) += tud_audio_desc_lengths[i]; + + return true; +} + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + +#if CFG_TUD_AUDIO_N_AS_INT > 0 + uint8_t const itf = tu_u16_low(p_request->wIndex); + + // Find index of audio streaming interface + uint8_t idxDriver, idxItf; + uint8_t const *dummy; + + TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + + return true; + +#else + (void) p_request; + return false; +#endif +} + +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Here we need to do the following: + + // 1. Find the audio driver interface which was assigned to the given interface which is to be set + // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. + // The audio driver interface is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + + // 2. Close EPs which are currently open + // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them + + // 3. Open new EP + + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const alt = tu_u16_low(p_request->wValue); + + // Find index of audio streaming interface and index of interface + uint8_t idxDriver, idxItf; + uint8_t const *p_desc; + TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 + if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); + _audiod_itf[idxDriver].ep_out = 0; // Necessary? + + // Close corresponding feedback EP +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? +#endif + } +#endif + + + // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + + // p_desc starts at required interface with alternate setting zero + while (p_desc < p_desc_end) + { + // Find correct interface + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) + { + // Open EPs + uint8_t foundEPs = 0; + while (foundEPs < ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints && p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + _audiod_itf[idxDriver].ep_in = ep_addr; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; + } +#endif + +#endif + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); + } + + // We are done - abort loop + break; + } + + // Increase index, bytes read, and pointer + p_desc = tu_desc_next(p_desc); + } + + // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! + TU_VERIFY(p_desc < p_desc_end); + + // Conduct audio driver function specific stuff + + // HERE DO WHAT YOU HAVE TO DO - E.G. START ADC OR SO + //#error Implementation specific setInterface code required here! + + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + + return true; +} + +bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + return true; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + default: + return false; + } +} + +bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + // Search for interface belonging to given end point address and proceed as required + uint8_t idxDriver; + for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + { + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + + // Data transmission of control interrupt finished + if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + { + // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) + // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? + // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? + + // Load new data + uint16 *n_bytes_copied; + TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) + { + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + } + +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + + // Data transmission of audio packet finished + if (_audiod_itf[idxDriver].ep_in == ep_addr) + { + // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." + // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." + // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. + + // Check if there is data to load into EPs buffer - if not load it with ZLP + // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! + // This is the only place where we can fill something into the EPs buffer! + + // Load new data + uint16_t *n_bytes_copied = NULL; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + + // New audio packet received + if (_audiod_itf[idxDriver].ep_out == ep_addr) + { + // Save into buffer - do whatever has to be done + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + + // prepare for next transmission + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + + return true; + } + + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // Transmission of feedback EP finished + if (_audiod_itf[idxDriver].ep_fb == ep_addr) + { + if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } +#endif +#endif + } + + return false; + +} + +static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + // Loop over audio driver interfaces + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors + uint8_t const * p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + } + + return false; +} + +#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO + +// OLD +//// In order that this function works the following is mandatory: +// // - An IAD descriptor is required and has to be placed directly before the Standard AC Interface Descriptor (4.7.1) ALSO if no Audio Streaming interfaces are used! +// // - The Standard AC Interface Descriptor (4.7.1) has to be the first interface listed (required by UAC2 specification) +// // - The alternate interfaces of the Standard AS Interface Descriptor(4.9.1) must be listed in increasing order and alternate 0 must have zero EPs +// +// TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && +// AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); +// +// // Verify version is correct - this check can be omitted +// TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); +// +// // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted +// if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed +// { +// TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); +// } +// +// // Alternate setting MUST be zero - this check can be omitted +// TU_VERIFY(itf_desc->bAlternateSetting == 0); +// +// // Since checks are successful we get the number of interfaces we have to process by exploiting the fact that an IAD descriptor has to be provided directly before this AC descriptor +// // We do not get this value delivered by the stack so we need to hack a little bit - the number of interfaces to be processed is listed in the IAD descriptor with an offset of exactly 5 +// uint8_t nItfs = *(((uint8_t const *) itf_desc) - 5) - 1; // -1 since we already process the (included) AC interface +// +// // Notify caller we have read Standard AC Interface Descriptor (4.7.1) +// (*p_length) = sizeof(tusb_desc_interface_t); +// +// // Go to next descriptor which has to be a Class-Specific AC Interface Header Descriptor(4.7.2) - always present +// audio_desc_cs_ac_interface_t const * p_desc_cs_ac = (audio_desc_cs_ac_interface_t const *) tu_desc_next ( (uint8_t const *) itf_desc ); +// +// // Verify its the correct descriptor - this check can be omitted +// TU_VERIFY(p_desc_cs_ac->bDescriptorType == TUSB_DESC_CS_INTERFACE +// && p_desc_cs_ac->bDescriptorSubType == AUDIO_CS_AC_INTERFACE_HEADER +// && p_desc_cs_ac->bcdADC == 0x0200); +// +// // We do not check the Audio Function Category Codes +// +// // We do not check all the following Clock Source, Unit and Terminal descriptors +// +// // We do not check the latency control +// +// // We jump over all the following descriptor to the next following interface (which should be a Standard AS Interface Descriptor(4.9.1) if nItfs > 0) +// (*p_length) += p_desc_cs_ac->wTotalLength; // Notify caller of read bytes +// itf_desc = (tusb_desc_interface_t const * )(((uint8_t const *)p_desc_cs_ac ) + p_desc_cs_ac->wTotalLength); // Move pointer +// +// // From this point on we have nItfs packs of audio streaming interfaces (consisting of multiple descriptors always starting with a Standard AS Interface Descriptor(4.9.1)) +// +// uint8_t cnt; +// uint8_t nEPs; +// audio_format_type_t formatType; +// uint8_t intNum; +// uint8_t altInt; +// +// for (cnt = 0; cnt < nItfs; cnt++) +// { +// +// // Here starts an unknown number of alternate interfaces - the art here is to find the end of this interface pack. We do not have the total number of descriptor bytes available (not provided by tinyUSB stack for .open() function) so we try to find the end of this interface pack by deducing it from the order and content of the descriptor pack +// while(1) +// { +// // At first this should be a Standard AS Interface Descriptor(4.9.1) - this check can be omitted +// TU_VERIFY(itf_desc->bDescriptorType == TUSB_DESC_INTERFACE && +// itf_desc->bInterfaceClass == TUSB_CLASS_AUDIO && +// itf_desc->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING && +// itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); +// +// // Remember number of EPs this interface has - required for later +// nEPs = itf_desc->bNumEndpoints; +// intNum = itf_desc->bInterfaceNumber; +// altInt = itf_desc->bAlternateSetting; +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // It is possible now that the following interface is again a Standard AS Interface Descriptor(4.9.1) (in case the related terminal has more than zero EPs at all and this is the following alternative interface > 0 - the alternative (that this is not a Standard AS Interface Descriptor(4.9.1) but a Class-Specific AS Interface Descriptor(4.9.2)) could be in case the related terminal has no EPs at all e.g. SPDIF connector +// if (tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE) +// { +// // It is not possible, that a Standard AS Interface Descriptor(4.9.1) ends without a Class-Specific AS Interface Descriptor(4.9.2) +// // hence the next interface has to be an alternative interface with regard to the one we started above - continue +// continue; +// } +// +// // Second, this interface has to be a Class-Specific AS Interface Descriptor(4.9.2) - this check can be omitted +// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && +// ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_AS_GENERAL); +// +// // Remember format type of this interface - required for later +// formatType = ((audio_desc_cs_as_interface_t *) itf_desc)->bFormatType; +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // Every Class-Specific AS Interface Descriptor(4.9.2) defines a format type and thus a format type descriptor e.g. Type I Format Type Descriptor(2.3.1.6 - Audio Formats) should follow - only if the format type is undefined no format type descriptor follows +// if (formatType != AUDIO_FORMAT_TYPE_UNDEFINED) +// { +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Now there might be an encoder/decoder interface - i found no clue if this interface is mandatory (although examples found by google never use this descriptor) or if there is any way to determine if this descriptor is reliably present or not. Problem here: Since we need to find the end of this interface pack and we do not have the total amount of descriptor bytes available here (not given by the tinyUSB stack for the .open() function), we have to make a speculative check if the following is an encoder/decoder interface or not. +// // It could be possible that we ready over the total length of all descriptor bytes here - we simply hope that the combination of descriptor length, type, and sub type does not occur randomly in memory here. The only way to make this check waterproof is to know how many bytes we can read at all but this would be an information we need to be given by tinyUSB! +// if (tu_desc_len((uint8_t const *) itf_desc) == 21 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && (((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_ENCODER || ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_DECODER)) +// { +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Here may be some EP descriptors +// for (uint8_t cntEP = 0; cntEP < nEPs; cntEP++) +// { +// // This check can be omitted +// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_ENDPOINT); +// +// // Here we can find information about our EPs address etc. but in the initialization process we do not set anything, we have to wait for the host to send a setInterface request where the EPs etc. are set up according +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // If the usage type is something else than feedback there is a Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) following up +// if (((tusb_desc_endpoint_t *) itf_desc)->bmAttributes.usage != 0x10) +// { +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// } +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Okay we processed a complete pack - now we have to make a speculative check if the next interface is an alternate interface belonging to the ones processed before - since it is speculative we check a lot to reduce the chances we go wrong and hope for the best +// if (!(tu_desc_len((uint8_t const *) itf_desc) == 9 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE && itf_desc->bInterfaceNumber == intNum && itf_desc->bAlternateSetting == altInt + 1)) +// { +// // The current interface is not a consecutive alternate interface to the one processed above +// break; +// } +// } +// +// } + + +// Here follow the encoding steps + +//#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_UNDEFINED +// +//#error Individual encoding procedure required! +// +//#elif CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM +// +//#if CFG_TUD_AUDIO_USE_TX_FIFO +// TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); +//#else +//#error YOUR ENCODING AND SENDING IS REQUIRED HERE! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX not implemented! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! +//#endif +// +// // Call a weak callback here - a possibility for user to get informed TX was completed +// TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); +// return true; + +//#if CFG_TUD_AUDIO_EPSIZE_OUT +//static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { +// +// // Here follow the decoding steps +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_UNDEFINED +// +//#error Individual decoding procedure required! +// +//#elif CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM +// +//#if CFG_TUD_AUDIO_USE_RX_FIFO +// TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); +//#else +//#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX not implemented! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! +//#endif +// +// TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); +// return true; +//} +//#endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h new file mode 100644 index 000000000..5354adbd4 --- /dev/null +++ b/src/class/audio/audio_device.h @@ -0,0 +1,304 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) and Reinhard Panhuber + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_AUDIO_DEVICE_H_ +#define _TUSB_AUDIO_DEVICE_H_ + +#include "assert.h" +#include "common/tusb_common.h" +#include "device/usbd.h" + +#include "audio.h" +#include "tusb_config.h" + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) +#ifndef CFG_TUD_AUDIO_N_AS_INT +#define CFG_TUD_AUDIO_N_AS_INT 0 +#endif + +// Use internal FIFOs - In this case, audio.c implements FIFOs for RX and TX (whatever required) and implements encoding and decoding (parameterized by the defines below). +// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). +// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. +// If you disable this you need to fill in desired code into audio_rx_done_cb() and Y on your own, however, this allows for optimizations in byte processing. +#ifndef CFG_TUD_AUDIO_USE_RX_FIFO +#define CFG_TUD_AUDIO_USE_RX_FIFO 0 +#endif + +#ifndef CFG_TUD_AUDIO_USE_TX_FIFO +#define CFG_TUD_AUDIO_USE_TX_FIFO 0 +#endif + +// End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 +#ifndef CFG_TUD_AUDIO_EPSIZE_IN +#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#ifndef CFG_TUD_AUDIO_TX_BUFSIZE +#define CFG_TUD_AUDIO_TX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_IN // Buffer size per channel +#endif +#endif + +#ifndef CFG_TUD_AUDIO_EPSIZE_OUT +#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 +#ifndef CFG_TUD_AUDIO_RX_BUFSIZE +#define CFG_TUD_AUDIO_RX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_OUT // Buffer size per channel +#endif +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif +#endif + +#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#endif + +#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#endif + +// Audio data format types +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c +#endif + +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#endif + +// Audio data format type I specifications +#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I + +// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#endif + +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#endif + +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 +#define CFG_TUD_AUDIO_TX_ITEMSIZE 1 +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 +#define CFG_TUD_AUDIO_TX_ITEMSIZE 2 +#else +#define CFG_TUD_AUDIO_TX_ITEMSIZE 4 +#endif + +#endif + +#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I + +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#endif + +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#endif + +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 +#define CFG_TUD_AUDIO_RX_ITEMSIZE 1 +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 +#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 +#else +#define CFG_TUD_AUDIO_RX_ITEMSIZE 4 +#endif + +#endif + +//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); + +// Supported types of this driver: +// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup AUDIO_Serial Serial + * @{ + * \defgroup AUDIO_Serial_Device Device + * @{ */ + +//--------------------------------------------------------------------+ +// Application API (Multiple Interfaces) +// CFG_TUD_AUDIO > 1 +//--------------------------------------------------------------------+ +bool tud_audio_n_mounted (uint8_t itf); + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); +void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_read_flush (uint8_t itf); +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +#endif + +//--------------------------------------------------------------------+ +// Application API (Interface0) +//--------------------------------------------------------------------+ + +inline bool tud_audio_mounted (void); + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +inline uint16_t tud_audio_available (void); +inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +inline void tud_audio_read_flush (void); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +inline uint32_t tud_audio_int_ctr_available (void); +inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +inline void tud_audio_int_ctr_read_flush (void); +inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN +bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT +bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +bool tud_audio_fb_done_cb(uint8_t rhport); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +#endif + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +inline bool tud_audio_mounted(void) +{ + return tud_audio_n_mounted(0); +} + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, channelId, buffer, bufsize); +} +#endif // CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +inline uint16_t tud_audio_available(uint8_t channelId) +{ + return tud_audio_n_available(0, channelId); +} + +inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +{ + return tud_audio_n_read(0, channelId, buffer, bufsize); +} + +inline void tud_audio_read_flush(uint8_t channelId) +{ + tud_audio_n_read_flush(0, channelId); +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +inline uint16_t tud_audio_int_ctr_available(void) +{ + return tud_audio_int_ctr_n_available(0); +} + +inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) +{ + return tud_audio_int_ctr_n_read(0, buffer, bufsize); +} + +inline void tud_audio_int_ctr_read_flush(void) +{ + return tud_audio_int_ctr_n_read_flush(0); +} + +inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +{ + return tud_audio_int_ctr_n_write(0, buffer, bufsize); +} +#endif + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void audiod_init (void); +void audiod_reset (uint8_t rhport); +bool audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_AUDIO_DEVICE_H_ */ + +/** @} */ +/** @} */ diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..a19993cad 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -135,6 +135,19 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif +#if CFG_TUD_AUDIO +{ + DRIVER_NAME("AUDIO") + .init = audiod_init, + .reset = audiod_reset, + .open = audiod_open, + .control_request = audiod_control_request, + .control_complete = audiod_control_complete, + .xfer_cb = audiod_xfer_cb, + .sof = NULL +}, +#endif + #if CFG_TUD_MIDI { DRIVER_NAME("MIDI") diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..24a2332e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -307,6 +307,43 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ TUD_MIDI_JACKID_OUT_EMB(1) +//------------- AUDIO -------------// + +// Length of template descriptor (132 bytes) +#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) +#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 + +// AUDIO simple descriptor (UAC2) for 1 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source +#define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ + /* Standard AC Interface Descriptor(4.7.1) */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ + /* Clock Source Descriptor(4.7.2.1) */\ + 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ + /* Input Terminal Descriptor(4.7.2.4) */\ + 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ + /* Output Terminal Descriptor(4.7.2.5) */\ + 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ + /* Feature Unit Descriptor(4.7.2.8) */\ + 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, \ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000)\ //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) diff --git a/src/tusb.h b/src/tusb.h index 55c105121..ecd885c26 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -76,6 +76,10 @@ #include "class/msc/msc_device.h" #endif +#if CFG_TUD_AUDIO + #include "class/audio/audio_device.h" +#endif + #if CFG_TUD_MIDI #include "class/midi/midi_device.h" #endif -- cgit v1.3.1 From e3404049686adfd934a6444fadf9ae00f1f94f8a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 19:01:59 +0700 Subject: changing usbd driver open() return type, add max_len only done with cdc and msc, push this interim for feedback first --- src/class/cdc/cdc_device.c | 26 ++++++++++++++------------ src/class/cdc/cdc_device.h | 12 ++++++------ src/class/msc/msc_device.c | 16 ++++++++++------ src/class/msc/msc_device.h | 12 ++++++------ src/device/usbd.c | 30 ++++++++++++++++++------------ 5 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2d8f986ae..a24f348f4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -222,14 +222,16 @@ void cdcd_reset(uint8_t rhport) } } -bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA)); + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); + + uint16_t len = 0; // Find available interface cdcd_interface_t * p_cdc = NULL; @@ -242,29 +244,29 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t break; } } - TU_ASSERT(p_cdc); + TU_ASSERT(p_cdc, 0); //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + len = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) { - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -276,15 +278,15 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_desc = tu_desc_next(p_desc); // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data _prep_out_transaction(cdc_id); - return true; + return len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 69542a3b3..a2523d8d0 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -229,12 +229,12 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 70ba956aa..9955f2f05 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -154,25 +154,29 @@ void mscd_reset(uint8_t rhport) tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } -bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) +uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // only support SCSI's BOT protocol TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + // Max length mus be at least 1 interface + 2 endpoints + TU_VERIFY(max_len >= sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t), 0); + + uint16_t len = 0; mscd_interface_t * p_msc = &_mscd_itf; // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); p_msc->itf_num = itf_desc->bInterfaceNumber; - (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); // Prepare for Command Block Wrapper - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); - return true; + return len; } // Handle class control request diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 66180777e..30ffd02e1 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -151,12 +151,12 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -bool mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..971417a35 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -85,13 +85,13 @@ typedef struct char const* name; #endif - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; static usbd_class_driver_t const _usbd_driver[] = @@ -713,6 +713,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint16_t const remaining_len = desc_end-p_desc; + uint8_t drv_id; uint16_t drv_len; @@ -720,13 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + drv_len = driver->open(rhport, desc_itf, remaining_len); + + if ( drv_len > 0 ) { + // Open successfully, check if length is correct + TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); + // Interface number must not be used already TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -748,8 +754,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + // Failed if cannot find supported driver + TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor -- cgit v1.3.1 From 2eeeda1bcf37b0b5cc6f202e95ef5b05605ecf3d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 00:46:32 +0700 Subject: change signature for dfu runtime --- src/class/dfu/dfu_rt_device.c | 13 +++++++------ src/class/dfu/dfu_rt_device.h | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 0ef5fe63f..426680e8e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -56,24 +56,25 @@ void dfu_rtd_reset(uint8_t rhport) (void) rhport; } -bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; + (void) max_len; // Ensure this is DFU Runtime - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); - TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && + itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t len = sizeof(tusb_desc_interface_t); if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { - (*p_length) += p_desc[DESC_OFFSET_LEN]; + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - return true; + return len; } bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 294d993e3..91ead88c6 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -63,12 +63,12 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_rtd_init(void); -void dfu_rtd_reset(uint8_t rhport); -bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void dfu_rtd_init(void); +void dfu_rtd_reset(uint8_t rhport); +uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); +bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); +bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 7a15d2e0d25a8fad65c27477c0dbf62bebac2196 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 00:56:33 +0700 Subject: improve msc --- src/class/msc/msc_device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9955f2f05..0ae25f89a 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -161,22 +161,22 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + // msc driver length is fixed + enum { _MSC_DRIVER_LEN = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) }; + // Max length mus be at least 1 interface + 2 endpoints - TU_VERIFY(max_len >= sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t), 0); + TU_VERIFY(max_len >= _MSC_DRIVER_LEN, 0); - uint16_t len = 0; mscd_interface_t * p_msc = &_mscd_itf; + p_msc->itf_num = itf_desc->bInterfaceNumber; // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); - p_msc->itf_num = itf_desc->bInterfaceNumber; - len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - // Prepare for Command Block Wrapper TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); - return len; + return _MSC_DRIVER_LEN; } // Handle class control request -- cgit v1.3.1 From 89a3d1f6d17822bed498b5b872b76348f7c520a2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 11:19:12 +0700 Subject: update hid open() --- src/class/hid/hid_device.c | 21 +++++++++++---------- src/class/hid/hid_device.h | 12 ++++++------ src/class/msc/msc_device.c | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index cbdc5bece..51bd153ec 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -158,11 +158,12 @@ void hidd_reset(uint8_t rhport) tu_memclr(_hidd_itf, sizeof(_hidd_itf)); } -bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len) +uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - uint8_t const *p_desc = (uint8_t const *) desc_itf; + // max length is at least interface + hid descriptor + 1 endpoint + TU_ASSERT(max_len >= sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t), 0); // Find available interface hidd_interface_t * p_hid = NULL; @@ -175,16 +176,18 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t break; } } - TU_ASSERT(p_hid); + TU_ASSERT(p_hid, 0); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType); + TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType, 0); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in)); + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol; @@ -192,12 +195,10 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t p_hid->itf_num = desc_itf->bInterfaceNumber; memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); - *p_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - // Prepare for output endpoint - if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); + if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)), 0); - return true; + return sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); } // Handle class control request diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index efdde9569..ad8c9ece4 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -300,12 +300,12 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -bool hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidd_init (void); +void hidd_reset (uint8_t rhport); +uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 0ae25f89a..c3ce495e1 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -165,7 +165,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 enum { _MSC_DRIVER_LEN = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) }; // Max length mus be at least 1 interface + 2 endpoints - TU_VERIFY(max_len >= _MSC_DRIVER_LEN, 0); + TU_ASSERT(max_len >= _MSC_DRIVER_LEN, 0); mscd_interface_t * p_msc = &_mscd_itf; p_msc->itf_num = itf_desc->bInterfaceNumber; -- cgit v1.3.1 From 8f560bf275b9c0d6d6e524962deb4d7e2502623e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 11:41:37 +0700 Subject: update midi open() --- src/class/midi/midi_device.c | 55 ++++++++++++++++++++++---------------------- src/class/midi/midi_device.h | 12 +++++----- 2 files changed, 34 insertions(+), 33 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 7bc8cef84..69dafe0a0 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -290,31 +290,30 @@ void midid_reset(uint8_t rhport) } } -bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length) +uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { - // 1st Interface is Audio Control v1 TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol); + AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol, 0); uint16_t drv_len = tu_desc_len(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf); // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } // 2nd Interface is MIDI Streaming - TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol ); + AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; @@ -327,40 +326,42 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t } } - p_midi->itf_num = desc_midi->bInterfaceNumber; + p_midi->itf_num = desc_midi->bInterfaceNumber; // next descriptor drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); // Find and open endpoint descriptors uint8_t found_endpoints = 0; - while (found_endpoints < desc_midi->bNumEndpoints) + while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - p_midi->ep_in = ep_addr; - } else { - p_midi->ep_out = ep_addr; - } + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) + { + p_midi->ep_in = ep_addr; + } else { + p_midi->ep_out = ep_addr; + } + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); - drv_len += p_desc[DESC_OFFSET_LEN]; - p_desc = tu_desc_next(p_desc); - found_endpoints += 1; + found_endpoints += 1; } - drv_len += p_desc[DESC_OFFSET_LEN]; - p_desc = tu_desc_next(p_desc); - } - *p_length = drv_len; + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } // Prepare for incoming data - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), 0 ); - return true; + return drv_len; } bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index e4d4f9d51..bec0984f2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -136,12 +136,12 @@ static inline bool tud_midi_send (uint8_t const packet[4]) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -bool midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init (void); +void midid_reset (uint8_t rhport); +uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 13860e9f947af18265f53d6b8663016fbf025bc7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 11:51:25 +0700 Subject: update net open() --- src/class/net/net_device.c | 38 +++++++++++++++++++------------------- src/class/net/net_device.h | 14 +++++++------- 2 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index fedd4db99..2d2a0b46d 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -135,7 +135,7 @@ void netd_reset(uint8_t rhport) netd_init(); } -bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && @@ -145,10 +145,10 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && 0x00 == itf_desc->bInterfaceProtocol); - TU_VERIFY ( is_rndis || is_ecm ); + TU_VERIFY(is_rndis || is_ecm, 0); // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_notif); + TU_ASSERT(0 == _netd_itf.ep_notif, 0); // sanity check the descriptor _netd_itf.ecm_mode = is_ecm; @@ -156,25 +156,25 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const * p_desc = tu_desc_next( itf_desc ); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { - (*p_length) += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } // notification endpoint (if any) if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface -------------// @@ -182,19 +182,19 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t // - CDC-ECM data interface has 2 alternate settings // - 0 : zero endpoints for inactive (default) // - 1 : IN & OUT endpoints for active networking - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); do { tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass); + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - (*p_length) += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) ); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) ); // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); if ( _netd_itf.ecm_mode ) { @@ -204,7 +204,7 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t }else { // Open endpoint pair for RNDIS - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); tud_network_init_cb(); @@ -215,9 +215,9 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t tud_network_recv_renew(); } - (*p_length) += 2*sizeof(tusb_desc_endpoint_t); + drv_len += 2*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..fb72146b0 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -72,13 +72,13 @@ void tud_network_xmit(struct pbuf *p); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); +void netd_init (void); +void netd_reset (uint8_t rhport); +uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); #ifdef __cplusplus } -- cgit v1.3.1 From bec5b5f9da8ecb82aed51452bedbcc5142df4c87 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 12:13:48 +0700 Subject: update usbtmc open() --- src/class/usbtmc/usbtmc_device.c | 43 +++++++++++++++++++++------------------- src/class/usbtmc/usbtmc_device.h | 12 +++++------ 2 files changed, 29 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index b14135146..a3ff76079 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -260,37 +260,39 @@ void usbtmcd_init_cb(void) usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } -bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void)rhport; + + uint16_t drv_len; uint8_t const * p_desc; uint8_t found_endpoints = 0; - TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); + TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); #ifndef NDEBUG // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); + TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); #endif - TU_ASSERT(usbtmc_state.state == STATE_CLOSED); + TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); // Interface - (*p_length) = 0u; + drv_len = 0u; p_desc = (uint8_t const *) itf_desc; usbtmc_state.itf_id = itf_desc->bInterfaceNumber; usbtmc_state.rhport = rhport; - while (found_endpoints < itf_desc->bNumEndpoints) + while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; switch(ep_desc->bmAttributes.xfer) { case TUSB_XFER_BULK: - TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE); + TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE, 0); if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) { usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; @@ -301,45 +303,46 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin break; case TUSB_XFER_INTERRUPT: #ifndef NDEBUG - TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN); - TU_ASSERT(usbtmc_state.ep_int_in == 0); + TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); + TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); #endif usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; break; default: - TU_ASSERT(false); + TU_ASSERT(false, 0); } - TU_VERIFY( usbd_edpt_open(rhport, ep_desc)); + TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); found_endpoints++; } - (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); - p_desc = tu_desc_next(p_desc); + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } // bulk endpoints are required, but interrupt IN is optional #ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0); - TU_ASSERT(usbtmc_state.ep_bulk_out != 0); + TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); + TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); if (itf_desc->bNumEndpoints == 2) { - TU_ASSERT(usbtmc_state.ep_int_in == 0); + TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); } else if (itf_desc->bNumEndpoints == 3) { - TU_ASSERT(usbtmc_state.ep_int_in != 0); + TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); } #if (CFG_TUD_USBTMC_ENABLE_488) if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || usbtmc_state.capabilities->bmDevCapabilities488.SR1) { - TU_ASSERT(usbtmc_state.ep_int_in != 0); + TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); } #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); tud_usbtmc_open_cb(itf_desc->iInterface); - return true; + return drv_len; } // Tell USBTMC class to set its bulk-in EP to ACK so that it can // receive USBTMC commands. diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index e231dd72d..a6b5e4cca 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -108,12 +108,12 @@ bool tud_usbtmc_start_bus_read(void); /* "callbacks" from USB device core */ -bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -void usbtmcd_reset_cb(uint8_t rhport); -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); -void usbtmcd_init_cb(void); +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +void usbtmcd_reset_cb(uint8_t rhport); +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +void usbtmcd_init_cb(void); /************************************************************ * USBTMC Descriptor Templates -- cgit v1.3.1 From c1db36a15c1e38adc142ec74fd5f3b0320053cc9 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 12:19:06 +0700 Subject: update vendor open() --- src/class/vendor/vendor_device.c | 14 +++++++------- src/class/vendor/vendor_device.h | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/class') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 7f2fe9793..98eafe44c 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -166,9 +166,9 @@ void vendord_reset(uint8_t rhport) } } -bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass); + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass, 0); // Find available interface vendord_interface_t* p_vendor = NULL; @@ -180,18 +180,18 @@ bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 break; } } - TU_VERIFY(p_vendor); + TU_VERIFY(p_vendor, 0); // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in)); + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); p_vendor->itf_num = itf_desc->bInterfaceNumber; - (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf))); + TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), drv_len); - return true; + return drv_len; } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 30fe94c3a..a4235bfce 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -118,10 +118,10 @@ static inline uint32_t tud_vendor_write_available (void) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void vendord_init(void); -void vendord_reset(uint8_t rhport); -bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void vendord_init(void); +void vendord_reset(uint8_t rhport); +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 10cd3f24bf0af9b7a1f357505ebbb5ef2132e34b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 13:48:02 +0700 Subject: initial transfer failed in open() shouldn't cause the driver open to fail. --- src/class/cdc/cdc_device.c | 11 +++++------ src/class/hid/hid_device.c | 9 ++++++++- src/class/midi/midi_device.c | 6 +++++- src/class/msc/msc_device.c | 6 +++++- src/class/vendor/vendor_device.c | 9 ++++++--- src/common/tusb_common.h | 3 +++ 6 files changed, 32 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a24f348f4..a8a58980a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -231,8 +231,6 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Note: 0xFF can be used with RNDIS TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); - uint16_t len = 0; - // Find available interface cdcd_interface_t * p_cdc = NULL; uint8_t cdc_id; @@ -249,13 +247,13 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; + uint16_t len = sizeof(tusb_desc_interface_t); uint8_t const * p_desc = tu_desc_next( itf_desc ); - len = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) { - len += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -266,7 +264,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - len += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -275,12 +273,13 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - len += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len += 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 51bd153ec..64a57e90e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -196,7 +196,14 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); // Prepare for output endpoint - if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)), 0); + if (p_hid->ep_out) + { + if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } + } return sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); } diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 69dafe0a0..14fb3e50d 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -359,7 +359,11 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } // Prepare for incoming data - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), 0 ); + if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } return drv_len; } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index c3ce495e1..00a5b4525 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -174,7 +174,11 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); // Prepare for Command Block Wrapper - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); + if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } return _MSC_DRIVER_LEN; } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 98eafe44c..8f2dfef32 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -186,12 +186,15 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); p_vendor->itf_num = itf_desc->bInterfaceNumber; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), drv_len); + if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } - return drv_len; + return sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f144cda73..4b4183ae6 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -228,6 +228,7 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) for(uint32_t i=0; i 1 @@ -277,6 +279,7 @@ static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t ke #define TU_LOG1_VAR(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) + #define TU_LOG1_FAILED() #endif #ifndef TU_LOG2 -- cgit v1.3.1 From fb214f7cf792d3e8a3e1161c9797b68db71a1f68 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 13:57:49 +0700 Subject: rename to drv_len to be consistent --- src/class/cdc/cdc_device.c | 20 ++++++++++---------- src/class/dfu/dfu_rt_device.c | 8 ++++---- src/class/msc/msc_device.c | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a8a58980a..9180065c4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -247,14 +247,14 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; - uint16_t len = sizeof(tusb_desc_interface_t); + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const * p_desc = tu_desc_next( itf_desc ); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) @@ -264,8 +264,8 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// @@ -273,19 +273,19 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - len += 2*sizeof(tusb_desc_endpoint_t); + drv_len += 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data _prep_out_transaction(cdc_id); - return len; + return drv_len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 426680e8e..01d4e3490 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -66,15 +66,15 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t len = sizeof(tusb_desc_interface_t); + uint16_t drv_len = sizeof(tusb_desc_interface_t); if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } - return len; + return drv_len; } bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 00a5b4525..b038d00f7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -162,10 +162,10 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); // msc driver length is fixed - enum { _MSC_DRIVER_LEN = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) }; + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); // Max length mus be at least 1 interface + 2 endpoints - TU_ASSERT(max_len >= _MSC_DRIVER_LEN, 0); + TU_ASSERT(max_len >= drv_len, 0); mscd_interface_t * p_msc = &_mscd_itf; p_msc->itf_num = itf_desc->bInterfaceNumber; @@ -180,7 +180,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_BREAKPOINT(); } - return _MSC_DRIVER_LEN; + return drv_len; } // Handle class control request -- cgit v1.3.1 From 53b749fd72e9e4573c80f0bc4083c5cf9e82177c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 14:44:26 +0700 Subject: check max_len for vendor and hid --- src/class/hid/hid_device.c | 7 ++++--- src/class/vendor/vendor_device.c | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 64a57e90e..2a20bc173 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -162,8 +162,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - // max length is at least interface + hid descriptor + 1 endpoint - TU_ASSERT(max_len >= sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t), 0); + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len, 0); // Find available interface hidd_interface_t * p_hid = NULL; @@ -205,7 +206,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 } } - return sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + return drv_len; } // Handle class control request diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8f2dfef32..3fcea89c4 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -170,6 +170,9 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass, 0); + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_VERIFY(max_len >= drv_len, 0); + // Find available interface vendord_interface_t* p_vendor = NULL; for(uint8_t i=0; ibNumEndpoints*sizeof(tusb_desc_endpoint_t); + return drv_len; } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -- cgit v1.3.1 From 56d46483e48879cb8a38dc13d7327daa15165754 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 17:04:10 +0200 Subject: Add bt hci device class Code implements USB transport for bluetooth HCI. --- src/class/bth/bth_device.c | 252 +++++++++++++++++++++++++++++++++++++++++++++ src/class/bth/bth_device.h | 110 ++++++++++++++++++++ src/device/usbd.c | 13 +++ src/device/usbd.h | 54 ++++++++++ src/tusb.h | 4 + src/tusb_option.h | 4 + 6 files changed, 437 insertions(+) create mode 100755 src/class/bth/bth_device.c create mode 100755 src/class/bth/bth_device.h (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c new file mode 100755 index 000000000..04011bcdb --- /dev/null +++ b/src/class/bth/bth_device.c @@ -0,0 +1,252 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "bth_device.h" +#include +#include + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_ev; + uint8_t ep_acl_in; + uint8_t ep_acl_out; + uint8_t ep_voice[2]; // Not used yet + uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; + +} btd_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; + +static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) +{ + // skip if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); + + TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +bool tud_bt_event_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_ev, event, event_len); +} + +bool tud_bt_acl_data_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void btd_init(void) +{ + tu_memclr(&_btd_itf, sizeof(_btd_itf)); +} + +void btd_reset(uint8_t rhport) +{ + (void)rhport; +} + +uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + tusb_desc_endpoint_t const *desc_ep; + uint16_t drv_len = 0; + // Size of single alternative of ISO interface + const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); + // Size of hci interface + const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + // Ensure this is BT Primary Controller + TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + + // Distinguish interface by number of endpoints, as both interface have same class, subclass and protocol + if (itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size) + { + _btd_itf.itf_num = itf_desc->bInterfaceNumber; + + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0); + _btd_itf.ep_ev = desc_ep->bEndpointAddress; + + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, + &_btd_itf.ep_acl_in), 0); + + // Prepare for incoming data from host + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + + drv_len = hci_itf_size; + } + else if (itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size) + { + uint8_t dir; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + + for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { + // Make sure rest of alternatives matches + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || + TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || + TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) + { + // Not an Iso interface instance + break; + } + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + } + } + + return drv_len; +} + +bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); + + return true; +} + +bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) + { + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); + } + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + { + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } + } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); +} + +bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + + // received new data from host + if (ep_addr == _btd_itf.ep_acl_out) + { + if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); + + // prepare for next data + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); + } + else if (ep_addr == _btd_itf.ep_ev) + { + if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); + } + else if (ep_addr == _btd_itf.ep_acl_in) + { + if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); + } + + return TUSB_ERROR_NONE; +} + +#endif diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h new file mode 100755 index 000000000..5e5468084 --- /dev/null +++ b/src/class/bth/bth_device.h @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_BTH_DEVICE_H_ +#define _TUSB_BTH_DEVICE_H_ + +#include +#include + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ +#ifndef CFG_TUD_BTH_EVENT_EPSIZE +#define CFG_TUD_BTH_EVENT_EPSIZE 16 +#endif +#ifndef CFG_TUD_BTH_DATA_EPSIZE +#define CFG_TUD_BTH_DATA_EPSIZE 64 +#endif + +typedef struct TU_ATTR_PACKED +{ + uint16_t op_code; + uint8_t param_length; + uint8_t param[255]; +} bt_hci_cmd_t; + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when HCI command was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.1. +// Length of the command is from 3 bytes (2 bytes for OpCode, +// 1 byte for parameter total length) to 258. +TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); + +// Invoked when ACL data was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.2. +// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length) to endpoint size. +TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); + +// Called when event sent with tud_bt_event_send() was delivered to BT stack. +// Controller can release/reuse buffer with Event packet at this point. +TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); + +// Called when ACL data that was sent with tud_bt_acl_data_send() +// was delivered to BT stack. +// Controller can release/reuse buffer with ACL packet at this point. +TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); + +// Bluetooth controller calls this function when it wants to send even packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. +// Event has at least 2 bytes, first is Event code second contains parameter +// total length. Controller can release/reuse event memory after +// tud_bt_event_sent_cb() is called. +bool tud_bt_event_send(void *event, uint16_t event_len); + +// Bluetooth controller calls this to send ACL data packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 +// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length). Upper limit is not limited +// to endpoint size since buffer is allocate by controller +// and must not be reused till tud_bt_acl_data_sent_cb() is called. +bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 3cbd50644..fe392ef6e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,19 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL, }, #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_request = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..2070b50c6 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -438,6 +438,60 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 +//------------- BT Radio -------------// +#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) +#define TUD_BT_APP_SUBCLASS 0x01 +#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 +#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 + +#ifndef CFG_TUD_BTH_ISO_ALT_COUNT +#define CFG_TUD_BTH_ISO_ALT_COUNT 0 +#endif + +// Length of template descriptor: 30 bytes + number of ISO alternatives * 23 +#define TUD_BTH_DESC_LEN (9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) + +/* Primary Interface */ +#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + +#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + +#define _FIRST(a, ...) a +#define _REST(a, ...) __VA_ARGS__ + +#define TUD_BTH_ISO_ITF_0(_itfnum, ...) +#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + +#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + +// BT Primary controller descriptor +// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes +#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus } diff --git a/src/tusb.h b/src/tusb.h index 55c105121..defbc54fb 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -95,6 +95,10 @@ #if CFG_TUD_NET #include "class/net/net_device.h" #endif + + #if CFG_TUD_BTH + #include "class/bth/bth_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 9e6a2b532..0a227483f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -219,6 +219,10 @@ #define CFG_TUD_NET 0 #endif +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From 4362665fb3ec1ef0d749bbcdaabe161ce1c06614 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 12:36:05 +0200 Subject: Fix mic audio descriptor, fix too strict check on IAD desc. in usbd.c --- src/class/audio/audio.h | 6 + src/class/audio/audio_device.c | 8 +- src/class/audio/audio_device.h | 2 +- src/device/usbd.c | 2 +- src/device/usbd.h | 521 +++++++++++++++++++++++++---------------- 5 files changed, 330 insertions(+), 209 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index f4f460c22..022f3118f 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -57,6 +57,12 @@ typedef enum AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; +/// Audio Function Subclass Codes +typedef enum +{ + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; + /// Audio Protocol Codes typedef enum { diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fbd412564..1c9e0494e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -632,7 +632,7 @@ void audiod_reset(uint8_t rhport) } } -bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); @@ -666,9 +666,11 @@ bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_ // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) // Notify caller we read complete descriptor - (*p_length) += tud_audio_desc_lengths[i]; +// (*p_length) += tud_audio_desc_lengths[i]; + // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - return true; + return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5354adbd4..3e1fa7a92 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -289,7 +289,7 @@ inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) //--------------------------------------------------------------------+ void audiod_init (void); void audiod_reset (uint8_t rhport); -bool audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 26c7d3936..912c922c5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -779,7 +779,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // IAD's first interface number and class/subclass/protocol should match with opened interface TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && - desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && + // desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); for(uint8_t i=1; ibInterfaceCount; i++) diff --git a/src/device/usbd.h b/src/device/usbd.h index 7bc79a6f6..39ad7639e 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -31,7 +31,7 @@ #define _TUSB_USBD_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif #include "common/tusb_common.h" @@ -62,7 +62,7 @@ bool tud_suspended(void); // Check if device is ready to transfer static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + return tud_mounted() && !tud_suspended(); } // Remote wake up host, only if suspended and enabled by host @@ -72,18 +72,18 @@ bool tud_remote_wakeup(void); // Return false on unsupported MCUs static inline bool tud_disconnect(void) { - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; } // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs static inline bool tud_connect(void) { - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; } // Carry out Data and Status stage of control transfer @@ -146,11 +146,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // total length, number of device caps #define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num + 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num // Device Capability Platform 128-bit UUID + Data #define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ + 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ //------------- WebUSB BOS Platform -------------// @@ -159,22 +159,22 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Vendor Code, iLandingPage #define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) #define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ + 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 //------------- Microsoft OS 2.0 Platform -------------// #define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 // Total Length of descriptor set, vendor code #define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) #define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ + 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ // Configuration & Interface Descriptor Templates @@ -185,7 +185,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// @@ -195,26 +195,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ - /* CDC Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC Call */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ + /* CDC Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC Call */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* CDC ACM: support line request */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- MSC -------------// @@ -223,12 +223,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & EP In address, EP size #define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- HID -------------// @@ -238,12 +238,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input only descriptor // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval // Length of template descriptor: 32 bytes #define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) @@ -251,57 +251,57 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + /* Audio Control (AC) Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ + /* AC Header */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + /* MIDI Streaming (MS) Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + /* MS Header */\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) #define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) + (uint8_t)(((_cablenum) - 1) * 4 + 1) #define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) + (uint8_t)(((_cablenum) - 1) * 4 + 2) #define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) + (uint8_t)(((_cablenum) - 1) * 4 + 3) #define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) + (uint8_t)(((_cablenum) - 1) * 4 + 4) #define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) #define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + /* MS In Jack (Embedded) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ + /* MS In Jack (External) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ + /* MS Out Jack (Embedded), connected to In Jack External */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ + /* MS Out Jack (External), connected to In Jack Embedded */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 #define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + /* Endpoint */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables // Length of template descriptor (88 bytes) #define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) @@ -310,50 +310,163 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // - 1 Embedded Jack In connected to 1 External Jack Out // - 1 Embedded Jack out connected to 1 External Jack In #define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) //------------- AUDIO -------------// -// Length of template descriptor (132 bytes) -#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) -#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 +/* Standard Interface Association Descriptor (IAD) */ +#define TUD_AUDIO_DESC_IAD_LEN 8 +#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_PROTOCOL_V2, _stridx + +/* Standard AC Interface Descriptor(4.7.1) */ +#define TUD_AUDIO_DESC_STD_AC_LEN 9 +#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx + +/* Class-Specific AC Interface Header Descriptor(4.7.2) */ +#define TUD_AUDIO_DESC_CS_AC_LEN 9 +#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ + TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl + +/* Clock Source Descriptor(4.7.2.1) */ +#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 +#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ + TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx + +/* Input Terminal Descriptor(4.7.2.4) */ +#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 +#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ + TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx + +/* Output Terminal Descriptor(4.7.2.5) */ +#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 +#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx + +/* Feature Unit Descriptor(4.7.2.8) */ +// 1 - Channel +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx + +// For more channels, add definitions here + +/* Standard AS Interface Descriptor(4.9.1) */ +#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 +#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, _stridx + +/* Class-Specific AS Interface Descriptor(4.9.2) */ +#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 +#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ + TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx + +/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ +#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 +#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution + +/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval + +/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ +#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 +#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces + #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ - /* Standard AC Interface Descriptor(4.7.1) */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ - /* Clock Source Descriptor(4.7.2.1) */\ - 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ - /* Input Terminal Descriptor(4.7.2.4) */\ - 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ - /* Output Terminal Descriptor(4.7.2.5) */\ - 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ - /* Feature Unit Descriptor(4.7.2.8) */\ - 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, \ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000)\ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// Length of template descriptor (132 bytes) +//#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) +//#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 +// +// // AUDIO simple descriptor (UAC2) for 1 microphone input +// // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source +// #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +// /* Standard Interface Association Descriptor (IAD) */\ +// 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Standard AC Interface Descriptor(4.7.1) */\ +// 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ +// /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ +// 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ +// /* Clock Source Descriptor(4.7.2.1) */\ +// 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ +// /* Input Terminal Descriptor(4.7.2.4) */\ +// 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ +// /* Output Terminal Descriptor(4.7.2.5) */\ +// 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ +// /* Feature Unit Descriptor(4.7.2.8) */\ +// 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ +// /* Standard AS Interface Descriptor(4.9.1) */\ +// /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ +// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Standard AS Interface Descriptor(4.9.1) */\ +// /* Interface 1, Alternate 1 - alternate interface for data streaming */\ +// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Class-Specific AS Interface Descriptor(4.9.2) */\ +// 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00,\ +// /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ +// 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ +// /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ +// 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ +// /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ +// 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000) + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -365,23 +478,23 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID #define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ - /* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + /* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx #define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u #define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ - /* Endpoint Out */ \ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ - /* Endpoint In */ \ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + /* Endpoint Out */ \ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ + /* Endpoint In */ \ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u #define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) /* optional interrupt endpoint */ \ // _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? #define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ - 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) @@ -391,12 +504,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & IN address, EP size #define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- DFU Runtime -------------// #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -408,10 +521,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // DFU runtime descriptor // Interface number, string index, attributes, detach timeout, transfer size #define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) //------------- CDC-ECM -------------// @@ -422,40 +535,40 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-ECM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-ECM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- RNDIS -------------// #if 0 - /* Windows XP */ - #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC - #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL - #define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ +/* Windows XP */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC +#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else - /* Windows 7+ */ - #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER - #define TUD_RNDIS_ITF_SUBCLASS 0x01 - #define TUD_RNDIS_ITF_PROTOCOL 0x03 +/* Windows 7+ */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER +#define TUD_RNDIS_ITF_SUBCLASS 0x01 +#define TUD_RNDIS_ITF_PROTOCOL 0x03 #endif // Length of template descriptor: 66 bytes @@ -464,26 +577,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // RNDIS Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- BT Radio -------------// #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) @@ -500,20 +613,20 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 #define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 #define _FIRST(a, ...) a #define _REST(a, ...) __VA_ARGS__ @@ -521,27 +634,27 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_BTH_ISO_ITF_0(_itfnum, ...) #define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus - } +} #endif #endif /* _TUSB_USBD_H_ */ -- cgit v1.3.1 From 2b1c7730b719c6d4abd7d1bfbfdb80b0d64ee892 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Jun 2020 00:53:06 +0700 Subject: fix hs port1 build with net endpoint --- src/class/net/net_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..964bc8a00 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -37,7 +37,7 @@ #include "netif/ethernet.h" /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -#define CFG_TUD_NET_ENDPOINT_SIZE ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) +#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) /* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ #define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) -- cgit v1.3.1 From 57b553e023ccac4c623bd7f57a7370fb43411ec1 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 16 Jun 2020 14:13:30 +0200 Subject: Fix IAR warnings. Pa039 : use of address of unaligned structure member. Pe188: enumerated type mixed with another type. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 13 +++++++------ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 29b10c0fa..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -846,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -861,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -915,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From 8fe887198b63520c23af9f4c27d9733f6bb18e90 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 18 Jun 2020 01:13:44 -0700 Subject: Add tx callback to cdc device Useful for continuous transmission of data, which is difficult currently because there is no notification of tx completion. --- src/class/cdc/cdc_device.c | 3 +++ src/class/cdc/cdc_device.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 9180065c4..b979b11f1 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,6 +416,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); + if ( 0 == tud_cdc_n_write_flush(itf) ) { // There is no data left, a ZLP should be sent if diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index a2523d8d0..13b59416b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -128,6 +128,9 @@ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); +// Invoked when space becomes available in TX buffer +TU_ATTR_WEAK void tud_cdc_tx_cb(uint8_t itf); + // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); -- cgit v1.3.1 From ada82b840f642681f8012cb2a46aa7577393dd30 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 20 Jun 2020 10:51:21 +0200 Subject: Get update from tinyusb. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 21 ++++++++++----------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 3708a9aff..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -763,11 +763,9 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // If IAD exist, assign all interfaces to the same driver if (desc_itf_assoc) { - // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && - desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && - desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + // IAD's first interface number and class should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { @@ -848,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -863,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -917,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From 7ae47a93979071ec3c7724c35f1ef55572ad1a1f Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Sat, 20 Jun 2020 22:12:10 -0700 Subject: Call tud_cdc_tx_cb right after flush to keep tx fifo full --- src/class/cdc/cdc_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b979b11f1..d8be48688 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,9 +416,6 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); - if ( 0 == tud_cdc_n_write_flush(itf) ) { // There is no data left, a ZLP should be sent if @@ -428,6 +425,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } } + + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); } // nothing to do with notif endpoint for now -- cgit v1.3.1 From 12a145b27db28a55cc99a89487bdd531bc5f950e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Jul 2020 01:33:02 +0700 Subject: fix dfu-rt to response to SET_INTERFACE and DFU_GETSTATUS fix #450 --- src/class/cdc/cdc_device.c | 2 +- src/class/dfu/dfu_rt_device.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 9180065c4..4d6e57878 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -364,7 +364,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request tud_control_status(rhport, request); // Invoke callback - if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts); + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 01d4e3490..d4c3ecb62 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -44,6 +44,14 @@ typedef enum { DFU_REQUEST_ABORT = 6, } dfu_requests_t; +typedef struct TU_ATTR_PACKED +{ + uint8_t status; + uint8_t poll_timeout[3]; + uint8_t state; + uint8_t istring; +} dfu_status_t; + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ @@ -88,10 +96,19 @@ bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * req bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request) { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + switch ( request->bRequest ) { case DFU_REQUEST_DETACH: @@ -99,6 +116,14 @@ bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * requ tud_dfu_rt_reboot_to_dfu(); break; + case DFU_REQUEST_GETSTATUS: + { + // status = OK, poll timeout = 0, state = app idle, istring = 0 + uint8_t status_response[6] = { 0, 0, 0, 0, 0, 0 }; + tud_control_xfer(rhport, request, status_response, sizeof(status_response)); + } + break; + default: return false; // stall unsupported request } -- cgit v1.3.1 From 323ae5a84fec36e1ad6233d8721b4648a3cf406b Mon Sep 17 00:00:00 2001 From: Craig Hutchinson <54269136+CraigHutchinson@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:24:09 +0100 Subject: Improve comment on CDC tud_cdc_write_available() Fixes #460 --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index a2523d8d0..897fd272b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -95,7 +95,7 @@ uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); // Force sending data if possible, return number of forced bytes uint32_t tud_cdc_n_write_flush (uint8_t itf); -// Return number of characters available for writing +// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. uint32_t tud_cdc_n_write_available (uint8_t itf); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 706413f7510a78e262cf3cb398256e06fadbd500 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 00:44:09 +0700 Subject: add tud_speed_get() - define both fs and hs configuration descriptor - rename CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE with default size of 64 for FS, and 512 for HS --- .../device/cdc_dual_ports/src/usb_descriptors.c | 48 +++++++++++++++++----- examples/device/cdc_msc/src/usb_descriptors.c | 28 +++++++++++-- .../device/webusb_serial/src/usb_descriptors.c | 6 +-- examples/rules.mk | 8 +++- src/class/cdc/cdc_device.c | 14 +++---- src/class/cdc/cdc_device.h | 4 +- src/device/usbd.c | 5 +++ src/device/usbd.h | 3 ++ tools/build_all.py | 2 +- 9 files changed, 90 insertions(+), 28 deletions(-) (limited to 'src/class') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index a4674b7a9..a27a2cdbd 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -74,10 +74,10 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ enum { - ITF_NUM_CDC1 = 0, - ITF_NUM_CDC_DATA1, - ITF_NUM_CDC2, - ITF_NUM_CDC_DATA2, + ITF_NUM_CDC_0 = 0, + ITF_NUM_CDC_0_DATA, + ITF_NUM_CDC_1, + ITF_NUM_CDC_1_DATA, ITF_NUM_TOTAL }; @@ -86,30 +86,58 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x84 + #define EPNUM_CDC_1_DATA 0x05 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x83 + #define EPNUM_CDC_1_DATA 0x04 #endif -uint8_t const desc_configuration[] = +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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC2, 4, 0x83, 8, EPNUM_CDC + 2, 0x80 | (EPNUM_CDC + 2), TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512), + + // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 9a4d71f24..447dc2644 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -114,18 +114,32 @@ enum #endif -uint8_t const desc_configuration[] = +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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -133,7 +147,13 @@ uint8_t const desc_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index a39b34c3c..935731c0b 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -86,10 +86,10 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 5 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 3 #endif @@ -99,7 +99,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC_0, 0x80 | EPNUM_CDC_0, TUD_OPT_HIGH_SPEED ? 512 : 64), // Interface number, string index, EP Out & IN address, EP size TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR, 0x80 | EPNUM_VENDOR, TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/rules.mk b/examples/rules.mk index eeb548d08..dacb81363 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -131,8 +131,14 @@ size: $(BUILD)/$(BOARD)-firmware.elf @$(SIZE) $< -@echo '' +.PHONY: clean clean: - rm -rf $(BUILD) + $(RM) -rf $(BUILD) + +# Print out the value of a make variable. +# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +print-%: + @echo $* = $($*) # Flash binary using Jlink ifeq ($(OS),Windows_NT) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 4d6e57878..89326f71d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -61,8 +61,8 @@ typedef struct #endif // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; }cdcd_interface_t; @@ -82,9 +82,9 @@ static void _prep_out_transaction (uint8_t itf) // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) ) + if ( max_read >= sizeof(p_cdc->epout_buf) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf)); + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } } @@ -148,7 +148,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EPSIZE ) + if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +164,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // skip if previous transfer not complete yet TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected @@ -420,7 +420,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 897fd272b..39ccf6b76 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -34,8 +34,8 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_CDC_EPSIZE -#define CFG_TUD_CDC_EPSIZE 64 +#ifndef CFG_TUD_CDC_EP_BUFSIZE +#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..f59b19427 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -294,6 +294,11 @@ void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ +tusb_speed_t tud_speed_get(void) +{ + return (tusb_speed_t) _usbd_dev.speed; +} + bool tud_mounted(void) { return _usbd_dev.configured; diff --git a/src/device/usbd.h b/src/device/usbd.h index e9b82747a..d9facf719 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -53,6 +53,9 @@ bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD #define tud_int_handler dcd_int_handler +// Get current bus speed +tusb_speed_t tud_speed_get(void); + // Check if device is connected and configured bool tud_mounted(void); diff --git a/tools/build_all.py b/tools/build_all.py index 25cdc9778..af57cdd5c 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -38,7 +38,7 @@ all_boards.sort() def build_example(example, board): subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, + return subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def build_size(example, board): -- cgit v1.3.1 From fea6fb73a1ef65afd848ec71d49d65cc87a9eec9 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 13:02:20 +0700 Subject: add fs & hs config for cdc_msc_freertos, midi_test, msc_dual_lun --- .../device/cdc_msc_freertos/src/usb_descriptors.c | 25 +++++++++++++++++++--- examples/device/midi_test/src/usb_descriptors.c | 23 +++++++++++++++++--- examples/device/msc_dual_lun/src/usb_descriptors.c | 23 +++++++++++++++++--- src/class/cdc/cdc_device.h | 2 +- src/class/midi/midi_device.c | 10 ++++----- src/class/midi/midi_device.h | 2 +- 6 files changed, 69 insertions(+), 16 deletions(-) (limited to 'src/class') diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 62ab4f10f..e167ac05f 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -114,7 +114,7 @@ enum #endif -uint8_t const desc_configuration[] = +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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), @@ -123,9 +123,22 @@ uint8_t const desc_configuration[] = TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -133,7 +146,13 @@ uint8_t const desc_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 2867a205f..d529a0547 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -88,22 +88,39 @@ enum #define EPNUM_MIDI 0x01 #endif -uint8_t const desc_configuration[] = +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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, TUD_OPT_HIGH_SPEED ? 512 : 64) + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) }; +#if TUD_OPT_HIGH_SPEED +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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 512) +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index d0c915b1d..a4e03e68c 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -96,22 +96,39 @@ enum #endif -uint8_t const desc_configuration[] = +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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 39ccf6b76..2d3312b21 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -35,7 +35,7 @@ // Class Driver Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUD_CDC_EP_BUFSIZE -#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 14fb3e50d..d4ed21c78 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -67,8 +67,8 @@ typedef struct uint8_t read_target_length; // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; } midid_interface_t; @@ -160,7 +160,7 @@ static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) // skip if previous transfer not complete TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EPSIZE); + uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); if (count > 0) { TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); @@ -359,7 +359,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } // Prepare for incoming data - if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE) ) + if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE) ) { TU_LOG1_FAILED(); TU_BREAKPOINT(); @@ -404,7 +404,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false ); } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index bec0984f2..8f60d264a 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -37,7 +37,7 @@ // Class Driver Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUD_MIDI_EPSIZE -#define CFG_TUD_MIDI_EPSIZE 64 + #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus -- cgit v1.3.1 From 5ca748a68e01deec929e846b7263cf736bf891fb Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 15:34:16 +0700 Subject: rename CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE rename CFG_TUD_HID_BUFSIZE to CFG_TUD_HID_EP_BUFSIZE --- examples/device/board_test/src/tusb_config.h | 5 +---- examples/device/cdc_msc/src/tusb_config.h | 6 +----- examples/device/cdc_msc_freertos/src/tusb_config.h | 6 +----- .../device/dynamic_configuration/src/tusb_config.h | 24 +++++++++------------- examples/device/hid_composite/src/tusb_config.h | 12 +++++------ .../device/hid_composite/src/usb_descriptors.c | 2 +- .../hid_composite_freertos/src/tusb_config.h | 12 +++++------ .../hid_composite_freertos/src/usb_descriptors.c | 2 +- .../device/hid_generic_inout/src/tusb_config.h | 12 +++++------ .../device/hid_generic_inout/src/usb_descriptors.c | 4 ++-- examples/device/midi_test/src/tusb_config.h | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 2 +- examples/device/msc_dual_lun/src/tusb_config.h | 12 +++++------ examples/device/usbtmc/src/tusb_config.h | 6 +++--- examples/device/webusb_serial/src/tusb_config.h | 4 ++-- src/class/hid/hid_device.c | 8 ++++---- src/class/hid/hid_device.h | 10 +++++++-- src/class/msc/msc_device.c | 4 ++-- src/class/msc/msc_device.h | 13 +++++++++--- test/test/support/tusb_config.h | 2 +- 20 files changed, 74 insertions(+), 76 deletions(-) (limited to 'src/class') diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 0587d48e3..da33729e7 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -73,14 +73,11 @@ //------------- CLASS -------------// #define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 1 +#define CFG_TUD_MSC 0 #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -// MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - #ifdef __cplusplus } #endif diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 13021d5d3..1370e61c5 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -97,7 +97,6 @@ #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 #define CFG_TUD_HID 0 - #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 @@ -106,10 +105,7 @@ #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index f7e48f66e..712f328ea 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -99,7 +99,6 @@ #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 #define CFG_TUD_HID 0 - #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 @@ -108,10 +107,7 @@ #define CFG_TUD_CDC_TX_BUFSIZE 64 // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/dynamic_configuration/src/tusb_config.h b/examples/device/dynamic_configuration/src/tusb_config.h index 0950305eb..2f8072f89 100644 --- a/examples/device/dynamic_configuration/src/tusb_config.h +++ b/examples/device/dynamic_configuration/src/tusb_config.h @@ -94,26 +94,22 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 1 -#define CFG_TUD_MSC 1 -#define CFG_TUD_HID 0 - -#define CFG_TUD_MIDI 1 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC 1 +#define CFG_TUD_MSC 1 +#define CFG_TUD_MIDI 1 +#define CFG_TUD_HID 0 +#define CFG_TUD_VENDOR 0 // CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // MIDI FIFO size of TX and RX -#define CFG_TUD_MIDI_RX_BUFSIZE 64 -#define CFG_TUD_MIDI_TX_BUFSIZE 64 +#define CFG_TUD_MIDI_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_MIDI_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index abc243436..d8e6b73e8 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_HID 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_HID 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 16 #ifdef __cplusplus } diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 02cbc17f6..fe46f7d69 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -105,7 +105,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index 677a9b2c6..4b0458ef0 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_HID 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_HID 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 16 #ifdef __cplusplus } diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index 02cbc17f6..fe46f7d69 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -105,7 +105,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index 39eebbbeb..347cb06d6 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 1 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 1 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 64 +#define CFG_TUD_HID_EP_BUFSIZE 64 #ifdef __cplusplus } diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 5c769c9c9..290e12dfd 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -72,7 +72,7 @@ uint8_t const * tud_descriptor_device_cb(void) uint8_t const desc_hid_report[] = { - TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_BUFSIZE) + TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) }; // Invoked when received GET HID REPORT DESCRIPTOR @@ -103,7 +103,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index fd109ad32..d0c327e27 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -101,8 +101,8 @@ #define CFG_TUD_VENDOR 0 // MIDI FIFO size of TX and RX -#define CFG_TUD_MIDI_RX_BUFSIZE 64 -#define CFG_TUD_MIDI_TX_BUFSIZE 64 +#define CFG_TUD_MIDI_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_MIDI_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #ifdef __cplusplus } diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index d529a0547..3c556a156 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -98,7 +98,7 @@ uint8_t const desc_fs_configuration[] = }; #if TUD_OPT_HIGH_SPEED -uint8_t const desc_fs_configuration[] = +uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 1ee3faec4..e153a7967 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 1 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 1 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 3fab286a9..603e67453 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -77,9 +77,9 @@ //------------- CLASS -------------// -#define CFG_TUD_USBTMC 1 -#define CFG_TUD_USBTMC_ENABLE_INT_EP 1 -#define CFG_TUD_USBTMC_ENABLE_488 1 +#define CFG_TUD_USBTMC 1 +#define CFG_TUD_USBTMC_ENABLE_INT_EP 1 +#define CFG_TUD_USBTMC_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index a9b7a82d5..48c9ddad6 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -101,8 +101,8 @@ #define CFG_TUD_VENDOR 1 // 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) +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // Vendor FIFO size of TX and RX // If not configured vendor endpoints will not be buffered diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 526394d4a..c46fc591a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -48,8 +48,8 @@ typedef struct uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; tusb_hid_descriptor_hid_t const * hid_descriptor; } hidd_interface_t; @@ -86,7 +86,7 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) if (report_id) { - len = tu_min8(len, CFG_TUD_HID_BUFSIZE-1); + len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); p_hid->epin_buf[0] = report_id; memcpy(p_hid->epin_buf+1, report, len); @@ -94,7 +94,7 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) }else { // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_BUFSIZE); + len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); memcpy(p_hid->epin_buf, report, len); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index ad8c9ece4..ad26ab369 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -39,8 +39,14 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#ifndef CFG_TUD_HID_BUFSIZE -#define CFG_TUD_HID_BUFSIZE 16 +#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) + // TODO warn user to use new name later on + // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE +#endif + +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 16 #endif //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3ddcd4e49..692fd2441 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -65,7 +65,7 @@ typedef struct }mscd_interface_t; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -564,7 +564,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t else { // READ10 & WRITE10 Can be executed with large bulk of data e.g write 8K bytes (several flash write) - // We break it into multiple smaller command whose data size is up to CFG_TUD_MSC_BUFSIZE + // We break it into multiple smaller command whose data size is up to CFG_TUD_MSC_EP_BUFSIZE if (SCSI_CMD_READ_10 == p_cbw->command[0]) { proc_read10_cmd(rhport, p_msc); diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 30ffd02e1..995491ec4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -38,12 +38,19 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); -#ifndef CFG_TUD_MSC_BUFSIZE - #error CFG_TUD_MSC_BUFSIZE must be defined, value of a block size should work well, the more the better +#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) + // TODO warn user to use new name later on + // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE + #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE #endif +#ifndef CFG_TUD_MSC_EP_BUFSIZE + #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better +#endif + +TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); + /** \addtogroup ClassDriver_MSC * @{ * \defgroup MSC_Device Device diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 76f975323..80ea0a1ea 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -94,7 +94,7 @@ //------------- HID -------------// // Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 16 #ifdef __cplusplus } -- cgit v1.3.1 From d0f3d039332cf22637d191cc62bed620c4f14dce Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 17 Jul 2020 08:40:10 +0200 Subject: Intermediate commit. --- src/class/audio/audio.h | 332 ++++++++++++++++++++++++++++++----------- src/class/audio/audio_device.c | 268 ++++++++++++++++++++++++++++++--- src/class/audio/audio_device.h | 21 +++ src/device/usbd.h | 43 +----- src/tusb_option.h | 6 +- 5 files changed, 525 insertions(+), 145 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 022f3118f..f1784a006 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -38,17 +38,22 @@ extern "C" { #endif -/// Isochronous End Point Attributes +/// Audio Device Class Codes + +/// A.2 - Audio Function Subclass Codes typedef enum { - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point -} tusb_iso_ep_attribute_t; + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; -/// Audio Interface Subclass Codes +/// A.3 - Audio Function Protocol Codes +typedef enum +{ + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_function_protocol_code_t; + +/// A.5 - Audio Interface Subclass Codes typedef enum { AUDIO_SUBCLASS_UNDEFINED = 0x00, @@ -57,23 +62,17 @@ typedef enum AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; -/// Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// Audio Protocol Codes +/// A.6 - Audio Interface Protocol Codes typedef enum { - AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 - AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 - AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 -} audio_protocol_type_t; + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_t; -/// Audio Function Category Codes +/// A.7 - Audio Function Category Codes typedef enum { + AUDIO_FUNC_UNDEF = 0x00, AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, AUDIO_FUNC_HOME_THEATER = 0x02, AUDIO_FUNC_MICROPHONE = 0x03, @@ -86,9 +85,10 @@ typedef enum AUDIO_FUNC_PRO_AUDIO = 0x0A, AUDIO_FUNC_AUDIO_VIDEO = 0x0B, AUDIO_FUNC_CONTROL_PANEL = 0x0C, -} audio_function_t; + AUDIO_FUNC_OTHER = 0xFF, +} audio_function_code_t; -/// Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 typedef enum { AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, @@ -107,7 +107,7 @@ typedef enum AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, } audio_cs_ac_interface_subtype_t; -/// Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 typedef enum { AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, @@ -117,6 +117,150 @@ typedef enum AUDIO_CS_AS_INTERFACE_DECODER = 0x04, } audio_cs_as_interface_subtype_t; +/// A.11 - Effect Unit Effect Types +typedef enum +{ + AUDIO_EFFECT_TYPE_UNDEF = 0x00, + AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio_effect_unit_effect_type_t; + +/// A.12 - Processing Unit Process Types +typedef enum +{ + AUDIO_PROCESS_TYPE_UNDEF = 0x00, + AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio_processing_unit_process_type_t; + +/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// A.14 - Audio Class-Specific Request Codes +typedef enum +{ + AUDIO_CS_REQ_UNDEF = 0x00, + AUDIO_CS_REQ_CUR = 0x01, + AUDIO_CS_REQ_RANGE = 0x02, + AUDIO_CS_REQ_MEM = 0x03, +} audio_cs_req_t; + +/// A.17 - Control Selector Codes + +/// A.17.1 - Clock Source Control Selectors +typedef enum +{ + AUDIO_CLK_SRC_CTRL_UNDEF = 0x00, + AUDIO_CLK_SRC_CTRL_SAM_FREQ = 0x01, + AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, +} audio_clock_src_control_selector_t; + +/// A.17.7 - Feature Unit Control Selectors +typedef enum +{ + AUDIO_FU_CTRL_UNDEF = 0x00, + AUDIO_FU_CTRL_MUTE = 0x01, + AUDIO_FU_CTRL_VOLUME = 0x02, + AUDIO_FU_CTRL_BASS = 0x03, + AUDIO_FU_CTRL_MID = 0x04, + AUDIO_FU_CTRL_TREBLE = 0x05, + AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO_FU_CTRL_AGC = 0x07, + AUDIO_FU_CTRL_DELAY = 0x08, + AUDIO_FU_CTRL_BASS_BOOST = 0x09, + AUDIO_FU_CTRL_LOUDNESS = 0x0A, + AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO_FU_CTRL_INVERTER = 0x0D, + AUDIO_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO_FU_CTRL_OVERVLOW = 0x0F, + AUDIO_FU_CTRL_LATENCY = 0x10, +} audio_feature_unit_control_selector_t; + +// Rest is yet to be implemented! + +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +/// Additional Audio Device Class Codes - Source: Audio Data Formats + +/// A.1 - Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), +} audio_data_format_type_I_t; + +/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification + +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + /// Audio Class-Control Values UAC2 typedef enum { @@ -138,13 +282,6 @@ typedef enum AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, } audio_cs_as_interface_control_pos_t; -/// Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_DESCRIPTOR_UNDEFINED = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - /// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 typedef enum { @@ -198,26 +335,6 @@ typedef enum AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, } audio_clock_multiplier_control_pos_t; -/// Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - /// Audio Class-Input Terminal Controls UAC2 typedef enum { @@ -229,19 +346,6 @@ typedef enum AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, } audio_terminal_input_control_pos_t; -/// Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - /// Audio Class-Output Terminal Controls UAC2 typedef enum { @@ -272,29 +376,6 @@ typedef enum AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, } audio_feature_unit_control_pos_t; -/// Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -/// Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = 0x00000000, - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = 0x00000001, - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x00000002, - AUDIO_DATA_FORMAT_TYPE_I_ALAW = 0x00000003, - AUDIO_DATA_FORMAT_TYPE_I_MULAW = 0x00000004, -} audio_data_format_type_I_t; - /// Audio Class-Audio Channel Configuration UAC2 typedef enum { @@ -490,6 +571,85 @@ typedef struct TU_ATTR_PACKED uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; +//// 5.2.3 Control Request Parameter Block Layout + +// 5.2.3.1 1-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_1_t; + +// 5.2.3.2 2-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_2_t; + +// 5.2.3.3 4-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_4_t; + +// 5.2.3.1 1-byte Control RANGE Parameter Block +//#define audio_control_range_1_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_1_t; + +// 5.2.3.2 2-byte Control RANGE Parameter Block +//#define audio_control_range_2_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_2_t; + +// 5.2.3.3 4-byte Control RANGE Parameter Block +//#define audio_control_range_4_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_4_t; /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1c9e0494e..67c94837a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -152,6 +152,9 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID); +static bool audiod_verify_itf_exists(uint8_t itf); +static bool audiod_verify_ep_exists(uint8_t ep); bool tud_audio_n_mounted(uint8_t itf) { @@ -638,7 +641,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed @@ -666,7 +669,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) // Notify caller we read complete descriptor -// (*p_length) += tud_audio_desc_lengths[i]; + // (*p_length) += tud_audio_desc_lengths[i]; // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor @@ -675,8 +678,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - #if CFG_TUD_AUDIO_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); @@ -690,6 +691,7 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * return true; #else + (void) rhport; (void) p_request; return false; #endif @@ -805,21 +807,85 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! TU_VERIFY(p_desc < p_desc_end); - // Conduct audio driver function specific stuff - - // HERE DO WHAT YOU HAVE TO DO - E.G. START ADC OR SO - //#error Implementation specific setInterface code required here! + // Invoke callback + if (tud_audio_set_itf_cb) + { + if (!tud_audio_set_itf_cb(rhport, p_request)) + { + return false; + } + } // Save current alternative interface setting _audiod_itf[idxDriver].altSetting[idxItf] = alt; + tud_control_status(rhport, p_request); + return true; } +// Invoked when class request DATA stage is finished. +// return false to stall control EP (e.g Host send non-sense DATA) bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - (void) p_request; + // Handle audio class specific set requests + if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + if (entityID != 0) + { + // Invoke callback + if (tud_audio_set_req_entity_cb && tud_audio_set_req_entity_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + else + { + // Invoke callback + if (tud_audio_set_req_itf_cb && tud_audio_set_req_itf_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Invoke callback + if (tud_audio_set_req_ep_cb && tud_audio_set_req_ep_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + + break; + + // Unknown/Unsupported recipient + default: TU_BREAKPOINT(); return false; + } + } return true; } @@ -829,17 +895,103 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req { (void) rhport; - switch (p_request->bRequest) + // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + if (entityID != 0) + { + TU_VERIFY(audiod_verify_entity_exists(itf, entityID)); + + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + } + } + else + { + TU_VERIFY(audiod_verify_itf_exists(itf)); + + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + // Verify if EP is present - This check may be omitted if we trust the host not to send rubbish + TU_VERIFY(audiod_verify_ep_exists(ep)); - default: + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + } + + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // Host expects an answer - in case no callback function is present we stall the request return false; } + + // There went something wrong + TU_BREAKPOINT(); + return false; } bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -936,19 +1088,22 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } +// This helper function finds for a given interface number the index of the attached driver interface, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the start i.e. alternate interface zero. static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (!_audiod_itf[i].p_desc) + if (_audiod_itf[i].p_desc) { // Get pointer at end uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; // Advance past AC descriptors - uint8_t const * p_desc = tu_desc_next(_audiod_itf[i].p_desc); + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; uint8_t tmp = 0; @@ -973,6 +1128,83 @@ static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t return false; } +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + // Look for the correct driver by checking if the unique standard AC interface number fits + if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_itf_exists(uint8_t itf) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at beginning and end + uint8_t const *p_desc = _audiod_itf[i].p_desc; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_ep_exists(uint8_t ep) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors - EP we look for are streaming EPs + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO // OLD diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 3e1fa7a92..95b361acd 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -229,6 +229,27 @@ bool tud_audio_fb_done_cb(uint8_t rhport); TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); #endif +// Invoked when audio set interface request received +TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an EP +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an interface +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an entity +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an EP +TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an interface +TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an entity +TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 39ad7639e..fa0be803c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -322,12 +322,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 #define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 #define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AC Interface Header Descriptor(4.7.2) */ #define TUD_AUDIO_DESC_CS_AC_LEN 9 @@ -360,7 +360,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AS Interface Descriptor(4.9.2) */ #define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 @@ -431,43 +431,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) -// Length of template descriptor (132 bytes) -//#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) -//#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 -// -// // AUDIO simple descriptor (UAC2) for 1 microphone input -// // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -// #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ -// /* Standard Interface Association Descriptor (IAD) */\ -// 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Standard AC Interface Descriptor(4.7.1) */\ -// 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ -// /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ -// 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ -// /* Clock Source Descriptor(4.7.2.1) */\ -// 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ -// /* Input Terminal Descriptor(4.7.2.4) */\ -// 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ -// /* Output Terminal Descriptor(4.7.2.5) */\ -// 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ -// /* Feature Unit Descriptor(4.7.2.8) */\ -// 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ -// /* Standard AS Interface Descriptor(4.9.1) */\ -// /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ -// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Standard AS Interface Descriptor(4.9.1) */\ -// /* Interface 1, Alternate 1 - alternate interface for data streaming */\ -// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Class-Specific AS Interface Descriptor(4.9.2) */\ -// 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00,\ -// /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ -// 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ -// /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ -// 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ -// /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ -// 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000) - - //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u diff --git a/src/tusb_option.h b/src/tusb_option.h index 0a227483f..cc91b1863 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -163,7 +163,7 @@ // Debug enable to print out error message #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 + #define CFG_TUSB_DEBUG 2 #endif // place data in accessible RAM for usb controller @@ -199,6 +199,10 @@ #define CFG_TUD_HID 0 #endif +#ifndef CFG_TUD_AUDIO + #define CFG_TUD_AUDIO 0 +#endif + #ifndef CFG_TUD_MIDI #define CFG_TUD_MIDI 0 #endif -- cgit v1.3.1 From 881025afdcdc3e8954163f8cc7337caa8455f594 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Jul 2020 23:01:39 +0700 Subject: add new name warning to cdc and midi (skip msc, hid warning for now) --- src/class/cdc/cdc_device.h | 5 +++++ src/class/hid/hid_device.h | 2 +- src/class/midi/midi_device.h | 8 +++++++- src/class/msc/msc_device.h | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2d3312b21..9d257bbe9 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -34,6 +34,11 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ +#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) + #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE +#endif + #ifndef CFG_TUD_CDC_EP_BUFSIZE #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index ad26ab369..f7ad38bab 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -41,7 +41,7 @@ #if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) // TODO warn user to use new name later on - // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE + // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE #endif diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 8f60d264a..1828a21a3 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -36,7 +36,13 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_MIDI_EPSIZE + +#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) + #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE +#endif + +#ifndef CFG_TUD_MIDI_EP_BUFSIZE #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 995491ec4..3aa93ffd7 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -41,7 +41,7 @@ #if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) // TODO warn user to use new name later on - // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE + // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE #endif -- cgit v1.3.1 From 47bcedc0b4744d3554f385906414005b511e9ae4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 18 Jul 2020 19:27:00 +0200 Subject: Add A.17.4 - Terminal Control Selectors --- src/class/audio/audio.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index f1784a006..301a26b2e 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -162,6 +162,19 @@ typedef enum AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, } audio_clock_src_control_selector_t; +/// A.17.4 - Terminal Control Selectors +typedef enum +{ + AUDIO_TERMINAL_CTRL_UNDEF = 0x00, + AUDIO_TERMINAL_CTRL_COPY_PROTECT = 0x01, + AUDIO_TERMINAL_CTRL_CONNECTOR = 0x02, + AUDIO_TERMINAL_CTRL_OVERLOAD = 0x03, + AUDIO_TERMINAL_CTRL_CLUSTER = 0x04, + AUDIO_TERMINAL_CTRL_UNDERFLOW = 0x05, + AUDIO_TERMINAL_CTRL_OVERFLOW = 0x06, + AUDIO_TERMINAL_CTRL_LATENCY = 0x07, +} audio_terminal_control_selector_t; + /// A.17.7 - Feature Unit Control Selectors typedef enum { -- cgit v1.3.1 From 077e881c92c0704c53ede854f50701c3ba6dd921 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 19 Jul 2020 11:53:35 +0200 Subject: Implement all missing A.17 control selectors --- src/class/audio/audio.h | 253 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 241 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 301a26b2e..011f5381b 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -157,24 +157,58 @@ typedef enum /// A.17.1 - Clock Source Control Selectors typedef enum { - AUDIO_CLK_SRC_CTRL_UNDEF = 0x00, - AUDIO_CLK_SRC_CTRL_SAM_FREQ = 0x01, - AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, + AUDIO_CS_CTRL_UNDEF = 0x00, + AUDIO_CS_CTRL_SAM_FREQ = 0x01, + AUDIO_CS_CTRL_CLK_VALID = 0x02, } audio_clock_src_control_selector_t; +/// A.17.2 - Clock Selector Control Selectors +typedef enum +{ + AUDIO_CX_CTRL_UNDEF = 0x00, + AUDIO_CX_CTRL_CONTROL = 0x01, +} audio_clock_sel_control_selector_t; + +/// A.17.3 - Clock Multiplier Control Selectors +typedef enum +{ + AUDIO_CM_CTRL_UNDEF = 0x00, + AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, + AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, +} audio_clock_mul_control_selector_t; + /// A.17.4 - Terminal Control Selectors typedef enum { - AUDIO_TERMINAL_CTRL_UNDEF = 0x00, - AUDIO_TERMINAL_CTRL_COPY_PROTECT = 0x01, - AUDIO_TERMINAL_CTRL_CONNECTOR = 0x02, - AUDIO_TERMINAL_CTRL_OVERLOAD = 0x03, - AUDIO_TERMINAL_CTRL_CLUSTER = 0x04, - AUDIO_TERMINAL_CTRL_UNDERFLOW = 0x05, - AUDIO_TERMINAL_CTRL_OVERFLOW = 0x06, - AUDIO_TERMINAL_CTRL_LATENCY = 0x07, + AUDIO_TE_CTRL_UNDEF = 0x00, + AUDIO_TE_CTRL_COPY_PROTECT = 0x01, + AUDIO_TE_CTRL_CONNECTOR = 0x02, + AUDIO_TE_CTRL_OVERLOAD = 0x03, + AUDIO_TE_CTRL_CLUSTER = 0x04, + AUDIO_TE_CTRL_UNDERFLOW = 0x05, + AUDIO_TE_CTRL_OVERFLOW = 0x06, + AUDIO_TE_CTRL_LATENCY = 0x07, } audio_terminal_control_selector_t; +/// A.17.5 - Mixer Control Selectors +typedef enum +{ + AUDIO_MU_CTRL_UNDEF = 0x00, + AUDIO_MU_CTRL_MIXER = 0x01, + AUDIO_MU_CTRL_CLUSTER = 0x02, + AUDIO_MU_CTRL_UNDERFLOW = 0x03, + AUDIO_MU_CTRL_OVERFLOW = 0x04, + AUDIO_MU_CTRL_LATENCY = 0x05, +} audio_mixer_control_selector_t; + +/// A.17.6 - Selector Control Selectors +typedef enum +{ + AUDIO_SU_CTRL_UNDEF = 0x00, + AUDIO_SU_CTRL_SELECTOR = 0x01, + AUDIO_SU_CTRL_LATENCY = 0x02, +} audio_sel_control_selector_t; + /// A.17.7 - Feature Unit Control Selectors typedef enum { @@ -197,7 +231,202 @@ typedef enum AUDIO_FU_CTRL_LATENCY = 0x10, } audio_feature_unit_control_selector_t; -// Rest is yet to be implemented! +/// A.17.8 Effect Unit Control Selectors + +/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors +typedef enum +{ + AUDIO_PE_CTRL_UNDEF = 0x00, + AUDIO_PE_CTRL_ENABLE = 0x01, + AUDIO_PE_CTRL_CENTERFREQ = 0x02, + AUDIO_PE_CTRL_QFACTOR = 0x03, + AUDIO_PE_CTRL_GAIN = 0x04, + AUDIO_PE_CTRL_UNDERFLOW = 0x05, + AUDIO_PE_CTRL_OVERFLOW = 0x06, + AUDIO_PE_CTRL_LATENCY = 0x07, +} audio_parametric_equalizer_control_selector_t; + +/// A.17.8.2 Reverberation Effect Unit Control Selectors +typedef enum +{ + AUDIO_RV_CTRL_UNDEF = 0x00, + AUDIO_RV_CTRL_ENABLE = 0x01, + AUDIO_RV_CTRL_TYPE = 0x02, + AUDIO_RV_CTRL_LEVEL = 0x03, + AUDIO_RV_CTRL_TIME = 0x04, + AUDIO_RV_CTRL_FEEDBACK = 0x05, + AUDIO_RV_CTRL_PREDELAY = 0x06, + AUDIO_RV_CTRL_DENSITY = 0x07, + AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, + AUDIO_RV_CTRL_UNDERFLOW = 0x09, + AUDIO_RV_CTRL_OVERFLOW = 0x0A, + AUDIO_RV_CTRL_LATENCY = 0x0B, +} audio_reverberation_effect_control_selector_t; + +/// A.17.8.3 Modulation Delay Effect Unit Control Selectors +typedef enum +{ + AUDIO_MD_CTRL_UNDEF = 0x00, + AUDIO_MD_CTRL_ENABLE = 0x01, + AUDIO_MD_CTRL_BALANCE = 0x02, + AUDIO_MD_CTRL_RATE = 0x03, + AUDIO_MD_CTRL_DEPTH = 0x04, + AUDIO_MD_CTRL_TIME = 0x05, + AUDIO_MD_CTRL_FEEDBACK = 0x06, + AUDIO_MD_CTRL_UNDERFLOW = 0x07, + AUDIO_MD_CTRL_OVERFLOW = 0x08, + AUDIO_MD_CTRL_LATENCY = 0x09, +} audio_modulation_delay_control_selector_t; + +/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors +typedef enum +{ + AUDIO_DR_CTRL_UNDEF = 0x00, + AUDIO_DR_CTRL_ENABLE = 0x01, + AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO_DR_CTRL_MAXAMPL = 0x03, + AUDIO_DR_CTRL_THRESHOLD = 0x04, + AUDIO_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO_DR_CTRL_RELEASE_TIME = 0x06, + AUDIO_DR_CTRL_UNDERFLOW = 0x07, + AUDIO_DR_CTRL_OVERFLOW = 0x08, + AUDIO_DR_CTRL_LATENCY = 0x09, +} audio_dynamic_range_compression_control_selector_t; + +/// A.17.9 Processing Unit Control Selectors + +/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors +typedef enum +{ + AUDIO_UD_CTRL_UNDEF = 0x00, + AUDIO_UD_CTRL_ENABLE = 0x01, + AUDIO_UD_CTRL_MODE_SELECT = 0x02, + AUDIO_UD_CTRL_CLUSTER = 0x03, + AUDIO_UD_CTRL_UNDERFLOW = 0x04, + AUDIO_UD_CTRL_OVERFLOW = 0x05, + AUDIO_UD_CTRL_LATENCY = 0x06, +} audio_up_down_mix_control_selector_t; + +/// A.17.9.2 Dolby Prologic â„¢ Processing Unit Control Selectors +typedef enum +{ + AUDIO_DP_CTRL_UNDEF = 0x00, + AUDIO_DP_CTRL_ENABLE = 0x01, + AUDIO_DP_CTRL_MODE_SELECT = 0x02, + AUDIO_DP_CTRL_CLUSTER = 0x03, + AUDIO_DP_CTRL_UNDERFLOW = 0x04, + AUDIO_DP_CTRL_OVERFLOW = 0x05, + AUDIO_DP_CTRL_LATENCY = 0x06, +} audio_dolby_prologic_control_selector_t; + +/// A.17.9.3 Stereo Extender Processing Unit Control Selectors +typedef enum +{ + AUDIO_ST_EXT_CTRL_UNDEF = 0x00, + AUDIO_ST_EXT_CTRL_ENABLE = 0x01, + AUDIO_ST_EXT_CTRL_WIDTH = 0x02, + AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, + AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, + AUDIO_ST_EXT_CTRL_LATENCY = 0x05, +} audio_stereo_extender_control_selector_t; + +/// A.17.10 Extension Unit Control Selectors +typedef enum +{ + AUDIO_XU_CTRL_UNDEF = 0x00, + AUDIO_XU_CTRL_ENABLE = 0x01, + AUDIO_XU_CTRL_CLUSTER = 0x02, + AUDIO_XU_CTRL_UNDERFLOW = 0x03, + AUDIO_XU_CTRL_OVERFLOW = 0x04, + AUDIO_XU_CTRL_LATENCY = 0x05, +} audio_extension_unit_control_selector_t; + +/// A.17.11 AudioStreaming Interface Control Selectors +typedef enum +{ + AUDIO_AS_CTRL_UNDEF = 0x00, + AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, + AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, + AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, +} audio_audiostreaming_interface_control_selector_t; + +/// A.17.12 Encoder Control Selectors +typedef enum +{ + AUDIO_EN_CTRL_UNDEF = 0x00, + AUDIO_EN_CTRL_BIT_RATE = 0x01, + AUDIO_EN_CTRL_QUALITY = 0x02, + AUDIO_EN_CTRL_VBR = 0x03, + AUDIO_EN_CTRL_TYPE = 0x04, + AUDIO_EN_CTRL_UNDERFLOW = 0x05, + AUDIO_EN_CTRL_OVERFLOW = 0x06, + AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, + AUDIO_EN_CTRL_PARAM1 = 0x08, + AUDIO_EN_CTRL_PARAM2 = 0x09, + AUDIO_EN_CTRL_PARAM3 = 0x0A, + AUDIO_EN_CTRL_PARAM4 = 0x0B, + AUDIO_EN_CTRL_PARAM5 = 0x0C, + AUDIO_EN_CTRL_PARAM6 = 0x0D, + AUDIO_EN_CTRL_PARAM7 = 0x0E, + AUDIO_EN_CTRL_PARAM8 = 0x0F, +} audio_encoder_control_selector_t; + +/// A.17.13 Decoder Control Selectors + +/// A.17.13.1 MPEG Decoder Control Selectors +typedef enum +{ + AUDIO_MPD_CTRL_UNDEF = 0x00, + AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, + AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, + AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, + AUDIO_MPD_CTRL_DYN_RANGE = 0x04, + AUDIO_MPD_CTRL_SCALING = 0x05, + AUDIO_MPD_CTRL_HILO_SCALING = 0x06, + AUDIO_MPD_CTRL_UNDERFLOW = 0x07, + AUDIO_MPD_CTRL_OVERFLOW = 0x08, + AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, +} audio_MPEG_decoder_control_selector_t; + +/// A.17.13.2 AC-3 Decoder Control Selectors +typedef enum +{ + AUDIO_AD_CTRL_UNDEF = 0x00, + AUDIO_AD_CTRL_MODE = 0x01, + AUDIO_AD_CTRL_DYN_RANGE = 0x02, + AUDIO_AD_CTRL_SCALING = 0x03, + AUDIO_AD_CTRL_HILO_SCALING = 0x04, + AUDIO_AD_CTRL_UNDERFLOW = 0x05, + AUDIO_AD_CTRL_OVERFLOW = 0x06, + AUDIO_AD_CTRL_DECODER_ERROR = 0x07, +} audio_AC3_decoder_control_selector_t; + +/// A.17.13.3 WMA Decoder Control Selectors +typedef enum +{ + AUDIO_WD_CTRL_UNDEF = 0x00, + AUDIO_WD_CTRL_UNDERFLOW = 0x01, + AUDIO_WD_CTRL_OVERFLOW = 0x02, + AUDIO_WD_CTRL_DECODER_ERROR = 0x03, +} audio_WMA_decoder_control_selector_t; + +/// A.17.13.4 DTS Decoder Control Selectors +typedef enum +{ + AUDIO_DD_CTRL_UNDEF = 0x00, + AUDIO_DD_CTRL_UNDERFLOW = 0x01, + AUDIO_DD_CTRL_OVERFLOW = 0x02, + AUDIO_DD_CTRL_DECODER_ERROR = 0x03, +} audio_DTS_decoder_control_selector_t; + +/// A.17.14 Endpoint Control Selectors +typedef enum +{ + AUDIO_EP_CTRL_UNDEF = 0x00, + AUDIO_EP_CTRL_PITCH = 0x01, + AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, + AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, +} audio_EP_control_selector_t; /// Terminal Types -- cgit v1.3.1 From fdb156a3bb1eb4bc223dbca1dd287c7eff7a8e7c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 20 Jul 2020 20:18:45 +0200 Subject: Implement control EP0 buffer and get rid of CFG_TUD_AUDIO_USE_TX_FIFO --- src/class/audio/audio_device.c | 78 +++++++++++++++++++++++------------------- src/class/audio/audio_device.h | 45 +++++++++++------------- 2 files changed, 62 insertions(+), 61 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 67c94837a..7e7fef19f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -73,18 +73,22 @@ typedef struct uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; #endif /*------------- From this point, data is not cleared by bus reset -------------*/ + + // Buffer for control requests + CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + // FIFO -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif @@ -119,19 +123,21 @@ typedef struct } audiod_interface_t; -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) -#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) -#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) -#elif CFG_TUD_AUDIO_EPSIZE_OUT -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) -#elif CFG_TUD_AUDIO_EPSIZE_IN -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) -#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) -#endif +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) + +//#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) +//#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) +//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) +//#elif CFG_TUD_AUDIO_EPSIZE_OUT +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) +//#elif CFG_TUD_AUDIO_EPSIZE_IN +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) +//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) +//#endif //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -195,7 +201,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) { @@ -237,7 +243,7 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) #endif // This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_RX_FIFO = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_FIFO_SIZE = 0. #if CFG_TUD_AUDIO_EPSIZE_OUT @@ -256,7 +262,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_RX_FIFO_SIZE TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! @@ -283,8 +289,8 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* #endif //CFG_TUD_AUDIO_EPSIZE_OUT -// The following functions are used in case CFG_TUD_AUDIO_USE_RX_FIFO == 1 -#if CFG_TUD_AUDIO_USE_RX_FIFO +// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 +#if CFG_TUD_AUDIO_RX_FIFO_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -320,7 +326,7 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } } } } -#endif //CFG_TUD_AUDIO_USE_RX_FIFO +#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT @@ -342,7 +348,7 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) { audiod_interface_t* audio = &_audiod_itf[itf]; @@ -370,7 +376,7 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_TX_FIFO = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0. #if CFG_TUD_AUDIO_EPSIZE_IN static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { @@ -387,7 +393,7 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_TX_FIFO_SIZE TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); #else #error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! @@ -414,7 +420,7 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t #endif //CFG_TUD_AUDIO_EPSIZE_IN -#if CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_TX_FIFO_SIZE static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { // We encode directly into IN EP's buffer - abort if previous transfer not complete @@ -478,7 +484,7 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a return true; } -#endif //CFG_TUD_AUDIO_USE_TX_FIFO +#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent @@ -580,20 +586,20 @@ void audiod_init(void) audiod_interface_t* audio = &_audiod_itf[i]; // Initialize TX FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_BUFSIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_BUFSIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif @@ -619,14 +625,14 @@ void audiod_reset(uint8_t rhport) tu_memclr(audio, ITF_MEM_RESET_SIZE); uint8_t cnt; -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); @@ -1376,7 +1382,7 @@ static bool audiod_verify_ep_exists(uint8_t ep) // //#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM // -//#if CFG_TUD_AUDIO_USE_TX_FIFO +//#if CFG_TUD_AUDIO_TX_FIFO_SIZE // TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); //#else //#error YOUR ENCODING AND SENDING IS REQUIRED HERE! @@ -1407,7 +1413,7 @@ static bool audiod_verify_ep_exists(uint8_t ep) // //#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM // -//#if CFG_TUD_AUDIO_USE_RX_FIFO +//#if CFG_TUD_AUDIO_RX_FIFO_SIZE // TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); //#else //#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 95b361acd..cc757d451 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -43,16 +43,23 @@ #define CFG_TUD_AUDIO_N_AS_INT 0 #endif -// Use internal FIFOs - In this case, audio.c implements FIFOs for RX and TX (whatever required) and implements encoding and decoding (parameterized by the defines below). +// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors +#ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE +#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#endif + +// Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). // For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). // For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. -// If you disable this you need to fill in desired code into audio_rx_done_cb() and Y on your own, however, this allows for optimizations in byte processing. -#ifndef CFG_TUD_AUDIO_USE_RX_FIFO -#define CFG_TUD_AUDIO_USE_RX_FIFO 0 +// Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). +// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and Y. This, however, allows for optimizations. + +#ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE +#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif -#ifndef CFG_TUD_AUDIO_USE_TX_FIFO -#define CFG_TUD_AUDIO_USE_TX_FIFO 0 +#ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE +#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 @@ -60,22 +67,10 @@ #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX #endif -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 -#ifndef CFG_TUD_AUDIO_TX_BUFSIZE -#define CFG_TUD_AUDIO_TX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_IN // Buffer size per channel -#endif -#endif - #ifndef CFG_TUD_AUDIO_EPSIZE_OUT #define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 -#ifndef CFG_TUD_AUDIO_RX_BUFSIZE -#define CFG_TUD_AUDIO_RX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_OUT // Buffer size per channel -#endif -#endif - #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback #endif @@ -169,13 +164,13 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -192,13 +187,13 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16 inline bool tud_audio_mounted (void); -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available (void); inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); inline void tud_audio_read_flush (void); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -259,14 +254,14 @@ inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { return tud_audio_n_write(0, channelId, buffer, bufsize); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); -- cgit v1.3.1 From 141db1278aabd9a5d508450752fd5df79759747c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 20 Jul 2020 20:24:05 +0200 Subject: Make definition of CFG_TUD_AUDIO_CTRL_BUF_SIZE mandatory --- src/class/audio/audio_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index cc757d451..8494281c4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -45,7 +45,7 @@ // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors #ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#error You must define an audio class control request buffer size! #endif // Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). @@ -79,7 +79,7 @@ #define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN #ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE #define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif -- cgit v1.3.1 From d91843bcd21262658b43480240e5dfc2b7d7bd20 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 25 Jul 2020 11:18:50 +0200 Subject: Get and set requests work --- src/class/audio/audio.h | 311 +++++++++++++++++++++-------------------- src/class/audio/audio_device.c | 201 +++++++++++++++++--------- src/class/audio/audio_device.h | 14 +- 3 files changed, 309 insertions(+), 217 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 011f5381b..36f9f211c 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -652,165 +652,172 @@ typedef enum AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, } audio_channel_config_t; +/// AUDIO Channel Cluster Descriptor (4.1) +typedef struct TU_ATTR_PACKED { + uint8_t bNrChannels; ///< Number of channels currently connected. + audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. +} audio_desc_channel_cluster_t; + /// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. } audio_desc_cs_ac_interface_t; /// AUDIO Clock Source Descriptor (4.7.2.1) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. } audio_desc_clock_source_t; /// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. } audio_desc_clock_selector_t; /// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins #define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ + struct TU_ATTR_PACKED { \ uint8_t bLength ; \ uint8_t bDescriptorType ; \ uint8_t bDescriptorSubType ; \ uint8_t bClockID ; \ uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ - } + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ +} /// AUDIO Clock Multiplier Descriptor (4.7.2.3) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. } audio_desc_clock_multiplier_t; /// AUDIO Input Terminal Descriptor(4.7.2.4) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. } audio_desc_input_terminal_t; /// AUDIO Output Terminal Descriptor(4.7.2.5) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. } audio_desc_output_terminal_t; /// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. } audio_desc_feature_unit_t; /// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels #define audio_desc_feature_unit_n_t(ch_num) \ - struct TU_ATTR_PACKED { \ + struct TU_ATTR_PACKED { \ uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ - } + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ +} /// AUDIO Class-Specific AS Interface Descriptor(4.9.2) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. } audio_desc_cs_as_interface_t; /// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. } audio_desc_type_I_format_t; /// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; //// 5.2.3 Control Request Parameter Block Layout @@ -818,87 +825,91 @@ typedef struct TU_ATTR_PACKED // 5.2.3.1 1-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_1_t; // 5.2.3.2 2-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_2_t; // 5.2.3.3 4-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_4_t; +// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like // 5.2.3.1 1-byte Control RANGE Parameter Block -//#define audio_control_range_1_n_t(numSubRanges) \ -// struct TU_ATTR_PACKED { \ -// uint16_t wNumSubRanges = numSubRanges; \ -// struct TU_ATTR_PACKED { \ -// int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ -// int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ -// uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ -// } setting[numSubRanges] ; \ -// } - typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } setting[] ; + struct TU_ATTR_PACKED { + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_1_t; // 5.2.3.2 2-byte Control RANGE Parameter Block -//#define audio_control_range_2_n_t(numSubRanges) \ -// struct TU_ATTR_PACKED { \ -// uint16_t wNumSubRanges = numSubRanges; \ -// struct TU_ATTR_PACKED { \ -// int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ -// int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ -// uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ -// } setting[numSubRanges] ; \ -// } - typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } setting[] ; + struct TU_ATTR_PACKED { + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_2_t; // 5.2.3.3 4-byte Control RANGE Parameter Block -//#define audio_control_range_4_n_t(numSubRanges) \ -// struct TU_ATTR_PACKED { \ -// uint16_t wNumSubRanges = numSubRanges; \ -// struct TU_ATTR_PACKED { \ -// int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ -// int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ -// uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ -// } setting[numSubRanges] ; \ -// } - typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } setting[] ; + struct TU_ATTR_PACKED { + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_4_t; -/** @} */ +// 5.2.3.1 1-byte Control RANGE Parameter Block +#define audio_control_range_1_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ +} + + // 5.2.3.2 2-byte Control RANGE Parameter Block +#define audio_control_range_2_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ + } + + // 5.2.3.3 4-byte Control RANGE Parameter Block +#define audio_control_range_4_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ + } + + /** @} */ #ifdef __cplusplus -} + } #endif #endif -/** @} */ + /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7e7fef19f..5f57c5e4a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -157,10 +157,10 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID); -static bool audiod_verify_itf_exists(uint8_t itf); -static bool audiod_verify_ep_exists(uint8_t ep); +static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { @@ -691,7 +691,7 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t idxDriver, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); return true; @@ -724,7 +724,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find index of audio streaming interface and index of interface uint8_t idxDriver, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_EPSIZE_IN > 0 @@ -837,6 +837,8 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) { + uint8_t idxDriver; + switch (p_request->bmRequestType_bit.recipient) { case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label @@ -844,28 +846,35 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish if (entityID != 0) { - // Invoke callback - if (tud_audio_set_req_entity_cb && tud_audio_set_req_entity_cb(rhport, p_request)) + if (tud_audio_set_req_entity_cb) { - tud_control_status(rhport, p_request); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { + TU_LOG2(" No entity set request callback available!\r\n"); return false; // In case no callback function is present or request can not be conducted we stall it } } else { - // Invoke callback - if (tud_audio_set_req_itf_cb && tud_audio_set_req_itf_cb(rhport, p_request)) + if (tud_audio_set_req_itf_cb) { - tud_control_status(rhport, p_request); + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { + TU_LOG2(" No interface set request callback available!\r\n"); return false; // In case no callback function is present or request can not be conducted we stall it } } @@ -876,18 +885,20 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Invoke callback - if (tud_audio_set_req_ep_cb && tud_audio_set_req_ep_cb(rhport, p_request)) + if (tud_audio_set_req_ep_cb) { - tud_control_status(rhport, p_request); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { + TU_LOG2(" No EP set request callback available!\r\n"); return false; // In case no callback function is present or request can not be conducted we stall it } - break; - // Unknown/Unsupported recipient default: TU_BREAKPOINT(); return false; } @@ -920,82 +931,89 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req // Handle class requests if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t idxDriver; + // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + // Verify if entity is present if (entityID != 0) { - TU_VERIFY(audiod_verify_entity_exists(itf, entityID)); - - // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (tud_audio_get_req_entity_cb) + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } } } else { - TU_VERIFY(audiod_verify_itf_exists(itf)); - - // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (tud_audio_get_req_itf_cb) + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } } } - break; case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Verify if EP is present - This check may be omitted if we trust the host not to send rubbish - TU_VERIFY(audiod_verify_ep_exists(ep)); + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; - - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - TU_LOG2(" No EP get request callback available!\r\n"); + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall + } } - break; // Unknown/Unsupported recipient default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; } - // Host expects an answer - in case no callback function is present we stall the request - return false; + // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + return true; } - // There went something wrong + // There went something wrong - unsupported control request type TU_BREAKPOINT(); return false; } @@ -1094,10 +1112,61 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } -// This helper function finds for a given interface number the index of the attached driver interface, the index of the interface in the audio function +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) +{ + // Handles only sending of data not receiving + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; + + // Get corresponding driver index + uint8_t idxDriver; + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + } + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // Crop length + if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + + // Copy into buffer + memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); + + // Schedule transmit + return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); +} + +// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the start i.e. alternate interface zero. -static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. +static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; @@ -1134,7 +1203,8 @@ static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t return false; } -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) +// Verify an entity with the given ID exists and returns also the corresponding driver index +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -1151,6 +1221,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { + *idxDriver = i; return true; } p_desc = tu_desc_next(p_desc); @@ -1160,7 +1231,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) return false; } -static bool audiod_verify_itf_exists(uint8_t itf) +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -1175,6 +1246,7 @@ static bool audiod_verify_itf_exists(uint8_t itf) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) { + *idxDriver = i; return true; } p_desc = tu_desc_next(p_desc); @@ -1184,7 +1256,7 @@ static bool audiod_verify_itf_exists(uint8_t itf) return false; } -static bool audiod_verify_ep_exists(uint8_t ep) +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -1202,6 +1274,7 @@ static bool audiod_verify_ep_exists(uint8_t ep) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { + *idxDriver = i; return true; } p_desc = tu_desc_next(p_desc); diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 8494281c4..9766eb5f9 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -204,6 +204,14 @@ inline void tud_audio_int_ctr_read_flush (void); inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); #endif +// Buffer control EP data and schedule a transmit +// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a +// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. +// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such +// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. +// If the request's wLength is zero, a status packet is sent instead. +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ @@ -228,13 +236,13 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific get request received for an EP TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); -- cgit v1.3.1 From 1269bb440a62120108ebe9a6d5436b88b28b4de3 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 25 Jul 2020 14:31:25 +0200 Subject: Fix structure definition audio_control_range_X_n_t --- src/class/audio/audio.h | 10 +++++----- src/class/audio/audio_device.c | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 36f9f211c..8f2c0d214 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -874,7 +874,7 @@ typedef struct TU_ATTR_PACKED { // 5.2.3.1 1-byte Control RANGE Parameter Block #define audio_control_range_1_n_t(numSubRanges) \ struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges = numSubRanges; \ + uint16_t wNumSubRanges; \ struct TU_ATTR_PACKED { \ int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ @@ -884,8 +884,8 @@ typedef struct TU_ATTR_PACKED { // 5.2.3.2 2-byte Control RANGE Parameter Block #define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ struct TU_ATTR_PACKED { \ int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ @@ -895,8 +895,8 @@ typedef struct TU_ATTR_PACKED { // 5.2.3.3 4-byte Control RANGE Parameter Block #define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ struct TU_ATTR_PACKED { \ int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 5f57c5e4a..b5fbf70f3 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -694,6 +694,8 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + return true; #else @@ -709,9 +711,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Here we need to do the following: - // 1. Find the audio driver interface which was assigned to the given interface which is to be set + // 1. Find the audio driver assigned to the given interface to be set // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver interface is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching // 2. Close EPs which are currently open // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them @@ -721,6 +723,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const itf = tu_u16_low(p_request->wIndex); uint8_t const alt = tu_u16_low(p_request->wValue); + TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); + // Find index of audio streaming interface and index of interface uint8_t idxDriver, idxItf; uint8_t const *p_desc; @@ -768,7 +772,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { - TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); +// TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; #if CFG_TUD_AUDIO_EPSIZE_IN > 0 @@ -813,18 +818,15 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! TU_VERIFY(p_desc < p_desc_end); + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + // Invoke callback if (tud_audio_set_itf_cb) { - if (!tud_audio_set_itf_cb(rhport, p_request)) - { - return false; - } + if (!tud_audio_set_itf_cb(rhport, p_request)) return false; } - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; - tud_control_status(rhport, p_request); return true; -- cgit v1.3.1 From 9bf2b3336610044dfb0187311797c5324eeec0ea Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 1 Aug 2020 12:02:59 +0700 Subject: correct isr context for nrf DCD_EVENT_UNPLUGGED also rename debug lookup to prevent conflict --- src/class/msc/msc_device.c | 6 +++--- src/common/tusb_common.h | 10 +++++----- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 692fd2441..9b79b68a7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -105,7 +105,7 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 -static lookup_entry_t const _msc_scsi_cmd_lookup[] = +static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, @@ -120,7 +120,7 @@ static lookup_entry_t const _msc_scsi_cmd_lookup[] = { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } }; -static lookup_table_t const _msc_scsi_cmd_table = +static tu_lookup_table_t const _msc_scsi_cmd_table = { .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), .items = _msc_scsi_cmd_lookup @@ -418,7 +418,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\r\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + TU_LOG2(" SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 1dba6c914..d95c0ffc4 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -251,16 +251,16 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) typedef struct { uint32_t key; - char const * data; -}lookup_entry_t; + const char* data; +} tu_lookup_entry_t; typedef struct { uint16_t count; - lookup_entry_t const* items; -} lookup_table_t; + tu_lookup_entry_t const* items; +} tu_lookup_table_t; -static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t key) +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { for(uint16_t i=0; icount; i++) { diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 7ca32c4f6..fdf56b6ca 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -829,7 +829,7 @@ void tusb_hal_nrf_power_event (uint32_t event) hfclk_disable(); - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false); } break; -- cgit v1.3.1 From 01b9b77d3b94ed83931d6a51c1b357f03f188e76 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 14:47:32 +0700 Subject: allow application driver to overwrite built-in one - position application driver before built-in - remove dcd.h from public include. --- src/class/msc/msc_device.c | 1 + src/class/usbtmc/usbtmc_device.c | 1 - src/device/usbd.c | 47 +++++++++++++++++++++++----------------- src/device/usbd.h | 16 +++----------- 4 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9b79b68a7..f3f2e536e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -31,6 +31,7 @@ #include "common/tusb_common.h" #include "msc_device.h" #include "device/usbd_pvt.h" +#include "device/dcd.h" // for faking dcd_event_xfer_complete //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index a3ff76079..bc5f23f42 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -80,7 +80,6 @@ #include #include "usbtmc.h" #include "usbtmc_device.h" -#include "device/dcd.h" #include "device/usbd.h" #include "osal/osal.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 7fc7189a5..6b91048b6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -203,30 +203,30 @@ static usbd_class_driver_t const _usbd_driver[] = #endif }; -enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; // Additional class drivers implemented by application static usbd_class_driver_t const * _app_driver = NULL; static uint8_t _app_driver_count = 0; -// virtually joins built-in and application drivers together -// All drivers = built-in + application +// virtually joins built-in and application drivers together. +// Application is positioned first to allow overwriting built-in ones. static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { - // Built-in drivers - if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; - - // App drivers + // Application drivers if ( usbd_app_driver_get_cb ) { - drvid -= USBD_CLASS_DRIVER_COUNT; if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + drvid -= _app_driver_count; } + // Built-in drivers + if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; + return NULL; } -#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) //--------------------------------------------------------------------+ // DCD Event @@ -245,6 +245,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); +// from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); @@ -252,7 +253,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ -// Debugging +// Debug //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = @@ -327,6 +328,20 @@ bool tud_remote_wakeup(void) return true; } +bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ @@ -593,7 +608,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const cfg_num = (uint8_t) p_request->wValue; if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.configured = cfg_num ? 1 : 0; tud_control_status(rhport, p_request); @@ -688,18 +702,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_clear_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; @@ -773,7 +781,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = get_driver(drv_id); - uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); if ( drv_len > 0 ) diff --git a/src/device/usbd.h b/src/device/usbd.h index 098e94075..5338be157 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -35,7 +35,6 @@ #endif #include "common/tusb_common.h" -#include "dcd.h" //--------------------------------------------------------------------+ // Application API @@ -53,6 +52,7 @@ void tud_task (void); bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD +extern void dcd_int_handler(uint8_t rhport); #define tud_int_handler dcd_int_handler // Get current bus speed @@ -75,21 +75,11 @@ bool tud_remote_wakeup(void); // Enable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_disconnect(void) -{ - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; -} +bool tud_disconnect(void); // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_connect(void) -{ - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; -} +bool tud_connect(void); // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only -- cgit v1.3.1 From 61e96e97cb078a8ae52a2bef107ebefd540603a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Aug 2020 22:09:16 +0700 Subject: use usbd_edpt_open in bth driver --- src/class/bth/bth_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 04011bcdb..252e20e37 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -121,7 +121,7 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); _btd_itf.ep_ev = desc_ep->bEndpointAddress; // Open endpoint pair -- cgit v1.3.1 From 444e4d282137953e6834360a9fb866331d21d954 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 16 Aug 2020 13:48:25 +0200 Subject: Add EP close. Fix bug in set_interface within audio. --- src/class/audio/audio_device.c | 1545 ++++++++++++++++--------------- src/portable/st/synopsys/dcd_synopsys.c | 37 + 2 files changed, 812 insertions(+), 770 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index b5fbf70f3..2e3625825 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -48,77 +48,77 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function #if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. + uint8_t ep_fb; // Feedback EP. #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. + uint8_t ep_int_ctr; // Audio control interrupt EP. #endif #if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif - /*------------- From this point, data is not cleared by bus reset -------------*/ + /*------------- From this point, data is not cleared by bus reset -------------*/ - // Buffer for control requests - CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + // Buffer for control requests + CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; - // FIFO + // FIFO #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; + osal_mutex_def_t int_ctr_ff_mutex; #endif #endif - // Endpoint Transfer buffers + // Endpoint Transfer buffers #if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - // TODO: required? - //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! - //#endif + // TODO: required? + //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // uint16_t fb_val; // Feedback value for asynchronous mode! + //#endif #endif #if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; #endif } audiod_interface_t; @@ -164,37 +164,37 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { - audiod_interface_t* audio = &_audiod_itf[itf]; + audiod_interface_t* audio = &_audiod_itf[itf]; #if CFG_TUD_AUDIO_EPSIZE_OUT - if (audio->ep_out == 0) - { - return false; - } + if (audio->ep_out == 0) + { + return false; + } #endif #if CFG_TUD_AUDIO_EPSIZE_IN - if (audio->ep_in == 0) - { - return false; - } + if (audio->ep_in == 0) + { + return false; + } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) - { - return false; - } + if (audio->ep_int_ctr == 0) + { + return false; + } #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) - { - return false; - } + if (audio->ep_fb == 0) + { + return false; + } #endif - return true; + return true; } //--------------------------------------------------------------------+ @@ -205,20 +205,20 @@ bool tud_audio_n_mounted(uint8_t itf) uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } #endif @@ -227,17 +227,17 @@ void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) uint16_t tud_audio_int_ctr_n_available(uint8_t itf) { - return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); + return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); } uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); + return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); } void tud_audio_int_ctr_n_read_flush (uint8_t itf) { - tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); + tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); } #endif @@ -249,42 +249,42 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { - switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - asm("nop"); - break; + switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; - case AUDIO_FORMAT_TYPE_I: + case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_RX_FIFO_SIZE - TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! #endif - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - asm("nop"); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - asm("nop"); - break; - } - - // Call a weak callback here - a possibility for user to get informed RX was completed - TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); - return true; + break; + + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed RX was completed + TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; } #endif //CFG_TUD_AUDIO_EPSIZE_OUT @@ -293,38 +293,38 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* #if CFG_TUD_AUDIO_RX_FIFO_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { - (void) rhport; + (void) rhport; - // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { - return false; - } + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + return false; + } - uint8_t chId = 0; - uint16_t cnt; + uint8_t chId = 0; + uint16_t cnt; #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 - uint8_t sample = 0; + uint8_t sample = 0; #elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 - uint16_t sample = 0; + uint16_t sample = 0; #else - uint32_t sample = 0; + uint32_t sample = 0; #endif - for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) - { - // Let alignment problems be handled by memcpy - memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); - if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) - { - // Buffer overflow - return false; - } - - if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) - { - chId = 0; - } - } + for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) + { + // Let alignment problems be handled by memcpy + memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); + if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) + { + // Buffer overflow + return false; + } + + if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) + { + chId = 0; + } + } } } #endif //CFG_TUD_AUDIO_RX_FIFO_SIZE @@ -332,15 +332,15 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a #if CFG_TUD_AUDIO_EPSIZE_OUT TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) { - (void) rhport; - (void) buffer; - (void) bufsize; + (void) rhport; + (void) buffer; + (void) bufsize; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_rx_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif @@ -351,12 +351,12 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } - return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); + return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); } #endif @@ -364,12 +364,12 @@ uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->itf_num == 0) { - return 0; - } + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->itf_num == 0) { + return 0; + } - return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); + return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); } #endif @@ -380,42 +380,42 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t #if CFG_TUD_AUDIO_EPSIZE_IN static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { - switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - asm("nop"); - break; + switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; - case AUDIO_FORMAT_TYPE_I: + case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_TX_FIFO_SIZE - TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); #else #error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! #endif - break; - - default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! - asm("nop"); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - asm("nop"); - break; - } - - // Call a weak callback here - a possibility for user to get informed TX was completed - TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); - return true; + break; + + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed TX was completed + TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); + return true; } #endif //CFG_TUD_AUDIO_EPSIZE_IN @@ -423,65 +423,65 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t #if CFG_TUD_AUDIO_TX_FIFO_SIZE static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { - // We encode directly into IN EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint16_t nSamplesPerChannelToSend = 0xFFFF; - uint8_t cntChannel; - - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) - { - if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) - { - nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; - } - } - - // Check if there is enough - if (nSamplesPerChannelToSend == 0) - { - *n_bytes_copied = 0; - return true; - } - - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) - { - nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - } - - // Encode - uint16_t cntSample; - uint8_t * pBuff = audio->epin_buf; + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint8_t cntChannel; + + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + { + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + } + } + + // Check if there is enough + if (nSamplesPerChannelToSend == 0) + { + *n_bytes_copied = 0; + return true; + } + + // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! + if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) + { + nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + + // Encode + uint16_t cntSample; + uint8_t * pBuff = audio->epin_buf; #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 - uint8_t sample; + uint8_t sample; #elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 - uint16_t sample; + uint16_t sample; #else - uint32_t sample; + uint32_t sample; #endif - // TODO: Big endianess handling - for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) - { - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) - { - // Get sample from buffer - tu_fifo_read(&audio->tx_ff[cntChannel], &sample); - - // Put it into EP's buffer - Let alignment problems be handled by memcpy - memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); - - // Advance pointer - pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - } - } - - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); - *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - return true; + // TODO: Big endianess handling + for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + { + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + // Get sample from buffer + tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + + // Put it into EP's buffer - Let alignment problems be handled by memcpy + memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + + // Advance pointer + pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + } + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); + *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + return true; } #endif //CFG_TUD_AUDIO_TX_FIFO_SIZE @@ -491,14 +491,14 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) { - (void) rhport; - (void) audio; + (void) rhport; + (void) audio; - // Here we need to return the feedback value + // Here we need to return the feedback value #error RETURN YOUR FEEDBACK VALUE HERE! - TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return 0; + TU_VERIFY(tud_audio_fb_done_cb(rhport)); + return 0; } #endif @@ -508,23 +508,23 @@ static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); - // TODO: Big endianess handling - uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); + // TODO: Big endianess handling + uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); - if (cnt > 0) - { - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); - } + if (cnt > 0) + { + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); + } - *n_bytes_copied = cnt; + *n_bytes_copied = cnt; - TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); + TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); - return true; + return true; } #endif @@ -534,41 +534,41 @@ static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uin #if CFG_TUD_AUDIO_EPSIZE_IN TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) { - (void) rhport; - (void) n_bytes_copied; + (void) rhport; + (void) n_bytes_copied; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_tx_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport) { - (void) rhport; + (void) rhport; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_fb_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) { - (void) rhport; - (void) n_bytes_copied; + (void) rhport; + (void) n_bytes_copied; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_int_ctr_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif @@ -578,591 +578,596 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c //--------------------------------------------------------------------+ void audiod_init(void) { - uint8_t cnt; - tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + uint8_t cnt; + tu_memclr(_audiod_itf, sizeof(_audiod_itf)); - for(uint8_t i=0; itx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif - } + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) - { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif - } + } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 - tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); + tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); + tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); #endif #endif - } + } } void audiod_reset(uint8_t rhport) { - (void) rhport; + (void) rhport; - for(uint8_t i=0; itx_ff[cnt]); - } + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_clear(&audio->tx_ff[cnt]); + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) - { - tu_fifo_clear(&audio->rx_ff[cnt]); - } + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_clear(&audio->rx_ff[cnt]); + } #endif - } + } } uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); - - // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); - - // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted - if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed - { - TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); - } - - // Alternate setting MUST be zero - this check can be omitted - TU_VERIFY(itf_desc->bAlternateSetting == 0); - - // Find available audio driver interface - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (!_audiod_itf[i].p_desc) - { - _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one - break; - } - } - - // Verify we found a free one - TU_ASSERT( i < CFG_TUD_AUDIO ); - - // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - - // Notify caller we read complete descriptor - // (*p_length) += tud_audio_desc_lengths[i]; - // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - - return drv_len; + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + + // Verify version is correct - this check can be omitted + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); + + // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted + if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed + { + TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); + } + + // Alternate setting MUST be zero - this check can be omitted + TU_VERIFY(itf_desc->bAlternateSetting == 0); + + // Find available audio driver interface + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + break; + } + } + + // Verify we found a free one + TU_ASSERT( i < CFG_TUD_AUDIO ); + + // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) + + // Notify caller we read complete descriptor + // (*p_length) += tud_audio_desc_lengths[i]; + // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + + return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { #if CFG_TUD_AUDIO_N_AS_INT > 0 - uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const itf = tu_u16_low(p_request->wIndex); - // Find index of audio streaming interface - uint8_t idxDriver, idxItf; - uint8_t const *dummy; + // Find index of audio streaming interface + uint8_t idxDriver, idxItf; + uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); - return true; + return true; #else - (void) rhport; - (void) p_request; - return false; + (void) rhport; + (void) p_request; + return false; #endif } static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; + (void) rhport; - // Here we need to do the following: + // Here we need to do the following: - // 1. Find the audio driver assigned to the given interface to be set - // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + // 1. Find the audio driver assigned to the given interface to be set + // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. + // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching - // 2. Close EPs which are currently open - // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them + // 2. Close EPs which are currently open + // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them - // 3. Open new EP + // 3. Open new EP - uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const alt = tu_u16_low(p_request->wValue); - TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); + TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); - // Find index of audio streaming interface and index of interface - uint8_t idxDriver, idxItf; - uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + // Find index of audio streaming interface and index of interface + uint8_t idxDriver, idxItf; + uint8_t const *p_desc; + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); - // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_EPSIZE_IN > 0 - if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) - { - _audiod_itf[idxDriver].ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? - } + if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) - { - _audiod_itf[idxDriver].ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); + _audiod_itf[idxDriver].ep_out = 0; // Necessary? - // Close corresponding feedback EP + // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? #endif - } + } #endif - // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; - - // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) + // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + + // p_desc starts at required interface with alternate setting zero + while (p_desc < p_desc_end) + { + // Find correct interface + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) + { + // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary + uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; + while (foundEPs < nEps && p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { - // Find correct interface - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) - { - // Open EPs - uint8_t foundEPs = 0; - while (foundEPs < ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints && p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { -// TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; #if CFG_TUD_AUDIO_EPSIZE_IN > 0 - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP - { - _audiod_itf[idxDriver].ep_in = ep_addr; - } + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + _audiod_itf[idxDriver].ep_in = ep_addr; + _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + _audiod_itf[idxDriver].ep_out_as_intf_num = itf; - // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); - } + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback - { - _audiod_itf[idxDriver].ep_fb = ep_addr; - } + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; + } #endif #endif - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); - } + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); + } - // We are done - abort loop - break; - } + TU_VERIFY(foundEPs == nEps); - // Increase index, bytes read, and pointer - p_desc = tu_desc_next(p_desc); - } + // We are done - abort loop + break; + } - // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! - TU_VERIFY(p_desc < p_desc_end); + // Moving forward + p_desc = tu_desc_next(p_desc); + } - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; +// // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! +// TU_VERIFY(p_desc < p_desc_end); - // Invoke callback - if (tud_audio_set_itf_cb) - { - if (!tud_audio_set_itf_cb(rhport, p_request)) return false; - } + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + + // Invoke callback + if (tud_audio_set_itf_cb) + { + if (!tud_audio_set_itf_cb(rhport, p_request)) return false; + } + + // Start sending or receiving? - tud_control_status(rhport, p_request); + tud_control_status(rhport, p_request); - return true; + return true; } // Invoked when class request DATA stage is finished. // return false to stall control EP (e.g Host send non-sense DATA) bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { - // Handle audio class specific set requests - if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + // Handle audio class specific set requests + if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + uint8_t idxDriver; + + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + if (entityID != 0) + { + if (tud_audio_set_req_entity_cb) { - uint8_t idxDriver; - - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) - { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - else - { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - - // Unknown/Unsupported recipient - default: TU_BREAKPOINT(); return false; - } + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + else + { + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } - return true; + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + if (tud_audio_set_req_ep_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + + // Unknown/Unsupported recipient + default: TU_BREAKPOINT(); return false; + } + } + return true; } // Handle class control request // return false to stall control endpoint (e.g unsupported request) bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - - // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + (void) rhport; + + // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + { + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t idxDriver; + + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } + } + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - switch (p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } + } + } + break; - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - // Handle class requests - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t idxDriver; - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); - return true; + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall } + } + break; - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + return true; + } + + // There went something wrong - unsupported control request type + TU_BREAKPOINT(); + return false; } bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; + (void) result; - // Search for interface belonging to given end point address and proceed as required - uint8_t idxDriver; - for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) - { + // Search for interface belonging to given end point address and proceed as required + uint8_t idxDriver; + for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + { #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - // Data transmission of control interrupt finished - if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) - { - // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) - // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? - // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - - // Load new data - uint16 *n_bytes_copied; - TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); - - if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) - { - // There is no data left to send, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } - } + // Data transmission of control interrupt finished + if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + { + // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) + // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? + // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? + + // Load new data + uint16 *n_bytes_copied; + TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) + { + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + } #endif #if CFG_TUD_AUDIO_EPSIZE_IN - // Data transmission of audio packet finished - if (_audiod_itf[idxDriver].ep_in == ep_addr) - { - // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." - // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." - // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. - - // Check if there is data to load into EPs buffer - if not load it with ZLP - // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! - // This is the only place where we can fill something into the EPs buffer! - - // Load new data - uint16_t *n_bytes_copied = NULL; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); - - if (*n_bytes_copied == 0) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } - - return true; - } + // Data transmission of audio packet finished + if (_audiod_itf[idxDriver].ep_in == ep_addr) + { + // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." + // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." + // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. + + // Check if there is data to load into EPs buffer - if not load it with ZLP + // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! + // This is the only place where we can fill something into the EPs buffer! + + // Load new data + uint16_t *n_bytes_copied = NULL; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - // New audio packet received - if (_audiod_itf[idxDriver].ep_out == ep_addr) - { - // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + // New audio packet received + if (_audiod_itf[idxDriver].ep_out == ep_addr) + { + // Save into buffer - do whatever has to be done + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); - // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + // prepare for next transmission + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); - return true; - } + return true; + } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Transmission of feedback EP finished - if (_audiod_itf[idxDriver].ep_fb == ep_addr) - { - if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } - - return true; - } + // Transmission of feedback EP finished + if (_audiod_itf[idxDriver].ep_fb == ep_addr) + { + if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } #endif #endif - } + } - return false; + return false; } bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) { - // Handles only sending of data not receiving - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; + // Handles only sending of data not receiving + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; - // Get corresponding driver index - uint8_t idxDriver; - uint8_t itf = TU_U16_LOW(p_request->wIndex); + // Get corresponding driver index + uint8_t idxDriver; + uint8_t itf = TU_U16_LOW(p_request->wIndex); - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - } - break; + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + } + break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - uint8_t ep = TU_U16_LOW(p_request->wIndex); + uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - break; + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + break; - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } - // Crop length - if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + // Crop length + if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; - // Copy into buffer - memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); + // Copy into buffer + memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); - // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); + // Schedule transmit + return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); } // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function @@ -1170,120 +1175,120 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { - // Loop over audio driver interfaces - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + // Loop over audio driver interfaces + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) { - if (_audiod_itf[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *idxDriver = i; - *pp_desc_int = p_desc; - return true; - } - - // Increase index, bytes read, and pointer - tmp++; - p_desc = tu_desc_next(p_desc); - } - } + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; } - return false; + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + } + + return false; } // Verify an entity with the given ID exists and returns also the corresponding driver index static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver) { - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + // Look for the correct driver by checking if the unique standard AC interface number fits + if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { - // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) - { - // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - - while (p_desc < p_desc_end) - { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + *idxDriver = i; + return true; } - return false; + p_desc = tu_desc_next(p_desc); + } + } + } + return false; } static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at beginning and end + uint8_t const *p_desc = _audiod_itf[i].p_desc; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) { - if (_audiod_itf[i].p_desc) - { - // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + *idxDriver = i; + return true; } - return false; + p_desc = tu_desc_next(p_desc); + } + } + } + return false; } static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) { - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors - EP we look for are streaming EPs + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { - if (_audiod_itf[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; - - // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + *idxDriver = i; + return true; } - return false; + p_desc = tu_desc_next(p_desc); + } + } + } + return false; } #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 133a3736a..68c30c4b5 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -673,6 +673,43 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +/** + * Close an EP. + * + * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! + * + */ +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + uint32_t const epnum = tu_edpt_number(ep_addr); + uint32_t const dir = tu_edpt_dir(ep_addr); + + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + if(dir == TUSB_DIR_IN) + { + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // Disable interrupt for this EP + dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); + + // Clear USB active EP + in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; + } + else + { + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + + // Disable interrupt for this EP + dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; + + // Clear USB active EP bit + out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; + + } +} + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); -- cgit v1.3.1 From c14f68e2c1db7ce82fb8e05d40d8b0b9a83aced6 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 19 Aug 2020 21:07:43 +0200 Subject: Commit before sharing. Setup a test example - UNTESTED! Missing: Start transmitting audio data in set_interface. --- examples/device/audio_test/Makefile | 12 + examples/device/audio_test/src/main.c | 367 +++++ examples/device/audio_test/src/tusb_config.h | 112 ++ examples/device/audio_test/src/usb_descriptors.c | 167 +++ src/class/audio/audio.h | 1627 +++++++++++----------- src/class/audio/audio_device.c | 90 +- src/class/audio/audio_device.h | 9 +- src/portable/st/synopsys/dcd_synopsys.c | 1 + 8 files changed, 1503 insertions(+), 882 deletions(-) create mode 100644 examples/device/audio_test/Makefile create mode 100644 examples/device/audio_test/src/main.c create mode 100644 examples/device/audio_test/src/tusb_config.h create mode 100644 examples/device/audio_test/src/usb_descriptors.c (limited to 'src/class') diff --git a/examples/device/audio_test/Makefile b/examples/device/audio_test/Makefile new file mode 100644 index 000000000..5a455078e --- /dev/null +++ b/examples/device/audio_test/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c new file mode 100644 index 000000000..e55c64c7c --- /dev/null +++ b/examples/device/audio_test/src/main.c @@ -0,0 +1,367 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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 +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +// Audio controls +// Current states +bool mute[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint32_t sampFreq; +uint8_t clkValid; + +// Range states +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state + +void led_blinking_task(void); +void audio_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + // Init values + sampFreq = 44100; + clkValid = 1; + + sampleFreqRng.wNumSubRanges = 1; + sampleFreqRng.subrange[0].bMin = 44100; + sampleFreqRng.subrange[0].bMax = 44100; + sampleFreqRng.subrange[0].bRes = 0; + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + audio_task(); + } + + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void) +{ + // Yet to be filled - e.g. put meas data into TX FIFOs etc. + asm("nop"); +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an interface +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // If request is for our feature unit + if (entityID == 2) + { + switch (ctrlSel) + { + case AUDIO_FU_CTRL_MUTE: + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + + mute[channelNum] = ((audio_control_cur_1_t *)pBuff)->bCur; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + + return true; + + case AUDIO_FU_CTRL_VOLUME: + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + + volume[channelNum] = ((audio_control_cur_2_t *)pBuff)->bCur; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + + return true; + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + } + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // return tud_control_xfer(rhport, p_request, &tmp, 1); + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an interface +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Input terminal (Microphone input) + if (entityID == 1) + { + switch (ctrlSel) + { + case AUDIO_TE_CTRL_CONNECTOR:; + // The terminal connector control only has a get request with only the CUR attribute. + + audio_desc_channel_cluster_t ret; + + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; + + TU_LOG2(" Get terminal connector\r\n"); + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + + // Unknown/Unsupported control selector + default: TU_BREAKPOINT(); return false; + } + } + + // Feature unit + if (entityID == 2) + { + switch (ctrlSel) + { + case AUDIO_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO_FU_CTRL_VOLUME: + + switch (p_request->bRequest) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) ret; + + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + } + + // Clock Source unit + if (entityID == 4) + { + switch (ctrlSel) + { + case AUDIO_CS_CTRL_SAM_FREQ: + + // channelNum is always zero in this case + + switch (p_request->bRequest) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + } + + TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; // Yet not implemented +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h new file mode 100644 index 000000000..6cd6882bc --- /dev/null +++ b/examples/device/audio_test/src/tusb_config.h @@ -0,0 +1,112 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#endif + +#define CFG_TUSB_OS OPT_OS_NONE + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_AUDIO 1 +#define CFG_TUD_VENDOR 0 + +//-------------------------------------------------------------------- +// AUDIO CLASS DRIVER CONFIGURATION +//-------------------------------------------------------------------- + +// Audio format type +#define CFG_TUD_AUDIO_USE_TX_FIFO 1 +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED + +// Audio format type I specifications +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 3 + +// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) +#define CFG_TUD_AUDIO_EPSIZE_IN 45*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 45 Samples (44.1 kHz) x 3 Bytes/Sample x 1 Channels +#define CFG_TUD_AUDIO_TX_FIFO_SIZE 45*4 // 45 Samples (44.1 kHz) x 4 Bytes/Sample (1 word) + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_N_AS_INT 1 + +// Size of control request buffer +#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c new file mode 100644 index 000000000..0b4f9b62c --- /dev/null +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -0,0 +1,167 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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 "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // 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 = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX +// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number +// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... +#define EPNUM_AUDIO 0x03 +#else +#define EPNUM_AUDIO 0x01 +#endif + +// These variables are required by the audio driver in audio_device.c + +// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO - unfortunately this is not possible to determine otherwise +const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_MIC_DESC_LEN}; + +// TAKE CARE - THE NUMBER OF AUDIO STREAMING INTERFACES PER AUDIO FUNCTION MUST NOT EXCEED CFG_TUD_AUDIO_N_AS_INT - IF IT DOES INCREASE CFG_TUD_AUDIO_N_AS_INT IN tusb_config.h! + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 3, /*_nBitsUsedPerSample*/ 24, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ 45*3) +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode", // 2: Product + "123456", // 3: Serials, should use chip ID + "UAC2", // 4: Audio Interface +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + for(uint8_t i=0; i 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { + // Save address _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + + // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? + // Invoke callback - fill something in the FIFO here for now + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + + uint16_t n_bytes_copied; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); } #endif @@ -791,6 +759,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_out = ep_addr; _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Prepare for incoming data TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); } @@ -799,6 +770,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback { _audiod_itf[idxDriver].ep_fb = ep_addr; + + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } #endif @@ -818,20 +792,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_desc = tu_desc_next(p_desc); } -// // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! -// TU_VERIFY(p_desc < p_desc_end); - - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; - - // Invoke callback - if (tud_audio_set_itf_cb) - { - if (!tud_audio_set_itf_cb(rhport, p_request)) return false; - } - - // Start sending or receiving? - tud_control_status(rhport, p_request); return true; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 9766eb5f9..b745ceb09 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -1,7 +1,8 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Ha Thach (tinyusb.org) and Reinhard Panhuber + * Copyright (c) 2020 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -217,15 +218,15 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_EPSIZE_IN -bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); #endif #if CFG_TUD_AUDIO_EPSIZE_OUT -bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -bool tud_audio_fb_done_cb(uint8_t rhport); +TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 2d42dd43b..c188bb485 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -4,6 +4,7 @@ * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2020 Jan Duempelmann + * Copyright (c) 2020 Reinhard Panhuber * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.3.1 From 15b063beb287785b2bf84d00361000036afaba2c Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 20 Aug 2020 02:20:01 -0700 Subject: Smarter CDC TX refill logic --- src/class/cdc/cdc_device.c | 10 ++++++---- src/class/cdc/cdc_device.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d8be48688..da9e94133 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,7 +416,12 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - if ( 0 == tud_cdc_n_write_flush(itf) ) + uint32_t flushed = tud_cdc_n_write_flush(itf); + + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + + if ( 0 == flushed && tu_fifo_empty(&p_cdc->tx_ff) ) { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero @@ -425,9 +430,6 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } } - - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); } // nothing to do with notif endpoint for now diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 13b59416b..7e9e8ca21 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -129,7 +129,7 @@ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); // Invoked when space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_cb(uint8_t itf); +TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); -- cgit v1.3.1 From 72183c7bb44ff117d9abac7b6e9c373c0945fb0b Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 20 Aug 2020 09:59:23 -0700 Subject: Slight optimization for cdc tx refill --- src/class/cdc/cdc_device.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index da9e94133..513fe203b 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,12 +416,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - uint32_t flushed = tud_cdc_n_write_flush(itf); - // invoke transmit callback to possibly refill tx fifo if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); - if ( 0 == flushed && tu_fifo_empty(&p_cdc->tx_ff) ) + if ( 0 == tud_cdc_n_write_flush(itf) ) { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero -- cgit v1.3.1 From 37be0ca73238a40a2387c2e2566ae39f5cae6e08 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 20 Aug 2020 20:09:44 +0200 Subject: Fix formatting, get rid of all tabs. --- src/class/audio/audio.h | 1584 +++++++++++++++---------------- src/class/audio/audio_device.c | 660 ++++--------- src/class/audio/audio_device.h | 88 +- src/portable/st/synopsys/dcd_synopsys.c | 103 +- 4 files changed, 1093 insertions(+), 1342 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 1afacf0c4..5e64549ed 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -39,748 +39,748 @@ extern "C" { #endif - /// Audio Device Class Codes - - /// A.2 - Audio Function Subclass Codes - typedef enum - { - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, - } audio_function_subclass_type_t; - - /// A.3 - Audio Function Protocol Codes - typedef enum - { - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 - } audio_function_protocol_code_t; - - /// A.5 - Audio Interface Subclass Codes - typedef enum - { - AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming - } audio_subclass_type_t; - - /// A.6 - Audio Interface Protocol Codes - typedef enum - { - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 - } audio_interface_protocol_code_t; - - /// A.7 - Audio Function Category Codes - typedef enum - { - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, - } audio_function_code_t; - - /// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 - typedef enum - { - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, - } audio_cs_ac_interface_subtype_t; - - /// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 - typedef enum - { - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, - } audio_cs_as_interface_subtype_t; - - /// A.11 - Effect Unit Effect Types - typedef enum - { - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, - } audio_effect_unit_effect_type_t; - - /// A.12 - Processing Unit Process Types - typedef enum - { - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, - } audio_processing_unit_process_type_t; - - /// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 - typedef enum - { - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, - } audio_cs_ep_subtype_t; - - /// A.14 - Audio Class-Specific Request Codes - typedef enum - { - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, - } audio_cs_req_t; - - /// A.17 - Control Selector Codes - - /// A.17.1 - Clock Source Control Selectors - typedef enum - { - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, - } audio_clock_src_control_selector_t; - - /// A.17.2 - Clock Selector Control Selectors - typedef enum - { - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, - } audio_clock_sel_control_selector_t; - - /// A.17.3 - Clock Multiplier Control Selectors - typedef enum - { - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, - } audio_clock_mul_control_selector_t; - - /// A.17.4 - Terminal Control Selectors - typedef enum - { - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, - } audio_terminal_control_selector_t; - - /// A.17.5 - Mixer Control Selectors - typedef enum - { - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, - } audio_mixer_control_selector_t; - - /// A.17.6 - Selector Control Selectors - typedef enum - { - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, - } audio_sel_control_selector_t; - - /// A.17.7 - Feature Unit Control Selectors - typedef enum - { - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, - } audio_feature_unit_control_selector_t; - - /// A.17.8 Effect Unit Control Selectors - - /// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors - typedef enum - { - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, - } audio_parametric_equalizer_control_selector_t; - - /// A.17.8.2 Reverberation Effect Unit Control Selectors - typedef enum - { - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, - } audio_reverberation_effect_control_selector_t; - - /// A.17.8.3 Modulation Delay Effect Unit Control Selectors - typedef enum - { - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, - } audio_modulation_delay_control_selector_t; - - /// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors - typedef enum - { - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, - } audio_dynamic_range_compression_control_selector_t; - - /// A.17.9 Processing Unit Control Selectors - - /// A.17.9.1 Up/Down-mix Processing Unit Control Selectors - typedef enum - { - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, - } audio_up_down_mix_control_selector_t; - - /// A.17.9.2 Dolby Prologic â„¢ Processing Unit Control Selectors - typedef enum - { - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, - } audio_dolby_prologic_control_selector_t; - - /// A.17.9.3 Stereo Extender Processing Unit Control Selectors - typedef enum - { - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, - } audio_stereo_extender_control_selector_t; - - /// A.17.10 Extension Unit Control Selectors - typedef enum - { - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, - } audio_extension_unit_control_selector_t; - - /// A.17.11 AudioStreaming Interface Control Selectors - typedef enum - { - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, - } audio_audiostreaming_interface_control_selector_t; - - /// A.17.12 Encoder Control Selectors - typedef enum - { - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, - } audio_encoder_control_selector_t; - - /// A.17.13 Decoder Control Selectors - - /// A.17.13.1 MPEG Decoder Control Selectors - typedef enum - { - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, - } audio_MPEG_decoder_control_selector_t; - - /// A.17.13.2 AC-3 Decoder Control Selectors - typedef enum - { - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, - } audio_AC3_decoder_control_selector_t; - - /// A.17.13.3 WMA Decoder Control Selectors - typedef enum - { - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, - } audio_WMA_decoder_control_selector_t; - - /// A.17.13.4 DTS Decoder Control Selectors - typedef enum - { - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, - } audio_DTS_decoder_control_selector_t; - - /// A.17.14 Endpoint Control Selectors - typedef enum - { - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, - } audio_EP_control_selector_t; - - /// Terminal Types - - /// 2.1 - Audio Class-Terminal Types UAC2 - typedef enum - { - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, - } audio_terminal_type_t; - - /// 2.2 - Audio Class-Input Terminal Types UAC2 - typedef enum - { - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, - } audio_terminal_input_type_t; - - /// 2.3 - Audio Class-Output Terminal Types UAC2 - typedef enum - { - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, - } audio_terminal_output_type_t; - - /// Rest is yet to be implemented - - /// Additional Audio Device Class Codes - Source: Audio Data Formats - - /// A.1 - Audio Class-Format Type Codes UAC2 - typedef enum - { - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, - } audio_format_type_t; - - /// A.2.1 - Audio Class-Audio Data Format Type I UAC2 - typedef enum - { - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), - } audio_data_format_type_I_t; - - /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification - - /// Isochronous End Point Attributes - typedef enum - { - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point - } tusb_iso_ep_attribute_t; - - /// Audio Class-Control Values UAC2 - typedef enum - { - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access - } audio_control_t; - - /// Audio Class-Specific AC Interface Descriptor Controls UAC2 - typedef enum - { - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, - } audio_cs_ac_interface_control_pos_t; - - /// Audio Class-Specific AS Interface Descriptor Controls UAC2 - typedef enum - { - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, - } audio_cs_as_interface_control_pos_t; - - /// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 - typedef enum - { - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, - } audio_cs_as_iso_data_ep_attribute_t; - - /// Audio Class-Specific AS Isochronous Data EP Controls UAC2 - typedef enum - { - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, - } audio_cs_as_iso_data_ep_control_pos_t; - - /// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 - typedef enum - { - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, - } audio_cs_as_iso_data_ep_lock_delay_unit_t; - - /// Audio Class-Clock Source Attributes UAC2 - typedef enum - { - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, - } audio_clock_source_attribute_t; - - /// Audio Class-Clock Source Controls UAC2 - typedef enum - { - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, - } audio_clock_source_control_pos_t; - - /// Audio Class-Clock Selector Controls UAC2 - typedef enum - { - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, - } audio_clock_selector_control_pos_t; - - /// Audio Class-Clock Multiplier Controls UAC2 - typedef enum - { - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, - } audio_clock_multiplier_control_pos_t; - - /// Audio Class-Input Terminal Controls UAC2 - typedef enum - { - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, - } audio_terminal_input_control_pos_t; - - /// Audio Class-Output Terminal Controls UAC2 - typedef enum - { - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, - } audio_terminal_output_control_pos_t; - - /// Audio Class-Feature Unit Controls UAC2 - typedef enum - { - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, - } audio_feature_unit_control_pos_t; - - /// Audio Class-Audio Channel Configuration UAC2 - typedef enum - { - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, - } audio_channel_config_t; - - /// AUDIO Channel Cluster Descriptor (4.1) - typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. - } audio_desc_channel_cluster_t; - - /// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. - } audio_desc_cs_ac_interface_t; - - /// AUDIO Clock Source Descriptor (4.7.2.1) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. - } audio_desc_clock_source_t; - - /// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. - } audio_desc_clock_selector_t; - - /// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins +/// Audio Device Class Codes + +/// A.2 - Audio Function Subclass Codes +typedef enum +{ + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; + +/// A.3 - Audio Function Protocol Codes +typedef enum +{ + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_function_protocol_code_t; + +/// A.5 - Audio Interface Subclass Codes +typedef enum +{ + AUDIO_SUBCLASS_UNDEFINED = 0x00, + AUDIO_SUBCLASS_CONTROL , ///< Audio Control + AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming +} audio_subclass_type_t; + +/// A.6 - Audio Interface Protocol Codes +typedef enum +{ + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_t; + +/// A.7 - Audio Function Category Codes +typedef enum +{ + AUDIO_FUNC_UNDEF = 0x00, + AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO_FUNC_HOME_THEATER = 0x02, + AUDIO_FUNC_MICROPHONE = 0x03, + AUDIO_FUNC_HEADSET = 0x04, + AUDIO_FUNC_TELEPHONE = 0x05, + AUDIO_FUNC_CONVERTER = 0x06, + AUDIO_FUNC_SOUND_RECODER = 0x07, + AUDIO_FUNC_IO_BOX = 0x08, + AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO_FUNC_PRO_AUDIO = 0x0A, + AUDIO_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO_FUNC_CONTROL_PANEL = 0x0C, + AUDIO_FUNC_OTHER = 0xFF, +} audio_function_code_t; + +/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio_cs_ac_interface_subtype_t; + +/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO_CS_AS_INTERFACE_DECODER = 0x04, +} audio_cs_as_interface_subtype_t; + +/// A.11 - Effect Unit Effect Types +typedef enum +{ + AUDIO_EFFECT_TYPE_UNDEF = 0x00, + AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio_effect_unit_effect_type_t; + +/// A.12 - Processing Unit Process Types +typedef enum +{ + AUDIO_PROCESS_TYPE_UNDEF = 0x00, + AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio_processing_unit_process_type_t; + +/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// A.14 - Audio Class-Specific Request Codes +typedef enum +{ + AUDIO_CS_REQ_UNDEF = 0x00, + AUDIO_CS_REQ_CUR = 0x01, + AUDIO_CS_REQ_RANGE = 0x02, + AUDIO_CS_REQ_MEM = 0x03, +} audio_cs_req_t; + +/// A.17 - Control Selector Codes + +/// A.17.1 - Clock Source Control Selectors +typedef enum +{ + AUDIO_CS_CTRL_UNDEF = 0x00, + AUDIO_CS_CTRL_SAM_FREQ = 0x01, + AUDIO_CS_CTRL_CLK_VALID = 0x02, +} audio_clock_src_control_selector_t; + +/// A.17.2 - Clock Selector Control Selectors +typedef enum +{ + AUDIO_CX_CTRL_UNDEF = 0x00, + AUDIO_CX_CTRL_CONTROL = 0x01, +} audio_clock_sel_control_selector_t; + +/// A.17.3 - Clock Multiplier Control Selectors +typedef enum +{ + AUDIO_CM_CTRL_UNDEF = 0x00, + AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, + AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, +} audio_clock_mul_control_selector_t; + +/// A.17.4 - Terminal Control Selectors +typedef enum +{ + AUDIO_TE_CTRL_UNDEF = 0x00, + AUDIO_TE_CTRL_COPY_PROTECT = 0x01, + AUDIO_TE_CTRL_CONNECTOR = 0x02, + AUDIO_TE_CTRL_OVERLOAD = 0x03, + AUDIO_TE_CTRL_CLUSTER = 0x04, + AUDIO_TE_CTRL_UNDERFLOW = 0x05, + AUDIO_TE_CTRL_OVERFLOW = 0x06, + AUDIO_TE_CTRL_LATENCY = 0x07, +} audio_terminal_control_selector_t; + +/// A.17.5 - Mixer Control Selectors +typedef enum +{ + AUDIO_MU_CTRL_UNDEF = 0x00, + AUDIO_MU_CTRL_MIXER = 0x01, + AUDIO_MU_CTRL_CLUSTER = 0x02, + AUDIO_MU_CTRL_UNDERFLOW = 0x03, + AUDIO_MU_CTRL_OVERFLOW = 0x04, + AUDIO_MU_CTRL_LATENCY = 0x05, +} audio_mixer_control_selector_t; + +/// A.17.6 - Selector Control Selectors +typedef enum +{ + AUDIO_SU_CTRL_UNDEF = 0x00, + AUDIO_SU_CTRL_SELECTOR = 0x01, + AUDIO_SU_CTRL_LATENCY = 0x02, +} audio_sel_control_selector_t; + +/// A.17.7 - Feature Unit Control Selectors +typedef enum +{ + AUDIO_FU_CTRL_UNDEF = 0x00, + AUDIO_FU_CTRL_MUTE = 0x01, + AUDIO_FU_CTRL_VOLUME = 0x02, + AUDIO_FU_CTRL_BASS = 0x03, + AUDIO_FU_CTRL_MID = 0x04, + AUDIO_FU_CTRL_TREBLE = 0x05, + AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO_FU_CTRL_AGC = 0x07, + AUDIO_FU_CTRL_DELAY = 0x08, + AUDIO_FU_CTRL_BASS_BOOST = 0x09, + AUDIO_FU_CTRL_LOUDNESS = 0x0A, + AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO_FU_CTRL_INVERTER = 0x0D, + AUDIO_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO_FU_CTRL_OVERVLOW = 0x0F, + AUDIO_FU_CTRL_LATENCY = 0x10, +} audio_feature_unit_control_selector_t; + +/// A.17.8 Effect Unit Control Selectors + +/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors +typedef enum +{ + AUDIO_PE_CTRL_UNDEF = 0x00, + AUDIO_PE_CTRL_ENABLE = 0x01, + AUDIO_PE_CTRL_CENTERFREQ = 0x02, + AUDIO_PE_CTRL_QFACTOR = 0x03, + AUDIO_PE_CTRL_GAIN = 0x04, + AUDIO_PE_CTRL_UNDERFLOW = 0x05, + AUDIO_PE_CTRL_OVERFLOW = 0x06, + AUDIO_PE_CTRL_LATENCY = 0x07, +} audio_parametric_equalizer_control_selector_t; + +/// A.17.8.2 Reverberation Effect Unit Control Selectors +typedef enum +{ + AUDIO_RV_CTRL_UNDEF = 0x00, + AUDIO_RV_CTRL_ENABLE = 0x01, + AUDIO_RV_CTRL_TYPE = 0x02, + AUDIO_RV_CTRL_LEVEL = 0x03, + AUDIO_RV_CTRL_TIME = 0x04, + AUDIO_RV_CTRL_FEEDBACK = 0x05, + AUDIO_RV_CTRL_PREDELAY = 0x06, + AUDIO_RV_CTRL_DENSITY = 0x07, + AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, + AUDIO_RV_CTRL_UNDERFLOW = 0x09, + AUDIO_RV_CTRL_OVERFLOW = 0x0A, + AUDIO_RV_CTRL_LATENCY = 0x0B, +} audio_reverberation_effect_control_selector_t; + +/// A.17.8.3 Modulation Delay Effect Unit Control Selectors +typedef enum +{ + AUDIO_MD_CTRL_UNDEF = 0x00, + AUDIO_MD_CTRL_ENABLE = 0x01, + AUDIO_MD_CTRL_BALANCE = 0x02, + AUDIO_MD_CTRL_RATE = 0x03, + AUDIO_MD_CTRL_DEPTH = 0x04, + AUDIO_MD_CTRL_TIME = 0x05, + AUDIO_MD_CTRL_FEEDBACK = 0x06, + AUDIO_MD_CTRL_UNDERFLOW = 0x07, + AUDIO_MD_CTRL_OVERFLOW = 0x08, + AUDIO_MD_CTRL_LATENCY = 0x09, +} audio_modulation_delay_control_selector_t; + +/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors +typedef enum +{ + AUDIO_DR_CTRL_UNDEF = 0x00, + AUDIO_DR_CTRL_ENABLE = 0x01, + AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO_DR_CTRL_MAXAMPL = 0x03, + AUDIO_DR_CTRL_THRESHOLD = 0x04, + AUDIO_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO_DR_CTRL_RELEASE_TIME = 0x06, + AUDIO_DR_CTRL_UNDERFLOW = 0x07, + AUDIO_DR_CTRL_OVERFLOW = 0x08, + AUDIO_DR_CTRL_LATENCY = 0x09, +} audio_dynamic_range_compression_control_selector_t; + +/// A.17.9 Processing Unit Control Selectors + +/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors +typedef enum +{ + AUDIO_UD_CTRL_UNDEF = 0x00, + AUDIO_UD_CTRL_ENABLE = 0x01, + AUDIO_UD_CTRL_MODE_SELECT = 0x02, + AUDIO_UD_CTRL_CLUSTER = 0x03, + AUDIO_UD_CTRL_UNDERFLOW = 0x04, + AUDIO_UD_CTRL_OVERFLOW = 0x05, + AUDIO_UD_CTRL_LATENCY = 0x06, +} audio_up_down_mix_control_selector_t; + +/// A.17.9.2 Dolby Prologic â„¢ Processing Unit Control Selectors +typedef enum +{ + AUDIO_DP_CTRL_UNDEF = 0x00, + AUDIO_DP_CTRL_ENABLE = 0x01, + AUDIO_DP_CTRL_MODE_SELECT = 0x02, + AUDIO_DP_CTRL_CLUSTER = 0x03, + AUDIO_DP_CTRL_UNDERFLOW = 0x04, + AUDIO_DP_CTRL_OVERFLOW = 0x05, + AUDIO_DP_CTRL_LATENCY = 0x06, +} audio_dolby_prologic_control_selector_t; + +/// A.17.9.3 Stereo Extender Processing Unit Control Selectors +typedef enum +{ + AUDIO_ST_EXT_CTRL_UNDEF = 0x00, + AUDIO_ST_EXT_CTRL_ENABLE = 0x01, + AUDIO_ST_EXT_CTRL_WIDTH = 0x02, + AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, + AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, + AUDIO_ST_EXT_CTRL_LATENCY = 0x05, +} audio_stereo_extender_control_selector_t; + +/// A.17.10 Extension Unit Control Selectors +typedef enum +{ + AUDIO_XU_CTRL_UNDEF = 0x00, + AUDIO_XU_CTRL_ENABLE = 0x01, + AUDIO_XU_CTRL_CLUSTER = 0x02, + AUDIO_XU_CTRL_UNDERFLOW = 0x03, + AUDIO_XU_CTRL_OVERFLOW = 0x04, + AUDIO_XU_CTRL_LATENCY = 0x05, +} audio_extension_unit_control_selector_t; + +/// A.17.11 AudioStreaming Interface Control Selectors +typedef enum +{ + AUDIO_AS_CTRL_UNDEF = 0x00, + AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, + AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, + AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, +} audio_audiostreaming_interface_control_selector_t; + +/// A.17.12 Encoder Control Selectors +typedef enum +{ + AUDIO_EN_CTRL_UNDEF = 0x00, + AUDIO_EN_CTRL_BIT_RATE = 0x01, + AUDIO_EN_CTRL_QUALITY = 0x02, + AUDIO_EN_CTRL_VBR = 0x03, + AUDIO_EN_CTRL_TYPE = 0x04, + AUDIO_EN_CTRL_UNDERFLOW = 0x05, + AUDIO_EN_CTRL_OVERFLOW = 0x06, + AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, + AUDIO_EN_CTRL_PARAM1 = 0x08, + AUDIO_EN_CTRL_PARAM2 = 0x09, + AUDIO_EN_CTRL_PARAM3 = 0x0A, + AUDIO_EN_CTRL_PARAM4 = 0x0B, + AUDIO_EN_CTRL_PARAM5 = 0x0C, + AUDIO_EN_CTRL_PARAM6 = 0x0D, + AUDIO_EN_CTRL_PARAM7 = 0x0E, + AUDIO_EN_CTRL_PARAM8 = 0x0F, +} audio_encoder_control_selector_t; + +/// A.17.13 Decoder Control Selectors + +/// A.17.13.1 MPEG Decoder Control Selectors +typedef enum +{ + AUDIO_MPD_CTRL_UNDEF = 0x00, + AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, + AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, + AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, + AUDIO_MPD_CTRL_DYN_RANGE = 0x04, + AUDIO_MPD_CTRL_SCALING = 0x05, + AUDIO_MPD_CTRL_HILO_SCALING = 0x06, + AUDIO_MPD_CTRL_UNDERFLOW = 0x07, + AUDIO_MPD_CTRL_OVERFLOW = 0x08, + AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, +} audio_MPEG_decoder_control_selector_t; + +/// A.17.13.2 AC-3 Decoder Control Selectors +typedef enum +{ + AUDIO_AD_CTRL_UNDEF = 0x00, + AUDIO_AD_CTRL_MODE = 0x01, + AUDIO_AD_CTRL_DYN_RANGE = 0x02, + AUDIO_AD_CTRL_SCALING = 0x03, + AUDIO_AD_CTRL_HILO_SCALING = 0x04, + AUDIO_AD_CTRL_UNDERFLOW = 0x05, + AUDIO_AD_CTRL_OVERFLOW = 0x06, + AUDIO_AD_CTRL_DECODER_ERROR = 0x07, +} audio_AC3_decoder_control_selector_t; + +/// A.17.13.3 WMA Decoder Control Selectors +typedef enum +{ + AUDIO_WD_CTRL_UNDEF = 0x00, + AUDIO_WD_CTRL_UNDERFLOW = 0x01, + AUDIO_WD_CTRL_OVERFLOW = 0x02, + AUDIO_WD_CTRL_DECODER_ERROR = 0x03, +} audio_WMA_decoder_control_selector_t; + +/// A.17.13.4 DTS Decoder Control Selectors +typedef enum +{ + AUDIO_DD_CTRL_UNDEF = 0x00, + AUDIO_DD_CTRL_UNDERFLOW = 0x01, + AUDIO_DD_CTRL_OVERFLOW = 0x02, + AUDIO_DD_CTRL_DECODER_ERROR = 0x03, +} audio_DTS_decoder_control_selector_t; + +/// A.17.14 Endpoint Control Selectors +typedef enum +{ + AUDIO_EP_CTRL_UNDEF = 0x00, + AUDIO_EP_CTRL_PITCH = 0x01, + AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, + AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, +} audio_EP_control_selector_t; + +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +/// Additional Audio Device Class Codes - Source: Audio Data Formats + +/// A.1 - Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), +} audio_data_format_type_I_t; + +/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification + +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + +/// Audio Class-Control Values UAC2 +typedef enum +{ + AUDIO_CTRL_NONE = 0x00, ///< No Host access + AUDIO_CTRL_R = 0x01, ///< Host read access only + AUDIO_CTRL_RW = 0x03, ///< Host read write access +} audio_control_t; + +/// Audio Class-Specific AC Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio_cs_ac_interface_control_pos_t; + +/// Audio Class-Specific AS Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio_cs_as_interface_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio_cs_as_iso_data_ep_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Clock Source Attributes UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio_clock_source_attribute_t; + +/// Audio Class-Clock Source Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio_clock_source_control_pos_t; + +/// Audio Class-Clock Selector Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, +} audio_clock_selector_control_pos_t; + +/// Audio Class-Clock Multiplier Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio_clock_multiplier_control_pos_t; + +/// Audio Class-Input Terminal Controls UAC2 +typedef enum +{ + AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio_terminal_input_control_pos_t; + +/// Audio Class-Output Terminal Controls UAC2 +typedef enum +{ + AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio_terminal_output_control_pos_t; + +/// Audio Class-Feature Unit Controls UAC2 +typedef enum +{ + AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio_feature_unit_control_pos_t; + +/// Audio Class-Audio Channel Configuration UAC2 +typedef enum +{ + AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, +} audio_channel_config_t; + +/// AUDIO Channel Cluster Descriptor (4.1) +typedef struct TU_ATTR_PACKED { + uint8_t bNrChannels; ///< Number of channels currently connected. + audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. +} audio_desc_channel_cluster_t; + +/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. +} audio_desc_cs_ac_interface_t; + +/// AUDIO Clock Source Descriptor (4.7.2.1) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio_desc_clock_source_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio_desc_clock_selector_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins #define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bClockID ; \ + uint8_t bNrInPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ } - /// AUDIO Clock Multiplier Descriptor (4.7.2.3) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. - } audio_desc_clock_multiplier_t; - - /// AUDIO Input Terminal Descriptor(4.7.2.4) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. - } audio_desc_input_terminal_t; - - /// AUDIO Output Terminal Descriptor(4.7.2.5) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. - } audio_desc_output_terminal_t; - - /// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. - } audio_desc_feature_unit_t; - - /// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num) \ +/// AUDIO Clock Multiplier Descriptor (4.7.2.3) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio_desc_clock_multiplier_t; + +/// AUDIO Input Terminal Descriptor(4.7.2.4) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. +} audio_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor(4.7.2.5) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. +} audio_desc_output_terminal_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. +} audio_desc_feature_unit_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels +#define audio_desc_feature_unit_n_t(ch_num)\ struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ + uint8_t bLength ; /* 6+(ch_num+1)*4 */\ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ } /// AUDIO Class-Specific AS Interface Descriptor(4.9.2) @@ -789,13 +789,13 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. } audio_desc_cs_as_interface_t; /// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) @@ -804,9 +804,9 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. } audio_desc_type_I_format_t; /// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) @@ -815,10 +815,10 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; //// 5.2.3 Control Request Parameter Block Layout @@ -826,19 +826,19 @@ typedef struct TU_ATTR_PACKED // 5.2.3.1 1-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_1_t; // 5.2.3.2 2-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_2_t; // 5.2.3.3 4-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_4_t; // Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like @@ -846,64 +846,64 @@ typedef struct TU_ATTR_PACKED typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_1_t; // 5.2.3.2 2-byte Control RANGE Parameter Block typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_2_t; // 5.2.3.3 4-byte Control RANGE Parameter Block typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_4_t; // 5.2.3.1 1-byte Control RANGE Parameter Block #define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ - } + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ +} - // 5.2.3.2 2-byte Control RANGE Parameter Block + /// 5.2.3.2 2-byte Control RANGE Parameter Block #define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ - } + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges]; \ +} // 5.2.3.3 4-byte Control RANGE Parameter Block #define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ - } + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges]; \ +} /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 129aed481..6fe5d6717 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -48,29 +48,29 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function #if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. + uint8_t ep_fb; // Feedback EP. #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. + uint8_t ep_int_ctr; // Audio control interrupt EP. #endif #if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -104,17 +104,17 @@ typedef struct // Endpoint Transfer buffers #if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) // TODO: required? //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! + // uint16_t fb_val; // Feedback value for asynchronous mode! //#endif #endif #if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -125,20 +125,6 @@ typedef struct #define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) -//#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) -//#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) -//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) -//#elif CFG_TUD_AUDIO_EPSIZE_OUT -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) -//#elif CFG_TUD_AUDIO_EPSIZE_IN -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) -//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) -//#endif - //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -253,37 +239,41 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - asm("nop"); + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); + TU_BREAKPOINT(); break; case AUDIO_FORMAT_TYPE_I: switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_RX_FIFO_SIZE - TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! #endif - break; + break; - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - asm("nop"); - break; + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); + TU_BREAKPOINT(); + break; } break; - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - asm("nop"); - break; + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); + TU_BREAKPOINT(); + break; } // Call a weak callback here - a possibility for user to get informed RX was completed - TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + if (tud_audio_rx_done_cb) TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; } @@ -325,25 +315,9 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a chId = 0; } } -} } +} } #endif //CFG_TUD_AUDIO_RX_FIFO_SIZE - -#if CFG_TUD_AUDIO_EPSIZE_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) -{ - (void) rhport; - (void) buffer; - (void) bufsize; - - /* NOTE: This function should not be modified, when the callback is needed, - the tud_audio_rx_done_cb could be implemented in the user file - */ - - return true; -} -#endif - //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ @@ -392,28 +366,28 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_TX_FIFO_SIZE - TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); #else #error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! #endif - break; + break; - default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); + TU_BREAKPOINT(); + break; } break; - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - break; + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); + TU_BREAKPOINT(); + break; } // Call a weak callback here - a possibility for user to get informed TX was completed @@ -601,8 +575,8 @@ void audiod_reset(uint8_t rhport) uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); // Verify version is correct - this check can be omitted TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); @@ -622,7 +596,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { if (!_audiod_itf[i].p_desc) { - _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one break; } } @@ -631,11 +605,8 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - - // Notify caller we read complete descriptor - // (*p_length) += tud_audio_desc_lengths[i]; // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } @@ -694,7 +665,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? + _audiod_itf[idxDriver].ep_in = 0; // Necessary? } #endif @@ -703,12 +674,12 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_out_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + _audiod_itf[idxDriver].ep_out = 0; // Necessary? // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? #endif } #endif @@ -730,56 +701,56 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; while (foundEPs < nEps && p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; #if CFG_TUD_AUDIO_EPSIZE_IN > 0 - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP - { - // Save address - _audiod_itf[idxDriver].ep_in = ep_addr; - _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - - // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? - // Invoke callback - fill something in the FIFO here for now - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - - uint16_t n_bytes_copied; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); - } + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + // Save address + _audiod_itf[idxDriver].ep_in = ep_addr; + _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + + // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? + // Invoke callback - fill something in the FIFO here for now + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + + uint16_t n_bytes_copied; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; - _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + _audiod_itf[idxDriver].ep_out_as_intf_num = itf; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); - } + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback - { - _audiod_itf[idxDriver].ep_fb = ep_addr; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - } + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } #endif #endif - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); } TU_VERIFY(foundEPs == nEps); @@ -808,62 +779,62 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); if (entityID != 0) { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + if (tud_audio_set_req_entity_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } else { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); if (tud_audio_set_req_ep_cb) { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it } // Unknown/Unsupported recipient @@ -885,12 +856,12 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req switch (p_request->bRequest) { case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + return audiod_get_interface(rhport, p_request); case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + return audiod_set_interface(rhport, p_request); - // Unknown/Unsupported request + // Unknown/Unsupported request default: TU_BREAKPOINT(); return false; } } @@ -904,52 +875,52 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Verify if entity is present if (entityID != 0) { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } + } } else { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } + } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); @@ -959,15 +930,15 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall + } } break; @@ -1009,9 +980,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) { - // There is no data left to send, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } } @@ -1036,8 +1007,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (*n_bytes_copied == 0) { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } return true; @@ -1065,8 +1036,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } return true; @@ -1091,7 +1062,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label uint8_t entityID = TU_U16_HIGH(p_request->wIndex); @@ -1108,7 +1079,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); @@ -1151,18 +1122,18 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 uint8_t tmp = 0; while (p_desc < p_desc_end) { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *idxDriver = i; - *pp_desc_int = p_desc; - return true; - } - - // Increase index, bytes read, and pointer - tmp++; - p_desc = tu_desc_next(p_desc); + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); } } } @@ -1180,18 +1151,18 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) { // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor while (p_desc < p_desc_end) { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + *idxDriver = i; + return true; + } + p_desc = tu_desc_next(p_desc); } } } @@ -1211,12 +1182,12 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) while (p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + *idxDriver = i; + return true; + } + p_desc = tu_desc_next(p_desc); } } } @@ -1239,12 +1210,12 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) while (p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) + { + *idxDriver = i; + return true; + } + p_desc = tu_desc_next(p_desc); } } } @@ -1252,222 +1223,3 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) } #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO - -// OLD -//// In order that this function works the following is mandatory: -// // - An IAD descriptor is required and has to be placed directly before the Standard AC Interface Descriptor (4.7.1) ALSO if no Audio Streaming interfaces are used! -// // - The Standard AC Interface Descriptor (4.7.1) has to be the first interface listed (required by UAC2 specification) -// // - The alternate interfaces of the Standard AS Interface Descriptor(4.9.1) must be listed in increasing order and alternate 0 must have zero EPs -// -// TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && -// AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); -// -// // Verify version is correct - this check can be omitted -// TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); -// -// // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted -// if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed -// { -// TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); -// } -// -// // Alternate setting MUST be zero - this check can be omitted -// TU_VERIFY(itf_desc->bAlternateSetting == 0); -// -// // Since checks are successful we get the number of interfaces we have to process by exploiting the fact that an IAD descriptor has to be provided directly before this AC descriptor -// // We do not get this value delivered by the stack so we need to hack a little bit - the number of interfaces to be processed is listed in the IAD descriptor with an offset of exactly 5 -// uint8_t nItfs = *(((uint8_t const *) itf_desc) - 5) - 1; // -1 since we already process the (included) AC interface -// -// // Notify caller we have read Standard AC Interface Descriptor (4.7.1) -// (*p_length) = sizeof(tusb_desc_interface_t); -// -// // Go to next descriptor which has to be a Class-Specific AC Interface Header Descriptor(4.7.2) - always present -// audio_desc_cs_ac_interface_t const * p_desc_cs_ac = (audio_desc_cs_ac_interface_t const *) tu_desc_next ( (uint8_t const *) itf_desc ); -// -// // Verify its the correct descriptor - this check can be omitted -// TU_VERIFY(p_desc_cs_ac->bDescriptorType == TUSB_DESC_CS_INTERFACE -// && p_desc_cs_ac->bDescriptorSubType == AUDIO_CS_AC_INTERFACE_HEADER -// && p_desc_cs_ac->bcdADC == 0x0200); -// -// // We do not check the Audio Function Category Codes -// -// // We do not check all the following Clock Source, Unit and Terminal descriptors -// -// // We do not check the latency control -// -// // We jump over all the following descriptor to the next following interface (which should be a Standard AS Interface Descriptor(4.9.1) if nItfs > 0) -// (*p_length) += p_desc_cs_ac->wTotalLength; // Notify caller of read bytes -// itf_desc = (tusb_desc_interface_t const * )(((uint8_t const *)p_desc_cs_ac ) + p_desc_cs_ac->wTotalLength); // Move pointer -// -// // From this point on we have nItfs packs of audio streaming interfaces (consisting of multiple descriptors always starting with a Standard AS Interface Descriptor(4.9.1)) -// -// uint8_t cnt; -// uint8_t nEPs; -// audio_format_type_t formatType; -// uint8_t intNum; -// uint8_t altInt; -// -// for (cnt = 0; cnt < nItfs; cnt++) -// { -// -// // Here starts an unknown number of alternate interfaces - the art here is to find the end of this interface pack. We do not have the total number of descriptor bytes available (not provided by tinyUSB stack for .open() function) so we try to find the end of this interface pack by deducing it from the order and content of the descriptor pack -// while(1) -// { -// // At first this should be a Standard AS Interface Descriptor(4.9.1) - this check can be omitted -// TU_VERIFY(itf_desc->bDescriptorType == TUSB_DESC_INTERFACE && -// itf_desc->bInterfaceClass == TUSB_CLASS_AUDIO && -// itf_desc->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING && -// itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); -// -// // Remember number of EPs this interface has - required for later -// nEPs = itf_desc->bNumEndpoints; -// intNum = itf_desc->bInterfaceNumber; -// altInt = itf_desc->bAlternateSetting; -// -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// -// // It is possible now that the following interface is again a Standard AS Interface Descriptor(4.9.1) (in case the related terminal has more than zero EPs at all and this is the following alternative interface > 0 - the alternative (that this is not a Standard AS Interface Descriptor(4.9.1) but a Class-Specific AS Interface Descriptor(4.9.2)) could be in case the related terminal has no EPs at all e.g. SPDIF connector -// if (tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE) -// { -// // It is not possible, that a Standard AS Interface Descriptor(4.9.1) ends without a Class-Specific AS Interface Descriptor(4.9.2) -// // hence the next interface has to be an alternative interface with regard to the one we started above - continue -// continue; -// } -// -// // Second, this interface has to be a Class-Specific AS Interface Descriptor(4.9.2) - this check can be omitted -// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && -// ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_AS_GENERAL); -// -// // Remember format type of this interface - required for later -// formatType = ((audio_desc_cs_as_interface_t *) itf_desc)->bFormatType; -// -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// -// // Every Class-Specific AS Interface Descriptor(4.9.2) defines a format type and thus a format type descriptor e.g. Type I Format Type Descriptor(2.3.1.6 - Audio Formats) should follow - only if the format type is undefined no format type descriptor follows -// if (formatType != AUDIO_FORMAT_TYPE_UNDEFINED) -// { -// // We do not need any information from this descriptor - we simply advance -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// } -// -// // Now there might be an encoder/decoder interface - i found no clue if this interface is mandatory (although examples found by google never use this descriptor) or if there is any way to determine if this descriptor is reliably present or not. Problem here: Since we need to find the end of this interface pack and we do not have the total amount of descriptor bytes available here (not given by the tinyUSB stack for the .open() function), we have to make a speculative check if the following is an encoder/decoder interface or not. -// // It could be possible that we ready over the total length of all descriptor bytes here - we simply hope that the combination of descriptor length, type, and sub type does not occur randomly in memory here. The only way to make this check waterproof is to know how many bytes we can read at all but this would be an information we need to be given by tinyUSB! -// if (tu_desc_len((uint8_t const *) itf_desc) == 21 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && (((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_ENCODER || ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_DECODER)) -// { -// // We do not need any information from this descriptor - we simply advance -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// } -// -// // Here may be some EP descriptors -// for (uint8_t cntEP = 0; cntEP < nEPs; cntEP++) -// { -// // This check can be omitted -// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_ENDPOINT); -// -// // Here we can find information about our EPs address etc. but in the initialization process we do not set anything, we have to wait for the host to send a setInterface request where the EPs etc. are set up according -// -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // If the usage type is something else than feedback there is a Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) following up -// if (((tusb_desc_endpoint_t *) itf_desc)->bmAttributes.usage != 0x10) -// { -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// -// // We do not need any information from this descriptor - we simply advance -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// } -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// } -// -// // Okay we processed a complete pack - now we have to make a speculative check if the next interface is an alternate interface belonging to the ones processed before - since it is speculative we check a lot to reduce the chances we go wrong and hope for the best -// if (!(tu_desc_len((uint8_t const *) itf_desc) == 9 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE && itf_desc->bInterfaceNumber == intNum && itf_desc->bAlternateSetting == altInt + 1)) -// { -// // The current interface is not a consecutive alternate interface to the one processed above -// break; -// } -// } -// -// } - - -// Here follow the encoding steps - -//#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_UNDEFINED -// -//#error Individual encoding procedure required! -// -//#elif CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I -// -//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM -// -//#if CFG_TUD_AUDIO_TX_FIFO_SIZE -// TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); -//#else -//#error YOUR ENCODING AND SENDING IS REQUIRED HERE! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX not implemented! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! -//#endif -// -// // Call a weak callback here - a possibility for user to get informed TX was completed -// TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); -// return true; - -//#if CFG_TUD_AUDIO_EPSIZE_OUT -//static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { -// -// // Here follow the decoding steps -// -//#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_UNDEFINED -// -//#error Individual decoding procedure required! -// -//#elif CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I -// -//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM -// -//#if CFG_TUD_AUDIO_RX_FIFO_SIZE -// TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); -//#else -//#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX not implemented! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! -//#endif -// -// TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); -// return true; -//} -//#endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b745ceb09..c23cf72c2 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -41,7 +41,7 @@ // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) #ifndef CFG_TUD_AUDIO_N_AS_INT -#define CFG_TUD_AUDIO_N_AS_INT 0 +#define CFG_TUD_AUDIO_N_AS_INT 0 #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors @@ -56,51 +56,51 @@ // If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and Y. This, however, allows for optimizations. #ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel +#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif #ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel +#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN -#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX #endif #ifndef CFG_TUD_AUDIO_EPSIZE_OUT -#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback #endif #ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN #ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 #endif // Audio data format types #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c #endif // Audio data format type I specifications @@ -108,11 +108,11 @@ // Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 @@ -128,11 +128,11 @@ #if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 @@ -148,7 +148,7 @@ //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); // Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL +// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL #ifdef __cplusplus extern "C" { @@ -172,26 +172,26 @@ void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_read_flush (uint8_t itf); -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_read_flush (uint8_t itf); +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); #endif //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ -inline bool tud_audio_mounted (void); +inline bool tud_audio_mounted (void); #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE -inline uint16_t tud_audio_available (void); -inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -inline void tud_audio_read_flush (void); +inline uint16_t tud_audio_available (void); +inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +inline void tud_audio_read_flush (void); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE @@ -199,10 +199,10 @@ inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -inline uint32_t tud_audio_int_ctr_available (void); -inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -inline void tud_audio_int_ctr_read_flush (void); -inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +inline uint32_t tud_audio_int_ctr_available (void); +inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +inline void tud_audio_int_ctr_read_flush (void); +inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); #endif // Buffer control EP data and schedule a transmit @@ -260,52 +260,52 @@ TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_reque inline bool tud_audio_mounted(void) { - return tud_audio_n_mounted(0); + return tud_audio_n_mounted(0); } #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE -inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { - return tud_audio_n_write(0, channelId, buffer, bufsize); + return tud_audio_n_write(0, channelId, buffer, bufsize); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available(uint8_t channelId) { - return tud_audio_n_available(0, channelId); + return tud_audio_n_available(0, channelId); } inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) { - return tud_audio_n_read(0, channelId, buffer, bufsize); + return tud_audio_n_read(0, channelId, buffer, bufsize); } inline void tud_audio_read_flush(uint8_t channelId) { - tud_audio_n_read_flush(0, channelId); + tud_audio_n_read_flush(0, channelId); } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 inline uint16_t tud_audio_int_ctr_available(void) { - return tud_audio_int_ctr_n_available(0); + return tud_audio_int_ctr_n_available(0); } inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) { - return tud_audio_int_ctr_n_read(0, buffer, bufsize); + return tud_audio_int_ctr_n_read(0, buffer, bufsize); } inline void tud_audio_int_ctr_read_flush(void) { - return tud_audio_int_ctr_n_read_flush(0); + return tud_audio_int_ctr_n_read_flush(0); } inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) { - return tud_audio_int_ctr_n_write(0, buffer, bufsize); + return tud_audio_int_ctr_n_write(0, buffer, bufsize); } #endif @@ -314,7 +314,7 @@ inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) //--------------------------------------------------------------------+ void audiod_init (void); void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c188bb485..56d606717 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -142,9 +142,9 @@ typedef struct { typedef struct TU_ATTR_PACKED { // The following format may look complicated but it is the most elegant way of addressing the required fields: EP number, EP direction, and EP transfer type. // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. - uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) - bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt - ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! + uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) + bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt + ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! } ep_sz_tt_report_t; typedef volatile uint32_t * usb_fifo_t; @@ -166,7 +166,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); -// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + // USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -220,9 +220,9 @@ static void bus_reset(uint8_t rhport) // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size - _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) -// _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + // _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) usb_otg->GRXFSIZ = _allocated_fifo_words; @@ -237,29 +237,29 @@ static void bus_reset(uint8_t rhport) usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; -//#if TUD_OPT_HIGH_SPEED -// _allocated_fifo_words = 271 + 2*EP_MAX; -//#else -// _allocated_fifo_words = 47 + 2*EP_MAX; -//#endif -// -// usb_otg->GRXFSIZ = _allocated_fifo_words; -// -// // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) -// usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; -// -// _allocated_fifo_words += 16; -// -// // TU_LOG2_INT(_allocated_fifo_words); -// -// // Fixed control EP0 size to 64 bytes -// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); -// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; -// -// // Set SETUP packet count to 3 -// out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); -// -// usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + //#if TUD_OPT_HIGH_SPEED + // _allocated_fifo_words = 271 + 2*EP_MAX; + //#else + // _allocated_fifo_words = 47 + 2*EP_MAX; + //#endif + // + // usb_otg->GRXFSIZ = _allocated_fifo_words; + // + // // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + // usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + // + // _allocated_fifo_words += 16; + // + // // TU_LOG2_INT(_allocated_fifo_words); + // + // // Fixed control EP0 size to 64 bytes + // in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + // xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + // + // // Set SETUP packet count to 3 + // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); + // + // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } // Required after new configuration received in case EP0 max packet size has changed @@ -273,12 +273,12 @@ static void set_EP0_max_pkt_size() // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL. switch (enum_spd) { - case 0x00: // High speed - always 64 byte + case 0x00: // High speed - always 64 byte in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; break; - case 0x03: // Full speed + case 0x03: // Full speed #if CFG_TUD_ENDPOINT0_SIZE == 64 in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; @@ -298,7 +298,7 @@ static void set_EP0_max_pkt_size() #endif break; - default: // Low speed - always 8 bytes + default: // Low speed - always 8 bytes in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = 8; xfer_status[0][TUSB_DIR_IN].max_size = 8; @@ -375,7 +375,6 @@ static void set_speed(uint8_t rhport, tusb_speed_t speed) dev->DCFG |= (bitvalue << USB_OTG_DCFG_DSPD_Pos); } - #if defined(USB_HS_PHYC) static bool USB_HS_PHYCInit(void) { @@ -1140,7 +1139,7 @@ static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * { (void) rhport; -// tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! + // tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! // EP0 sizes and usages are fixed p_report->ep_size[0][TUSB_DIR_OUT] = p_report->ep_size[0][TUSB_DIR_IN] = CFG_TUD_ENDPOINT0_SIZE; @@ -1153,22 +1152,22 @@ static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * uint8_t addr; while( p_desc < desc_end ) + { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) - { - addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - // Verify values - this checks may be omitted in case we trust the descriptors to be okay - TU_VERIFY(tu_edpt_number(addr) < EP_MAX); - TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); - TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); + // Verify values - this checks may be omitted in case we trust the descriptors to be okay + TU_VERIFY(tu_edpt_number(addr) < EP_MAX); + TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); + TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); - p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); - p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; - } - p_desc = tu_desc_next(p_desc); // Proceed + p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); + p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; } + p_desc = tu_desc_next(p_desc); // Proceed + } return true; } @@ -1201,10 +1200,10 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); - // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); + // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); // Determine maximum required spaces for individual EPs and what kind of usage (control, bulk, etc.) they are used for - ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type + ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type TU_VERIFY(get_ep_size_report(rhport, desc_cfg, &report)); // With that information, set the following up: @@ -1233,14 +1232,14 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration } // For configuration use the approach as explained in bus_reset() - _allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work + _allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (report.ep_size[0][TUSB_DIR_IN]/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders + _allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. @@ -1283,7 +1282,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // EP0 is already taken care of so exclude that here for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) { - ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders! + ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders! nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); } @@ -1293,7 +1292,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration return false; } - uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused + uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused uint16_t fifo_size; // Setup FIFOs @@ -1315,7 +1314,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; - // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_CNAK; -- cgit v1.3.1 From c61e9fb96def7b77b4001374b362141a29dcba5b Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 24 Aug 2020 09:01:03 +0200 Subject: audio_device: Fix descriptor limit calculation In several place p_desc_end calculation was not taking into account that starting pointer (_audiod_itf[idxDriver].p_desc) was pointing past interface association descriptor. It would result in accessing random memory. --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 6fe5d6717..f8676d4b5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -689,7 +689,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver] - TUD_AUDIO_DESC_IAD_LEN; // p_desc starts at required interface with alternate setting zero while (p_desc < p_desc_end) @@ -1113,7 +1113,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // Advance past AC descriptors uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1178,7 +1178,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { -- cgit v1.3.1 From a1b7e767af7c4916e9b004120715988268079d28 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Aug 2020 14:31:46 +0700 Subject: improve midi - fix #436 tud_midi_rx_cb() not invoked - fix xfer_cb() not handle ep in - add ZLP if needed --- src/class/cdc/cdc_device.c | 7 +++--- src/class/cdc/cdc_device.h | 1 - src/class/midi/midi_device.c | 51 ++++++++++++++++++++++++++------------------ src/class/midi/midi_device.h | 2 +- 4 files changed, 35 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 94473d036..b4ebfc92e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -164,7 +164,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // skip if previous transfer not complete yet TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); + uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected @@ -376,7 +376,6 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) rhport; (void) result; uint8_t itf; @@ -393,6 +392,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Received new data if ( ep_addr == p_cdc->ep_out ) { + // TODO search for wanted char first for better performance for(uint32_t i=0; irx_ff, &p_cdc->epout_buf[i]); @@ -423,9 +423,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero + // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); } } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index f9692e20f..145381c42 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -57,7 +57,6 @@ // CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ - // Check if terminal is connected to this port bool tud_cdc_n_connected (uint8_t itf); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index d4ed21c78..71a24cbcd 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -101,8 +101,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu // Fill empty buffer if (midi->read_buffer_length == 0) { - if (!tud_midi_n_receive(itf, midi->read_buffer)) - return 0; + if (!tud_midi_n_receive(itf, midi->read_buffer)) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. @@ -119,8 +118,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu } uint32_t n = midi->read_buffer_length - midi->read_target_length; - if (bufsize < n) - n = bufsize; + if (bufsize < n) n = bufsize; // Skip the header in the buffer memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); @@ -153,10 +151,8 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu // WRITE API //--------------------------------------------------------------------+ -static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) +static uint32_t write_flush(midid_interface_t* midi) { - (void) itf_index; - // skip if previous transfer not complete TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); @@ -165,7 +161,7 @@ static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) { TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); } - return true; + return count; } uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) @@ -234,7 +230,8 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u } i++; } - maybe_transmit(midi, itf); + + write_flush(midi); return i; } @@ -250,7 +247,7 @@ bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) return false; tu_fifo_write_n(&midi->tx_ff, packet, 4); - maybe_transmit(midi, itf); + write_flush(midi); return true; } @@ -389,27 +386,39 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 (void) result; uint8_t itf = 0; - midid_interface_t* p_midi = _midid_itf; + midid_interface_t* p_midi; - for ( ; ; itf++, p_midi++) + // Identify which interface to use + for (itf = 0; itf < CFG_TUD_MIDI; itf++) { - if (itf >= TU_ARRAY_SIZE(_midid_itf)) return false; - - if ( ep_addr == p_midi->ep_out ) break; + p_midi = &_midid_itf[itf]; + if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; } + TU_ASSERT(itf < CFG_TUD_CDC); // receive new data if ( ep_addr == p_midi->ep_out ) { - midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); + tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, xferred_bytes); + + // invoke receive callback if available + if (tud_midi_rx_cb) tud_midi_rx_cb(itf); // prepare for next - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false ); - } else if ( ep_addr == p_midi->ep_in ) { - maybe_transmit(p_midi, itf); + TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); + } + else if ( ep_addr == p_midi->ep_in ) + { + if (0 == write_flush(p_midi)) + { + // There is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) + { + usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + } + } } - - // nothing to do with in and notif endpoint return true; } diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 1828a21a3..b8fb55cc2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -72,7 +72,7 @@ bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ -// Application API (Interface0) +// Application API (Single Interface) //--------------------------------------------------------------------+ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); -- cgit v1.3.1 From 2d8787cdeb649f6b4e3c34ea2bd7015f0f120861 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Aug 2020 15:29:34 +0700 Subject: fix typo --- src/class/midi/midi_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 71a24cbcd..376b3670a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -385,7 +385,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 { (void) result; - uint8_t itf = 0; + uint8_t itf; midid_interface_t* p_midi; // Identify which interface to use @@ -394,7 +394,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 p_midi = &_midid_itf[itf]; if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; } - TU_ASSERT(itf < CFG_TUD_CDC); + TU_ASSERT(itf < CFG_TUD_MIDI); // receive new data if ( ep_addr == p_midi->ep_out ) -- cgit v1.3.1 From a4c096be377dd57554a67db92dd3d3167475c142 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 13:15:43 +0200 Subject: audio_device: Fix FIFO element size discrepancies Buffer for TX and RX FIFO was not taking into account size of element leading to out of bound access. audio_tx_done_type_I_pcm_ff_cb() reported copied bytes was not returning correct value number if channels was omitted in computation. Transfer size calculation uses simpler arithmetic. --- src/class/audio/audio_device.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f8676d4b5..1f2660825 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -80,7 +80,7 @@ typedef struct // FIFO #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE * CFG_TUD_AUDIO_TX_ITEMSIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif @@ -88,7 +88,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE * CFG_TUD_AUDIO_RX_ITEMSIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif @@ -404,10 +404,12 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); + uint16_t nBytesToSend; uint8_t cntChannel; - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) { @@ -423,10 +425,8 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) - { - nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - } + nSamplesPerChannelToSend = min(nSamplesPerChannelToSend, nEndpointSampleCapacity); + nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode uint16_t cntSample; @@ -456,8 +456,8 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); - *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nBytesToSend)); + *n_bytes_copied = nBytesToSend; return true; } -- cgit v1.3.1 From a3eff0c51a8b5ad58fa7111e770e3b5b3d959351 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 14:30:02 +0200 Subject: audio_device: Fix NULL pointer access in audiod_xfer_cb b_bytes_copied was pointer with NULL value instead of plain variable. NULL pointer was passed to audio_tx_done_cb() and dereference as well. Now variable is not a pointer. --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1f2660825..cbb13afc9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1002,10 +1002,10 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - uint16_t *n_bytes_copied = NULL; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + uint16_t n_bytes_copied; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); - if (*n_bytes_copied == 0) + if (n_bytes_copied == 0) { // Load with ZLP return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); -- cgit v1.3.1 From b1f0d6f57eb14aec8c5d83bd54a70a56558d24e8 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 14:41:50 +0200 Subject: audio_device: Change CFG_TUD_AUDIO_TX_BUFSIZE to CFG_TUD_AUDIO_TX_FIFO_SIZE CFG_TUD_AUDIO_TX_BUFSIZE seems to be used only in 3 preprocessor condition while in other places CFG_TUD_AUDIO_TX_FIFO_SIZE is used. --- src/class/audio/audio_device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c23cf72c2..41356c61a 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -171,7 +171,7 @@ uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, u void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -194,7 +194,7 @@ inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); inline void tud_audio_read_flush (void); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -263,12 +263,12 @@ inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { return tud_audio_n_write(0, channelId, buffer, bufsize); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available(uint8_t channelId) -- cgit v1.3.1 From b9c9cfdbac66b38faacdff6b5b2629c332d328a9 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:22:21 +0200 Subject: Change min to tu_min16. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index cbb13afc9..3be100890 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -425,7 +425,7 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerChannelToSend = min(nSamplesPerChannelToSend, nEndpointSampleCapacity); + nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode -- cgit v1.3.1 From 43c4b536356fdb9cb54a79f59fa0524cd14dc28c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:24:10 +0200 Subject: Fix CFG_TUD_AUDIO_RX_FIFO_SIZE defines. --- src/class/audio/audio_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 41356c61a..2f86168f5 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -165,7 +165,7 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); @@ -188,7 +188,7 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, inline bool tud_audio_mounted (void); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE inline uint16_t tud_audio_available (void); inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); inline void tud_audio_read_flush (void); @@ -270,7 +270,7 @@ inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint1 } #endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); -- cgit v1.3.1 From 83bd21420375d42f3788b3d3abd5e20ae00cd5b2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:26:41 +0200 Subject: Fix comment. --- src/class/audio/audio_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2f86168f5..f5830b3a1 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -53,7 +53,7 @@ // For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). // For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. // Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). -// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and Y. This, however, allows for optimizations. +// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and audio_tx_done_cb(). This, however, allows for optimizations. #ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel -- cgit v1.3.1 From 8f0693346cf4cba4ea9ea5755a7690b9ee4dc28f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 1 Sep 2020 11:26:16 +0200 Subject: Allow epin_buf to be written directly into in case no TX FIFOs are used. This is helpful if you have already encoded audio data and want an efficient way to send it. However, this approach is NOT THREADSAFE so far and works realiably ONLY IF tud_audio_n_write_ep_in_buffer() is NOT called form an interrupt! --- src/class/audio/audio_device.c | 120 ++++++++++++++++++++++++++++++++--------- src/class/audio/audio_device.h | 13 ++++- 2 files changed, 107 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3be100890..19be2d6d1 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -52,6 +52,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_IN uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint16_t epin_buf_cnt; // Count filling status of EP in buffer uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif @@ -104,11 +105,11 @@ typedef struct // Endpoint Transfer buffers #if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) // TODO: required? //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! + // uint16_t fb_val; // Feedback value for asynchronous mode! //#endif #endif @@ -137,7 +138,7 @@ static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, #endif #if CFG_TUD_AUDIO_EPSIZE_IN -static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); @@ -322,38 +323,93 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a // WRITE API //--------------------------------------------------------------------+ +/** + * \brief Write data to EP in buffer + * + * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). + * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. + * + * \param[in] itf: Index of audio function interface + * \param[in] data: Pointer to data array to be copied from + * \param[in] len: # of array elements to copy + * \return Number of bytes actually written + */ +#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE +uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if audiod_tx_done_cb() is executed in between! + + // FOR SINGLE THREADED OPERATION: + // AS LONG AS THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + + // Determine free space + uint16_t free = CFG_TUD_AUDIO_EPSIZE_IN - audio->epin_buf_cnt; + + // Clip length if needed + if (len > free) len = free; + + // Write data + memcpy((void *) &audio->epin_buf[audio->epin_buf_cnt], data, len); + + audio->epin_buf_cnt += len; + + // Return number of bytes written + return len; +} +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) +uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; if (audio->p_desc == NULL) { return 0; } - return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); + return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 - uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) { audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->itf_num == 0) { + if (audio->p_desc == NULL) { return 0; } return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); } - #endif // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. // If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0. + +// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_EPSIZE_IN -static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { + uint8_t idxDriver, idxItf; + uint8_t const *dummy2; + + // If a callback is used determine current alternate setting of + if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) + { + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + } + + // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or + // if no FIFOs are used the user may use this call back to load its data into the EP in buffer by use of tud_audio_n_write_ep_in_buffer(). + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + +#if CFG_TUD_AUDIO_TX_FIFO_SIZE switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -368,15 +424,12 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_TX_FIFO_SIZE - TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); -#else -#error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! -#endif + TU_VERIFY(audiod_tx_done_type_I_pcm_ff_cb(rhport, audio)); + break; default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! + // YOUR ENCODING IS REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); TU_BREAKPOINT(); break; @@ -389,16 +442,36 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t TU_BREAKPOINT(); break; } +#endif + + // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if tud_audio_n_write_ep_in_buffer() is executed in between! + + // THIS IS NOT SOLVED SO FAR! + + // FOR SINGLE THREADED OPERATION: + // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); + + // Inform how many bytes were copied + *n_bytes_copied = audio->epin_buf_cnt; + + // Declare EP in buffer empty + audio->epin_buf_cnt = 0; + + // TO HERE + + // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); - // Call a weak callback here - a possibility for user to get informed TX was completed - if (tud_audio_tx_done_cb) TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); return true; } #endif //CFG_TUD_AUDIO_EPSIZE_IN #if CFG_TUD_AUDIO_TX_FIFO_SIZE -static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); @@ -420,7 +493,7 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a // Check if there is enough if (nSamplesPerChannelToSend == 0) { - *n_bytes_copied = 0; + audio->epin_buf_cnt = 0; return true; } @@ -455,9 +528,8 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } } - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nBytesToSend)); - *n_bytes_copied = nBytesToSend; + audio->epin_buf_cnt = nBytesToSend; + return true; } @@ -718,7 +790,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); uint16_t n_bytes_copied; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); } #endif @@ -1003,7 +1075,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Load new data uint16_t n_bytes_copied; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); if (n_bytes_copied == 0) { diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index f5830b3a1..c5b8e3e15 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -59,6 +59,10 @@ #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif +#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE +#error TX_FIFOs and TX_DMA_RINGBUFFER can not be used simultaneously! +#endif + #ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE #define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif @@ -171,8 +175,12 @@ uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, u void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif +#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE +uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 @@ -218,7 +226,8 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_EPSIZE_OUT -- cgit v1.3.1 From 84425c50b3bb5c892bfab9d094cc3da6a9c04da5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Sep 2020 19:16:50 +0700 Subject: add more logging to host stack tested host with lpc4357, don't use fpu with lpc m4 since it seems to cause hardfault (stack does not make use of fpu anyway). --- hw/bsp/ea4357/board.mk | 6 ++---- hw/bsp/mcb1800/board.mk | 2 +- hw/bsp/ngx4330/board.mk | 2 -- src/class/msc/msc_host.c | 1 + src/host/usbh.c | 44 ++++++++++++++++++++++++++++++++++---------- src/host/usbh.h | 4 ++++ src/osal/osal.h | 4 ++-- 7 files changed, 44 insertions(+), 19 deletions(-) (limited to 'src/class') diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index 2ee6b695c..c77ee4536 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -3,8 +3,6 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ -nostdlib \ -D__USE_LPCOPEN \ -DCORE_M4 \ @@ -40,8 +38,8 @@ CHIP_FAMILY = transdimension FREERTOS_PORT = ARM_CM4F # For flash-jlink target -JLINK_DEVICE = LPC4357 -JLINK_IF = jtag +JLINK_DEVICE = LPC4357_M4 +JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/mcb1800/board.mk b/hw/bsp/mcb1800/board.mk index 7ff17dae3..e3f07d0d0 100644 --- a/hw/bsp/mcb1800/board.mk +++ b/hw/bsp/mcb1800/board.mk @@ -6,7 +6,7 @@ CFLAGS += \ -nostdlib \ -DCORE_M3 \ -D__USE_LPCOPEN \ - -DCFG_TUSB_MCU=OPT_MCU_LPC18XX \ + -DCFG_TUSB_MCU=OPT_MCU_LPC18XX # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes diff --git a/hw/bsp/ngx4330/board.mk b/hw/bsp/ngx4330/board.mk index 97c24b40e..df9df63a1 100644 --- a/hw/bsp/ngx4330/board.mk +++ b/hw/bsp/ngx4330/board.mk @@ -3,8 +3,6 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX \ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 98c71eb70..3aa697b17 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -310,6 +310,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); //------------- Get Max Lun -------------// + TU_LOG2("MSC Get Max Lun\r\n"); tusb_control_request_t request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, .bRequest = MSC_REQ_GET_MAX_LUN, diff --git a/src/host/usbh.c b/src/host/usbh.c index 8536cec0a..c5f28cf0e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -42,10 +42,17 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + static host_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_CDC { + DRIVER_NAME("CDC") .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, @@ -56,6 +63,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_MSC { + DRIVER_NAME("MSC") .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, @@ -66,6 +74,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if HOST_CLASS_HID { + DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open_subtask, @@ -76,6 +85,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_HUB { + DRIVER_NAME("HUB") .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, @@ -86,6 +96,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_VENDOR { + DRIVER_NAME("VENDOR") .class_code = TUSB_CLASS_VENDOR_SPECIFIC, .init = cush_init, .open = cush_open_subtask, @@ -131,7 +142,7 @@ static inline void osal_task_delay(uint32_t msec) { (void) msec; - uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); + const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} } @@ -162,7 +173,11 @@ bool usbh_init(void) } // Class drivers init - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) usbh_class_drivers[drv_id].init(); + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].init(); + } TU_ASSERT(hcd_init()); hcd_int_enable(TUH_OPT_RHPORT); @@ -269,6 +284,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev if (usbh_class_drivers[drv_id].isr) { + TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].isr(dev_addr, ep_addr, event, xferred_bytes); } else @@ -336,7 +352,11 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ if (tuh_umount_cb) tuh_umount_cb(dev_addr); // Close class driver - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) usbh_class_drivers[drv_id].close(dev_addr); + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].close(dev_addr); + } memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping @@ -381,7 +401,7 @@ bool enum_task(hcd_event_t* event) { if( hcd_port_connect_status(dev0->rhport) ) { - TU_LOG2("Connect \r\n"); + TU_LOG2("Device connect \r\n"); // connection event osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get @@ -396,7 +416,7 @@ bool enum_task(hcd_event_t* event) } else { - TU_LOG2("Disconnect \r\n"); + TU_LOG2("Device disconnect \r\n"); // disconnection event usbh_device_unplugged(dev0->rhport, 0, 0); @@ -451,7 +471,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - TU_LOG2("Get 8 byte of Device Descriptor \r\n"); + TU_LOG2("Get 8 byte of Device Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -536,7 +556,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// - TU_LOG2("Get 9 bytes of Configuration Descriptor \r\n"); + TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -550,7 +570,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); //------------- Get full configuration descriptor -------------// - TU_LOG2("Get full Configuration Descriptor \r\n"); + TU_LOG2("Get full Configuration Descriptor\r\n"); request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); @@ -558,7 +578,7 @@ bool enum_task(hcd_event_t* event) new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; //------------- Set Configure -------------// - TU_LOG2("Set Configuration Descriptor \r\n"); + TU_LOG2("Set Configuration Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_CONFIGURATION, @@ -568,6 +588,7 @@ bool enum_task(hcd_event_t* event) }; TU_ASSERT(usbh_control_xfer( new_addr, &request, NULL )); + TU_LOG2("Device configured\r\n"); new_dev->state = TUSB_DEVICE_STATE_CONFIGURED; //------------- TODO Get String Descriptors -------------// @@ -575,6 +596,8 @@ bool enum_task(hcd_event_t* event) //------------- parse configuration & install drivers -------------// uint8_t const* p_desc = _usbh_ctrl_buf + sizeof(tusb_desc_configuration_t); + TU_LOG2_MEM(_usbh_ctrl_buf, ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength, 0); + // parse each interfaces while( p_desc < _usbh_ctrl_buf + ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ) { @@ -584,7 +607,7 @@ bool enum_task(hcd_event_t* event) p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length }else { - tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; // Check if class is supported uint8_t drv_id; @@ -614,6 +637,7 @@ bool enum_task(hcd_event_t* event) { uint16_t itf_len = 0; + TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); TU_ASSERT( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; diff --git a/src/host/usbh.h b/src/host/usbh.h index cc112d756..39e7a4e0d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -52,6 +52,10 @@ typedef enum tusb_interface_status_{ } tusb_interface_status_t; typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + uint8_t class_code; void (* const init) (void); diff --git a/src/osal/osal.h b/src/osal/osal.h index c61f0c912..b5057ff4c 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -37,9 +37,9 @@ #include "common/tusb_common.h" // Return immediately -#define OSAL_TIMEOUT_NOTIMEOUT (0) +#define OSAL_TIMEOUT_NOTIMEOUT (0) // Default timeout -#define OSAL_TIMEOUT_NORMAL (10) +#define OSAL_TIMEOUT_NORMAL (10) // Wait forever #define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) -- cgit v1.3.1 From ef651e073409bac1a9793d97bf5a25220913f32e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 17:07:29 +0700 Subject: fix #449 remove obsolete pipehandle from hid host --- examples/host/cdc_msc_hid/Makefile | 5 +-- src/class/hid/hid_host.c | 66 +++++++++++++++++++++----------------- src/class/hid/hid_host.h | 10 ++---- src/class/msc/msc_host.c | 6 ++-- src/class/msc/msc_host.h | 2 +- 5 files changed, 45 insertions(+), 44 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 29a323957..35de0a9a0 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -13,12 +13,13 @@ CFLAGS += -Wno-error=cast-align # TinyUSB Host Stack source SRC_C += \ + src/class/cdc/cdc_host.c \ + src/class/hid/hid_host.c \ + src/class/msc/msc_host.c \ src/host/usbh.c \ src/host/hub.c \ src/host/ehci/ehci.c \ src/host/ohci/ohci.c \ - src/class/cdc/cdc_host.c \ - src/class/msc/msc_host.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8abb3cd22..ec5333917 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,35 +35,43 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct { + uint8_t itf_numr; + uint8_t ep_in; + uint8_t ep_out; + + uint16_t report_size; +}hidh_interface_t; + //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) +static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_t *p_hid) { - p_hid->pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); - p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->interface_number = interface_number; + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, p_endpoint_desc) ); - TU_ASSERT (pipehandle_is_valid(p_hid->pipe_hdl)); + p_hid->ep_in = p_endpoint_desc->bEndpointAddress; + p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor + p_hid->itf_numr = interface_number; return true; } -static inline void hidh_interface_close(hidh_interface_info_t *p_hid) +static inline void hidh_interface_close(hidh_interface_t *p_hid) { - tu_memclr(p_hid, sizeof(hidh_interface_info_t)); + tu_memclr(p_hid, sizeof(hidh_interface_t)); } // called from public API need to validate parameters -tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid) +tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) { //------------- parameters validation -------------// // TODO change to use is configured function TU_ASSERT (TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY (report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT (!hcd_edpt_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_ASSERT (!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - TU_ASSERT_ERR( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ; + TU_ASSERT_ERR( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; return TUSB_ERROR_NONE; } @@ -85,12 +93,12 @@ uint8_t const hid_keycode_to_ascii_tbl[2][128] = }; #endif -static hidh_interface_info_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 +static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && pipehandle_is_valid(keyboardh_data[dev_addr-1].pipe_hdl); + return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); } tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) @@ -100,8 +108,7 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_is_mounted(dev_addr) && - hcd_edpt_busy( keyboardh_data[dev_addr-1].pipe_hdl ); + return tuh_hid_keyboard_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); } #endif @@ -111,18 +118,17 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) //--------------------------------------------------------------------+ #if CFG_TUH_HID_MOUSE -static hidh_interface_info_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 +static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// bool tuh_hid_mouse_is_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && pipehandle_is_valid(mouseh_data[dev_addr-1].pipe_hdl); + return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_is_mounted(dev_addr) && - hcd_edpt_busy( mouseh_data[dev_addr-1].pipe_hdl ); + return tuh_hid_mouse_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) @@ -149,11 +155,11 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) void hidh_init(void) { #if CFG_TUH_HID_KEYBOARD - tu_memclr(&keyboardh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&keyboardh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUH_HID_MOUSE - tu_memclr(&mouseh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUSB_HOST_HID_GENERIC @@ -165,7 +171,7 @@ void hidh_init(void) CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; #endif -bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) { uint8_t const *p_desc = (uint8_t const *) p_interface_desc; @@ -208,7 +214,7 @@ bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interfac #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); tuh_hid_keyboard_mounted_cb(dev_addr); } else #endif @@ -216,7 +222,7 @@ bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interfac #if CFG_TUH_HID_MOUSE if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); tuh_hid_mouse_mounted_cb(dev_addr); } else #endif @@ -236,22 +242,22 @@ bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interfac return true; } -void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) +void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later #if CFG_TUH_HID_KEYBOARD - if ( pipehandle_is_equal(pipe_hdl, keyboardh_data[pipe_hdl.dev_addr-1].pipe_hdl) ) + if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) { - tuh_hid_keyboard_isr(pipe_hdl.dev_addr, event); + tuh_hid_keyboard_isr(dev_addr, event); return; } #endif #if CFG_TUH_HID_MOUSE - if ( pipehandle_is_equal(pipe_hdl, mouseh_data[pipe_hdl.dev_addr-1].pipe_hdl) ) + if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) { - tuh_hid_mouse_isr(pipe_hdl.dev_addr, event); + tuh_hid_mouse_isr(dev_addr, event); return; } #endif @@ -264,7 +270,7 @@ void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_byte void hidh_close(uint8_t dev_addr) { #if CFG_TUH_HID_KEYBOARD - if ( pipehandle_is_valid( keyboardh_data[dev_addr-1].pipe_hdl ) ) + if ( keyboardh_data[dev_addr-1].ep_in != 0 ) { hidh_interface_close(&keyboardh_data[dev_addr-1]); tuh_hid_keyboard_unmounted_cb(dev_addr); @@ -272,7 +278,7 @@ void hidh_close(uint8_t dev_addr) #endif #if CFG_TUH_HID_MOUSE - if( pipehandle_is_valid( mouseh_data[dev_addr-1].pipe_hdl ) ) + if( mouseh_data[dev_addr-1].ep_in != 0 ) { hidh_interface_close(&mouseh_data[dev_addr-1]); tuh_hid_mouse_unmounted_cb( dev_addr ); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index a3b614cd7..2e7f52674 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -195,15 +195,9 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -typedef struct { - pipe_handle_t pipe_hdl; - uint16_t report_size; - uint8_t interface_number; -}hidh_interface_info_t; - void hidh_init(void); -bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); +bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 3aa697b17..539e98376 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -306,7 +306,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } - p_msc->itf_numr = itf_desc->bInterfaceNumber; + p_msc->itf_num = itf_desc->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); //------------- Get Max Lun -------------// @@ -315,7 +315,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, .bRequest = MSC_REQ_GET_MAX_LUN, .wValue = 0, - .wIndex = p_msc->itf_numr, + .wIndex = p_msc->itf_num, .wLength = 1 }; // TODO STALL means zero @@ -328,7 +328,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, .bRequest = MSC_REQ_RESET, .wValue = 0, - .wIndex = p_msc->itf_numr, + .wIndex = p_msc->itf_num, .wLength = 0 }; TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 76cf86853..959294adf 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -175,7 +175,7 @@ void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_numr; + uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; -- cgit v1.3.1 From d9eaa54e14775ebcf6a78cb84c354e69e57903d3 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 3 Sep 2020 16:40:53 +0200 Subject: Remove connected check for write flushing --- src/class/cdc/cdc_device.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b4ebfc92e..91799b2de 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -165,11 +165,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - if ( count ) - { - TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); - } + if ( count ) TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); return count; } -- cgit v1.3.1 From fd6cf9010b522019a4434ebd02fb447b567e7131 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 3 Sep 2020 17:03:13 +0200 Subject: Turn transmit fifo overwritable in no DTR mode --- src/class/cdc/cdc_device.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 91799b2de..6c0f5fc7a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -197,7 +197,7 @@ void cdcd_init(void) // config fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false); + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); @@ -355,6 +355,9 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; + // Disable fifo overwriting if DTR bit is set + p_cdc->tx_ff.overwritable = dtr ? false : true; + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); tud_control_status(rhport, request); -- cgit v1.3.1 From 4071e490e259de5bf2891c9893ab7965b5be3d2e Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 3 Sep 2020 17:21:32 +0200 Subject: New function to modify fifo overwritability --- src/class/cdc/cdc_device.c | 2 +- src/common/tusb_fifo.c | 19 +++++++++++++++++++ src/common/tusb_fifo.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6c0f5fc7a..6f71cb781 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -356,7 +356,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set - p_cdc->tx_ff.overwritable = dtr ? false : true; + tu_fifo_change_mode(&p_cdc->tx_ff, (dtr?false:true)); TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 6ab158cca..fdd8c3e35 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -319,3 +319,22 @@ bool tu_fifo_clear(tu_fifo_t *f) return true; } + +/******************************************************************************/ +/*! + @brief Change the fifo mode to overwritable or not overwritable + + @param[in] f + Pointer to the FIFO buffer to manipulate +*/ +/******************************************************************************/ +bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable) +{ + tu_fifo_lock(f); + + f->overwritable = overwritable; + + tu_fifo_unlock(f); + + return true; +} diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index fb0c896f3..7957d83af 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -76,6 +76,7 @@ typedef struct .overwritable = _overwritable, \ } +bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); -- cgit v1.3.1 From 338e96fa826b2e2bbb6fb489456202e9e4ec4fe2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 3 Sep 2020 18:09:46 +0200 Subject: Remove tud_audio_n_write_ep_in_buffer() as long as ISO EPs are not RBs. --- src/class/audio/audio_device.c | 4 ++++ src/class/audio/audio_device.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 19be2d6d1..942933b5d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -334,6 +334,8 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ + +/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers #if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { @@ -363,6 +365,8 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t } #endif +*/ + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c5b8e3e15..11f444daa 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -175,9 +175,11 @@ uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, u void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif +/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers #if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) #endif +*/ #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); -- cgit v1.3.1 From 35aee4a6af40c7c8befb5dfe81bbf7e26dc01ca8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 23:57:51 +0700 Subject: more hid host work --- examples/host/cdc_msc_hid/src/main.c | 63 +++++++++++++++++++++++++++++++++--- src/class/hid/hid_host.c | 22 ++++--------- src/host/usbh.c | 2 +- 3 files changed, 65 insertions(+), 22 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 9ec213090..8f61310d5 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -110,21 +110,74 @@ void cdc_task(void) // USB HID //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD -void hid_task(void) + +uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +// look up new key in previous keys +static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) +{ + for(uint8_t i=0; i<6; i++) + { + if (p_report->keycode[i] == keycode) return true; + } + + return false; +} + +static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) { + static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released + + //------------- example code ignore control (non-printable) key affects -------------// + for(uint8_t i=0; i<6; i++) + { + if ( p_new_report->keycode[i] ) + { + if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) ) + { + // exist in previous report means the current key is holding + }else + { + // not existed in previous report means the current key is pressed + bool const is_shift = p_new_report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + uint8_t ch = keycode2ascii[p_new_report->keycode[i]][is_shift ? 1 : 0]; + putchar(ch); + if ( ch == '\r' ) putchar('\n'); // added new line for enter key + } + } + // TODO example skips key released + } + + prev_report = *p_new_report; +} + +CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; +void hid_task(void) +{ + uint8_t const addr = 1; + if ( tuh_hid_keyboard_is_mounted(addr) ) + { + if ( !tuh_hid_keyboard_is_busy(addr) ) + { + process_kbd_report(&usb_keyboard_report); + tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); + } + } } void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) { // application set-up - printf("\na Keyboard device (address %d) is mounted\n", dev_addr); + printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + + tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) { // application tear-down - printf("\na Keyboard device (address %d) is unmounted\n", dev_addr); + printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); } // invoked ISR context @@ -139,13 +192,13 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) void tuh_hid_mouse_mounted_cb(uint8_t dev_addr) { // application set-up - printf("\na Mouse device (address %d) is mounted\n", dev_addr); + printf("A Mouse device (address %d) is mounted\r\n", dev_addr); } void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) { // application tear-down - printf("\na Mouse device (address %d) is unmounted\n", dev_addr); + printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } // invoked ISR context diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ec5333917..d2d1c0397 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -67,11 +67,11 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int { //------------- parameters validation -------------// // TODO change to use is configured function - TU_ASSERT (TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - TU_VERIFY (report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT (!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); + TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - TU_ASSERT_ERR( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; + TU_ASSERT( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; return TUSB_ERROR_NONE; } @@ -81,18 +81,6 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD -#if 0 -#define EXPAND_KEYCODE_TO_ASCII(keycode, ascii, shift_modified) \ - [0][keycode] = ascii,\ - [1][keycode] = shift_modified,\ - -// TODO size of table should be a macro for application to check boundary -uint8_t const hid_keycode_to_ascii_tbl[2][128] = -{ - HID_KEYCODE_TABLE(EXPAND_KEYCODE_TO_ASCII) -}; -#endif - static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// @@ -215,6 +203,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); tuh_hid_keyboard_mounted_cb(dev_addr); } else #endif @@ -223,6 +212,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); tuh_hid_mouse_mounted_cb(dev_addr); } else #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 352450588..58550c93b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -284,7 +284,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev if (usbh_class_drivers[drv_id].isr) { - TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); + //TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].isr(dev_addr, ep_addr, event, xferred_bytes); } else -- cgit v1.3.1 From a8e538efe7d11291e32e016fad5910ebaf9eac43 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 01:35:32 +0700 Subject: clean up --- src/class/hid/hid_host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index d2d1c0397..378278cc3 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -36,7 +36,7 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_numr; + uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; @@ -52,7 +52,7 @@ static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t p_hid->ep_in = p_endpoint_desc->bEndpointAddress; p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->itf_numr = interface_number; + p_hid->itf_num = interface_number; return true; } -- cgit v1.3.1 From 9cc22b635c5c4b9426b1530c3623b899dc652302 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 4 Sep 2020 15:40:23 +0200 Subject: Add functionality to abort an ongoing transfer --- src/class/cdc/cdc_device.c | 10 ++++++++++ src/device/dcd.h | 3 +++ src/device/usbd.c | 27 +++++++++++++++++++++++++++ src/device/usbd_pvt.h | 3 +++ 4 files changed, 43 insertions(+) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6f71cb781..56cc94abc 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -353,6 +353,16 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool const dtr = tu_bit_test(request->wValue, 0); bool const rts = tu_bit_test(request->wValue, 1); +#if CFG_TUD_CDC_CLEAR_AT_CONNECTION + // DTE connected event (if DTE supports DTR bit) + if ( dtr && !tu_bit_test(p_cdc->line_state, 0) ) + { + // Clear not transmitted data + usbd_edpt_xfer_abort(rhport, p_cdc->ep_in); + tu_fifo_clear(&p_cdc->tx_ff); + } +#endif + p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..ee41fefd0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -133,6 +133,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Abort a ongoing transfer +TU_ATTR_WEAK bool dcd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b91048b6..04ae31ce7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1100,6 +1100,33 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } +bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Abort XFER EP %02X ... ", ep_addr); + + // Abort API is optional for DCD + if ( dcd_edpt_xfer_abort ) + { + if ( dcd_edpt_xfer_abort(rhport, ep_addr) ) + { + _usbd_dev.ep_status[epnum][dir].busy = false; + TU_LOG2("OK\r\n"); + return true; + }else + { + TU_LOG2("failed\r\n"); + return false; + } + }else + { + TU_LOG2("no DCD support\r\n"); + return false; + } +} + bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a5d223329..d87c07c01 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,6 +70,9 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Abort a scheduled transfer +bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From f7cf8cdf27a016093df65c0de7167685e407d014 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 14:28:58 +0700 Subject: defer xfer_isr to xfer_cb --- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/cdc_host.h | 2 +- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- src/host/hcd.h | 8 ++--- src/host/hub.c | 2 +- src/host/hub.h | 2 +- src/host/usbh.c | 88 +++++++++++++++++++++++++++++++----------------- src/host/usbh.h | 2 +- 11 files changed, 70 insertions(+), 44 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e62f47b72..23e342134 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -209,7 +209,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) ep_addr; tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 306420ce4..0e2820fef 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -113,7 +113,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ void cdch_init(void); bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 378278cc3..e17bfc9e5 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -232,7 +232,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c return true; } -void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 2e7f52674..54542de55 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -197,7 +197,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ void hidh_init(void); bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 539e98376..b129d538f 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -383,7 +383,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void msch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; if ( ep_addr == p_msc->ep_in ) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 959294adf..3eb45e6fc 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -193,7 +193,7 @@ typedef struct void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void msch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/hcd.h b/src/host/hcd.h index 24cc62501..da530421d 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -51,17 +51,17 @@ typedef struct { uint8_t rhport; uint8_t event_id; + uint8_t dev_addr; union { - struct - { + struct { uint8_t hub_addr; uint8_t hub_port; } attach, remove; - struct - { + // XFER_COMPLETE + struct { uint8_t ep_addr; uint8_t result; uint32_t len; diff --git a/src/host/hub.c b/src/host/hub.c index eb85dfa42..4fb28b72f 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -199,7 +199,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf // is the response of interrupt endpoint polling #include "usbh_hcd.h" // FIXME remove -void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; diff --git a/src/host/hub.h b/src/host/hub.h index 621356315..8f307190b 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -182,7 +182,7 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ void hub_init(void); bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/usbh.c b/src/host/usbh.c index b6df6bad8..73a4fc9f3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -56,7 +56,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, - .isr = cdch_isr, + .xfer_cb = cdch_xfer_cb, .close = cdch_close }, #endif @@ -67,7 +67,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, - .isr = msch_isr, + .xfer_cb = msch_xfer_cb, .close = msch_close }, #endif @@ -78,7 +78,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open_subtask, - .isr = hidh_isr, + .xfer_cb = hidh_xfer_cb, .close = hidh_close }, #endif @@ -89,7 +89,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, - .isr = hub_isr, + .xfer_cb = hub_xfer_cb, .close = hub_close }, #endif @@ -100,7 +100,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_VENDOR_SPECIFIC, .init = cush_init, .open = cush_open_subtask, - .isr = cush_isr, + .xfer_cb = cush_isr, .close = cush_close } #endif @@ -263,33 +263,46 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } //--------------------------------------------------------------------+ -// USBH-HCD ISR/Callback API +// HCD Event Handler //--------------------------------------------------------------------+ + +void hcd_event_handler(hcd_event_t const* event, bool in_isr) +{ + switch (event->event_id) + { + default: + osal_queue_send(_usbh_q, event, in_isr); + break; + } +} + // interrupt caused by a TD (with IOC=1) in pipe of class class_code -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, uint32_t xferred_bytes) { usbh_device_t* dev = &_usbh_devices[ dev_addr ]; if (0 == tu_edpt_number(ep_addr)) { - dev->control.pipe_status = event; + dev->control.pipe_status = result; // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary osal_semaphore_post( dev->control.sem_hdl, true ); } else { - uint8_t drv_id = dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - if (usbh_class_drivers[drv_id].isr) + hcd_event_t event = { - //TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].isr(dev_addr, ep_addr, event, xferred_bytes); - } - else - { - TU_BREAKPOINT(); // something wrong, no one claims the isr's source - } + .rhport = 0, + .event_id = HCD_EVENT_XFER_COMPLETE, + .dev_addr = dev_addr, + .xfer_complete = + { + .ep_addr = ep_addr, + .result = result, + .len = xferred_bytes + } + }; + + hcd_event_handler(&event, true); } } @@ -307,16 +320,6 @@ void hcd_event_device_attach(uint8_t rhport) hcd_event_handler(&event, true); } -void hcd_event_handler(hcd_event_t const* event, bool in_isr) -{ - switch (event->event_id) - { - default: - osal_queue_send(_usbh_q, event, in_isr); - break; - } -} - void hcd_event_device_remove(uint8_t hostid) { hcd_event_t event = @@ -419,7 +422,7 @@ bool enum_task(hcd_event_t* event) return true; // restart task } } - #if CFG_TUH_HUB +#if CFG_TUH_HUB //------------- connected/disconnected via hub -------------// else { @@ -462,7 +465,7 @@ bool enum_task(hcd_event_t* event) hub_port_clear_feature_subtask(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); } } - #endif +#endif // CFG_TUH_HUB TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); @@ -684,6 +687,29 @@ void tuh_task(void) enum_task(&event); break; + case HCD_EVENT_XFER_COMPLETE: + { + usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + if ( 0 == epnum ) + { + // TODO control transfer + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + } + break; + default: break; } } diff --git a/src/host/usbh.h b/src/host/usbh.h index 1930dc20b..56a5ce72f 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -60,7 +60,7 @@ typedef struct { void (* const init) (void); bool (* const open)(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - void (* const isr) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t len); + void (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t len); void (* const close) (uint8_t); } host_class_driver_t; //--------------------------------------------------------------------+ -- cgit v1.3.1 From 9531e47d10915b652c2c5cff9ef2956889639f93 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 14:59:07 +0700 Subject: update example to test with mouse --- examples/host/cdc_msc_hid/src/main.c | 97 ++++++++++++++++++++++++++++++------ src/class/hid/hid_host.c | 5 +- 2 files changed, 85 insertions(+), 17 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 4200cc5e0..bbaac8644 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -111,6 +111,7 @@ void cdc_task(void) //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD +CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // look up new key in previous keys @@ -153,21 +154,6 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; - -void hid_task(void) -{ - uint8_t const addr = 1; - if ( tuh_hid_keyboard_is_mounted(addr) ) - { - if ( !tuh_hid_keyboard_is_busy(addr) ) - { - process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); - } - } -} - void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) { // application set-up @@ -192,6 +178,58 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) #endif #if CFG_TUH_HID_MOUSE + +CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; + +void cursor_movement(int8_t x, int8_t y, int8_t wheel) +{ + //------------- X -------------// + if ( x < 0) + { + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left + }else if ( x > 0) + { + printf(ANSI_CURSOR_FORWARD(%d), x); // move right + }else { } + + //------------- Y -------------// + if ( y < 0) + { + printf(ANSI_CURSOR_UP(%d), (-y)); // move up + }else if ( y > 0) + { + printf(ANSI_CURSOR_DOWN(%d), y); // move down + }else { } + + //------------- wheel -------------// + if (wheel < 0) + { + printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up + }else if (wheel > 0) + { + printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down + }else { } +} + +static inline void process_mouse_report(hid_mouse_report_t const * p_report) +{ + static hid_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; + if ( button_changed_mask & p_report->buttons) + { + printf(" %c%c%c ", + p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(p_report->x, p_report->y, p_report->wheel); +} + + void tuh_hid_mouse_mounted_cb(uint8_t dev_addr) { // application set-up @@ -212,6 +250,35 @@ void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) } #endif + + +void hid_task(void) +{ + uint8_t const addr = 1; + +#if CFG_TUH_HID_KEYBOARD + if ( tuh_hid_keyboard_is_mounted(addr) ) + { + if ( !tuh_hid_keyboard_is_busy(addr) ) + { + process_kbd_report(&usb_keyboard_report); + tuh_hid_keyboard_get_report(addr, &usb_mouse_report); + } + } +#endif + +#if CFG_TUH_HID_MOUSE + if ( tuh_hid_mouse_is_mounted(addr) ) + { + if ( !tuh_hid_mouse_is_busy(addr) ) + { + process_mouse_report(&usb_mouse_report); + tuh_hid_mouse_get_report(addr, &usb_mouse_report); + } + } +#endif +} + //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e17bfc9e5..d9ed1f651 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -173,7 +173,8 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); - //------------- SET IDLE (0) request -------------// + // SET IDLE = 0 request + // Device can stall if not support this request tusb_control_request_t request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, .bRequest = HID_REQ_CONTROL_SET_IDLE, @@ -181,7 +182,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c .wIndex = p_interface_desc->bInterfaceNumber, .wLength = 0 }; - TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); + usbh_control_xfer( dev_addr, &request, NULL ); // TODO stall is valid #if 0 //------------- Get Report Descriptor TODO HID parser -------------// -- cgit v1.3.1 From 15ad585e674f14e247aa7e5f42fb84f90f14be8b Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 6 Sep 2020 11:49:00 +0700 Subject: replacing hcd_pipe_xfer by usbh_edpt_xfer --- hw/bsp/ea4088qs/ea4088qs.c | 15 +++++++++++---- src/class/hid/hid_host.c | 2 +- src/host/ehci/ehci.c | 15 ++++++++++++++- src/host/hub.c | 4 ++-- src/host/ohci/ohci.c | 24 ++++++++++++++++++++++-- src/host/usbh.c | 6 ++++++ src/host/usbh.h | 2 ++ 7 files changed, 58 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index f164526d7..b25f9101c 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -98,6 +98,11 @@ void SystemInit(void) Chip_IOCON_Init(LPC_IOCON); Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); + + /* CPU clock source starts with IRC */ + /* Enable PBOOST for CPU clock over 100MHz */ + Chip_SYSCTL_EnableBoost(); + Chip_SetupXtalClocking(); } @@ -130,13 +135,15 @@ void board_init(void) Chip_USB_Init(); enum { - USBCLK = 0x1B // Host + Device + OTG + AHB + USBCLK_DEVCIE = 0x12, // AHB + Device + USBCLK_HOST = 0x19 , // AHB + OTG + Host + USBCLK_ALL = 0x1B // Host + Device + OTG + AHB }; - LPC_USB->OTGClkCtrl = USBCLK; - while ( (LPC_USB->OTGClkSt & USBCLK) != USBCLK ) {} + LPC_USB->OTGClkCtrl = USBCLK_ALL; + while ( (LPC_USB->OTGClkSt & USBCLK_ALL) != USBCLK_ALL ) {} - // USB1 = host, USB2 = device + // set portfunc: USB1 = host, USB2 = device LPC_USB->StCtrl = 0x3; } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index d9ed1f651..5ea8cc7e9 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -71,7 +71,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; + TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; return TUSB_ERROR_NONE; } diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 3c02086c9..23c8ea9ee 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -328,7 +328,20 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * qhd->qtd_overlay.next.address = (uint32_t) qtd; }else { - // TODO implement later + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + ehci_qtd_t *p_qtd = qtd_find_free(); + TU_ASSERT(p_qtd); + + qtd_init(p_qtd, buffer, buflen); + p_qtd->pid = p_qhd->pid; + + // Insert TD to QH + qtd_insert_to_qhd(p_qhd, p_qtd); + + p_qhd->p_qtd_list_tail->int_on_complete = 1; + + // attach head QTD to QHD start transferring + p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; } return true; diff --git a/src/host/hub.c b/src/host/hub.c index db1ca0786..abec20d06 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -167,8 +167,8 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); } - //------------- Queue the initial Status endpoint transfer -------------// - TU_ASSERT( hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1, true) ); + // Queue notification status endpoint + TU_ASSERT( usbh_edpt_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1) ); return true; } diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 87da374d5..d9bbfc8c6 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -306,6 +306,11 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } +// TODO move around +static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); +static ohci_gtd_t * gtd_find_free(void); +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd); + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -329,6 +334,21 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * p_ed->td_head.address = (uint32_t) p_data; OHCI_REG->command_status_bit.control_list_filled = 1; + }else + { + ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr); + ohci_gtd_t* p_gtd = gtd_find_free(); + + TU_ASSERT(p_gtd); + + gtd_init(p_gtd, buffer, buflen); + p_gtd->index = p_ed-ohci_data.ed_pool; + p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + td_insert_to_ed(p_ed, p_gtd); + + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; } return true; @@ -337,7 +357,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * //--------------------------------------------------------------------+ // BULK/INT/ISO PIPE API //--------------------------------------------------------------------+ -static inline ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) +static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; @@ -355,7 +375,7 @@ static inline ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) return NULL; } -static inline ohci_ed_t * ed_find_free(void) +static ohci_ed_t * ed_find_free(void) { ohci_ed_t* ed_pool = ohci_data.ed_pool; diff --git a/src/host/usbh.c b/src/host/usbh.c index f669cac05..da35340ce 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -208,6 +208,12 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 return true; } +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); +} + bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) { osal_semaphore_reset( _usbh_devices[dev_addr].control.sem_hdl ); diff --git a/src/host/usbh.h b/src/host/usbh.h index 1774666f1..10e0c21be 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -105,6 +105,8 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From b3e81673c0582a07a764981604a560ee3d310ef9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 6 Sep 2020 12:11:07 +0700 Subject: change xfer_cb return type from void to bool --- src/class/cdc/cdc_host.c | 3 ++- src/class/cdc/cdc_host.h | 2 +- src/class/hid/hid_host.c | 8 +++++--- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 6 +++++- src/class/msc/msc_host.h | 2 +- src/host/hub.c | 4 +++- src/host/hub.h | 2 +- src/host/usbh.c | 4 ++-- src/host/usbh.h | 7 +++++-- 10 files changed, 26 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 23e342134..ae1eef8a7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -209,10 +209,11 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) ep_addr; tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); + return true; } void cdch_close(uint8_t dev_addr) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 0e2820fef..f28a0a713 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -113,7 +113,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ void cdch_init(void); bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 5ea8cc7e9..6002ead3c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -233,7 +233,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c return true; } -void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later @@ -241,7 +241,7 @@ void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) { tuh_hid_keyboard_isr(dev_addr, event); - return; + return true; } #endif @@ -249,13 +249,15 @@ void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) { tuh_hid_mouse_isr(dev_addr, event); - return; + return true; } #endif #if CFG_TUSB_HOST_HID_GENERIC #endif + + return true; } void hidh_close(uint8_t dev_addr) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 54542de55..324dad203 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -197,7 +197,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ void hidh_init(void); bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index b129d538f..f47bbd163 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -336,6 +336,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it enum { SCSI_XFER_TIMEOUT = 2000 }; //------------- SCSI Inquiry -------------// + TU_LOG2("SCSI Inquiry\r\n"); tusbh_msc_inquiry(dev_addr, 0, msch_buffer); TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); @@ -343,6 +344,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); //------------- SCSI Read Capacity 10 -------------// + TU_LOG2("SCSI Read Capacity 10\r\n"); tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); @@ -383,7 +385,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; if ( ep_addr == p_msc->ep_in ) @@ -396,6 +398,8 @@ void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 osal_semaphore_post(msch_sem_hdl, true); } } + + return true; } void msch_close(uint8_t dev_addr) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 3eb45e6fc..a32134215 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -193,7 +193,7 @@ typedef struct void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/hub.c b/src/host/hub.c index abec20d06..ed96713e2 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -175,7 +175,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf // is the response of interrupt endpoint polling #include "usbh_hcd.h" // FIXME remove -void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; @@ -227,6 +227,8 @@ void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 // TODO [HUB] check if hub is still plugged before polling status endpoint since failed usually mean hub unplugged // TU_ASSERT ( hub_status_pipe_queue(dev_addr) ); } + + return true; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index 71dd39b8d..f00f13de7 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -182,7 +182,7 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ void hub_init(void); bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/usbh.c b/src/host/usbh.c index da35340ce..a7f6397cd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -48,7 +48,7 @@ #define DRIVER_NAME(_name) #endif -static host_class_driver_t const usbh_class_drivers[] = +static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_CDC { @@ -442,7 +442,7 @@ bool enum_task(hcd_event_t* event) dev0->state = TUSB_DEVICE_STATE_UNPLUG; //------------- connected/disconnected directly with roothub -------------// - if ( dev0->hub_addr == 0) + if (dev0->hub_addr == 0) { // wait until device is stable. Increase this if the first 8 bytes is failed to get osal_task_delay(POWER_STABLE_DELAY); diff --git a/src/host/usbh.h b/src/host/usbh.h index 10e0c21be..91afb90a3 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -60,9 +60,9 @@ typedef struct { void (* const init) (void); bool (* const open)(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - void (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t len); + bool (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); void (* const close) (uint8_t); -} host_class_driver_t; +} usbh_class_driver_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -107,6 +107,9 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, uint8_t* buffer, uint16_t buflen); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 4e789b240deb0b124b65fd3a177674f562f0b3c1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 6 Sep 2020 11:37:59 +0200 Subject: Start of sampling works. --- src/class/audio/audio_device.c | 15 ++++-- src/portable/st/synopsys/dcd_synopsys.c | 93 +++++++++++++++++---------------- 2 files changed, 59 insertions(+), 49 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 942933b5d..ebb8434cd 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -780,8 +780,12 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! + usbd_edpt_clear_stall(rhport, ep_addr); + #if CFG_TUD_AUDIO_EPSIZE_IN > 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { @@ -1081,11 +1085,12 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 uint16_t n_bytes_copied; TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); - if (n_bytes_copied == 0) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + // Transmission of ZLP is done by audiod_tx_done_cb() +// if (n_bytes_copied == 0) +// { +// // Load with ZLP +// return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); +// } return true; } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index d1f24916c..c1b087dac 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -682,42 +682,42 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -/** - * Close an EP. - * - * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! - * - */ -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - uint32_t const epnum = tu_edpt_number(ep_addr); - uint32_t const dir = tu_edpt_dir(ep_addr); - - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - - if(dir == TUSB_DIR_IN) - { - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - - // Disable interrupt for this EP - dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); - - // Clear USB active EP - in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; - } - else - { - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - - // Disable interrupt for this EP - dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; - - // Clear USB active EP bit - out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; - - } -} +///** +// * Close an EP. +// * +// * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! +// * +// */ +//void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +//{ +// (void)rhport; +// uint32_t const epnum = tu_edpt_number(ep_addr); +// uint32_t const dir = tu_edpt_dir(ep_addr); +// +// USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); +// +// if(dir == TUSB_DIR_IN) +// { +// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); +// +// // Disable interrupt for this EP +// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); +// +// // Clear USB active EP +// in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; +// } +// else +// { +// USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); +// +// // Disable interrupt for this EP +// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; +// +// // Clear USB active EP bit +// out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; +// +// } +//} bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { @@ -815,14 +815,14 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_disable(rhport, ep_addr, false); - if (dir == TUSB_DIR_IN) - { - uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; - uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; - // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. - TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); - _allocated_fifo_words -= fifo_size; - } +// if (dir == TUSB_DIR_IN) +// { +// uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; +// uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; +// // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. +// TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); +// _allocated_fifo_words -= fifo_size; +// } } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -1156,6 +1156,11 @@ void dcd_int_handler(uint8_t rhport) // IEPINT bit read-only handle_epin_ints(rhport, dev, in_ep); } + + // Check for Incomplete isochronous IN transfer + if(int_status & USB_OTG_GINTSTS_IISOIXFR) { + TU_LOG2(" IISOIXFR!\r\n"); + } } // Helper function which parses through the current configuration descriptors to find the biggest EPs in size. -- cgit v1.3.1 From 66a10ec9c8042a48053b4af67a932f3cfe9470c2 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Sep 2020 15:19:20 +0700 Subject: rework usbh control transfer use series of complete callback instead of blocking semaphore, which is more noOS friendly. still working with hid host --- examples/host/cdc_msc_hid/Makefile | 3 +- .../host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 1 + src/class/hid/hid_host.c | 22 +- src/common/tusb_types.h | 4 +- src/host/usbh.c | 299 ++++++++++++++++++--- src/host/usbh.h | 9 +- src/host/usbh_control.c | 135 ++++++++++ src/host/usbh_hcd.h | 11 +- 8 files changed, 435 insertions(+), 49 deletions(-) create mode 100644 src/host/usbh_control.c (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 35de0a9a0..b49c4c75c 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -16,8 +16,9 @@ SRC_C += \ src/class/cdc/cdc_host.c \ src/class/hid/hid_host.c \ src/class/msc/msc_host.c \ - src/host/usbh.c \ src/host/hub.c \ + src/host/usbh.c \ + src/host/usbh_control.c \ src/host/ehci/ehci.c \ src/host/ohci/ohci.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c \ diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2b5538957..271076b5c 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -23,6 +23,7 @@ debug_target_connection="J-Link" gcc_entry_point="Reset_Handler" linker_memory_map_file="$(ProjectDir)/LPC1857_MemoryMap.xml" + linker_printf_width_precision_supported="Yes" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" macros="DeviceFamily=LPC1800;DeviceSubFamily=LPC185x;Target=LPC1857;Placement=Flash;rootDir=../../../../..;lpcDir=../../../../../hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx" package_dependencies="LPC1800" diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6002ead3c..5058191f4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -175,14 +175,22 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c // SET IDLE = 0 request // Device can stall if not support this request - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, - .wLength = 0 + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = 0, // idle_rate = 0 + .wIndex = p_interface_desc->bInterfaceNumber, + .wLength = 0 }; - usbh_control_xfer( dev_addr, &request, NULL ); // TODO stall is valid + + // stall is a valid response for SET_IDLE, therefore we could ignore result of this request + tuh_control_xfer(dev_addr, &request, NULL, NULL); #if 0 //------------- Get Report Descriptor TODO HID parser -------------// diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 70d0db942..d6b6ea627 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -276,6 +276,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); + // USB Binary Device Object Store (BOS) Descriptor typedef struct TU_ATTR_PACKED { @@ -431,7 +433,7 @@ typedef struct TU_ATTR_PACKED{ uint16_t wLength; } tusb_control_request_t; -TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); // TODO move to somewhere suitable static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) diff --git a/src/host/usbh.c b/src/host/usbh.c index a7f6397cd..592eac267 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -108,6 +108,11 @@ static usbh_class_driver_t const usbh_class_drivers[] = enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; +enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer + +enum { CONFIG_NUM = 1 }; // default to use configuration 1 + + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -125,6 +130,9 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_H //------------- Helper Function Prototypes -------------// static inline uint8_t get_new_address(void); +// from usbh_control.c +extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -281,23 +289,21 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR } - else + + hcd_event_t event = { - hcd_event_t event = + .rhport = 0, // TODO correct rhport + .event_id = HCD_EVENT_XFER_COMPLETE, + .dev_addr = dev_addr, + .xfer_complete = { - .rhport = 0, - .event_id = HCD_EVENT_XFER_COMPLETE, - .dev_addr = dev_addr, - .xfer_complete = - { - .ep_addr = ep_addr, - .result = result, - .len = xferred_bytes - } - }; + .ep_addr = ep_addr, + .result = result, + .len = xferred_bytes + } + }; - hcd_event_handler(&event, in_isr); - } + hcd_event_handler(&event, in_isr); } void hcd_event_device_attach(uint8_t rhport, bool in_isr) @@ -373,8 +379,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura uint8_t const* p_desc = (uint8_t const*) desc_cfg; p_desc = tu_desc_next(p_desc); - TU_LOG2_MEM(desc_cfg, desc_cfg->wTotalLength, 0); - // parse each interfaces while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) { @@ -426,16 +430,226 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } -bool enum_task(hcd_event_t* event) +static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_LOG2_LOCATION(); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + TU_LOG2("Device configured\r\n"); + usbh_device_t* dev = &_usbh_devices[dev_addr]; + dev->state = TUSB_DEVICE_STATE_CONFIGURED; + + // Parse configuration & set up drivers + parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + + return true; +} + +static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - enum { - POWER_STABLE_DELAY = 100, - RESET_DELAY = 500, // 200 USB specs say only 50ms but many devices require much longer + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + TU_LOG2("Set Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = CONFIG_NUM, + .wIndex = 0, + .wLength = 0 }; + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); + + return true; +} + +static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + // TODO not enough buffer to hold configuration descriptor + tusb_desc_configuration_t const * desc_config = (tusb_desc_configuration_t const*) _usbh_ctrl_buf; + uint16_t total_len; + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); + + TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); + + //Get full configuration descriptor + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = total_len + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); + + return true; +} + +static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + dev->vendor_id = desc_device->idVendor; + dev->product_id = desc_device->idProduct; + +// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + + TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = 9 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); + + return true; +} + +// After SET_ADDRESS is complete +static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(0 == dev_addr); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + uint8_t const new_addr = (uint8_t const) request->wValue; + + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->addressed = 1; + + // TODO close device 0, may not be needed usbh_device_t* dev0 = &_usbh_devices[0]; - tusb_control_request_t request; + hcd_device_close(dev0->rhport, 0); + dev0->state = TUSB_DEVICE_STATE_UNPLUG; + + // open control pipe for new address + TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + + // Get full device descriptor + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = sizeof(tusb_desc_device_t) + }; + TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); + + return true; +} + +// After Get Device Descriptor of Address 0 +static bool enum_get_dev0_devic_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(0 == dev_addr); + + usbh_device_t* dev0 = &_usbh_devices[0]; + + if (XFER_RESULT_SUCCESS != result) + { +#if CFG_TUH_HUB + // TODO remove, waiting for next data on status pipe + if (dev0->hub_addr != 0) hub_status_pipe_queue( dev0->hub_addr); +#endif + + return false; + } + + // Reset device again before Set Address + TU_LOG2("Port reset \r\n"); + + if (dev0->hub_addr == 0) + { + // connected directly to roothub + hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor + osal_task_delay(RESET_DELAY); + } +#if CFG_TUH_HUB + else + { + // FIXME hub_port_reset use usbh_control_xfer + if ( hub_port_reset(dev0->hub_addr, dev0->hub_port) ) + { + osal_task_delay(RESET_DELAY); + + // Acknowledge Port Reset Change if Reset Successful + hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); + } + + (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe + } +#endif // CFG_TUH_HUB + + // Set Address + TU_LOG2("Set Address \r\n"); + uint8_t const new_addr = get_new_address(); + TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->rhport = dev0->rhport; + new_dev->hub_addr = dev0->hub_addr; + new_dev->hub_port = dev0->hub_port; + new_dev->speed = dev0->speed; + new_dev->connected = 1; + new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT(tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete)); + + return true; +} + +bool enum_task(hcd_event_t* event) +{ + usbh_device_t* dev0 = &_usbh_devices[0]; dev0->rhport = event->rhport; // TODO refractor integrate to device_pool dev0->hub_addr = event->connection.hub_addr; dev0->hub_port = event->connection.hub_port; @@ -445,14 +659,11 @@ bool enum_task(hcd_event_t* event) if (dev0->hub_addr == 0) { // wait until device is stable. Increase this if the first 8 bytes is failed to get - osal_task_delay(POWER_STABLE_DELAY); + osal_task_delay(RESET_DELAY); // device unplugged while delaying if ( !hcd_port_connect_status(dev0->rhport) ) return true; - hcd_port_reset( dev0->rhport ); // port must be reset to have correct speed operation - osal_task_delay(RESET_DELAY); - dev0->speed = hcd_port_speed_get( dev0->rhport ); } #if CFG_TUH_HUB @@ -460,8 +671,9 @@ bool enum_task(hcd_event_t* event) else { // TODO wait for PORT reset change instead - osal_task_delay(POWER_STABLE_DELAY); + osal_task_delay(RESET_DELAY); + // FIXME hub API use usbh_control_xfer hub_port_status_response_t port_status; TU_VERIFY_HDLR( hub_port_get_status(dev0->hub_addr, dev0->hub_port, &port_status), hub_status_pipe_queue( dev0->hub_addr) ); @@ -479,19 +691,27 @@ bool enum_task(hcd_event_t* event) } #endif // CFG_TUH_HUB + // TODO probably doesn't need to open/close each enumeration TU_ASSERT( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = 8 + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = 8 }; - bool is_ok = usbh_control_xfer(0, &request, _usbh_ctrl_buf); + TU_ASSERT(tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_dev0_devic_desc_complete)); +#if 0 //------------- Reset device again before Set Address -------------// TU_LOG2("Port reset \r\n"); @@ -526,6 +746,14 @@ bool enum_task(hcd_event_t* event) uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->rhport = dev0->rhport; + new_dev->hub_addr = dev0->hub_addr; + new_dev->hub_port = dev0->hub_port; + new_dev->speed = dev0->speed; + new_dev->connected = 1; + new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_ADDRESS, @@ -533,7 +761,7 @@ bool enum_task(hcd_event_t* event) .wIndex = 0, .wLength = 0 }; - TU_ASSERT(usbh_control_xfer(0, &request, NULL)); + TU_ASSERT(tuh_control_xfer(0, &request, NULL, enum_set_address_complete)); //------------- update port info & close control pipe of addr0 -------------// usbh_device_t* new_dev = &_usbh_devices[new_addr]; @@ -613,6 +841,7 @@ bool enum_task(hcd_event_t* event) // Invoke callback if available if (tuh_mount_cb) tuh_mount_cb(new_addr); +#endif return true; } @@ -679,7 +908,7 @@ void tuh_task(void) if ( 0 == epnum ) { - // TODO control transfer + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); }else { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; diff --git a/src/host/usbh.h b/src/host/usbh.h index 91afb90a3..814770722 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -63,6 +63,8 @@ typedef struct { bool (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); void (* const close) (uint8_t); } usbh_class_driver_t; + +typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -87,10 +89,12 @@ static inline bool tuh_device_is_configured(uint8_t dev_addr) return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; } +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); + //--------------------------------------------------------------------+ // APPLICATION CALLBACK //--------------------------------------------------------------------+ -TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); +//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); /** Callback invoked when device is mounted (configured) */ TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); @@ -107,9 +111,6 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, uint8_t* buffer, uint16_t buflen); - #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c new file mode 100644 index 000000000..595c011f5 --- /dev/null +++ b/src/host/usbh_control.c @@ -0,0 +1,135 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED + +#include "tusb.h" +#include "usbh_hcd.h" + +enum +{ + STAGE_SETUP, + STAGE_DATA, + STAGE_ACK +}; + +typedef struct +{ + tusb_control_request_t request TU_ATTR_ALIGNED(4); + + uint8_t stage; + uint8_t* buffer; + tuh_control_complete_cb_t complete_cb; +} usbh_control_xfer_t; + +static usbh_control_xfer_t _ctrl_xfer; + +//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +//static uint8_t _tuh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + const uint8_t rhport = dev->rhport; + + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = buffer; + _ctrl_xfer.stage = STAGE_SETUP; + _ctrl_xfer.complete_cb = complete_cb; + + TU_LOG2("Control Setup: "); + TU_LOG2_VAR(request); + TU_LOG2("\r\n"); + + // Send setup packet + TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); + + return true; +} + +static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) +{ + if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); +} + +bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + const uint8_t rhport = dev->rhport; + + tusb_control_request_t const * request = &_ctrl_xfer.request; + + if (XFER_RESULT_SUCCESS != result) + { + TU_LOG2("Control failed: result = %d\r\n", result); + + // terminate transfer if any stage failed + _xfer_complete(dev_addr, result); + }else + { + switch(_ctrl_xfer.stage) + { + case STAGE_SETUP: + _ctrl_xfer.stage = STAGE_DATA; + if (request->wLength) + { + // Note: initial data toggle is always 1 + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); + return true; + } + __attribute__((fallthrough)); + + case STAGE_DATA: + _ctrl_xfer.stage = STAGE_ACK; + + if (request->wLength) + { + TU_LOG2("Control data:\r\n"); + TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); + } + + // data toggle is always 1 + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); + break; + + case STAGE_ACK: + _xfer_complete(dev_addr, result); + break; + + default: return false; + } + } + + return true; +} + +#endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 435af96bb..f203f3baa 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -53,11 +53,20 @@ typedef struct { //------------- device descriptor -------------// uint16_t vendor_id; uint16_t product_id; + uint8_t ep0_packet_size; //------------- configuration descriptor -------------// - uint8_t interface_count; // bNumInterfaces alias + // uint8_t interface_count; // bNumInterfaces alias //------------- device -------------// + struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; + volatile uint8_t state; // device state, value from enum tusbh_device_state_t //------------- control pipe -------------// -- cgit v1.3.1 From 8b9893cadab88fa4abd17d5b9856e0d08ef03796 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 15:48:11 +0700 Subject: introduce optional usbd_edpt_claim, usbd_edpt_release which can be used to gain exclusive access to usbd_edpt_xfer --- src/class/cdc/cdc_device.c | 38 ++++++++++++++++--------- src/device/usbd.c | 71 +++++++++++++++++++++++++++++++++++++++++++++- src/device/usbd_pvt.h | 6 ++++ 3 files changed, 101 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b4ebfc92e..cd8904042 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -77,8 +77,8 @@ static void _prep_out_transaction (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return; + // claim endpoint + TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); @@ -161,17 +161,29 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // skip if previous transfer not complete yet - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); + // No data to send + if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - if ( count ) + uint8_t const rhport = TUD_OPT_RHPORT; + + // claim the endpoint first + TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + + // we can be blocked by another write()/write_flush() from other thread. + // causing us to attempt to transfer on an busy endpoint. + uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); + + if ( count && tud_cdc_n_connected(itf) ) { - TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + // Note: data is dropped if terminal is not connected + usbd_edpt_release(rhport, p_cdc->ep_in); + return 0; } - - return count; } uint32_t tud_cdc_n_write_available (uint8_t itf) @@ -194,7 +206,7 @@ void cdcd_init(void) p_cdc->wanted_char = -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; + p_cdc->line_coding.bit_rate = 115200; p_cdc->line_coding.stop_bits = 0; p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; @@ -421,10 +433,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( 0 == tud_cdc_n_write_flush(itf) ) { - // There is no data left, a ZLP should be sent if + // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) + if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b91048b6..25d3748e1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -63,9 +63,11 @@ typedef struct { volatile bool busy : 1; volatile bool stalled : 1; + volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[8][2]; + }usbd_device_t; static usbd_device_t _usbd_dev; @@ -237,6 +239,13 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE +static osal_mutex_def_t _ubsd_mutexdef; +static osal_mutex_t _usbd_mutex; +#endif + + //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ @@ -351,9 +360,15 @@ bool tud_init (void) tu_varclr(&_usbd_dev); +#if CFG_TUSB_OS != OPT_OS_NONE + // Init device mutex + _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); + TU_ASSERT(_usbd_mutex); +#endif + // Init device queue & task _usbd_q = osal_queue_create(&_usbd_qdef); - TU_ASSERT(_usbd_q != NULL); + TU_ASSERT(_usbd_q); // Get application driver if available if ( usbd_app_driver_get_cb ) @@ -478,6 +493,7 @@ void tud_task (void) TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; if ( 0 == epnum ) { @@ -1076,6 +1092,56 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) return dcd_edpt_open(rhport, desc_ep); } +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1083,6 +1149,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + // Attempt to transfer on busy or not claimed (skip now) endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0 /*&& _usbd_dev.ep_status[epnum][dir].claimed == 1*/); + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a5d223329..5fa9a72a5 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,6 +70,12 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Claim an endpoint before submitting a transfer +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); + +// Release an endpoint without submitting a transfer +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 33f0a18523accfcdebf186f33271dd92f8681b56 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:25:31 +0700 Subject: update cdc edpt read --- src/class/cdc/cdc_device.c | 12 +++++------- src/device/usbd.c | 2 ++ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cd8904042..317355ed7 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -77,15 +77,13 @@ static void _prep_out_transaction (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); + TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); + // claim endpoint TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= sizeof(p_cdc->epout_buf) ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - } + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 25d3748e1..5a7d72124 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1162,7 +1162,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; }else { + // DCD error, mark endpoint as ready to allow next transfer _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; TU_LOG2("failed\r\n"); TU_BREAKPOINT(); return false; -- cgit v1.3.1 From fe1b5dfa235550cc4eb63e237da50689fe407bf4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:29:45 +0700 Subject: clean up --- src/class/cdc/cdc_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 317355ed7..8ea44b28d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -164,11 +164,10 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; - // claim the endpoint first - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + // Claim the endpoint first + TU_VnERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); - // we can be blocked by another write()/write_flush() from other thread. - // causing us to attempt to transfer on an busy endpoint. + // Pull data from FIFO uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count && tud_cdc_n_connected(itf) ) -- cgit v1.3.1 From ed6d48b81e8a5d1ed8b518921b30b87c7daecee5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:45:54 +0700 Subject: typo --- src/class/cdc/cdc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 8ea44b28d..0792e745d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -165,7 +165,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; // Claim the endpoint first - TU_VnERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); // Pull data from FIFO uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); -- cgit v1.3.1 From b15c209805978dc115fe38c72b3f7c235aed42ec Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 10 Sep 2020 13:36:07 +0200 Subject: Set new define because of build failure --- src/class/cdc/cdc_device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 145381c42..1d7a64827 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -43,6 +43,10 @@ #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif +#ifndef CFG_TUD_CDC_CLEAR_AT_CONNECTION + #define CFG_TUD_CDC_CLEAR_AT_CONNECTION 0 +#endif + #ifdef __cplusplus extern "C" { #endif -- cgit v1.3.1 From 801f8b5b38b90cb3e15d0a1bb2accae58cde6130 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Sep 2020 23:32:08 +0700 Subject: update claim edpt for hid and midi --- src/class/cdc/cdc_device.c | 41 +++++++++++++++++++++++------------------ src/class/hid/hid_device.c | 13 ++++++++----- src/class/midi/midi_device.c | 27 +++++++++++++++++++++------ src/device/usbd_pvt.h | 3 ++- 4 files changed, 54 insertions(+), 30 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 0792e745d..6c1bf6bb2 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -73,17 +73,17 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; -static void _prep_out_transaction (uint8_t itf) +static void _prep_out_transaction (cdcd_interface_t* p_cdc) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); - // claim endpoint - TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + // claim endpoint and submit transfer + if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + } } //--------------------------------------------------------------------+ @@ -121,8 +121,9 @@ uint32_t tud_cdc_n_available(uint8_t itf) uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { - uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize); - _prep_out_transaction(itf); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize); + _prep_out_transaction(p_cdc); return num_read; } @@ -133,8 +134,9 @@ bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr) void tud_cdc_n_read_flush (uint8_t itf) { - tu_fifo_clear(&_cdcd_itf[itf].rx_ff); - _prep_out_transaction(itf); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + tu_fifo_clear(&p_cdc->rx_ff); + _prep_out_transaction(p_cdc); } //--------------------------------------------------------------------+ @@ -142,11 +144,12 @@ void tud_cdc_n_read_flush (uint8_t itf) //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) { - uint16_t ret = tu_fifo_write_n(&_cdcd_itf[itf].tx_ff, buffer, bufsize); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) + if ( tu_fifo_count(&p_cdc->tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +167,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; - // Claim the endpoint first + // Claim the endpoint TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); // Pull data from FIFO @@ -242,8 +245,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Find available interface cdcd_interface_t * p_cdc = NULL; - uint8_t cdc_id; - for(cdc_id=0; cdc_idrx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction - _prep_out_transaction(itf); + _prep_out_transaction(p_cdc); } // Data sent to host, we continue to fetch from tx fifo to send. @@ -435,7 +437,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) + { + usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + } } } } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index c46fc591a..10267d734 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -72,18 +72,21 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ bool tud_hid_ready(void) { - uint8_t itf = 0; + uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; - return tud_ready() && (ep_in != 0) && usbd_edpt_ready(TUD_OPT_RHPORT, ep_in); + return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) { - TU_VERIFY( tud_hid_ready() ); - - uint8_t itf = 0; + uint8_t const rhport = 0; + uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; + // claim endpoint + TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); + + // prepare data if (report_id) { len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 376b3670a..00b1bde92 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -153,15 +153,25 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu static uint32_t write_flush(midid_interface_t* midi) { + // No data to send + if ( !tu_fifo_count(&midi->tx_ff) ) return 0; + + uint8_t const rhport = TUD_OPT_RHPORT; + // skip if previous transfer not complete - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); + TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); if (count > 0) { - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); + TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, midi->ep_in); + return 0; } - return count; } uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) @@ -405,17 +415,22 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 if (tud_midi_rx_cb) tud_midi_rx_cb(itf); // prepare for next + // TODO for now ep_out is not used by public API therefore there is no race condition, + // and does not need to claim like ep_in TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); } else if ( ep_addr == p_midi->ep_in ) { if (0 == write_flush(p_midi)) { - // There is no data left, a ZLP should be sent if + // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) + if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) + { + usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + } } } } diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 5fa9a72a5..09b285581 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,7 +70,8 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Claim an endpoint before submitting a transfer +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); // Release an endpoint without submitting a transfer -- cgit v1.3.1 From 1804dba615653591a754c9221028c94a32e50495 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Sep 2020 08:48:49 +0700 Subject: typo --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 145381c42..3c679c48e 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -92,7 +92,7 @@ uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bu static inline uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); -// Write a nul-terminated string +// Write a null-terminated string static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); -- cgit v1.3.1 From 5931d19666667e9a5b2b99082fb24392e3983399 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Sep 2020 15:01:20 +0700 Subject: correct the TUD_HID_REPORT_DESC_GAMEPAD --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f7ad38bab..1e584e4c9 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -264,7 +264,7 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); HID_LOGICAL_MAX ( 1 ) ,\ HID_REPORT_COUNT ( 16 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ /* X, Y, Z, Rz (min -127, max 127 ) */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ HID_LOGICAL_MIN ( 0x81 ) ,\ -- cgit v1.3.1 From 3b0216d3bfe568e949fe1ea7c2c9f3f3a8dc6a4b Mon Sep 17 00:00:00 2001 From: Mark Lentczner Date: Sun, 13 Sep 2020 15:05:18 -0700 Subject: Update midi_device.c Fix a bug in writing SysEx messages. At the start of a new USB packet (4 bytes), while in the middle of a SysEx, the code mistakenly set the buffer length to 4, not the target length. As a consequence, the 3rd and 4th bytes from the last packet were included, after every byte of the SysEx after the first packet of three. The fix is simple, as it was just a typo, as can bee seen from the other branches in the same section of if/else statements: At the start of a new packet, the code should set up the target length... the buffer length should be left at 2 (as set on line 180). --- src/class/midi/midi_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 376b3670a..1a0bbd170 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -183,7 +183,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u if (data == 0xf7) { midi->write_buffer[0] = 0x5; } else { - midi->write_buffer_length = 4; + midi->write_target_length = 4; } } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { midi->write_buffer[0] = jack_id << 4 | msg; -- cgit v1.3.1 From 23e6ee2ea2e69f09b43c9f7736b95560a6e9ef7b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:14:31 +0700 Subject: cdc device: claim endpoint before checking fifo availability - add pre-check to reduce mutex lock in usbd_edpt_claim --- src/class/cdc/cdc_device.c | 23 ++++++++++++++++++----- src/device/usbd.c | 5 ++++- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6c1bf6bb2..e39adc5fa 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -75,14 +75,27 @@ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static void _prep_out_transaction (cdcd_interface_t* p_cdc) { + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); + // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); - TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); + // 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 >= sizeof(p_cdc->epout_buf), ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), ); - // claim endpoint and submit transfer - if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) ) + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_cdc->rx_ff); + + if ( available >= sizeof(p_cdc->epout_buf) ) { + usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + }else { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_cdc->ep_out); } } diff --git a/src/device/usbd.c b/src/device/usbd.c index 8fc0092eb..dfe30578e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1100,11 +1100,14 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); #if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); #endif // can only claim the endpoint if it is not busy and not claimed yet. - bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); if (ret) { _usbd_dev.ep_status[epnum][dir].claimed = 1; -- cgit v1.3.1 From 5ad2f8efc6ce77d3f58f3292838367dea8c41826 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 26 Aug 2020 16:34:56 +0200 Subject: audio_device: Fix inline function specifiers Having just inline keyword for function specified in header may not be enough to generate code for function. Adding static solves this problem. static inline is used in all other inline functions in TinyUSB. --- src/class/audio/audio_device.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 11f444daa..2adb95252 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -196,23 +196,23 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, // Application API (Interface0) //--------------------------------------------------------------------+ -inline bool tud_audio_mounted (void); +static inline bool tud_audio_mounted (void); #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -inline uint16_t tud_audio_available (void); -inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -inline void tud_audio_read_flush (void); +static inline uint16_t tud_audio_available (void); +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +static inline void tud_audio_read_flush (void); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -inline uint32_t tud_audio_int_ctr_available (void); -inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -inline void tud_audio_int_ctr_read_flush (void); -inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_audio_int_ctr_available (void); +static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +static inline void tud_audio_int_ctr_read_flush (void); +static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); #endif // Buffer control EP data and schedule a transmit @@ -269,52 +269,52 @@ TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_reque // Inline Functions //--------------------------------------------------------------------+ -inline bool tud_audio_mounted(void) +static inline bool tud_audio_mounted(void) { return tud_audio_n_mounted(0); } #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { return tud_audio_n_write(0, channelId, buffer, bufsize); } #endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -inline uint16_t tud_audio_available(uint8_t channelId) +static inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); } -inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) { return tud_audio_n_read(0, channelId, buffer, bufsize); } -inline void tud_audio_read_flush(uint8_t channelId) +static inline void tud_audio_read_flush(uint8_t channelId) { tud_audio_n_read_flush(0, channelId); } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -inline uint16_t tud_audio_int_ctr_available(void) +static inline uint16_t tud_audio_int_ctr_available(void) { return tud_audio_int_ctr_n_available(0); } -inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) { return tud_audio_int_ctr_n_read(0, buffer, bufsize); } -inline void tud_audio_int_ctr_read_flush(void) +static inline void tud_audio_int_ctr_read_flush(void) { return tud_audio_int_ctr_n_read_flush(0); } -inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) { return tud_audio_int_ctr_n_write(0, buffer, bufsize); } -- cgit v1.3.1 From f4a44ee06337366680958013143657aa693c80ef Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 10:56:17 +0200 Subject: audio: Update ISO endpoint attributes Explicit feedback attribute was missing. No synchronization now also has definition. --- src/class/audio/audio.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 5e64549ed..0027217cb 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -497,11 +497,13 @@ typedef enum /// Isochronous End Point Attributes typedef enum { + TUSB_ISO_EP_ATT_NO_SYNC = 0x00, TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point + TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point + TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback } tusb_iso_ep_attribute_t; /// Audio Class-Control Values UAC2 -- cgit v1.3.1 From e67fc808aada31a549399a0b0337b43ec45535d1 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:13:25 +0200 Subject: audio_device: Store rhport in interface data Some API uses interface number as argument, some wants to have rhport. To accommodate need of rhport for functions that don't have it rhport can be extracted from interface data. --- src/class/audio/audio_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index ebb8434cd..fd24d455c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -48,6 +48,7 @@ //--------------------------------------------------------------------+ typedef struct { + uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function #if CFG_TUD_AUDIO_EPSIZE_IN @@ -673,6 +674,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin if (!_audiod_itf[i].p_desc) { _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + _audiod_itf[i].rhport = rhport; break; } } -- cgit v1.3.1 From 66b091282f31275fff859c4cf61c3026215a3db7 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:16:41 +0200 Subject: audio_device: Fix audio_rx_done_type_I_pcm_ff_cb prototype Function prototype did not have return type specified by mistake. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fd24d455c..f83f395a8 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -135,7 +135,7 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; #if CFG_TUD_AUDIO_EPSIZE_OUT -static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize); +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_EPSIZE_IN -- cgit v1.3.1 From ca4a42156ceeb8dd6b70edc02b2b762645c62c66 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:18:11 +0200 Subject: audio_device: Fix audio_rx_done_type_I_pcm_ff_cb bufor size check Function was not checking buffer size correctly due missing parenthesis. --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f83f395a8..23a2cea96 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -288,7 +288,8 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a (void) rhport; // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) + { return false; } -- cgit v1.3.1 From 28cf63c7dbe08677d614d16a435487ae03b3cce6 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:24:41 +0200 Subject: audio_device: Fix tud_audio_n_read_flush TU_VERIFY usage void function used TU_VERIFY in a way that returned bool value. It would not compile. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 23a2cea96..2660cf368 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -205,7 +205,7 @@ uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } -- cgit v1.3.1 From 759d5305062e5261d580fa64e40fc755db34c436 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:42:52 +0200 Subject: audio_device: Allow one FIFO for N channels This allow to build with single FIFO for devices with multiple channels. Having just one FIFO greatly reduces time needed to feed endpoint. This change also allows to have one FIFO with 24 bit samples that is not rounded up to 32 bit elements. CFG_TUD_AUDIO_RX_ITEMSIZE and CFG_TUD_AUDIO_TX_ITEMSIZE can be manually defined. This allows to use FIFO more efficiently when 24 bits samples are already using 3 bytes, in this case there is no need to put them into FIFO one by one. For 8, 16, 32 bits samples size efficient FIFO access is always used when single FIFO is selected. This also changes FIFO element size to 1, FIFO usage was confusing in some place it treated content as byte base in other it looked like ITEM size is to be used. Also bufsize that in most (maybe all) cases was really meaning item count. bufsize now mean buffer size in bytes so there is no confusion. --- src/class/audio/audio_device.c | 147 ++++++++++++++++++++++++++++++++++------- src/class/audio/audio_device.h | 60 ++++++++++++++++- 2 files changed, 179 insertions(+), 28 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2660cf368..181703f75 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -46,6 +46,19 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT +#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX +#endif +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT +#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX +#endif +#endif + typedef struct { uint8_t rhport; @@ -81,18 +94,18 @@ typedef struct // FIFO #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE * CFG_TUD_AUDIO_TX_ITEMSIZE]; + tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT]; #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE * CFG_TUD_AUDIO_RX_ITEMSIZE]; + tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT]; #endif #endif @@ -190,7 +203,7 @@ bool tud_audio_n_mounted(uint8_t itf) //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) { TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); @@ -208,7 +221,22 @@ void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } +#else +uint16_t tud_audio_n_available(uint8_t itf) +{ + return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]); +} +uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +{ + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize); +} + +void tud_audio_n_read_flush (uint8_t itf) +{ + tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]); +} +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -283,6 +311,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* // The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 #if CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -318,7 +347,23 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a chId = 0; } } -} } + return true; +} +#else +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *audio, uint8_t *buffer, uint16_t bufsize) +{ + (void) rhport; + + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) + { + return false; + } + + tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); + return true; +} +#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 #endif //CFG_TUD_AUDIO_RX_FIFO_SIZE //--------------------------------------------------------------------+ @@ -336,9 +381,9 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ - +#if CFG_TUD_AUDIO_EPSIZE_IN +#if !CFG_TUD_AUDIO_TX_FIFO_SIZE /* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; @@ -365,11 +410,23 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t // Return number of bytes written return len; } -#endif - */ -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#else + +#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1 +uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) +{ + { + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) + { + return 0; + } + return tu_fifo_write_n(&audio->tx_ff[0], data, len); + } +} +#else uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; @@ -381,6 +438,23 @@ uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, ui } #endif +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); + +uint16_t tud_audio_n_write_flush(uint8_t itf) +{ + audiod_interface_t *audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + uint16_t n_bytes_copied; + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); + return n_bytes_copied; +} + +#endif +#endif + #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) { @@ -477,6 +551,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ #endif //CFG_TUD_AUDIO_EPSIZE_IN #if CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's buffer - abort if previous transfer not complete @@ -484,15 +559,15 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* // Determine amount of samples uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; uint16_t nBytesToSend; uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + if (audio->tx_ff[cntChannel].count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) { - nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count * CFG_TUD_AUDIO_TX_ITEMSIZE; } } @@ -524,7 +599,7 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { // Get sample from buffer - tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); // Put it into EP's buffer - Let alignment problems be handled by memcpy memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); @@ -539,6 +614,30 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } +#else +static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) +{ + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); + + nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN); + + // Check if there is enough + if (nByteCount == 0) + { + return true; + } + + nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); + audio->epin_buf_cnt = nByteCount; + + return true; +} +#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) + #endif //CFG_TUD_AUDIO_TX_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent @@ -588,7 +687,6 @@ static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uin //--------------------------------------------------------------------+ void audiod_init(void) { - uint8_t cnt; tu_memclr(_audiod_itf, sizeof(_audiod_itf)); for(uint8_t i=0; itx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif @@ -607,9 +705,9 @@ void audiod_init(void) #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif @@ -634,16 +732,15 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); - uint8_t cnt; #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2adb95252..2f48955f2 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -119,6 +119,7 @@ #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif +#ifndef CFG_TUD_AUDIO_TX_ITEMSIZE #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 #define CFG_TUD_AUDIO_TX_ITEMSIZE 1 #elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 @@ -126,6 +127,11 @@ #else #define CFG_TUD_AUDIO_TX_ITEMSIZE 4 #endif +#endif + +#if CFG_TUD_AUDIO_TX_ITEMSIZE < CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#error FIFO element size (ITEMSIZE) must not be smaller then sample size +#endif #endif @@ -170,9 +176,15 @@ extern "C" { bool tud_audio_n_mounted (uint8_t itf); #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); +#else +uint16_t tud_audio_n_available (uint8_t itf); +uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_n_read_flush (uint8_t itf); +#endif #endif /* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers @@ -182,7 +194,12 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t */ #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); +#else +uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +#endif +uint16_t tud_audio_n_write_flush(uint8_t itf); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 @@ -205,7 +222,11 @@ static inline void tud_audio_read_flush (void); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#else +static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize); +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 @@ -274,14 +295,31 @@ static inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 +static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, channelId, buffer, n_bytes); +} +#else +static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, buffer, n_bytes); +} +#endif + +static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used { - return tud_audio_n_write(0, channelId, buffer, bufsize); +#if CFG_TUD_AUDIO_TX_FIFO_SIZE + return tud_audio_n_write_flush(0); +#else + return 0; +#endif } #endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 static inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); @@ -296,6 +334,22 @@ static inline void tud_audio_read_flush(uint8_t channelId) { tud_audio_n_read_flush(0, channelId); } +#else +static inline uint16_t tud_audio_available(void) +{ + return tud_audio_n_available(0); +} + +static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize) +{ + return tud_audio_n_read(0, buffer, bufsize); +} + +static inline void tud_audio_read_flush(void) +{ + tud_audio_n_read_flush(0); +} +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -- cgit v1.3.1 From 2ace98e943831784e6c9d81258babce2b7b3221c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 11:28:05 +0200 Subject: audio_device: Update explicit feedback support Feedback can be specified by the user code and will be sent at feedback endpoint specified interval. --- src/class/audio/audio_device.c | 76 ++++++++++++++++++++++++++++++++---------- src/class/audio/audio_device.h | 5 +++ src/device/usbd.h | 5 +++ 3 files changed, 68 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 181703f75..1b9cfe13a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -121,10 +121,9 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_OUT CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - // TODO: required? - //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! - //#endif +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif #endif @@ -643,18 +642,51 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) { - (void) rhport; - (void) audio; + uint8_t fb[4]; + uint16_t len; - // Here we need to return the feedback value -#error RETURN YOUR FEEDBACK VALUE HERE! + if (audio->fb_val == 0) + { + len = 0; + return true; + } + else + { + len = 4; + // Here we need to return the feedback value + if (rhport == 0) + { + // For FS format is 10.14 + fb[0] = (audio->fb_val >> 2) & 0xFF; + fb[1] = (audio->fb_val >> 10) & 0xFF; + fb[2] = (audio->fb_val >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + fb[3] = 0; + } + else + { + // For HS format is 16.16 + fb[0] = (audio->fb_val >> 0) & 0xFF; + fb[1] = (audio->fb_val >> 8) & 0xFF; + fb[2] = (audio->fb_val >> 16) & 0xFF; + fb[3] = (audio->fb_val >> 24) & 0xFF; + } + return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len); + } - if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return 0; } +//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +//{ +// (void) rhport; +// (void) audio; +// +// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); +// return 0; +//} + #endif // This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send @@ -918,7 +950,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback { _audiod_itf[idxDriver].ep_fb = ep_addr; @@ -1215,13 +1247,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Transmission of feedback EP finished if (_audiod_itf[idxDriver].ep_fb == ep_addr) { - if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return true; + return audio_fb_send(rhport, &_audiod_itf[idxDriver]); } #endif #endif @@ -1403,4 +1431,16 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) return false; } +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback) +{ + audiod_interface_t *audio = &_audiod_itf[0]; + + audio->fb_val = feedback; + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true); + + return audio_fb_send(rhport, audio); +} +#endif + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2f48955f2..f4029a84c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -259,6 +259,11 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ #if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); +// User code should call this function with feedback value in 16.16 format for FS and HS. +// Value will be corrected for FS to 10.14 format automatically. +// (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). +// Feedback value will be sent at FB endpoint interval till it's changed. +bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/device/usbd.h b/src/device/usbd.h index 43af25076..a450bca7c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -377,6 +377,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) +/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -- cgit v1.3.1 From 529622710ca6a234fa385402e4a298759a04ad72 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 18:10:57 +0200 Subject: Cleanup for PR. --- src/class/audio/audio_device.c | 16 +++++--------- src/portable/st/synopsys/dcd_synopsys.c | 37 --------------------------------- 2 files changed, 5 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1b9cfe13a..d208d1c84 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Reinhard Panhuber + * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -66,7 +66,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_IN uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint16_t epin_buf_cnt; // Count filling status of EP in buffer + uint16_t epin_buf_cnt; // Count filling status of EP in buffer - this is a shared state currently and is intended to be removed once EP buffers can be implemented as FIFOs! uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif @@ -468,7 +468,7 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_EPSIZE_IN @@ -925,10 +925,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? - // Invoke callback - fill something in the FIFO here for now + // Invoke callback and trigger data generation - if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Schedule first transmit - in case no sample data is available a ZLP is loaded uint16_t n_bytes_copied; TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); } @@ -1218,12 +1218,6 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); // Transmission of ZLP is done by audiod_tx_done_cb() -// if (n_bytes_copied == 0) -// { -// // Load with ZLP -// return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); -// } - return true; } #endif diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4c670515a..b3d82c3aa 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -690,43 +690,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -///** -// * Close an EP. -// * -// * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! -// * -// */ -//void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) -//{ -// (void)rhport; -// uint32_t const epnum = tu_edpt_number(ep_addr); -// uint32_t const dir = tu_edpt_dir(ep_addr); -// -// USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); -// -// if(dir == TUSB_DIR_IN) -// { -// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); -// -// // Disable interrupt for this EP -// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); -// -// // Clear USB active EP -// in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; -// } -// else -// { -// USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); -// -// // Disable interrupt for this EP -// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; -// -// // Clear USB active EP bit -// out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; -// -// } -//} - bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); -- cgit v1.3.1 From da1c3c226b84faf2547a71fb7ed4acdb544d758b Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 22:44:09 +0200 Subject: Change AUDIO_PROTOCOL_V1 to AUDIO_FUNC_PROTOCOL_CODE_UNDEF in midi.c. The USB specification does not define any AUDIO_PROTOCOL_V1! --- src/class/midi/midi_device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index de05d93d1..a07acf0b8 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -300,9 +300,9 @@ void midid_reset(uint8_t rhport) uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); uint16_t drv_len = tu_desc_len(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf); @@ -318,9 +318,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; -- cgit v1.3.1 From 849681724af698c77b01a615595418ba2efd543e Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 11:51:33 -0500 Subject: create N functions and inlines for multi hid interfaces --- src/class/hid/hid_device.c | 24 ++++++++++----------- src/class/hid/hid_device.h | 53 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 20 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 10267d734..04ea31326 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -70,17 +70,17 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_ready(void) +bool tud_hid_n_ready(uint8_t itf) { - uint8_t const itf = 0; + //uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - uint8_t const itf = 0; + //uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; // claim endpoint @@ -104,16 +104,16 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); } -bool tud_hid_boot_mode(void) +bool tud_hid_n_boot_mode(uint8_t itf) { - uint8_t itf = 0; + //uint8_t itf = 0; return _hidd_itf[itf].boot_mode; } //--------------------------------------------------------------------+ // KEYBOARD API //--------------------------------------------------------------------+ -bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -127,13 +127,13 @@ bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycod tu_memclr(report.keycode, 6); } - return tud_hid_report(report_id, &report, sizeof(report)); + return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ // MOUSE APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = { @@ -144,7 +144,7 @@ bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y .pan = horizontal }; - return tud_hid_report(report_id, &report, sizeof(report)); + return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ @@ -197,7 +197,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - + // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1e584e4c9..e6961515c 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -50,25 +50,35 @@ #endif //--------------------------------------------------------------------+ -// Application API +// Application API (Multiple Ports) +// CFG_TUD_HID > 1 //--------------------------------------------------------------------+ // Check if the interface is ready to use -bool tud_hid_ready(void); +bool tud_hid_n_ready(uint8_t itf); // Check if current mode is Boot (true) or Report (false) -bool tud_hid_boot_mode(void); +bool tud_hid_n_boot_mode(uint8_t itf); // Send report to host -bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t -bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); + +//--------------------------------------------------------------------+ +// Application API (Single Port) +//--------------------------------------------------------------------+ +static inline bool tud_hid_ready(void); +static inline bool tud_hid_boot_mode(void); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -95,6 +105,34 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ +static inline bool tud_hid_ready(void) +{ + return tud_hid_n_ready(0); +} + +static inline bool tud_hid_boot_mode(void) +{ + return tud_hid_n_boot_mode(0); +} + +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +{ + return tud_hid_n_report(0, report_id, report, len); +} + +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +{ + return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); +} + +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +{ + return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); +} + /* --------------------------------------------------------------------+ * HID Report Descriptor Template * @@ -318,4 +356,3 @@ bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t e #endif #endif /* _TUSB_HID_DEVICE_H_ */ - -- cgit v1.3.1 From b7208d6f7e97e724853eb5d0e512a23005cc8790 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 12:51:48 -0500 Subject: add index to report descriptor callback. this is breaking and needs to be reviewed --- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 04ea31326..b4c75e3fb 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -237,7 +237,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - uint8_t const * desc_report = tud_hid_descriptor_report_cb(); + uint8_t const * desc_report = tud_hid_descriptor_report_cb((uint8_t) request->wIndex); tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index e6961515c..1873c4f09 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -86,7 +86,8 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void); +// TODO Talk about this change... because it is breaking. Might be better way to handle. +uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. -- cgit v1.3.1 From 081af79009dc40ab41be9976d22629c7d251a50d Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Fri, 2 Oct 2020 16:02:00 -0500 Subject: fix simple pull request comments. Implement descriptor index hack. --- examples/device/hid_multipleinterface/src/main.c | 8 ++--- .../hid_multipleinterface/src/usb_descriptors.c | 5 ++-- .../hid_multipleinterface/src/usb_descriptors.h | 34 ---------------------- src/class/hid/hid_device.c | 20 ++++++++++--- src/class/hid/hid_device.h | 5 +++- 5 files changed, 25 insertions(+), 47 deletions(-) delete mode 100644 examples/device/hid_multipleinterface/src/usb_descriptors.h (limited to 'src/class') diff --git a/examples/device/hid_multipleinterface/src/main.c b/examples/device/hid_multipleinterface/src/main.c index 985d87246..2efb1f5cb 100644 --- a/examples/device/hid_multipleinterface/src/main.c +++ b/examples/device/hid_multipleinterface/src/main.c @@ -30,8 +30,6 @@ #include "bsp/board.h" #include "tusb.h" -#include "usb_descriptors.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -138,13 +136,13 @@ void hid_task(void) uint8_t keycode[6] = { 0 }; keycode[0] = HID_KEY_A; - tud_hid_n_keyboard_report(keyboard_interface, REPORT_ID_KEYBOARD, 0, keycode); + tud_hid_n_keyboard_report(keyboard_interface, 0, 0, keycode); has_key = true; }else { // send empty key report if previously has key pressed - if (has_key) tud_hid_n_keyboard_report(keyboard_interface, REPORT_ID_KEYBOARD, 0, NULL); + if (has_key) tud_hid_n_keyboard_report(keyboard_interface, 0, 0, NULL); has_key = false; } } @@ -157,7 +155,7 @@ void hid_task(void) int8_t const delta = 5; // no button, right + down, no scroll pan - tud_hid_n_mouse_report(mouse_interface, REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); + tud_hid_n_mouse_report(mouse_interface, 0, 0x00, delta, delta, 0, 0); // delay a bit before attempt to send keyboard report board_delay(10); diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c index f8423bdd1..a1a98c773 100644 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.c +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -24,7 +24,6 @@ */ #include "tusb.h" -#include "usb_descriptors.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. @@ -73,12 +72,12 @@ uint8_t const * tud_descriptor_device_cb(void) uint8_t const desc_hid_report1[] = { - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD) ) + TUD_HID_REPORT_DESC_KEYBOARD() }; uint8_t desc_hid_report2[] = { - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE) ) + TUD_HID_REPORT_DESC_MOUSE() }; // Invoked when received GET HID REPORT DESCRIPTOR diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.h b/examples/device/hid_multipleinterface/src/usb_descriptors.h deleted file mode 100644 index 6992d3349..000000000 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ - -#ifndef USB_DESCRIPTORS_H_ -#define USB_DESCRIPTORS_H_ - -enum -{ - REPORT_ID_KEYBOARD = 1, - REPORT_ID_MOUSE -}; - -#endif /* USB_DESCRIPTORS_H_ */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b4c75e3fb..9e1c5fd33 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -67,12 +67,21 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) return NULL; } +static inline uint8_t get_descindex_by_itfnum(uint8_t itf_num) +{ + for (uint8_t i=0; i < CFG_TUD_HID; i++ ) + { + if ( itf_num == _hidd_itf[i].itf_num ) return i; + } + + return 0; +} + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ bool tud_hid_n_ready(uint8_t itf) { - //uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } @@ -80,7 +89,6 @@ bool tud_hid_n_ready(uint8_t itf) bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - //uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; // claim endpoint @@ -106,7 +114,6 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ bool tud_hid_n_boot_mode(uint8_t itf) { - //uint8_t itf = 0; return _hidd_itf[itf].boot_mode; } @@ -237,7 +244,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - uint8_t const * desc_report = tud_hid_descriptor_report_cb((uint8_t) request->wIndex); + #if CFG_TUD_HID>1 + uint8_t const calculated_desc_index = get_descindex_by_itfnum((uint8_t) request->wIndex); + uint8_t const * desc_report = tud_hid_descriptor_report_cb(calculated_desc_index); + #else + uint8_t const * desc_report = tud_hid_descriptor_report_cb(); + #endif tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1873c4f09..30d99ce47 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -86,8 +86,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// TODO Talk about this change... because it is breaking. Might be better way to handle. +#if CFG_TUD_HID>1 uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index); +#else +uint8_t const * tud_hid_descriptor_report_cb(void); +#endif // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. -- cgit v1.3.1 From 2050dc0dc743294b07d0534278027da689bc6813 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Oct 2020 09:46:22 +0200 Subject: Revert #define CFG_TUSB_DEBUG 2 to #define CFG_TUSB_DEBUG 0 Change 1 << 31 to 0x100000000 in audio.h --- src/class/audio/audio.h | 2 +- src/tusb_option.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 0027217cb..7e591fbe6 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/tusb_option.h b/src/tusb_option.h index cd7a0543f..e1ee45bde 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -171,7 +171,7 @@ // Debug enable to print out error message #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 2 + #define CFG_TUSB_DEBUG 0 #endif // place data in accessible RAM for usb controller -- cgit v1.3.1 From 3f54c27afa39a3b9f2e5911b566416be460389fb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 13:36:03 +0700 Subject: fix audio_test build --- .github/workflows/build.yml | 1 + examples/device/audio_test/.skip.MCU_SAMD11 | 0 examples/device/audio_test/.skip.MCU_SAMG | 0 examples/device/audio_test/src/main.c | 44 +++++++++++++++-------- examples/rules.mk | 1 + src/class/audio/audio.h | 56 ++++++++++++++++++----------- src/class/audio/audio_device.c | 8 +++-- src/class/audio/audio_device.h | 9 ++++- src/common/tusb_common.h | 8 ++--- 9 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 examples/device/audio_test/.skip.MCU_SAMD11 create mode 100644 examples/device/audio_test/.skip.MCU_SAMG (limited to 'src/class') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index da1f9e5e0..a891408ca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,7 @@ jobs: fail-fast: false matrix: example: + - 'device/audio_test' - 'device/board_test' - 'device/cdc_dual_ports' - 'device/cdc_msc' diff --git a/examples/device/audio_test/.skip.MCU_SAMD11 b/examples/device/audio_test/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/audio_test/.skip.MCU_SAMG b/examples/device/audio_test/.skip.MCU_SAMG new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index e55c64c7c..2ea1d36c6 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -137,6 +137,7 @@ void audio_task(void) bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { (void) rhport; + (void) pBuff; // We do not support any set range requests here, only current value requests TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); @@ -146,6 +147,8 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) ep; + return false; // Yet not implemented } @@ -153,6 +156,7 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { (void) rhport; + (void) pBuff; // We do not support any set range requests here, only current value requests TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); @@ -162,6 +166,8 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) itf; + return false; // Yet not implemented } @@ -176,39 +182,43 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + (void) itf; + // We do not support any set range requests here, only current value requests TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if (entityID == 2) + if ( entityID == 2 ) { - switch (ctrlSel) + switch ( ctrlSel ) { case AUDIO_FU_CTRL_MUTE: - // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *)pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; - TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + return true; case AUDIO_FU_CTRL_VOLUME: - // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = ((audio_control_cur_2_t *)pBuff)->bCur; + volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; - TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + return true; - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } } - return false; // Yet not implemented + return false; // Yet not implemented } // Invoked when audio class specific get request received for an EP @@ -221,6 +231,8 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) ep; + // return tud_control_xfer(rhport, p_request, &tmp, 1); return false; // Yet not implemented @@ -236,6 +248,8 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) itf; + return false; // Yet not implemented } diff --git a/examples/rules.mk b/examples/rules.mk index dacb81363..066956a40 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -33,6 +33,7 @@ SRC_C += \ src/common/tusb_fifo.c \ src/device/usbd.c \ src/device/usbd_control.c \ + src/class/audio/audio_device.c \ src/class/cdc/cdc_device.c \ src/class/dfu/dfu_rt_device.c \ src/class/hid/hid_device.c \ diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 7e591fbe6..05e61f8df 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -469,28 +469,44 @@ typedef enum /// Additional Audio Device Class Codes - Source: Audio Data Formats /// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; +//typedef enum +//{ +// AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, +// AUDIO_FORMAT_TYPE_I = 0x01, +// AUDIO_FORMAT_TYPE_II = 0x02, +// AUDIO_FORMAT_TYPE_III = 0x03, +// AUDIO_FORMAT_TYPE_IV = 0x04, +// AUDIO_EXT_FORMAT_TYPE_I = 0x81, +// AUDIO_EXT_FORMAT_TYPE_II = 0x82, +// AUDIO_EXT_FORMAT_TYPE_III = 0x83, +//} audio_format_type_t; + +#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +#define AUDIO_FORMAT_TYPE_I 0x01 +#define AUDIO_FORMAT_TYPE_II 0x02 +#define AUDIO_FORMAT_TYPE_III 0x03 +#define AUDIO_FORMAT_TYPE_IV 0x04 +#define AUDIO_EXT_FORMAT_TYPE_I 0x81 +#define AUDIO_EXT_FORMAT_TYPE_II 0x82 +#define AUDIO_EXT_FORMAT_TYPE_III 0x83 /// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, -} audio_data_format_type_I_t; +//typedef enum +//{ +// AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), +// AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), +// AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), +// AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), +// AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), +// AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, +//} audio_data_format_type_I_t; + +#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) +#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) +#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) +#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) +#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) +#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d208d1c84..0f501bb6e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -564,9 +564,10 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - if (audio->tx_ff[cntChannel].count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) + uint16_t const count = tu_fifo_count(&audio->tx_ff[cntChannel]); + if (count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) { - nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count * CFG_TUD_AUDIO_TX_ITEMSIZE; + nSamplesPerChannelToSend = count * CFG_TUD_AUDIO_TX_ITEMSIZE; } } @@ -782,6 +783,8 @@ void audiod_reset(uint8_t rhport) uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { + (void) max_len; + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); @@ -1171,6 +1174,7 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; + (void) xferred_bytes; // Search for interface belonging to given end point address and proceed as required uint8_t idxDriver; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index f4029a84c..ab223de6f 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,6 @@ #include "device/usbd.h" #include "audio.h" -#include "tusb_config.h" //--------------------------------------------------------------------+ // Class Driver Configuration @@ -59,6 +58,10 @@ #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif +#ifndef CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE +#define CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE 0 +#endif + #if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE #error TX_FIFOs and TX_DMA_RINGBUFFER can not be used simultaneously! #endif @@ -193,6 +196,10 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t #endif */ +#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT +#define CFG_TUD_AUDIO_TX_FIFO_COUNT 1 +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index d95c0ffc4..15892fa33 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -47,10 +47,10 @@ #define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16) #define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16) -#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB -#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff)) -#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff)) -#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB +#define U32_B1_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB +#define U32_B2_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) +#define U32_B3_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) +#define U32_B4_U8(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB #define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32) #define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32) -- cgit v1.3.1 From f700c08aeddd14ab5ae0a02a9eff330c5ae99dea Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 7 Oct 2020 10:57:12 +0200 Subject: Remove CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE which is not needed any more --- src/class/audio/audio_device.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index ab223de6f..d2f8155db 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -58,14 +58,6 @@ #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif -#ifndef CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE -#define CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE 0 -#endif - -#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE -#error TX_FIFOs and TX_DMA_RINGBUFFER can not be used simultaneously! -#endif - #ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE #define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif -- cgit v1.3.1 From db3fe97f62f22747df2c79a841bc1fb235f2f89e Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Wed, 7 Oct 2020 20:36:00 -0500 Subject: fix variable names. add itf n callbacks to multihid --- examples/device/hid_multipleinterface/src/main.c | 6 ++++-- .../hid_multipleinterface/src/usb_descriptors.c | 6 +++--- src/class/hid/hid_device.c | 22 +++++++++++++++++++--- src/class/hid/hid_device.h | 10 +++++++++- 4 files changed, 35 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_multipleinterface/src/main.c b/examples/device/hid_multipleinterface/src/main.c index 2efb1f5cb..b1957b9fc 100644 --- a/examples/device/hid_multipleinterface/src/main.c +++ b/examples/device/hid_multipleinterface/src/main.c @@ -167,9 +167,10 @@ void hid_task(void) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -180,9 +181,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) itf; (void) report_id; (void) report_type; (void) buffer; diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c index a1a98c773..396d22621 100644 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.c +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -83,13 +83,13 @@ uint8_t desc_hid_report2[] = // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index) +uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf) { - if (desc_index == 0) + if (itf == 0) { return desc_hid_report1; } - else if (desc_index == 1) + else if (itf == 1) { return desc_hid_report2; } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 9e1c5fd33..ffd495306 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -67,7 +67,7 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) return NULL; } -static inline uint8_t get_descindex_by_itfnum(uint8_t itf_num) +static inline uint8_t get_hid_index_by_itfnum(uint8_t itf_num) { for (uint8_t i=0; i < CFG_TUD_HID; i++ ) { @@ -230,6 +230,10 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) request->wIndex ); TU_ASSERT(p_hid); + #if CFG_TUD_HID>1 + uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); + #endif + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { //------------- STD Request -------------// @@ -245,8 +249,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { #if CFG_TUD_HID>1 - uint8_t const calculated_desc_index = get_descindex_by_itfnum((uint8_t) request->wIndex); - uint8_t const * desc_report = tud_hid_descriptor_report_cb(calculated_desc_index); + uint8_t const * desc_report = tud_hid_n_descriptor_report_cb(hid_itf); #else uint8_t const * desc_report = tud_hid_descriptor_report_cb(); #endif @@ -268,7 +271,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); + #if CFG_TUD_HID>1 + uint16_t xferlen = tud_hid_n_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + #else uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + #endif TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -336,7 +343,12 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ uint8_t const report_type = tu_u16_high(p_request->wValue); uint8_t const report_id = tu_u16_low(p_request->wValue); + #if CFG_TUD_HID>1 + uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); + tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); + #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); + #endif } return true; @@ -358,7 +370,11 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == p_hid->ep_out) { + #if CFG_TUD_HID>1 + tud_hid_n_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + #else tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + #endif TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 30d99ce47..4b8cb17d5 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -87,7 +87,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete #if CFG_TUD_HID>1 -uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index); +uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf); #else uint8_t const * tud_hid_descriptor_report_cb(void); #endif @@ -95,11 +95,19 @@ uint8_t const * tud_hid_descriptor_report_cb(void); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request +#if CFG_TUD_HID>1 +uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +#else uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +#endif // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) +#if CFG_TUD_HID>1 +void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +#else void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +#endif // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); -- cgit v1.3.1 From 298aa1b669a5c77f991c8161ba4c7d84f7a2b674 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 8 Oct 2020 11:59:12 -0500 Subject: Cleanup per review on PR --- .../device/hid_multipleinterface/src/tusb_config.h | 2 +- .../hid_multipleinterface/src/usb_descriptors.c | 20 ++++++++++---------- src/class/hid/hid_device.c | 4 +++- 3 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_multipleinterface/src/tusb_config.h b/examples/device/hid_multipleinterface/src/tusb_config.h index 9056d5173..412f9b004 100644 --- a/examples/device/hid_multipleinterface/src/tusb_config.h +++ b/examples/device/hid_multipleinterface/src/tusb_config.h @@ -101,7 +101,7 @@ #define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 8 #ifdef __cplusplus } diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c index 396d22621..dd8ef7120 100644 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.c +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -75,7 +75,7 @@ uint8_t const desc_hid_report1[] = TUD_HID_REPORT_DESC_KEYBOARD() }; -uint8_t desc_hid_report2[] = +uint8_t const desc_hid_report2[] = { TUD_HID_REPORT_DESC_MOUSE() }; @@ -86,15 +86,15 @@ uint8_t desc_hid_report2[] = uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf) { if (itf == 0) - { - return desc_hid_report1; - } - else if (itf == 1) - { - return desc_hid_report2; - } - - return 0; + { + return desc_hid_report1; + } + else if (itf == 1) + { + return desc_hid_report2; + } + + return NULL; } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ffd495306..09daa0309 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -74,7 +74,7 @@ static inline uint8_t get_hid_index_by_itfnum(uint8_t itf_num) if ( itf_num == _hidd_itf[i].itf_num ) return i; } - return 0; + return 0xFF; } //--------------------------------------------------------------------+ @@ -232,6 +232,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); + TU_VERIFY(hid_itf<0xFF, 0); #endif if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) @@ -345,6 +346,7 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); + TU_VERIFY(hid_itf<0xFF, 0); tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); -- cgit v1.3.1 From a4ba1f08275bc6fe8ce1f73d24f353861839cce7 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 8 Oct 2020 12:08:13 -0500 Subject: Fix tu_verify args --- src/class/hid/hid_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 09daa0309..45b6aaaca 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -232,7 +232,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf<0xFF, 0); + TU_VERIFY(hid_itf<0xFF); #endif if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) @@ -346,7 +346,7 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); - TU_VERIFY(hid_itf<0xFF, 0); + TU_VERIFY(hid_itf<0xFF); tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); -- cgit v1.3.1 From 13abcb953fcd3d51983e9768619adde776af257e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 20:24:10 +0700 Subject: rename multiple hid callback --- examples/device/hid_multiple_interface/src/main.c | 4 +-- .../hid_multiple_interface/src/usb_descriptors.c | 2 +- src/class/hid/hid_device.c | 8 +++--- src/class/hid/hid_device.h | 32 ++++++++++++---------- 4 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_multiple_interface/src/main.c b/examples/device/hid_multiple_interface/src/main.c index 3599683c5..7cb1d75a7 100644 --- a/examples/device/hid_multiple_interface/src/main.c +++ b/examples/device/hid_multiple_interface/src/main.c @@ -166,7 +166,7 @@ void hid_task(void) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented (void) itf; @@ -180,7 +180,7 @@ uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... (void) itf; diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index dd8ef7120..0d67d499a 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -83,7 +83,7 @@ uint8_t const desc_hid_report2[] = // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { if (itf == 0) { diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 45b6aaaca..b1a4bb8de 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -250,7 +250,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { #if CFG_TUD_HID>1 - uint8_t const * desc_report = tud_hid_n_descriptor_report_cb(hid_itf); + uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); #else uint8_t const * desc_report = tud_hid_descriptor_report_cb(); #endif @@ -273,7 +273,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request uint8_t const report_id = tu_u16_low(request->wValue); #if CFG_TUD_HID>1 - uint16_t xferlen = tud_hid_n_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); #else uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); #endif @@ -347,7 +347,7 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); TU_VERIFY(hid_itf<0xFF); - tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #endif @@ -373,7 +373,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == p_hid->ep_out) { #if CFG_TUD_HID>1 - tud_hid_n_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); #else tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); #endif diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 4b8cb17d5..fc060f0ce 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -84,30 +84,20 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Callbacks (Weak is optional) //--------------------------------------------------------------------+ +#if CFG_TUD_HID > 1 + // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -#if CFG_TUD_HID>1 -uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf); -#else -uint8_t const * tud_hid_descriptor_report_cb(void); -#endif +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -#if CFG_TUD_HID>1 -uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -#else -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -#endif +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -#if CFG_TUD_HID>1 -void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -#else -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -#endif +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); @@ -117,6 +107,18 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); +#else + +uint8_t const * tud_hid_descriptor_report_cb(void); +uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); + +TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); + +#endif + + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ -- cgit v1.3.1 From 8ba0c362ccb72a04ec101610f4b7f9c8577a26da Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 20:51:20 +0700 Subject: update tud_hid_boot_mode_cb/tud_hid_set_idle_cb support mul interfaces also clean up code --- src/class/hid/hid_device.c | 90 ++++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 5 +-- 2 files changed, 50 insertions(+), 45 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b1a4bb8de..11da5f220 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -57,17 +57,7 @@ typedef struct CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID]; /*------------- Helpers -------------*/ -static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i=0; i < CFG_TUD_HID; i++ ) - { - if ( itf_num == _hidd_itf[i].itf_num ) return &_hidd_itf[i]; - } - - return NULL; -} - -static inline uint8_t get_hid_index_by_itfnum(uint8_t itf_num) +static inline uint8_t get_index_by_itfnum(uint8_t itf_num) { for (uint8_t i=0; i < CFG_TUD_HID; i++ ) { @@ -227,13 +217,10 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) request->wIndex ); - TU_ASSERT(p_hid); + uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); + TU_VERIFY(hid_itf < CFG_TUD_HID); - #if CFG_TUD_HID>1 - uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf<0xFF); - #endif + hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { @@ -249,11 +236,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - #if CFG_TUD_HID>1 - uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - #else - uint8_t const * desc_report = tud_hid_descriptor_report_cb(); - #endif + uint8_t const * desc_report = tud_hid_descriptor_report_cb( + #if CFG_TUD_HID > 1 + hid_itf // TODO for backward compatible callback, remove later when appropriate + #endif + ); tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else @@ -272,11 +259,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - #if CFG_TUD_HID>1 - uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); - #else - uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); - #endif + uint16_t xferlen = tud_hid_get_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength + ); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -293,7 +281,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request if ( tud_hid_set_idle_cb ) { // stall request if callback return false - if ( !tud_hid_set_idle_cb(p_hid->idle_rate) ) return false; + TU_VERIFY( tud_hid_set_idle_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->idle_rate) + ); } tud_control_status(rhport, request); @@ -314,7 +307,15 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request case HID_REQ_CONTROL_SET_PROTOCOL: p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol - if (tud_hid_boot_mode_cb) tud_hid_boot_mode_cb(p_hid->boot_mode); + if (tud_hid_boot_mode_cb) + { + tud_hid_boot_mode_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->boot_mode + ); + } tud_control_status(rhport, request); break; @@ -334,8 +335,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { (void) rhport; - hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); - TU_ASSERT(p_hid); + + uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex); + TU_VERIFY(hid_itf < CFG_TUD_HID); + + hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) @@ -344,13 +348,12 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ uint8_t const report_type = tu_u16_high(p_request->wValue); uint8_t const report_id = tu_u16_low(p_request->wValue); - #if CFG_TUD_HID>1 - uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); - TU_VERIFY(hid_itf<0xFF); - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); - #else - tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); - #endif + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength + ); } return true; @@ -372,11 +375,12 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == p_hid->ep_out) { - #if CFG_TUD_HID>1 - tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); - #else - tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); - #endif + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + itf, // TODO for backward compatible callback, remove later when appropriate + #endif + 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes + ); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index fc060f0ce..d5b5b7296 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -100,15 +100,16 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); +TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); #else +// TODO for backward compatible callback, remove later when appropriate uint8_t const * tud_hid_descriptor_report_cb(void); uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -- cgit v1.3.1 From 032e84c9befa0797f6a6faf86fbfdff13ec77bbe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 19:50:05 +0200 Subject: Revert dcd_alloc_mem_for_conf() but keep changes from @kasjer for ISO EP Add tud_audio_set_itf_close_EP_cb() --- src/class/audio/audio_device.c | 6 +- src/class/audio/audio_device.h | 3 + src/device/dcd.h | 4 - src/device/usbd.c | 3 - src/portable/st/synopsys/dcd_synopsys.c | 469 ++++++++------------------------ 5 files changed, 115 insertions(+), 370 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0f501bb6e..2c8ba300d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -876,6 +876,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? } #endif @@ -928,7 +932,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - // Invoke callback and trigger data generation - if not already running + // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d2f8155db..d86232720 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -272,6 +272,9 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c // Invoked when audio set interface request received TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +// Invoked when audio set interface request received which closes an EP +TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); + // Invoked when audio class specific set request received for an EP TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); diff --git a/src/device/dcd.h b/src/device/dcd.h index c00e3c06d..776f782b8 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -115,10 +115,6 @@ void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; -// Invoked when a set configuration request was received -// Helper to allow for dynamic EP buffer allocation according to configuration descriptor -TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg); - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index d6d77dff2..90edc3dde 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -786,9 +786,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); - // Allow for dynamic allocation of EP buffer for current configuration - only one configuration may be active according to USB specification - if (dcd_alloc_mem_for_conf) TU_ASSERT(dcd_alloc_mem_for_conf(rhport, desc_cfg)); - // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5a89bb386..ca306ff8f 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -47,53 +47,53 @@ #if TUSB_OPT_DEVICE_ENABLED && \ ( (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ ) // EP_MAX : Max number of bi-directional endpoints including EP0 // EP_FIFO_SIZE : Size of dedicated USB SRAM #if CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - #define EP_MAX_FS 4 - #define EP_FIFO_SIZE_FS 1280 +#include "stm32f1xx.h" +#define EP_MAX_FS 4 +#define EP_FIFO_SIZE_FS 1280 #elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE +#include "stm32f2xx.h" +#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE - #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE +#include "stm32f4xx.h" +#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE +#define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - #define EP_MAX_FS 9 - #define EP_FIFO_SIZE_FS 4096 - #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 +#include "stm32h7xx.h" +#define EP_MAX_FS 9 +#define EP_FIFO_SIZE_FS 4096 +#define EP_MAX_HS 9 +#define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 - #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 +#include "stm32f7xx.h" +#define EP_MAX_FS 6 +#define EP_FIFO_SIZE_FS 1280 +#define EP_MAX_HS 9 +#define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 +#include "stm32l4xx.h" +#define EP_MAX_FS 6 +#define EP_FIFO_SIZE_FS 1280 #else - #error "Unsupported MCUs" +#error "Unsupported MCUs" #endif @@ -105,16 +105,16 @@ // On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS #if TUD_OPT_RHPORT == 0 - #define EP_MAX EP_MAX_FS - #define EP_FIFO_SIZE EP_FIFO_SIZE_FS - #define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE - #define RHPORT_IRQn OTG_FS_IRQn +#define EP_MAX EP_MAX_FS +#define EP_FIFO_SIZE EP_FIFO_SIZE_FS +#define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE +#define RHPORT_IRQn OTG_FS_IRQn #else - #define EP_MAX EP_MAX_HS - #define EP_FIFO_SIZE EP_FIFO_SIZE_HS - #define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE - #define RHPORT_IRQn OTG_HS_IRQn +#define EP_MAX EP_MAX_HS +#define EP_FIFO_SIZE EP_FIFO_SIZE_HS +#define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE +#define RHPORT_IRQn OTG_HS_IRQn #endif #define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) @@ -145,7 +145,7 @@ typedef struct TU_ATTR_PACKED { // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt - ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! + ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! } ep_sz_tt_report_t; typedef volatile uint32_t * usb_fifo_t; @@ -167,7 +167,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - // USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -217,93 +217,28 @@ static void bus_reset(uint8_t rhport) // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to // overwrite this. - // We rework this here and initialize the FIFOs here only for the USB reset case. The rest is done once a - // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. - - // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size - _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) - - // _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) +#if TUD_OPT_HIGH_SPEED + _allocated_fifo_words = 271 + 2*EP_MAX; +#else + _allocated_fifo_words = 47 + 2*EP_MAX; +#endif usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (CFG_TUD_ENDPOINT0_SIZE/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += CFG_TUD_ENDPOINT0_SIZE/4; + _allocated_fifo_words += 16; - // Set SETUP packet count to 3 - out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - - usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + // TU_LOG2_INT(_allocated_fifo_words); + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - //#if TUD_OPT_HIGH_SPEED - // _allocated_fifo_words = 271 + 2*EP_MAX; - //#else - // _allocated_fifo_words = 47 + 2*EP_MAX; - //#endif - // - // usb_otg->GRXFSIZ = _allocated_fifo_words; - // - // // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - // usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - // - // _allocated_fifo_words += 16; - // - // // TU_LOG2_INT(_allocated_fifo_words); - // - // // Fixed control EP0 size to 64 bytes - // in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - // xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - // - // // Set SETUP packet count to 3 - // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - // - // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; -} - -// Required after new configuration received in case EP0 max packet size has changed -static void set_EP0_max_pkt_size(void) -{ - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - - uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL. - switch (enum_spd) - { - case 0x00: // High speed - always 64 byte - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - break; - - case 0x03: // Full speed -#if CFG_TUD_ENDPOINT0_SIZE == 64 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; -#elif CFG_TUD_ENDPOINT0_SIZE == 32 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; -#elif CFG_TUD_ENDPOINT0_SIZE == 16 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; -#elif CFG_TUD_ENDPOINT0_SIZE == 8 - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; -#else -# error CFG_TUD_ENDPOINT0_SIZE MUST be 8, 16, 32, or 64! -#endif - break; + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - default: // Low speed - always 8 bytes - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } // Set turn-around timeout according to link speed @@ -536,8 +471,8 @@ void dcd_init (uint8_t rhport) if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; @@ -594,7 +529,7 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { -// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -620,15 +555,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if(dir == TUSB_DIR_OUT) { out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); } else { - // FIFO allocation done in dcd_alloc_mem_for_conf() - // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // @@ -654,35 +587,35 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // - Interrupt is EPSize // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) -// uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; -// uint16_t fifo_size = desc_edpt->wMaxPacketSize.size / 4; -// -// if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) -// { -// uint8_t opened = 0; -// for(uint8_t i = 0; i < EP_MAX; i++) -// { -// if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; -// } -// -// // EP Size or equally divided of remaining whichever is larger -// fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); -// } -// -// // FIFO overflows, we probably need a better allocating scheme -// TU_ASSERT(fifo_size <= fifo_remaining); -// -// // DIEPTXF starts at FIFO #1. -// // Both TXFD and TXSA are in unit of 32-bit words. -// usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; -// -// _allocated_fifo_words += fifo_size; + uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; + uint16_t fifo_size = (desc_edpt->wMaxPacketSize.size + 3) / 4; // +3 for rounding up to next full word + + if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) + { + uint8_t opened = 0; + for(uint8_t i = 0; i < EP_MAX; i++) + { + if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; + } + + // EP Size or equally divided of remaining whichever is larger + fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); + } + + // FIFO overflows, we probably need a better allocating scheme + TU_ASSERT(fifo_size <= fifo_remaining); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += fifo_size; in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | - (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); + (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); } @@ -780,7 +713,20 @@ static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) */ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_disable(rhport, ep_addr, false); + if (dir == TUSB_DIR_IN) + { + uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; + uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; + // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. + TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); + _allocated_fifo_words -= fifo_size; + } } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -892,7 +838,7 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ switch(pktsts) { case 0x01: // Global OUT NAK (Interrupt) - break; + break; case 0x02: // Out packet recvd { @@ -920,18 +866,18 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ case 0x04: // Setup packet done (Interrupt) out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - break; + break; case 0x06: // Setup packet recvd // We can receive up to three setup packets in succession, but // only the last one is valid. _setup_packet[0] = (* rx_fifo); _setup_packet[1] = (* rx_fifo); - break; + break; default: // Invalid TU_BREAKPOINT(); - break; + break; } } @@ -1049,9 +995,6 @@ void dcd_int_handler(uint8_t rhport) tusb_speed_t const speed = get_speed(rhport); set_turnaround(usb_otg, speed); - - set_EP0_max_pkt_size(); - dcd_event_bus_reset(rhport, speed, true); } @@ -1115,209 +1058,11 @@ void dcd_int_handler(uint8_t rhport) handle_epin_ints(rhport, dev, in_ep); } - // Check for Incomplete isochronous IN transfer - if(int_status & USB_OTG_GINTSTS_IISOIXFR) { - TU_LOG2(" IISOIXFR!\r\n"); - } -} - -// Helper function which parses through the current configuration descriptors to find the biggest EPs in size. -static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg, ep_sz_tt_report_t * p_report) -{ - (void) rhport; - - // tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! - - // EP0 sizes and usages are fixed - p_report->ep_size[0][TUSB_DIR_OUT] = p_report->ep_size[0][TUSB_DIR_IN] = CFG_TUD_ENDPOINT0_SIZE; - p_report->ep_transfer_type[0][TUSB_DIR_OUT][TUSB_XFER_CONTROL] = p_report->ep_transfer_type[0][TUSB_DIR_IN][TUSB_XFER_CONTROL] = true; - - // Parse interface descriptor - uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; - - uint8_t addr; - - while( p_desc < desc_end ) - { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) - { - - addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - // Verify values - this checks may be omitted in case we trust the descriptors to be okay - TU_VERIFY(tu_edpt_number(addr) < EP_MAX); - TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); - TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); - - p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); - p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; - } - p_desc = tu_desc_next(p_desc); // Proceed - } - return true; -} - -// Setup FIFO buffers at configuration time. -// The idea is to use this information such that the FIFOs need to be configured only once -// at configuration time and no more later. This makes it easy in case you want to close and open EPs for different -// purposes at any time (without taking care of other active EPs). You also avoid the nasty need of defragmenting -// the TX buffers, which is likely to happen. -// Certainly, this function does not allow for the highest possible flexibility as it only works in the worst case -// (all biggest EPs can be active at the same time). However, this should not be a problem for almost all applications. - -// Spare space is assigned equally divided to bulk and interrupt EPs. -// Pure isochronous EPs do not get any spare space as it does not make any sense. -TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg) -{ - (void) rhport; - - USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - - // for(uint8_t n = 0; n < EP_MAX; n++) { - // out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - // } - - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - - // Deactivate Interrupts? - dev->DAINTMSK &= ~((1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos)); - dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); - dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); - - // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); - - // Determine maximum required spaces for individual EPs and what kind of usage (control, bulk, etc.) they are used for - ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type - TU_VERIFY(get_ep_size_report(rhport, desc_cfg, &report)); - - // With that information, set the following up: - // The RX buffer size (as it is a shared buffer here) is set to the sum of the two biggest out EPs plus all the required extra words used for setup packets etc. - // This should work well for all kinds of applications - - // Determine number of used out EPs of current configuration and size of two biggest out EPs - uint8_t nUsedOutEPs = 0, cnt_ep, cnt_tt; - uint16_t sz[2] = {0, 0}; - uint16_t fifo_depth; - - for (cnt_ep = 0; cnt_ep < EP_MAX; cnt_ep++) - { - for (cnt_tt = 0; cnt_tt <= TUSB_XFER_INTERRUPT; cnt_tt++) - { - if (report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt]) - { - nUsedOutEPs++; - break; - } - } - - fifo_depth = report.ep_size[cnt_ep][TUSB_DIR_OUT] / 4 + 1; - if (sz[0] < fifo_depth) - { - sz[1] = sz[0]; - sz[0] = fifo_depth; - } - else if (sz[1] < report.ep_size[cnt_ep][TUSB_DIR_OUT]) - { - sz[1] = fifo_depth; - } - } - - // For configuration use the approach as explained in bus_reset() - _allocated_fifo_words = 13 + 1 + 1 + 2 * nUsedOutEPs + sz[0] + sz[1] + 2; // again, i do not really know why we need + 2 but otherwise it does not work - - usb_otg->GRXFSIZ = _allocated_fifo_words; - - // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) - fifo_depth = report.ep_size[0][TUSB_DIR_IN] / 4; - fifo_depth = tu_max16(16, fifo_depth); - usb_otg->DIEPTXF0_HNPTXFSIZ = (fifo_depth << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - - _allocated_fifo_words += fifo_depth; - - // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: - // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. - // Furthermore, double buffering is not possible (for this silicon) since once FIFO was written to and transmit bit was set you are - // not allowed to write to the FIFO any more until transmit was done. So you can not send something and buffer the next frame in the - // meantime into the buffer. TODO: check for high speed and uC types which can do this! - // - Interrupt EPs only get EP size as FIFO size - // - Bulk and control (other than EP0 - this is possible) get spare space equally divided - those profit the most from extra space - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + w + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + w + GRXFSIZ - // | IN FIFO 1 | - // --------------- w + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // In FIFO is allocated by following rules: - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - // - Offset: allocated so far - // - Size - as described above - - // Determine required numbers - // Remaining space available in bytes - uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; - - // Required space by EPs in words, number of bulk and control EPs - uint16_t ep_sz_total = 0; - // Number of bulk and control EPs - uint8_t nbc = 0; - // EP0 is already taken care of so exclude that here - for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) - { - fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4; // Since we need full words take care of remainders! - if (fifo_depth > 0 && fifo_depth < 16) fifo_depth = 16; // Minimum FIFO depth is 16 - ep_sz_total += fifo_depth; - nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); - } - - if (ep_sz_total > fifo_remaining) - { - // Too less space available to apply this allocation scheme - return false and set a flag such that a different approach may be used TODO: introduce flag - return false; - } - - uint16_t extra_space = nbc > 0 ? (fifo_remaining - ep_sz_total) / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused - - // Setup FIFOs - for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) - { - // If EP is used - if (report.ep_size[cnt_ep][TUSB_DIR_IN] > 0) - { - fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4 + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0); - fifo_depth = tu_max16(16, fifo_depth); - usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_depth << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += fifo_depth; - } - } - - // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; - - // Enable interrupts - dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); - dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; - dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; - - // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; - - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_CNAK; - - return true; +// // Check for Incomplete isochronous IN transfer +// if(int_status & USB_OTG_GINTSTS_IISOIXFR) { +// printf(" IISOIXFR!\r\n"); +//// TU_LOG2(" IISOIXFR!\r\n"); +// } } #endif -- cgit v1.3.1 From 9c07a2a4e23e4d82e3cbb28e92bf1234e4a6ce09 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 00:07:51 +0700 Subject: rework msc host - msc host enum is now async - implement async tuh_msc_scsi_command() / tuh_msc_request_sense() / tuh_msc_test_unit_ready() --- examples/host/cdc_msc_hid/src/msc_app.c | 15 +- src/class/msc/msc_host.c | 407 ++++++++++++++++++-------------- src/class/msc/msc_host.h | 75 ++---- src/host/usbh_control.c | 1 - 4 files changed, 252 insertions(+), 246 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 62bd961c1..53f0e6ac2 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -38,6 +38,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) printf("A MassStorage device is mounted\r\n"); //------------- Disk Information -------------// +#if 0 // SCSI VendorID[8] & ProductID[16] from Inquiry Command uint8_t const* p_vendor = tuh_msc_get_vendor_name(dev_addr); uint8_t const* p_product = tuh_msc_get_product_name(dev_addr); @@ -47,6 +48,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) putchar(' '); for(uint8_t i=0; i<16; i++) putchar(p_product[i]); putchar('\n'); +#endif uint32_t last_lba = 0; uint32_t block_size = 0; @@ -103,12 +105,11 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr) // } } -// invoked ISR context -void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) dev_addr; - (void) event; - (void) xferred_bytes; -} +//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +//{ +// (void) dev_addr; +// (void) cbw; +// (void) csw; +//} #endif diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index f47bbd163..e8bed989c 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -37,19 +37,41 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX]; +enum +{ + MSC_STAGE_IDLE = 0, + MSC_STAGE_CMD, + MSC_STAGE_DATA, + MSC_STAGE_STATUS, +}; + +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + uint8_t max_lun; + + scsi_read_capacity10_resp_t capacity; + + volatile bool is_initialized; + uint8_t vendor_id[8]; + uint8_t product_id[16]; + + uint8_t stage; + void* buffer; + tuh_msc_complete_cb_t complete_cb; + + msc_cbw_t cbw; + msc_csw_t csw; +}msch_interface_t; -//------------- Initalization Data -------------// -static osal_semaphore_def_t msch_sem_def; -static osal_semaphore_t msch_sem_hdl; +CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX]; // buffer used to read scsi information when mounted, largest response data currently is inquiry CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)]; -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ @@ -65,25 +87,17 @@ bool tuh_msc_is_busy(uint8_t dev_addr) hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); } -uint8_t const* tuh_msc_get_vendor_name(uint8_t dev_addr) +bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) { - return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL; -} + msch_interface_t* p_msc = &msch_data[dev_addr-1]; -uint8_t const* tuh_msc_get_product_name(uint8_t dev_addr) -{ - return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL; -} + if ( !p_msc->is_initialized ) return false; + TU_ASSERT(p_last_lba != NULL && p_block_size != NULL); -tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) -{ - if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED; - TU_ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA); + (*p_last_lba) = p_msc->capacity.last_lba; + (*p_block_size) = p_msc->capacity.block_size; - (*p_last_lba) = msch_data[dev_addr-1].last_lba; - (*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size; - - return TUSB_ERROR_NONE; + return true; } //--------------------------------------------------------------------+ @@ -92,30 +106,27 @@ tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32 static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) { p_cbw->signature = MSC_CBW_SIGNATURE; - p_cbw->tag = 0xCAFECAFE; + p_cbw->tag = 0x54555342; // TUSB p_cbw->lun = lun; } -static tusb_error_t msch_command_xfer(uint8_t dev_addr, msch_interface_t * p_msch, void* p_buffer) +bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { - if ( NULL != p_buffer) - { // there is data phase - if (p_msch->cbw.dir & TUSB_DIR_IN_MASK) - { - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cbw_t), false), TUSB_ERROR_FAILED ); - TU_ASSERT( hcd_pipe_queue_xfer(dev_addr, p_msch->ep_in , p_buffer, p_msch->cbw.total_bytes), TUSB_ERROR_FAILED ); - }else - { - TU_ASSERT( hcd_pipe_queue_xfer(dev_addr, p_msch->ep_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cbw_t)), TUSB_ERROR_FAILED ); - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_out , p_buffer, p_msch->cbw.total_bytes, false), TUSB_ERROR_FAILED ); - } - } + msch_interface_t* p_msc = &msch_data[dev_addr-1]; - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_in , (uint8_t*) &p_msch->csw, sizeof(msc_csw_t), true), TUSB_ERROR_FAILED); + // TODO claim endpoint - return TUSB_ERROR_NONE; + p_msc->cbw = *cbw; + p_msc->stage = MSC_STAGE_CMD; + p_msc->buffer = data; + p_msc->complete_cb = complete_cb; + + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); + + return true; } +#if 0 tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; @@ -127,7 +138,7 @@ tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); //------------- SCSI command -------------// - scsi_inquiry_t cmd_inquiry = + scsi_inquiry_t const cmd_inquiry = { .cmd_code = SCSI_CMD_INQUIRY, .alloc_length = sizeof(scsi_inquiry_resp_t) @@ -135,88 +146,51 @@ tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_data) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t); - - //------------- SCSI command -------------// - scsi_read_capacity10_t cmd_read_capacity10 = - { - .cmd_code = SCSI_CMD_READ_CAPACITY_10, - .lba = 0, - .partial_medium_indicator = 0 - }; - - memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_data) ); + TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_data) ); return TUSB_ERROR_NONE; } +#endif -tusb_error_t tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { - (void) lun; // TODO [MSCH] multiple lun support - - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - p_msch->cbw.total_bytes = 18; - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t); + msc_cbw_t cbw = { 0 }; + msc_cbw_add_signature(&cbw, lun); - //------------- SCSI command -------------// - scsi_request_sense_t cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; + cbw.total_bytes = 0; // Number of bytes + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification - memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb)); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_data) ); - - return TUSB_ERROR_NONE; + return true; } -tusb_error_t tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_csw_t * p_csw) +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; + msc_cbw_t cbw = { 0 }; + msc_cbw_add_signature(&cbw, lun); - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.total_bytes = 0; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_OUT; - p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.total_bytes = 18; // TODO sense response + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_request_sense_t); - //------------- SCSI command -------------// - scsi_test_unit_ready_t cmd_test_unit_ready = + scsi_request_sense_t const cmd_request_sense = { - .cmd_code = SCSI_CMD_TEST_UNIT_READY, - .lun = lun // according to wiki + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 }; - memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len); + memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - // TODO MSCH refractor test uinit ready - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cbw_t), false), TUSB_ERROR_FAILED ); - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_in , (uint8_t*) p_csw, sizeof(msc_csw_t), true), TUSB_ERROR_FAILED ); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb)); - return TUSB_ERROR_NONE; + return true; } +#if 0 tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; @@ -229,7 +203,7 @@ tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uin p_msch->cbw.cmd_len = sizeof(scsi_read10_t); //------------- SCSI command -------------// - scsi_read10_t cmd_read10 = + scsi_read10_t cmd_read10 =msch_sem_hdl { .cmd_code = SCSI_CMD_READ_10, .lba = tu_htonl(lba), @@ -238,7 +212,7 @@ tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uin memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_buffer)); + TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer)); return TUSB_ERROR_NONE; } @@ -264,10 +238,11 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, (void*) p_buffer)); + TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer)); return TUSB_ERROR_NONE; } +#endif //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) @@ -275,9 +250,75 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe void msch_init(void) { tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); - msch_sem_hdl = osal_semaphore_create(&msch_sem_def); } + +void msch_close(uint8_t dev_addr) +{ + tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback +} + +static bool get_csw(uint8_t dev_addr, msch_interface_t * p_msc) +{ + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); + return true; +} + +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msc_cbw_t const * cbw = &p_msc->cbw; + msc_csw_t * csw = &p_msc->csw; + + switch (p_msc->stage) + { + case MSC_STAGE_CMD: + // Must be Command Block + TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); + + if ( cbw->total_bytes && p_msc->buffer ) + { + // Data stage if any + p_msc->stage = MSC_STAGE_DATA; + + uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; + TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, cbw->total_bytes)); + }else + { + // Status stage + get_csw(dev_addr, p_msc); + } + break; + + case MSC_STAGE_DATA: + get_csw(dev_addr, p_msc); + break; + + case MSC_STAGE_STATUS: + // SCSI op is complete + p_msc->stage = MSC_STAGE_IDLE; + + if (p_msc->complete_cb) p_msc->complete_cb(dev_addr, cbw, csw); + break; + + // unknown state + default: break; + } + + return true; +} + +//--------------------------------------------------------------------+ +// MSC Enumeration +//--------------------------------------------------------------------+ + +static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); + bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && @@ -311,30 +352,52 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 1 + tusb_control_request_t request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 1 }; - // TODO STALL means zero - TU_ASSERT( usbh_control_xfer( dev_addr, &request, msch_buffer ) ); - p_msc->max_lun = msch_buffer[0]; + TU_ASSERT(tuh_control_xfer(dev_addr, &request, msch_buffer, open_get_maxlun_complete)); -#if 0 - //------------- Reset -------------// - request = (tusb_control_request_t) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 + return true; +} + +static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + + // STALL means zero + p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + + // MSCU Reset +#if 0 // not really needed + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = MSC_REQ_RESET, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 0 }; - TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); + TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); #endif - enum { SCSI_XFER_TIMEOUT = 2000 }; +#if 0 //------------- SCSI Inquiry -------------// TU_LOG2("SCSI Inquiry\r\n"); tusbh_msc_inquiry(dev_addr, 0, msch_buffer); @@ -342,77 +405,63 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it memcpy(p_msc->vendor_id , ((scsi_inquiry_resp_t*) msch_buffer)->vendor_id , 8); memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); +#endif - //------------- SCSI Read Capacity 10 -------------// - TU_LOG2("SCSI Read Capacity 10\r\n"); - tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); + // TODO multiple LUN support + TU_LOG2("SCSI Test Unit Ready\r\n"); + tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); - // NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence - // Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work - if ( hcd_edpt_stalled(dev_addr, p_msc->ep_in) ) + return true; +} + +static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + if (csw->status == 0) { - // clear stall TODO abstract clear stall function - request = (tusb_control_request_t) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_ENDPOINT, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, - .bRequest = TUSB_REQ_CLEAR_FEATURE, - .wValue = 0, - .wIndex = p_msc->ep_in, - .wLength = 0 - }; - - TU_ASSERT(usbh_control_xfer( dev_addr, &request, NULL )); - - hcd_edpt_clear_stall(dev_addr, p_msc->ep_in); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); // wait for SCSI status - - //------------- SCSI Request Sense -------------// - (void) tuh_msc_request_sense(dev_addr, 0, msch_buffer); - TU_ASSERT(osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); - - //------------- Re-read SCSI Read Capactity -------------// - tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); - TU_ASSERT(osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); - } + TU_LOG2("SCSI Read Capacity 10\r\n"); - p_msc->last_lba = tu_ntohl( ((scsi_read_capacity10_resp_t*)msch_buffer)->last_lba ); - p_msc->block_size = (uint16_t) tu_ntohl( ((scsi_read_capacity10_resp_t*)msch_buffer)->block_size ); + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msc_cbw_t new_cbw = { 0 }; - p_msc->is_initialized = true; + msc_cbw_add_signature(&new_cbw, cbw->lun); + new_cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); + new_cbw.dir = TUSB_DIR_IN_MASK; + new_cbw.cmd_len = sizeof(scsi_read_capacity10_t); + new_cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - tuh_msc_mounted_cb(dev_addr); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &new_cbw, &p_msc->capacity, open_read_capacity10_complete)); + }else + { + // Note: During enumeration, some device fails Test Unit Ready and require a few retries + // with Request Sense to start working !! + // TODO limit number of retries + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, open_request_sense_complete)); + } return true; } -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - if ( ep_addr == p_msc->ep_in ) - { - if (p_msc->is_initialized) - { - tuh_msc_isr(dev_addr, event, xferred_bytes); - }else - { // still initializing under open subtask - osal_semaphore_post(msch_sem_hdl, true); - } - } - + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); return true; } -void msch_close(uint8_t dev_addr) +static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { - tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); - osal_semaphore_reset(msch_sem_hdl); + TU_ASSERT(csw->status == 0); - tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback -} + msch_interface_t* p_msc = &msch_data[dev_addr-1]; -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ + // Note: Block size and last LBA are big-endian + p_msc->capacity.last_lba = tu_ntohl(p_msc->capacity.last_lba); + p_msc->capacity.block_size = tu_ntohl(p_msc->capacity.block_size); + // Enumeration is complete + p_msc->is_initialized = true; // open complete TODO remove + tuh_msc_mounted_cb(dev_addr); + + return true; +} #endif diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index a32134215..03231d17f 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -40,6 +40,9 @@ * \defgroup MSC_Host Host * The interface API includes status checking function, data transferring function and callback functions * @{ */ + +typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); + //--------------------------------------------------------------------+ // MASS STORAGE Application API //--------------------------------------------------------------------+ @@ -60,23 +63,9 @@ bool tuh_msc_is_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); -/** \brief Get SCSI vendor's name of MassStorage device - * \param[in] dev_addr device address - * \return pointer to vendor's name or NULL if specified device does not support MassStorage - * \note SCSI vendor's name is 8-byte length field in \ref scsi_inquiry_data_t. During enumeration, the stack has already - * retrieved (via SCSI INQUIRY) and store this information internally. There is no need for application to re-send SCSI INQUIRY - * command or allocate buffer for this. - */ -uint8_t const* tuh_msc_get_vendor_name(uint8_t dev_addr); +bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -/** \brief Get SCSI product's name of MassStorage device - * \param[in] dev_addr device address - * \return pointer to product's name or NULL if specified device does not support MassStorage - * \note SCSI product's name is 16-byte length field in \ref scsi_inquiry_data_t. During enumeration, the stack has already - * retrieved (via SCSI INQUIRY) and store this information internally. There is no need for application to re-send SCSI INQUIRY - * command or allocate buffer for this. - */ -uint8_t const* tuh_msc_get_product_name(uint8_t dev_addr); +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_t len); /** \brief Get SCSI Capacity of MassStorage device * \param[in] dev_addr device address @@ -87,8 +76,10 @@ uint8_t const* tuh_msc_get_product_name(uint8_t dev_addr); * retrieved (via SCSI READ CAPACITY 10) and store this information internally. There is no need for application * to re-send SCSI READ CAPACITY 10 command */ -tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); +bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); + +#if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit @@ -116,29 +107,25 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function */ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count); +#endif /** \brief Perform SCSI REQUEST SENSE command, used to retrieve sense data from MassStorage device * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit * \param[in] p_data Buffer to store response's data from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \note This function is non-blocking and returns immediately. + * Callback is invoked when command is complete */ -tusb_error_t tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data); +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); /** \brief Perform SCSI TEST UNIT READY command to test if MassStorage device is ready * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \note This function is non-blocking and returns immediately. + * Callback is invoked when command is complete */ -tusb_error_t tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_csw_t * p_csw); // TODO to be refractor +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); + //tusb_error_t tusbh_msc_scsi_send(uint8_t dev_addr, uint8_t lun, bool is_direction_in, // uint8_t const * p_command, uint8_t cmd_len, @@ -157,39 +144,9 @@ void tuh_msc_mounted_cb(uint8_t dev_addr); */ void tuh_msc_unmounted_cb(uint8_t dev_addr); -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \param[in] xferred_bytes Number of bytes transferred via USB bus - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note - */ -void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); - - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t max_lun; - uint16_t block_size; - uint32_t last_lba; // last logical block address - - volatile bool is_initialized; - uint8_t vendor_id[8]; - uint8_t product_id[16]; - - msc_cbw_t cbw; - msc_csw_t csw; -}msch_interface_t; void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 70800eba6..de55bd5e1 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -88,7 +88,6 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu (void) ep_addr; (void) xferred_bytes; - usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; -- cgit v1.3.1 From 437ccac6968b9c31446756c49524f7306ef2acd8 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 13:23:33 +0700 Subject: implement tuh_msc_scsi_inquiry() / tuh_msc_read_capacity() / tuh_msc_get_maxlun() --- examples/host/cdc_msc_hid/src/msc_app.c | 62 ++++++++++---- examples/obsolete/host/src/msc_host_app.c | 2 +- src/class/msc/msc_host.c | 131 +++++++++++------------------- src/class/msc/msc_host.h | 6 +- 4 files changed, 96 insertions(+), 105 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 53f0e6ac2..a45fba737 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -30,31 +30,59 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +static scsi_inquiry_resp_t inquiry_resp; +static scsi_read_capacity10_resp_t capacity_resp; +uint32_t block_size; +uint32_t block_count; + +bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + (void) dev_addr; + (void) cbw; + + if (csw->status != 0) + { + printf("Read Capacity (10) failed\r\n"); + return false; + } + + // Capacity response field: Block size and Last LBA are both Big-Endian + block_count = tu_ntohl(capacity_resp.last_lba) + 1; + block_size = tu_ntohl(capacity_resp.block_size); + + printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + + return true; +} + +bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + if (csw->status != 0) + { + printf("Inquiry failed\r\n"); + return false; + } + + // Print out Vendor ID, Product ID and Rev + printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + + // Read capacity of device + tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb); + + return true; +} //------------- IMPLEMENTATION -------------// void tuh_msc_mounted_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); - //------------- Disk Information -------------// -#if 0 - // SCSI VendorID[8] & ProductID[16] from Inquiry Command - uint8_t const* p_vendor = tuh_msc_get_vendor_name(dev_addr); - uint8_t const* p_product = tuh_msc_get_product_name(dev_addr); - - for(uint8_t i=0; i<8; i++) putchar(p_vendor[i]); - - putchar(' '); - for(uint8_t i=0; i<16; i++) putchar(p_product[i]); - putchar('\n'); -#endif + block_size = block_count = 0; - uint32_t last_lba = 0; - uint32_t block_size = 0; - tuh_msc_get_capacity(dev_addr, &last_lba, &block_size); - printf("Disk Size: %ld MB\r\n", (last_lba+1)/ ((1024*1024)/block_size) ); - printf("LBA 0-0x%lX Block Size: %ld\r\n", last_lba, block_size); + uint8_t const lun = 0; + tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // // //------------- file system (only 1 LUN support) -------------// // uint8_t phy_disk = dev_addr-1; diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c index 77747b536..8afb6ede8 100644 --- a/examples/obsolete/host/src/msc_host_app.c +++ b/examples/obsolete/host/src/msc_host_app.c @@ -64,7 +64,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) putchar('\n'); uint32_t last_lba, block_size; - tuh_msc_get_capacity(dev_addr, &last_lba, &block_size); + tuh_msc_read_capacity(dev_addr, &last_lba, &block_size); printf("Disk Size: %d MB\n", (last_lba+1)/ ((1024*1024)/block_size) ); printf("LBA 0-0x%X Block Size: %d\n", last_lba, block_size); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e8bed989c..7a46b6866 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -53,11 +53,7 @@ typedef struct uint8_t max_lun; - scsi_read_capacity10_resp_t capacity; - volatile bool is_initialized; - uint8_t vendor_id[8]; - uint8_t product_id[16]; uint8_t stage; void* buffer; @@ -75,6 +71,11 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_i //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) +{ + return msch_data[dev_addr-1].max_lun; +} + bool tuh_msc_is_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && // is configured can be omitted @@ -87,19 +88,6 @@ bool tuh_msc_is_busy(uint8_t dev_addr) hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); } -bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) -{ - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - - if ( !p_msc->is_initialized ) return false; - TU_ASSERT(p_last_lba != NULL && p_block_size != NULL); - - (*p_last_lba) = p_msc->capacity.last_lba; - (*p_block_size) = p_msc->capacity.block_size; - - return true; -} - //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ @@ -126,33 +114,46 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu return true; } -#if 0 -tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + if ( !p_msc->is_initialized ) return false; - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); + msc_cbw_t cbw = { 0 }; + + msc_cbw_add_signature(&cbw, lun); + cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read_capacity10_t); + cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; + + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); + + return true; +} + +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) +{ + msc_cbw_t cbw = { 0 }; + + msc_cbw_add_signature(&cbw, lun); + cbw.total_bytes = sizeof(scsi_inquiry_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_inquiry_t); - //------------- SCSI command -------------// scsi_inquiry_t const cmd_inquiry = { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_resp_t) }; + memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_data) ); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - return TUSB_ERROR_NONE; + return true; } -#endif -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { msc_cbw_t cbw = { 0 }; msc_cbw_add_signature(&cbw, lun); @@ -252,20 +253,12 @@ void msch_init(void) tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); } - void msch_close(uint8_t dev_addr) { tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback } -static bool get_csw(uint8_t dev_addr, msch_interface_t * p_msc) -{ - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - return true; -} - bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; @@ -288,12 +281,15 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 }else { // Status stage - get_csw(dev_addr, p_msc); + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); } break; case MSC_STAGE_DATA: - get_csw(dev_addr, p_msc); + // Status stage + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); break; case MSC_STAGE_STATUS: @@ -317,7 +313,6 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -331,9 +326,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) @@ -378,6 +371,7 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c // STALL means zero p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + p_msc->max_lun++; // MAX LUN is minus 1 by specs // MSCU Reset #if 0 // not really needed @@ -397,16 +391,6 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); #endif -#if 0 - //------------- SCSI Inquiry -------------// - TU_LOG2("SCSI Inquiry\r\n"); - tusbh_msc_inquiry(dev_addr, 0, msch_buffer); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); - - memcpy(p_msc->vendor_id , ((scsi_inquiry_resp_t*) msch_buffer)->vendor_id , 8); - memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); -#endif - // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); @@ -418,18 +402,11 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw { if (csw->status == 0) { - TU_LOG2("SCSI Read Capacity 10\r\n"); - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - msc_cbw_t new_cbw = { 0 }; - - msc_cbw_add_signature(&new_cbw, cbw->lun); - new_cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - new_cbw.dir = TUSB_DIR_IN_MASK; - new_cbw.cmd_len = sizeof(scsi_read_capacity10_t); - new_cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &new_cbw, &p_msc->capacity, open_read_capacity10_complete)); + // Unit is ready, Enumeration is complete + p_msc->is_initialized = true; // open complete TODO remove + tuh_msc_mounted_cb(dev_addr); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries @@ -442,25 +419,9 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw } static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); - return true; -} - -static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - - // Note: Block size and last LBA are big-endian - p_msc->capacity.last_lba = tu_ntohl(p_msc->capacity.last_lba); - p_msc->capacity.block_size = tu_ntohl(p_msc->capacity.block_size); - - // Enumeration is complete - p_msc->is_initialized = true; // open complete TODO remove - tuh_msc_mounted_cb(dev_addr); - + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); return true; } diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 03231d17f..63b4753b1 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -63,9 +63,11 @@ bool tuh_msc_is_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); + bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_t len); +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); /** \brief Get SCSI Capacity of MassStorage device * \param[in] dev_addr device address @@ -77,7 +79,7 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_ * to re-send SCSI READ CAPACITY 10 command */ -bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device -- cgit v1.3.1 From d92d1a03ca2df69856f02c64ae88d805d60ad088 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 13:45:22 +0700 Subject: clean up --- src/class/msc/msc_host.c | 97 +++++++++++++++++++++++++----------------------- src/class/msc/msc_host.h | 5 ++- 2 files changed, 55 insertions(+), 47 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7a46b6866..8bf240ac7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -53,7 +53,7 @@ typedef struct uint8_t max_lun; - volatile bool is_initialized; + volatile bool mounted; uint8_t stage; void* buffer; @@ -68,24 +68,32 @@ CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX] // buffer used to read scsi information when mounted, largest response data currently is inquiry CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)]; +static inline msch_interface_t* get_itf(uint8_t dev_addr) +{ + return &msch_data[dev_addr-1]; +} + //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) { - return msch_data[dev_addr-1].max_lun; + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->max_lun; } -bool tuh_msc_is_mounted(uint8_t dev_addr) +bool tuh_msc_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && // is configured can be omitted - msch_data[dev_addr-1].is_initialized; + msch_interface_t* p_msc = get_itf(dev_addr); + + // is configured can be omitted + return tuh_device_is_configured(dev_addr) && p_msc->mounted; } bool tuh_msc_is_busy(uint8_t dev_addr) { - return msch_data[dev_addr-1].is_initialized && - hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ @@ -100,7 +108,8 @@ static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); // TODO claim endpoint @@ -116,8 +125,8 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - if ( !p_msc->is_initialized ) return false; + msch_interface_t* p_msc = get_itf(dev_addr); + if ( !p_msc->mounted ) return false; msc_cbw_t cbw = { 0 }; @@ -127,9 +136,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r cbw.cmd_len = sizeof(scsi_read_capacity10_t); cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); } bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) @@ -148,9 +155,7 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* re }; memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); } bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) @@ -164,9 +169,7 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; cbw.command[1] = lun; // according to wiki TODO need verification - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); } bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) @@ -186,12 +189,11 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); } #if 0 + tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; @@ -245,6 +247,27 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe } #endif +#if 0 +// MSC interface Reset (not used now) +bool tuh_msc_reset(uint8_t dev_addr) +{ + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = MSC_REQ_RESET, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 0 + }; + TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); +} +#endif + //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -261,7 +284,7 @@ void msch_close(uint8_t dev_addr) bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); msc_cbw_t const * cbw = &p_msc->cbw; msc_csw_t * csw = &p_msc->csw; @@ -319,7 +342,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); //------------- Open Data Pipe -------------// tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -358,7 +381,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it .wIndex = p_msc->itf_num, .wLength = 1 }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, msch_buffer, open_get_maxlun_complete)); + TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, open_get_maxlun_complete)); return true; } @@ -367,30 +390,12 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c { (void) request; - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); // STALL means zero p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; p_msc->max_lun++; // MAX LUN is minus 1 by specs - // MSCU Reset -#if 0 // not really needed - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 - }; - TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); -#endif - // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); @@ -402,10 +407,10 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw { if (csw->status == 0) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); // Unit is ready, Enumeration is complete - p_msc->is_initialized = true; // open complete TODO remove + p_msc->mounted = true; tuh_msc_mounted_cb(dev_addr); }else { diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 63b4753b1..827311063 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -51,7 +51,10 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms * \retval true if device supports * \retval false if device does not support or is not mounted */ -bool tuh_msc_is_mounted(uint8_t dev_addr); + +// Check if device supports MassStorage interface. +// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() +bool tuh_msc_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address -- cgit v1.3.1 From 3623f578a4b9c75b61b1c7a7d0c0c3ff2440e690 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 14:00:25 +0700 Subject: more clean up --- src/class/msc/msc_host.c | 5 ++-- src/class/msc/msc_host.h | 60 ++++++++++++------------------------------------ src/host/usbh.c | 5 +++- 3 files changed, 22 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 8bf240ac7..83423cfc7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -109,7 +109,7 @@ static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); + // TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command // TODO claim endpoint @@ -278,7 +278,8 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { - tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + msch_interface_t* p_msc = get_itf(dev_addr); + tu_memclr(p_msc, sizeof(msch_interface_t)); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback } diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 827311063..06b1067cc 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -44,13 +44,8 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); //--------------------------------------------------------------------+ -// MASS STORAGE Application API +// Application API //--------------------------------------------------------------------+ -/** \brief Check if device supports MassStorage interface or not - * \param[in] dev_addr device address - * \retval true if device supports - * \retval false if device does not support or is not mounted - */ // Check if device supports MassStorage interface. // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() @@ -66,22 +61,24 @@ bool tuh_msc_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); +// Get Max Lun uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); +// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner. +// `complete_cb` callback is invoked when SCSI op is complete. +// return true if success, false if there is already pending operation. bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); +// Carry out SCSI INQUIRY command in non-blocking manner. bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); -/** \brief Get SCSI Capacity of MassStorage device - * \param[in] dev_addr device address - * \param[out] p_last_lba Last Logical Block Address of device - * \param[out] p_block_size Block Size of device in bytes - * \retval pointer to product's name or NULL if specified device does not support MassStorage - * \note MassStorage's capacity can be computed by last LBA x block size (in bytes). During enumeration, the stack has already - * retrieved (via SCSI READ CAPACITY 10) and store this information internally. There is no need for application - * to re-send SCSI READ CAPACITY 10 command - */ +// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); + +// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); +// Carry out SCSI READ CAPACITY (10) command in non-blocking manner. bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 @@ -114,39 +111,12 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count); #endif -/** \brief Perform SCSI REQUEST SENSE command, used to retrieve sense data from MassStorage device - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \param[in] p_data Buffer to store response's data from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \note This function is non-blocking and returns immediately. - * Callback is invoked when command is complete - */ -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); - -/** \brief Perform SCSI TEST UNIT READY command to test if MassStorage device is ready - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \note This function is non-blocking and returns immediately. - * Callback is invoked when command is complete - */ -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); - - -//tusb_error_t tusbh_msc_scsi_send(uint8_t dev_addr, uint8_t lun, bool is_direction_in, -// uint8_t const * p_command, uint8_t cmd_len, -// uint8_t * p_response, uint32_t resp_len); - //------------- Application Callback -------------// -/** \brief Callback function that will be invoked when a device with MassStorage interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ + +// Invoked when a device with MassStorage interface is mounted void tuh_msc_mounted_cb(uint8_t dev_addr); -/** \brief Callback function that will be invoked when a device with MassStorage interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ +// Invoked when a device with MassStorage interface is unmounted void tuh_msc_unmounted_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index 595024b9c..7d1201aa4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -880,9 +880,12 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura } else { + TU_LOG2("%s open\r\n", driver->name); + uint16_t itf_len = 0; - TU_LOG2("%s open\r\n", driver->name); + // TODO class driver can perform control transfer when opening which is + // non-blocking --> need a way to coordinate composite device TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; -- cgit v1.3.1 From f5b72f5796554910e14040cf747d6eea9505ee1a Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 24 Oct 2020 17:29:47 -0500 Subject: net_device: tweak 'pbuf chain' implementation --- src/class/net/net_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 1d7f9ce3a..238d64d81 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -374,8 +374,8 @@ static void handle_incoming_packet(uint32_t len) if (p) { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ memcpy(p->payload, pnt, size); - p->len = size; accepted = tud_network_recv_cb(p); if (!accepted) pbuf_free(p); @@ -441,11 +441,13 @@ void tud_network_xmit(struct pbuf *p) len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; data = transmitted + len; + /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ for(q = p; q != NULL; q = q->next) { memcpy(data, (char *)q->payload, q->len); data += q->len; len += q->len; + if (q->len == q->tot_len) break; } if (!_netd_itf.ecm_mode) -- cgit v1.3.1 From a097b7e51aac7fc92708e1bc536e84a9ec2af3ec Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 24 Oct 2020 20:27:57 -0500 Subject: net_device: re-factor code so as to not be specific to lwIP --- examples/device/net_lwip_webserver/src/main.c | 40 ++++++++++++++++++++++++--- src/class/net/net_device.c | 30 ++------------------ src/class/net/net_device.h | 15 +++++----- 3 files changed, 47 insertions(+), 38 deletions(-) (limited to 'src/class') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 020f4e4d6..27adce86f 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -99,7 +99,7 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) /* if the network driver can accept another packet, we make it happen */ if (tud_network_can_xmit()) { - tud_network_xmit(p); + tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; } @@ -152,17 +152,49 @@ bool dns_query_proc(const char *name, ip_addr_t *addr) return false; } -bool tud_network_recv_cb(struct pbuf *p) +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ if (received_frame) return false; - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; + if (size) + { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + + if (p) + { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ + memcpy(p->payload, src, size); + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + } + } + return true; } +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) +{ + struct pbuf *p = (struct pbuf *)ref; + struct pbuf *q; + uint16_t len = 0; + + (void)arg; /* unused for this example */ + + /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ + for(q = p; q != NULL; q = q->next) + { + memcpy(dst, (char *)q->payload, q->len); + dst += q->len; + len += q->len; + if (q->len == q->tot_len) break; + } + + return len; +} + static void service_traffic(void) { /* handle any packet received by tud_network_recv_cb() */ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 238d64d81..65fd1ab53 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -366,23 +366,7 @@ static void handle_incoming_packet(uint32_t len) } } - bool accepted = false; - - if (size) - { - struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - - if (p) - { - /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ - memcpy(p->payload, pnt, size); - accepted = tud_network_recv_cb(p); - - if (!accepted) pbuf_free(p); - } - } - - if (!accepted) + if (!tud_network_recv_cb(pnt, size)) { /* if a buffer was never handled by user code, we must renew on the user's behalf */ tud_network_recv_renew(); @@ -429,9 +413,8 @@ bool tud_network_can_xmit(void) return can_xmit; } -void tud_network_xmit(struct pbuf *p) +void tud_network_xmit(void *ref, uint16_t arg) { - struct pbuf *q; uint8_t *data; uint16_t len; @@ -441,14 +424,7 @@ void tud_network_xmit(struct pbuf *p) len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; data = transmitted + len; - /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ - for(q = p; q != NULL; q = q->next) - { - memcpy(data, (char *)q->payload, q->len); - data += q->len; - len += q->len; - if (q->len == q->tot_len) break; - } + len += tud_network_xmit_cb(data, ref, arg); if (!_netd_itf.ecm_mode) { diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 0175ea56b..795b2f9e3 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -32,15 +32,13 @@ #include "device/usbd.h" #include "class/cdc/cdc.h" -// TODO should not include external files -#include "lwip/pbuf.h" -#include "netif/ethernet.h" - /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ #define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) /* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ -#define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) +#ifndef CFG_TUD_NET_MTU +#define CFG_TUD_NET_MTU 1514 +#endif #ifdef __cplusplus extern "C" { @@ -54,7 +52,10 @@ void tud_network_init_cb(void); // client must provide this: return false if the packet buffer was not accepted -bool tud_network_recv_cb(struct pbuf *p); +bool tud_network_recv_cb(const uint8_t *src, uint16_t size); + +// client must provide this: copy from network stack packet pointer to dst +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); // client must provide this: 48-bit MAC address // TODO removed later since it is not part of tinyusb stack @@ -67,7 +68,7 @@ void tud_network_recv_renew(void); bool tud_network_can_xmit(void); // if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(struct pbuf *p); +void tud_network_xmit(void *ref, uint16_t arg); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API -- cgit v1.3.1 From 3ea813875034be8878d3f01a740c377ebb6c8306 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 31 Oct 2020 10:57:53 -0600 Subject: Rename CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL This was a confusing name; "Ethernet control model" (CDC ECM) and "network control model" (CDC NCM) are two separate USB subclasses. --- src/class/cdc/cdc.h | 2 +- src/class/net/net_device.c | 6 +++--- src/device/usbd.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f0488acbb..2c044ac7f 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -63,7 +63,7 @@ typedef enum CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL , ///< Telephone Control Model [USBPSTN1.2] CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL , ///< Multi-Channel Control Model [USBISDN1.2] CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL , ///< ATM Networking Control Model [USBATM1.2] CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL , ///< Wireless Handset Control Model [USBWMC1.1] CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT , ///< Device Management [USBWMC1.1] diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 65fd1ab53..3a45a9b99 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -141,9 +141,9 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); - bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0x00 == itf_desc->bInterfaceProtocol); + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); TU_VERIFY(is_rndis || is_ecm, 0); diff --git a/src/device/usbd.h b/src/device/usbd.h index d48f37eb0..0a446fdc2 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -554,9 +554,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, 0,\ /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, _desc_stridx,\ /* CDC-ECM Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC-ECM Union */\ -- cgit v1.3.1 From e029d6d7263f4a848c5150a567512f3990358b3f Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 1 Nov 2020 17:46:46 +0700 Subject: added host set_config driver to resolve control conflict with SET_CONFIGURE for class driver - open will be called to open endpoint only - set_config called later to initialized class driver --- src/class/hid/hid_host.c | 91 +++++++++++++++++++++++++++++------------------- src/class/hid/hid_host.h | 1 + src/class/msc/msc_host.c | 32 +++++++++++------ src/class/msc/msc_host.h | 1 + src/host/usbh.c | 46 +++++++++++++++++++----- src/host/usbh.h | 12 ++++--- src/host/usbh_hcd.h | 3 +- 7 files changed, 126 insertions(+), 60 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 5058191f4..a96eb6276 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -173,39 +173,6 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); - // SET IDLE = 0 request - // Device can stall if not support this request - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, - .wLength = 0 - }; - - // stall is a valid response for SET_IDLE, therefore we could ignore result of this request - tuh_control_xfer(dev_addr, &request, NULL, NULL); - -#if 0 - //------------- Get Report Descriptor TODO HID parser -------------// - if ( p_desc_hid->bNumDescriptors ) - { - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), - TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, - p_desc_hid->wReportLength, report_descriptor ), - error - ); - (void) error; // if error in getting report descriptor --> treating like there is none - } -#endif - if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD @@ -213,7 +180,6 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); - tuh_hid_keyboard_mounted_cb(dev_addr); } else #endif @@ -222,7 +188,6 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); - tuh_hid_mouse_mounted_cb(dev_addr); } else #endif @@ -241,6 +206,62 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c return true; } +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) +{ +#if 0 + //------------- Get Report Descriptor TODO HID parser -------------// + if ( p_desc_hid->bNumDescriptors ) + { + STASK_INVOKE( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), + TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, + p_desc_hid->wReportLength, report_descriptor ), + error + ); + (void) error; // if error in getting report descriptor --> treating like there is none + } +#endif + +#if 0 + // SET IDLE = 0 request + // Device can stall if not support this request + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = 0, // idle_rate = 0 + .wIndex = p_interface_desc->bInterfaceNumber, + .wLength = 0 + }; + + // stall is a valid response for SET_IDLE, therefore we could ignore result of this request + tuh_control_xfer(dev_addr, &request, NULL, NULL); +#endif + + usbh_driver_set_config_complete(dev_addr, itf_num); + +#if CFG_TUH_HID_KEYBOARD + if ( keyboardh_data[dev_addr-1].itf_num == itf_num) + { + tuh_hid_keyboard_mounted_cb(dev_addr); + } +#endif + +#if CFG_TUH_HID_MOUSE + if ( mouseh_data[dev_addr-1].ep_in == itf_num ) + { + tuh_hid_mouse_mounted_cb(dev_addr); + } +#endif + + return true; +} + bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 324dad203..5c77398f8 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -197,6 +197,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ void hidh_init(void); bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 83423cfc7..02ca81e77 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -334,9 +334,9 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -367,6 +367,14 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_msc->itf_num = itf_desc->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + return true; +} + +bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_ASSERT(p_msc->itf_num == itf_num); + //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); tusb_control_request_t request = @@ -379,15 +387,15 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it }, .bRequest = MSC_REQ_GET_MAX_LUN, .wValue = 0, - .wIndex = p_msc->itf_num, + .wIndex = itf_num, .wLength = 1 }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, open_get_maxlun_complete)); + TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete)); return true; } -static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { (void) request; @@ -399,17 +407,19 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); - tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); + tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete); return true; } -static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { if (csw->status == 0) { msch_interface_t* p_msc = get_itf(dev_addr); + usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); + // Unit is ready, Enumeration is complete p_msc->mounted = true; tuh_msc_mounted_cb(dev_addr); @@ -418,16 +428,16 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, open_request_sense_complete)); + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete)); } return true; } -static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { TU_ASSERT(csw->status == 0); - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete)); return true; } diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 06b1067cc..5913350b8 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -125,6 +125,7 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr); void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 7d1201aa4..3e321652b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -67,6 +67,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, + .set_config = msch_set_config, .xfer_cb = msch_xfer_cb, .close = msch_close }, @@ -78,6 +79,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open_subtask, + .set_config = hidh_set_config, .xfer_cb = hidh_xfer_cb, .close = hidh_close }, @@ -308,6 +310,7 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const usbh_device_t* dev = &_usbh_devices[dev_addr]; // new endpoints belongs to latest interface (last valid value) + // TODO FIXME not true with ISO uint8_t drvid = 0xff; for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) { @@ -525,6 +528,31 @@ static uint8_t get_new_address(void) return CFG_TUSB_HOST_DEVICE_MAX+1; } +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) + { + // continue with next valid interface + uint8_t const drv_id = dev->itf2drv[itf_num]; + if (drv_id != 0xff) + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + TU_LOG2("%s set config itf = %u\r\n", driver->name, itf_num); + driver->set_config(dev_addr, itf_num); + break; + } + } + + // all interface are configured + if (itf_num == sizeof(dev->itf2drv)) + { + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + } +} + //--------------------------------------------------------------------+ // Enumeration Process // is a lengthy process with a seires of control transfer to configure @@ -783,6 +811,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), .wIndex = 0, .wLength = total_len + }; TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); @@ -795,6 +824,10 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); + // Parse configuration & set up drivers + // Driver open aren't allowed to make any usb transfer yet + parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + TU_LOG2("Set Configuration Descriptor\r\n"); tusb_control_request_t const new_request = { @@ -825,12 +858,10 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co dev->configured = 1; dev->state = TUSB_DEVICE_STATE_CONFIGURED; - // Parse configuration & set up drivers - // TODO driver open still use usbh_control_xfer - parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); + // Start the Set Configuration process for interfaces (itf = 0xff) + // Since driver can perform control transfer within its set_config, this is done asynchronously. + // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + usbh_driver_set_config_complete(dev_addr, 0xff); return true; } @@ -883,9 +914,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura TU_LOG2("%s open\r\n", driver->name); uint16_t itf_len = 0; - - // TODO class driver can perform control transfer when opening which is - // non-blocking --> need a way to coordinate composite device TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; diff --git a/src/host/usbh.h b/src/host/usbh.h index fde1dd11c..19ab72f54 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -58,10 +58,11 @@ typedef struct { uint8_t class_code; - void (* const init) (void); - bool (* const open)(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close) (uint8_t); + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -105,6 +106,7 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // CLASS-USBH & INTERNAL API +// TODO move to usbh_pvt.h //--------------------------------------------------------------------+ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -116,6 +118,8 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 20348eed1..79b547fb3 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -47,6 +47,8 @@ //--------------------------------------------------------------------+ // USBH-HCD common data structure //--------------------------------------------------------------------+ + +// TODO move to usbh.c typedef struct { //------------- port -------------// uint8_t rhport; @@ -95,7 +97,6 @@ typedef struct { // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUH_EP_MAX][2]; - // Mutex for claiming endpoint, only needed when using with preempted RTOS #if CFG_TUSB_OS != OPT_OS_NONE osal_mutex_def_t mutexdef; -- cgit v1.3.1 From 14461beffa4f2e12bc37d523701be65fabd0d8ce Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 09:19:34 +0700 Subject: remove legacy blocking usbh_control_xfer() reworking cdc host driver --- src/class/cdc/cdc_host.c | 50 +++++++++++++++++++++++++++++++++--------------- src/class/cdc/cdc_host.h | 13 +++++++++++++ src/host/usbh.c | 48 +--------------------------------------------- src/host/usbh_hcd.h | 10 ---------- 4 files changed, 49 insertions(+), 72 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index ae1eef8a7..a897fb58a 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -51,9 +51,14 @@ typedef struct { //--------------------------------------------------------------------+ static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX]; +static inline cdch_data_t* get_itf(uint8_t dev_addr) +{ + return &cdch_data[dev_addr-1]; +} + bool tuh_cdc_mounted(uint8_t dev_addr) { - cdch_data_t* cdc = &cdch_data[dev_addr-1]; + cdch_data_t* cdc = get_itf(dev_addr); return cdc->ep_in && cdc->ep_out; } @@ -61,7 +66,7 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) { if ( !tuh_cdc_mounted(dev_addr) ) return false; - cdch_data_t const * p_cdc = &cdch_data[dev_addr-1]; + cdch_data_t const * p_cdc = get_itf(dev_addr); switch (pipeid) { @@ -111,6 +116,27 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify); } +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) +{ + cdch_data_t const * p_cdc = get_itf(dev_addr); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), + .wIndex = p_cdc->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, complete_cb) ); + return true; +} + //--------------------------------------------------------------------+ // USBH-CLASS DRIVER API //--------------------------------------------------------------------+ @@ -132,7 +158,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it cdch_data_t * p_cdc; p_desc = tu_desc_next(itf_desc); - p_cdc = &cdch_data[dev_addr-1]; + p_cdc = get_itf(dev_addr); p_cdc->itf_num = itf_desc->bInterfaceNumber; p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com @@ -194,18 +220,12 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it } } - // FIXME move to seperate API : connect - tusb_control_request_t request = - { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = 0x03, // dtr on, cst on - .wIndex = p_cdc->itf_num, - .wLength = 0 - }; - - TU_ASSERT( usbh_control_xfer(dev_addr, &request, NULL) ); + return true; +} +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + (void) dev_addr; (void) itf_num; return true; } @@ -218,7 +238,7 @@ bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void cdch_close(uint8_t dev_addr) { - cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; + cdch_data_t * p_cdc = get_itf(dev_addr); tu_memclr(p_cdc, sizeof(cdch_data_t)); } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index f28a0a713..66c2f0727 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -44,6 +44,18 @@ * \defgroup CDC_Serial_Host Host * @{ */ +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb); + +static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +{ + return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); +} + +static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +{ + return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); +} + /** \brief Check if device support CDC Serial interface or not * \param[in] dev_addr device address * \retval true if device supports @@ -113,6 +125,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ void cdch_init(void); bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 61db0d8b0..e7347ff56 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -56,6 +56,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, + .set_config = cdch_set_config, .xfer_cb = cdch_xfer_cb, .close = cdch_close }, @@ -174,9 +175,6 @@ bool tuh_init(void) { usbh_device_t * const dev = &_usbh_devices[i]; - dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def); - TU_ASSERT(dev->control.sem_hdl != NULL); - #if CFG_TUSB_OS != OPT_OS_NONE dev->mutex = osal_mutex_create(&dev->mutexdef); TU_ASSERT(dev->mutex); @@ -199,38 +197,6 @@ bool tuh_init(void) return true; } -//------------- USBH control transfer -------------// - -// TODO remove -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data) -{ - usbh_device_t* dev = &_usbh_devices[dev_addr]; - const uint8_t rhport = dev->rhport; - - dev->control.request = *request; - dev->control.pipe_status = 0; - - // Setup Stage - hcd_setup_send(rhport, dev_addr, (uint8_t*) &dev->control.request); - TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - - // Data stage : first data toggle is always 1 - if ( request->wLength ) - { - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), data, request->wLength); - TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - } - - // Status : data toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); - TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - - if ( XFER_RESULT_STALLED == dev->control.pipe_status ) return false; - if ( XFER_RESULT_FAILED == dev->control.pipe_status ) return false; - - return true; -} - bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -291,9 +257,6 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) { - osal_semaphore_reset( _usbh_devices[dev_addr].control.sem_hdl ); - //osal_mutex_reset( usbh_devices[dev_addr].control.mutex_hdl ); - tusb_desc_endpoint_t ep0_desc = { .bLength = sizeof(tusb_desc_endpoint_t), @@ -349,15 +312,6 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) // interrupt caused by a TD (with IOC=1) in pipe of class class_code void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { - usbh_device_t* dev = &_usbh_devices[ dev_addr ]; - - if (0 == tu_edpt_number(ep_addr)) - { - dev->control.pipe_status = result; -// usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary - osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR - } - hcd_event_t event = { .rhport = 0, // TODO correct rhport diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index dd0616704..abc7fd250 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -75,16 +75,6 @@ typedef struct { volatile uint8_t state; // device state, value from enum tusbh_device_state_t - //------------- control pipe -------------// - struct { - volatile uint8_t pipe_status; -// uint8_t xferred_bytes; TODO not yet necessary - tusb_control_request_t request; - - osal_semaphore_def_t sem_def; - osal_semaphore_t sem_hdl; // used to synchronize with HCD when control xfer complete - } control; - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) -- cgit v1.3.1 From 6fcd540cb68483b1b1b25344a1a5e4560c77e276 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 16:50:46 +0700 Subject: enable cdc auto flush on write() if there is enough data in the fifo --- README.md | 2 +- src/class/cdc/cdc_device.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/README.md b/README.md index 05f3521c4..072dfc841 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![tinyUSB_240x100](https://user-images.githubusercontent.com/249515/62646655-f9393200-b978-11e9-9c53-484862f15503.png) -[![Build Status](https://github.com/hathach/tinyusb/workflows/Build/badge.svg)](https://github.com/hathach/tinyusb/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) [![Coverity](https://img.shields.io/coverity/scan/458.svg)](https://scan.coverity.com/projects/tinyusb) +[![Build Status](https://github.com/hathach/tinyusb/workflows/Build/badge.svg)](https://github.com/hathach/tinyusb/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function. diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e39adc5fa..e54b7d260 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -34,6 +34,11 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +enum +{ + BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) +}; + typedef struct { uint8_t itf_num; @@ -160,13 +165,11 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); -#if 0 // TODO issue with circuitpython's REPL - // flush if queue more than endpoint size - if ( tu_fifo_count(&p_cdc->tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) + // flush if queue more than packet size + if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE ) { tud_cdc_n_write_flush(itf); } -#endif return ret; } @@ -250,8 +253,8 @@ void cdcd_reset(uint8_t rhport) uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass - TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Note: 0xFF can be used with RNDIS TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); @@ -446,9 +449,8 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( 0 == tud_cdc_n_write_flush(itf) ) { // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size - if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) + // xferred_bytes is multiple of EP Packet size and not zero + if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) { if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) { -- cgit v1.3.1 From 54e29e9ff451d5e30eb59d0411adbe5d4993c59b Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Wed, 18 Nov 2020 09:42:50 +0100 Subject: Implementation of the discussed changes - remove usbd_edpt_xfer_abort - rename tu_fifo_change_mode to tu_fifo_set_mode - remove CFG_TUD_CDC_CLEAR_AT_CONNECTION definition - remove auto fifo clear at connection event - add tud_cdc_n_write_clear function --- src/class/cdc/cdc_device.c | 21 +++++++++++---------- src/class/cdc/cdc_device.h | 13 +++++++++---- src/common/tusb_fifo.c | 4 +++- src/common/tusb_fifo.h | 2 +- src/device/usbd.c | 27 --------------------------- src/device/usbd_pvt.h | 3 --- 6 files changed, 24 insertions(+), 46 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 7eace24ff..2d0aed238 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -207,6 +207,10 @@ uint32_t tud_cdc_n_write_available (uint8_t itf) return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); } +bool tud_cdc_n_write_clear (uint8_t itf) +{ + return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); +} //--------------------------------------------------------------------+ // USBD Driver API @@ -229,6 +233,9 @@ void cdcd_init(void) // config fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + // tx fifo is set to overwritable at initialization and will be changed to not overwritable + // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. + // In this way, the most current data is prioritized. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); #if CFG_FIFO_MUTEX @@ -384,20 +391,14 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool const dtr = tu_bit_test(request->wValue, 0); bool const rts = tu_bit_test(request->wValue, 1); -#if CFG_TUD_CDC_CLEAR_AT_CONNECTION - // DTE connected event (if DTE supports DTR bit) - if ( dtr && !tu_bit_test(p_cdc->line_state, 0) ) - { - // Clear not transmitted data - usbd_edpt_xfer_abort(rhport, p_cdc->ep_in); - tu_fifo_clear(&p_cdc->tx_ff); - } -#endif + // TODO if terminal supports DTR we can check for an connection event here and + // clear the fifo as well as ongoing transfers with new usbd_edpt_xfer_abort api. + // Until then user can self clear the buffer with tud_cdc_n_write_clear in tud_cdc_line_state_cb p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set - tu_fifo_change_mode(&p_cdc->tx_ff, (dtr?false:true)); + tu_fifo_set_mode(&p_cdc->tx_ff, !dtr); TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 3bd2741bc..342025961 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -43,10 +43,6 @@ #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif -#ifndef CFG_TUD_CDC_CLEAR_AT_CONNECTION - #define CFG_TUD_CDC_CLEAR_AT_CONNECTION 0 -#endif - #ifdef __cplusplus extern "C" { #endif @@ -106,6 +102,9 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf); // Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. uint32_t tud_cdc_n_write_available (uint8_t itf); +// Clear the transmit FIFO +bool tud_cdc_n_write_clear (uint8_t itf); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -125,6 +124,7 @@ static inline uint32_t tud_cdc_write (void const* buffer, uint32_t buf static inline uint32_t tud_cdc_write_str (char const* str); static inline uint32_t tud_cdc_write_flush (void); static inline uint32_t tud_cdc_write_available (void); +static inline bool tud_cdc_write_clear (void); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -234,6 +234,11 @@ static inline uint32_t tud_cdc_write_available(void) return tud_cdc_n_write_available(0); } +static inline bool tud_cdc_write_clear(void) +{ + return tud_cdc_n_write_clear(0); +} + /** @} */ /** @} */ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 470e26b77..444c60f96 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -603,9 +603,11 @@ bool tu_fifo_clear(tu_fifo_t *f) @param[in] f Pointer to the FIFO buffer to manipulate + @param[in] overwritable + Overwritable mode the fifo is set to */ /******************************************************************************/ -bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable) +bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable) { tu_fifo_lock(f); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 603a74609..abb301b5f 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -89,7 +89,7 @@ typedef struct .non_used_index_space = 0xFFFF - 2*_depth-1, \ } -bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable); +bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); diff --git a/src/device/usbd.c b/src/device/usbd.c index 8d3fbac59..90edc3dde 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1191,33 +1191,6 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - TU_LOG2(" Abort XFER EP %02X ... ", ep_addr); - - // Abort API is optional for DCD - if ( dcd_edpt_xfer_abort ) - { - if ( dcd_edpt_xfer_abort(rhport, ep_addr) ) - { - _usbd_dev.ep_status[epnum][dir].busy = false; - TU_LOG2("OK\r\n"); - return true; - }else - { - TU_LOG2("failed\r\n"); - return false; - } - }else - { - TU_LOG2("no DCD support\r\n"); - return false; - } -} - bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 4eb17a501..09b285581 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,9 +70,6 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Abort a scheduled transfer -bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); - // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 3c31d0805130e9551f97afae94f765b5d032991b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 21:01:33 +0700 Subject: merge class driver control_request & control_complete to control_xfer_cb() migrated msc_device --- src/class/msc/msc_device.c | 19 ++++++------------- src/class/msc/msc_device.h | 3 +-- src/common/tusb_types.h | 7 +++++++ src/device/usbd.c | 39 +++++++++++++++++++-------------------- src/device/usbd.h | 2 +- src/device/usbd_control.c | 8 ++++---- src/device/usbd_pvt.h | 5 ++++- 7 files changed, 42 insertions(+), 41 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index f3f2e536e..cfb8a43a3 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -186,10 +186,14 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request) { + // nothing to do with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) return true; + // Handle class request only TU_VERIFY(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -219,17 +223,6 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque return true; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool mscd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - (void) request; - - // nothing to do - return true; -} - // return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) // In case of a failed status, sense key must be set for reason of failure int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 3aa93ffd7..f1e6c40f4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -161,8 +161,7 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); void mscd_init (void); void mscd_reset (uint8_t rhport); uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d6b6ea627..5ab15aa3c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -250,6 +250,13 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; +enum +{ + CONTROL_STAGE_SETUP, + CONTROL_STAGE_DATA, + CONTROL_STAGE_ACK +}; + //--------------------------------------------------------------------+ // USB Descriptors //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 90edc3dde..02f631dea 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -97,7 +97,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, - .control_request = cdcd_control_request, + .control_xfer_cb = cdcd_control_request, .control_complete = cdcd_control_complete, .xfer_cb = cdcd_xfer_cb, .sof = NULL @@ -110,8 +110,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = mscd_init, .reset = mscd_reset, .open = mscd_open, - .control_request = mscd_control_request, - .control_complete = mscd_control_complete, + .control_xfer_cb = mscd_control_xfer_cb, .xfer_cb = mscd_xfer_cb, .sof = NULL }, @@ -123,7 +122,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = hidd_init, .reset = hidd_reset, .open = hidd_open, - .control_request = hidd_control_request, + .control_xfer_cb = hidd_control_request, .control_complete = hidd_control_complete, .xfer_cb = hidd_xfer_cb, .sof = NULL @@ -134,9 +133,9 @@ static usbd_class_driver_t const _usbd_driver[] = { DRIVER_NAME("AUDIO") .init = audiod_init, - .reset = audiod_reset, + .reset = audiod_reset, .open = audiod_open, - .control_request = audiod_control_request, + .control_xfer_cb = audiod_control_request, .control_complete = audiod_control_complete, .xfer_cb = audiod_xfer_cb, .sof = NULL @@ -149,7 +148,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = midid_init, .open = midid_open, .reset = midid_reset, - .control_request = midid_control_request, + .control_xfer_cb = midid_control_request, .control_complete = midid_control_complete, .xfer_cb = midid_xfer_cb, .sof = NULL @@ -162,7 +161,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = vendord_init, .reset = vendord_reset, .open = vendord_open, - .control_request = tud_vendor_control_request_cb, + .control_xfer_cb = tud_vendor_control_request_cb, .control_complete = tud_vendor_control_complete_cb, .xfer_cb = vendord_xfer_cb, .sof = NULL @@ -175,7 +174,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, - .control_request = usbtmcd_control_request_cb, + .control_xfer_cb = usbtmcd_control_request_cb, .control_complete = usbtmcd_control_complete_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL @@ -188,7 +187,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, - .control_request = dfu_rtd_control_request, + .control_xfer_cb = dfu_rtd_control_request, .control_complete = dfu_rtd_control_complete, .xfer_cb = dfu_rtd_xfer_cb, .sof = NULL @@ -201,7 +200,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = netd_init, .reset = netd_reset, .open = netd_open, - .control_request = netd_control_request, + .control_xfer_cb = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, .sof = NULL, @@ -214,7 +213,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = btd_init, .reset = btd_reset, .open = btd_open, - .control_request = btd_control_request, + .control_xfer_cb = btd_control_request, .control_complete = btd_control_complete, .xfer_cb = btd_xfer_cb, .sof = NULL @@ -274,7 +273,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); @@ -313,12 +312,12 @@ static char const* const _tusb_std_request_str[] = }; // for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) +void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { usbd_class_driver_t const * driver = get_driver(i); - if ( driver->control_complete == control_complete ) + if ( driver->control_xfer_cb == callback ) { TU_LOG2(" %s control complete\r\n", driver->name); return; @@ -565,9 +564,9 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { - usbd_control_set_complete_callback(driver->control_complete); + usbd_control_set_complete_callback(driver->control_xfer_cb); TU_LOG2(" %s control request\r\n", driver->name); - return driver->control_request(rhport, request); + return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); } // This handles the actual request and its response. @@ -581,10 +580,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_request_cb); + TU_VERIFY(tud_vendor_control_xfer_cb); - if (tud_vendor_control_complete_cb) usbd_control_set_complete_callback(tud_vendor_control_complete_cb); - return tud_vendor_control_request_cb(rhport, p_request); + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 diff --git a/src/device/usbd.h b/src/device/usbd.h index e88f64ba8..cf7e9f0db 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -125,7 +125,7 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE -TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); // Invoked when vendor control request is complete TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index db0eb70a7..f1edad376 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -33,7 +33,7 @@ #include "dcd.h" #if CFG_TUSB_DEBUG >= 2 -extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); +extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif enum @@ -50,7 +50,7 @@ typedef struct uint16_t data_len; uint16_t total_xferred; - bool (*complete_cb) (uint8_t, tusb_control_request_t const *); + usbd_control_xfer_cb_t complete_cb; } usbd_control_xfer_t; static usbd_control_xfer_t _ctrl_xfer; @@ -146,7 +146,7 @@ void usbd_control_reset(void) } // TODO may find a better way -void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ) +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) { _ctrl_xfer.complete_cb = fp; } @@ -199,7 +199,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif - is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request); + is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); } if ( is_ok ) diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 09b285581..57331041b 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -46,7 +46,7 @@ typedef struct void (* init ) (void); void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void (* sof ) (uint8_t rhport); /* optional */ @@ -57,6 +57,9 @@ typedef struct // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + +typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From dd07fecc5f37c85b87060c7f7158d26ff19757a6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 21:26:06 +0700 Subject: migrate cdc_device to new control_xfer_cb --- src/class/cdc/cdc_device.c | 85 +++++++++++++++++++--------------------------- src/class/cdc/cdc_device.h | 11 +++--- src/class/msc/msc_device.h | 10 +++--- src/device/usbd.c | 3 +- src/device/usbd_control.c | 9 +++++ 5 files changed, 55 insertions(+), 63 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e54b7d260..2933dcd3d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -315,38 +315,10 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool cdcd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - //------------- Class Specific Request -------------// - TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; - - // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - - if ( p_cdc->itf_num == request->wIndex ) break; - } - - // Invoke callback - if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest ) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - - return true; -} - -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { // Handle class request only TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -365,34 +337,47 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: - TU_LOG2(" Set Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Set Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } + else if ( stage == CONTROL_STAGE_ACK) + { + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + } break; case CDC_REQUEST_GET_LINE_CODING: - TU_LOG2(" Get Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Get Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - bool const dtr = tu_bit_test(request->wValue, 0); - bool const rts = tu_bit_test(request->wValue, 1); - - p_cdc->line_state = (uint8_t) request->wValue; + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + // CDC PSTN v1.2 section 6.3.12 + // Bit 0: Indicates if DTE is present or not. + // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) + // Bit 1: Carrier control for half-duplex modems. + // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); + p_cdc->line_state = (uint8_t) request->wValue; - tud_control_status(rhport, request); + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); - } + // Invoke callback + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + } break; default: return false; // stall unsupported request diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 3c679c48e..3e68e2a88 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -236,12 +236,11 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index f1e6c40f4..469f2f2f7 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -158,11 +158,11 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 02f631dea..dbe11d380 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -97,8 +97,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, - .control_xfer_cb = cdcd_control_request, - .control_complete = cdcd_control_complete, + .control_xfer_cb = cdcd_control_xfer_cb, .xfer_cb = cdcd_xfer_cb, .sof = NULL }, diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f1edad376..bb631320a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -171,7 +171,16 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + + // invoke optional dcd hook if available if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + + if (_ctrl_xfer.complete_cb) + { + // TODO refactor with usbd_driver_print_control_complete_name + _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); + } + return true; } -- cgit v1.3.1 From dc9a30983982717b1a0e8b48833fca841de5e70e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 22:00:49 +0700 Subject: migrate hid device to new control xfer cb --- src/class/hid/hid_device.c | 190 +++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 11 ++- src/device/usbd.c | 3 +- 3 files changed, 102 insertions(+), 102 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 11da5f220..1f03f8862 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -211,9 +211,10 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 return drv_len; } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); @@ -225,27 +226,29 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { //------------- STD Request -------------// - uint8_t const desc_type = tu_u16_high(request->wValue); - uint8_t const desc_index = tu_u16_low (request->wValue); - (void) desc_index; - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor != NULL); - TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb( - #if CFG_TUD_HID > 1 - hid_itf // TODO for backward compatible callback, remove later when appropriate - #endif - ); - tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); - } - else + if ( stage == CONTROL_STAGE_SETUP ) { - return false; // stall unsupported request + uint8_t const desc_type = tu_u16_high(request->wValue); + //uint8_t const desc_index = tu_u16_low (request->wValue); + + if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) + { + TU_VERIFY(p_hid->hid_descriptor != NULL); + TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); + } + else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) + { + uint8_t const * desc_report = tud_hid_descriptor_report_cb( + #if CFG_TUD_HID > 1 + hid_itf // TODO for backward compatible callback, remove later when appropriate + #endif + ); + tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); + } + else + { + return false; // stall unsupported request + } } } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) @@ -254,70 +257,98 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request switch( request->bRequest ) { case HID_REQ_CONTROL_GET_REPORT: - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); + if ( stage == CONTROL_STAGE_SETUP ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength - ); - TU_ASSERT( xferlen > 0 ); + uint16_t xferlen = tud_hid_get_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength + ); + TU_ASSERT( xferlen > 0 ); - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } + tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); + } break; case HID_REQ_CONTROL_SET_REPORT: - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); + tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength + ); + } break; case HID_REQ_CONTROL_SET_IDLE: - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) + if ( stage == CONTROL_STAGE_SETUP ) { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->idle_rate) - ); + p_hid->idle_rate = tu_u16_high(request->wValue); + if ( tud_hid_set_idle_cb ) + { + // stall request if callback return false + TU_VERIFY( tud_hid_set_idle_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->idle_rate) + ); + } + + tud_control_status(rhport, request); } - - tud_control_status(rhport, request); break; case HID_REQ_CONTROL_GET_IDLE: - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + if ( stage == CONTROL_STAGE_SETUP ) + { + // TODO idle rate of report + tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + } break; case HID_REQ_CONTROL_GET_PROTOCOL: - { - uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); // 0 is Boot, 1 is Report protocol - tud_control_xfer(rhport, request, &protocol, 1); - } + if ( stage == CONTROL_STAGE_SETUP ) + { + // 0 is Boot, 1 is Report protocol + uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); + tud_control_xfer(rhport, request, &protocol, 1); + } break; case HID_REQ_CONTROL_SET_PROTOCOL: - p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol - - if (tud_hid_boot_mode_cb) + if ( stage == CONTROL_STAGE_SETUP ) { - tud_hid_boot_mode_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->boot_mode - ); + // 0 is Boot, 1 is Report protocol + p_hid->boot_mode = 1 - request->wValue; + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if (tud_hid_boot_mode_cb) + { + tud_hid_boot_mode_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->boot_mode + ); + } } - - tud_control_status(rhport, request); break; default: return false; // stall unsupported request @@ -330,35 +361,6 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request return true; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(p_request->wValue); - uint8_t const report_id = tu_u16_low(p_request->wValue); - - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength - ); - } - - return true; -} - bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index d5b5b7296..2d4c59d8f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -359,12 +359,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidd_init (void); +void hidd_reset (uint8_t rhport); +uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index dbe11d380..1e6722ffb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -121,8 +121,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = hidd_init, .reset = hidd_reset, .open = hidd_open, - .control_xfer_cb = hidd_control_request, - .control_complete = hidd_control_complete, + .control_xfer_cb = hidd_control_xfer_cb, .xfer_cb = hidd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From e2abb089f4e96cd7731bc97067566541090a1eda Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:30:36 +0700 Subject: migrate midi device to new control xfer cb --- src/class/midi/midi_device.c | 12 +++--------- src/class/midi/midi_device.h | 11 +++++------ src/device/usbd.c | 3 +-- 3 files changed, 9 insertions(+), 17 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a07acf0b8..b61df59aa 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -375,17 +375,11 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint return drv_len; } -bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { (void) rhport; - (void) p_request; - return true; -} - -bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - (void) p_request; + (void) stage; + (void) request; // driver doesn't support any request yet return false; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index b8fb55cc2..9235448f2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -142,12 +142,11 @@ static inline bool tud_midi_send (uint8_t const packet[4]) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init (void); +void midid_reset (uint8_t rhport); +uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 1e6722ffb..3686ec28c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -146,8 +146,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = midid_init, .open = midid_open, .reset = midid_reset, - .control_xfer_cb = midid_control_request, - .control_complete = midid_control_complete, + .control_xfer_cb = midid_control_xfer_cb, .xfer_cb = midid_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 8813f9d3b8a997e7a16c61a094f117a50c6ae435 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:32:16 +0700 Subject: clean up --- src/class/midi/midi_device.c | 3 + src/device/usbd.c | 146 +++++++++++++++++++++---------------------- 2 files changed, 76 insertions(+), 73 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index b61df59aa..ce4c9cafe 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -375,6 +375,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint return drv_len; } +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { (void) rhport; diff --git a/src/device/usbd.c b/src/device/usbd.c index 3686ec28c..bea41b592 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -93,43 +93,43 @@ static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL + DRIVER_NAME("CDC") + .init = cdcd_init, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_MSC { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL + DRIVER_NAME("MSC") + .init = mscd_init, + .reset = mscd_reset, + .open = mscd_open, + .control_xfer_cb = mscd_control_xfer_cb, + .xfer_cb = mscd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_HID { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL + DRIVER_NAME("HID") + .init = hidd_init, + .reset = hidd_reset, + .open = hidd_open, + .control_xfer_cb = hidd_control_xfer_cb, + .xfer_cb = hidd_xfer_cb, + .sof = NULL }, #endif -#if CFG_TUD_AUDIO -{ - DRIVER_NAME("AUDIO") + #if CFG_TUD_AUDIO + { + DRIVER_NAME("AUDIO") .init = audiod_init, .reset = audiod_reset, .open = audiod_open, @@ -137,83 +137,83 @@ static usbd_class_driver_t const _usbd_driver[] = .control_complete = audiod_control_complete, .xfer_cb = audiod_xfer_cb, .sof = NULL -}, -#endif + }, + #endif #if CFG_TUD_MIDI { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL + DRIVER_NAME("MIDI") + .init = midid_init, + .open = midid_open, + .reset = midid_reset, + .control_xfer_cb = midid_control_xfer_cb, + .xfer_cb = midid_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_VENDOR { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_request_cb, - .control_complete = tud_vendor_control_complete_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL + DRIVER_NAME("VENDOR") + .init = vendord_init, + .reset = vendord_reset, + .open = vendord_open, + .control_xfer_cb = tud_vendor_control_request_cb, + .control_complete = tud_vendor_control_complete_cb, + .xfer_cb = vendord_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_USBTMC { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_request_cb, - .control_complete = usbtmcd_control_complete_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL + DRIVER_NAME("TMC") + .init = usbtmcd_init_cb, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_xfer_cb = usbtmcd_control_request_cb, + .control_complete = usbtmcd_control_complete_cb, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_DFU_RT { - DRIVER_NAME("DFU-RT") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, - .xfer_cb = dfu_rtd_xfer_cb, - .sof = NULL + DRIVER_NAME("DFU-RT") + .init = dfu_rtd_init, + .reset = dfu_rtd_reset, + .open = dfu_rtd_open, + .control_xfer_cb = dfu_rtd_control_request, + .control_complete = dfu_rtd_control_complete, + .xfer_cb = dfu_rtd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_NET { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_request, - .control_complete = netd_control_complete, - .xfer_cb = netd_xfer_cb, - .sof = NULL, + DRIVER_NAME("NET") + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_xfer_cb = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL, }, #endif #if CFG_TUD_BTH { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_request, - .control_complete = btd_control_complete, - .xfer_cb = btd_xfer_cb, - .sof = NULL + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_xfer_cb = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL }, #endif }; -- cgit v1.3.1 From 7df979673db0e2e268c576a8a4d738069cf5e32b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:38:56 +0700 Subject: migrate usbtmc device to new control xfer cb --- src/class/usbtmc/usbtmc_device.c | 17 +++++++---------- src/class/usbtmc/usbtmc_device.h | 3 +-- src/device/usbd.c | 3 +-- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index bc5f23f42..88776d169 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -575,7 +575,13 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return false; } -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (CFG_TUD_USBTMC_ENABLE_488) @@ -855,13 +861,4 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(false); } -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) -{ - (void)rhport; - //------------- Class Specific Request -------------// - TU_ASSERT (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - return true; -} - #endif /* CFG_TUD_TSMC */ diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a6b5e4cca..622800315 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -111,8 +111,7 @@ bool tud_usbtmc_start_bus_read(void); uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); void usbtmcd_reset_cb(uint8_t rhport); bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); void usbtmcd_init_cb(void); /************************************************************ diff --git a/src/device/usbd.c b/src/device/usbd.c index bea41b592..1d328ad5f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -171,8 +171,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_request_cb, - .control_complete = usbtmcd_control_complete_cb, + .control_xfer_cb = usbtmcd_control_xfer_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 3cc1979adbfb8f91ce4a938573e729e8b80d4627 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:42:32 +0700 Subject: migrate dfu runtime device to new control xfer cb --- src/class/dfu/dfu_rt_device.c | 15 ++++++--------- src/class/dfu/dfu_rt_device.h | 3 +-- src/device/usbd.c | 3 +-- 3 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d4c3ecb62..38644615a 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -85,17 +85,14 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui return drv_len; } -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - (void) rhport; - (void) request; + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; - // nothing to do - return true; -} - -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request) -{ TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 91ead88c6..643e25d8f 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -66,8 +66,7 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi void dfu_rtd_init(void); void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 1d328ad5f..b629a1ff8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -183,8 +183,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, + .control_xfer_cb = dfu_rtd_control_xfer_cb, .xfer_cb = dfu_rtd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 9f853685ae06c4eac03b277d61440de28d5ba41a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:13:58 +0700 Subject: migrate bth device to new control xfer cb --- src/class/bth/bth_device.c | 54 +++++++++++++++++++++++----------------------- src/class/bth/bth_device.h | 11 +++++----- src/device/usbd.c | 3 +-- 3 files changed, 33 insertions(+), 35 deletions(-) (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 252e20e37..c63b994e2 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -186,43 +186,43 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ return drv_len; } -bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { (void)rhport; - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); - - return true; -} - -bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) -{ - (void)rhport; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + if ( stage == CONTROL_STAGE_SETUP ) { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) { - // TODO: Set interface it would involve changing size of endpoint size + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); } - else + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); } - else return false; - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + return true; } bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 5e5468084..1b90d0915 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -96,12 +96,11 @@ bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 9773245c8..5639e1354 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -207,8 +207,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = btd_init, .reset = btd_reset, .open = btd_open, - .control_xfer_cb = btd_control_request, - .control_complete = btd_control_complete, + .control_xfer_cb = btd_control_xfer_cb, .xfer_cb = btd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From d6461abe7835c336ddfb165817ec966ebd259d62 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:30:03 +0700 Subject: clean up --- src/class/bth/bth_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index c63b994e2..f8215e7dd 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -186,6 +186,9 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ return drv_len; } +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { (void)rhport; -- cgit v1.3.1 From c4bc8b25613a74f932202047751d4cc73c0254bd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:59:33 +0700 Subject: migrate net device to new control xfer cb --- src/class/net/net_device.c | 177 ++++++++++++++++++++++----------------------- src/class/net/net_device.h | 13 ++-- src/device/usbd.c | 3 +- 3 files changed, 94 insertions(+), 99 deletions(-) (limited to 'src/class') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 3a45a9b99..ce1131223 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -220,26 +220,6 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send nonsense DATA) -bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - // Handle RNDIS class control OUT only - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.direction == TUSB_DIR_OUT && - _netd_itf.itf_num == request->wIndex) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - - return true; -} - static void ecm_report(bool nc) { notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; @@ -247,99 +227,116 @@ static void ecm_report(bool nc) netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - switch ( request->bmRequestType_bit.type ) + if ( stage == CONTROL_STAGE_SETUP ) { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } + break; - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - // ACM-ECM only: qequest to enable/disable network activities - TU_VERIFY(_netd_itf.ecm_mode); + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); - _netd_itf.itf_data_alt = req_alt; + _netd_itf.itf_data_alt = req_alt; - if ( _netd_itf.itf_data_alt ) - { - // TODO since we don't actually close endpoint - // hack here to not re-open it - if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + if ( _netd_itf.itf_data_alt ) + { + // TODO since we don't actually close endpoint + // hack here to not re-open it + if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + { + TU_ASSERT(_netd_itf.ecm_desc_epdata); + TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + // TODO should be merge with RNDIS's after endpoint opened + // Also should have opposite callback for application to disable network !! + tud_network_init_cb(); + can_xmit = true; // we are ready to transmit a packet + tud_network_recv_renew(); // prepare for incoming packets + } + }else { - TU_ASSERT(_netd_itf.ecm_desc_epdata); - TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - - // TODO should be merge with RNDIS's after endpoint opened - // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); - can_xmit = true; // we are ready to transmit a packet - tud_network_recv_renew(); // prepare for incoming packets + // TODO close the endpoint pair + // For now pretend that we did, this should have no harm since host won't try to + // communicate with the endpoints again + // _netd_itf.ep_in = _netd_itf.ep_out = 0 } - }else - { - // TODO close the endpoint pair - // For now pretend that we did, this should have no harm since host won't try to - // communicate with the endpoints again - // _netd_itf.ep_in = _netd_itf.ep_out = 0 + + tud_control_status(rhport, request); } + break; - tud_control_status(rhport, request); + // unsupported request + default: return false; } - break; + break; - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (_netd_itf.itf_num == request->wIndex); - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + if (_netd_itf.ecm_mode) { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } } else { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } } - } - break; + break; - // unsupported request - default: return false; + // unsupported request + default: return false; + } + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle RNDIS class control OUT only + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.direction == TUSB_DIR_OUT && + _netd_itf.itf_num == request->wIndex) + { + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } + } } return true; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 795b2f9e3..38c47d647 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,13 +73,12 @@ void tud_network_xmit(void *ref, uint16_t arg); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); +void netd_init (void); +void netd_reset (uint8_t rhport); +uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 5639e1354..4d2b44005 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -194,8 +194,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = netd_init, .reset = netd_reset, .open = netd_open, - .control_xfer_cb = netd_control_request, - .control_complete = netd_control_complete, + .control_xfer_cb = netd_control_xfer_cb, .xfer_cb = netd_xfer_cb, .sof = NULL, }, -- cgit v1.3.1 From cebb375eac0d560b53341012aa69ae2a54f4fbaf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 17:20:05 +0700 Subject: migrate audio device to new control xfer cb --- src/class/audio/audio_device.c | 18 ++++++++++++++++-- src/class/audio/audio_device.h | 9 ++++----- src/device/usbd.c | 3 +-- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2c8ba300d..8581925e4 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -989,7 +989,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Invoked when class request DATA stage is finished. // return false to stall control EP (e.g Host send non-sense DATA) -bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) @@ -1065,7 +1065,7 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re // Handle class control request // return false to stall control endpoint (e.g unsupported request) -bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { (void) rhport; @@ -1175,6 +1175,20 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req return false; } +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + return audiod_control_request(rhport, request); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + return audiod_control_complete(rhport, request); + } + + return true; +} + bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d86232720..5061501ce 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -384,11 +384,10 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t b //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 4d2b44005..15174f2ab 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -133,8 +133,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = audiod_init, .reset = audiod_reset, .open = audiod_open, - .control_xfer_cb = audiod_control_request, - .control_complete = audiod_control_complete, + .control_xfer_cb = audiod_control_xfer_cb, .xfer_cb = audiod_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 14138f105e6fa487fa0a0ed40db6f27e1c6039fb Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Nov 2020 13:12:51 +0700 Subject: have tusb_init() return true instead of TUSB_ERROR_NONE --- src/class/bth/bth_device.c | 2 +- src/common/tusb_error.h | 1 + src/tusb.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index f8215e7dd..481dc134e 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -249,7 +249,7 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); } - return TUSB_ERROR_NONE; + return true; } #endif diff --git a/src/common/tusb_error.h b/src/common/tusb_error.h index f600c4ae3..d7ad8c318 100644 --- a/src/common/tusb_error.h +++ b/src/common/tusb_error.h @@ -54,6 +54,7 @@ ENTRY(TUSB_ERROR_FAILED )\ /// \brief Error Code returned +/// TODO obsolete and to be remove typedef enum { ERROR_TABLE(ERROR_ENUM) diff --git a/src/tusb.c b/src/tusb.c index b4731f844..31452e897 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -52,7 +52,7 @@ bool tusb_init(void) _initialized = true; - return TUSB_ERROR_NONE; + return true; } bool tusb_inited(void) -- cgit v1.3.1 From 4b4f88078503648b38444feee1fda322b65baa43 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Nov 2020 23:40:13 +0700 Subject: add tud_ready() check in tud_cdc_n_write_flush() other clean up --- examples/device/cdc_msc/src/main.c | 10 ---------- src/class/cdc/cdc_device.c | 19 +++++++++++++------ src/common/tusb_fifo.c | 2 +- src/common/tusb_fifo.h | 2 +- 4 files changed, 15 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index e4477927f..cf2bfd7c9 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -145,16 +145,6 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) void tud_cdc_rx_cb(uint8_t itf) { (void) itf; - uint8_t const line_state = tud_cdc_get_line_state(); - - // Provide information that terminal did not set DTR bit - if( !(line_state & 0x01) ) - { - tud_cdc_write_str("\r\nTinyUSB example: Your terminal did not set DTR bit\r\n"); - tud_cdc_write_flush(); - // Clear rx fifo since we do not read the data - tud_cdc_read_flush(); - } } //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index bd1d9b0d4..58f485a5d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -178,6 +178,9 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + // Skip if usb is not ready yet + TU_VERIFY( tud_ready(), 0 ); + // No data to send if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; @@ -231,9 +234,10 @@ void cdcd_init(void) p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; - // config fifo + // Config RX fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - // tx fifo is set to overwritable at initialization and will be changed to not overwritable + + // Config TX fifo as overwritable at initialization and will be changed to non-overwritable // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. // In this way, the most current data is prioritized. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); @@ -251,9 +255,12 @@ void cdcd_reset(uint8_t rhport) for(uint8_t i=0; irx_ff); + tu_fifo_clear(&p_cdc->tx_ff); + tu_fifo_set_overwritable(&p_cdc->tx_ff, true); } } @@ -381,7 +388,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set - tu_fifo_set_mode(&p_cdc->tx_ff, !dtr); + tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 444c60f96..608bfd081 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -607,7 +607,7 @@ bool tu_fifo_clear(tu_fifo_t *f) Overwritable mode the fifo is set to */ /******************************************************************************/ -bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable) +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { tu_fifo_lock(f); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index abb301b5f..b965386ab 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -89,7 +89,7 @@ typedef struct .non_used_index_space = 0xFFFF - 2*_depth-1, \ } -bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable); +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); -- cgit v1.3.1 From f5e13d589826b25791464f2fe2050d36739ad56e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Nov 2020 23:42:30 +0700 Subject: msc only invoke scsi complete callback after status transaction is complete --- src/class/msc/msc_device.c | 36 +- src/common/sys_queue.h | 871 --------------------------------------------- 2 files changed, 18 insertions(+), 889 deletions(-) delete mode 100644 src/common/sys_queue.h (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index cfb8a43a3..a4ea5f6fb 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -585,6 +585,24 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); // TU_LOG2_MEM(p_csw, xferred_bytes, 2); + // Invoke complete callback if defined + // Note: There is racing issue with samd51 + qspi flash testing with arduino + // if complete_cb() is invoked after queuing the status. + switch(p_cbw->command[0]) + { + case SCSI_CMD_READ_10: + if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); + break; + + case SCSI_CMD_WRITE_10: + if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); + break; + + default: + if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); + break; + } + // Move to default CMD stage p_msc->stage = MSC_STAGE_CMD; @@ -608,24 +626,6 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } else { - // Invoke complete callback if defined - // Note: There is racing issue with samd51 + qspi flash testing with arduino - // if complete_cb() is invoked after queuing the status. - switch(p_cbw->command[0]) - { - case SCSI_CMD_READ_10: - if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); - break; - - case SCSI_CMD_WRITE_10: - if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); - break; - - default: - if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - break; - } - // Move to Status Sent stage p_msc->stage = MSC_STAGE_STATUS_SENT; diff --git a/src/common/sys_queue.h b/src/common/sys_queue.h deleted file mode 100644 index 443f01b22..000000000 --- a/src/common/sys_queue.h +++ /dev/null @@ -1,871 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD$ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -#include - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may be traversed in either direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * Below is a summary of implemented functions where: - * + means the macro is available - * - means the macro is not available - * s means the macro is available but is slow (runs in O(n) time) - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _CLASS_HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _CLASS_ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - + - + - * _LAST - - + + - * _LAST_FAST - - - + - * _FOREACH + + + + - * _FOREACH_FROM + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_FROM_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_FROM - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _FOREACH_REVERSE_FROM_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT s s + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE s + s + - * _SWAP + + + + - * - */ -#ifdef QUEUE_MACRO_DEBUG -#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH -#define QUEUE_MACRO_DEBUG_TRACE -#define QUEUE_MACRO_DEBUG_TRASH -#endif - -#ifdef QUEUE_MACRO_DEBUG_TRACE -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - unsigned long lastline; - unsigned long prevline; - const char *lastfile; - const char *prevfile; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else /* !QUEUE_MACRO_DEBUG_TRACE */ -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRACEBUF_INITIALIZER -#endif /* QUEUE_MACRO_DEBUG_TRACE */ - -#ifdef QUEUE_MACRO_DEBUG_TRASH -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) -#else /* !QUEUE_MACRO_DEBUG_TRASH */ -#define TRASHIT(x) -#define QMD_IS_TRASHED(x) 0 -#endif /* QUEUE_MACRO_DEBUG_TRASH */ - -#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH) -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) -#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */ -#define QMD_SAVELINK(name, link) -#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */ - -#ifdef __cplusplus -/* - * In C++ there can be structure lists and class lists: - */ -#define QUEUE_TYPEOF(type) type -#else -#define QUEUE_TYPEOF(type) struct type -#endif - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_CLASS_HEAD(name, type) \ -struct name { \ - class type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -#define SLIST_CLASS_ENTRY(type) \ -struct { \ - class type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ - if (*(prevp) != (elm)) \ - panic("Bad prevptr *(%p) == %p != %p", \ - (prevp), *(prevp), (elm)); \ -} while (0) -#else -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) -#endif - -#define SLIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ - if (curelm == NULL) { \ - if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ - SLIST_INIT(head2); \ - } else if (SLIST_FIRST(head2) != NULL) { \ - while (SLIST_NEXT(curelm, field) != NULL) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ - SLIST_INIT(head2); \ - } \ -} while (0) - -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ - QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ - *(prevp) = SLIST_NEXT(elm, field); \ - TRASHIT((elm)->field.sle_next); \ -} while (0) - -#define SLIST_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_CLASS_HEAD(name, type) \ -struct name { \ - class type *stqh_first; /* first element */ \ - class type **stqh_last; /* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -#define STAILQ_CLASS_ENTRY(type) \ -struct { \ - class type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? NULL : \ - __containerof((head)->stqh_last, \ - QUEUE_TYPEOF(type), field.stqe_next)) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ - QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ - STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ -} while (0) - - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_CLASS_HEAD(name, type) \ -struct name { \ - class type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -#define LIST_CLASS_ENTRY(type) \ -struct { \ - class type *le_next; /* next element */ \ - class type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#if (defined(_KERNEL) && defined(INVARIANTS)) -/* - * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) - * - * If the list is non-empty, validates that the first element of the list - * points back at 'head.' - */ -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) - -/* - * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) - * - * If an element follows 'elm' in the list, validates that the next element - * points back at 'elm.' - */ -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -/* - * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) - * - * Validates that the previous element (or head of the list) points to 'elm.' - */ -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define LIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ - if (curelm == NULL) { \ - if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ - LIST_FIRST(head2)->field.le_prev = \ - &LIST_FIRST((head1)); \ - LIST_INIT(head2); \ - } \ - } else if (LIST_FIRST(head2) != NULL) { \ - while (LIST_NEXT(curelm, field) != NULL) \ - curelm = LIST_NEXT(curelm, field); \ - LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ - LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ - LIST_INIT(head2); \ - } \ -} while (0) - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_PREV(elm, head, type, field) \ - ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ - __containerof((elm)->field.le_prev, \ - QUEUE_TYPEOF(type), field.le_next)) - -#define LIST_REMOVE(elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ -} while (0) - -#define LIST_SWAP(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_CLASS_HEAD(name, type) \ -struct name { \ - class type *tqh_first; /* first element */ \ - class type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -#define TAILQ_CLASS_ENTRY(type) \ -struct { \ - class type *tqe_next; /* next element */ \ - class type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -/* - * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) - * - * If the tailq is non-empty, validates that the first element of the tailq - * points back at 'head.' - */ -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) - * - * Validates that the tail of the tailq is a pointer to pointer to NULL. - */ -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) - * - * If an element follows 'elm' in the tailq, validates that the next element - * points back at 'elm.' - */ -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) - * - * Validates that the previous element (or head of the tailq) points to 'elm.' - */ -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ - for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ - for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&(listelm)->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&(listelm)->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -/* - * The FAST function is fast in that it causes no data access other - * then the access to the head. The standard LAST function above - * will cause a data access of both the element you want and - * the previous element. FAST is very useful for instances when - * you may want to prefetch the last data element. - */ -#define TAILQ_LAST_FAST(head, type, field) \ - (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_SWAP(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ - QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ -- cgit v1.3.1 From 13e6afd5897ab018047fdc8e4c34f4b782ee5118 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 20 Dec 2020 22:54:55 +0100 Subject: Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. Signed-off-by: HiFiPhile --- src/class/msc/msc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index cba8066b7..0bdc00692 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -255,7 +255,7 @@ typedef struct TU_ATTR_PACKED uint8_t : 3; uint8_t disable_block_descriptor : 1; - uint8_t : 0; + uint8_t : 4; uint8_t page_code : 6; uint8_t page_control : 2; -- cgit v1.3.1 From b3c0d417ef2b2d2ff3d00b7cdf623436ec7abf97 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 20 Dec 2020 23:06:32 +0100 Subject: Fix error if "Required Prototype" is selected. Signed-off-by: HiFiPhile --- src/class/msc/msc_device.c | 348 +++++++++++++++++++++++---------------------- src/common/tusb_compiler.h | 1 + src/device/usbd_control.c | 8 ++ 3 files changed, 184 insertions(+), 173 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a4ea5f6fb..194f4d3cb 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -71,6 +71,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); @@ -223,179 +224,6 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t return true; } -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - memcpy(buffer, &read_capa10, resplen); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, resplen); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - memcpy(buffer, &inquiry_rsp, resplen); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(lun); - } - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - memcpy(buffer, &mode_resp, resplen); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - - sense_rsp.sense_key = _mscd_itf.sense_key; - sense_rsp.add_sense_code = _mscd_itf.add_sense_code; - sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; - - resplen = sizeof(sense_rsp); - memcpy(buffer, &sense_rsp, resplen); - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { mscd_interface_t* p_msc = &_mscd_itf; @@ -640,6 +468,180 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t /*------------------------------------------------------------------*/ /* SCSI Command Process *------------------------------------------------------------------*/ + +// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) +// In case of a failed status, sense key must be set for reason of failure +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) +{ + (void) bufsize; // TODO refractor later + int32_t resplen; + + switch ( scsi_cmd[0] ) + { + case SCSI_CMD_TEST_UNIT_READY: + resplen = 0; + if ( !tud_msc_test_unit_ready_cb(lun) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + break; + + case SCSI_CMD_START_STOP_UNIT: + resplen = 0; + + if (tud_msc_start_stop_cb) + { + scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + } + break; + + case SCSI_CMD_READ_CAPACITY_10: + { + uint32_t block_count; + uint32_t block_size; + uint16_t block_size_u16; + + tud_msc_capacity_cb(lun, &block_count, &block_size_u16); + block_size = (uint32_t) block_size_u16; + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + scsi_read_capacity10_resp_t read_capa10; + + read_capa10.last_lba = tu_htonl(block_count-1); + read_capa10.block_size = tu_htonl(block_size); + + resplen = sizeof(read_capa10); + memcpy(buffer, &read_capa10, resplen); + } + } + break; + + case SCSI_CMD_READ_FORMAT_CAPACITY: + { + scsi_read_format_capacity_data_t read_fmt_capa = + { + .list_length = 8, + .block_num = 0, + .descriptor_type = 2, // formatted media + .block_size_u16 = 0 + }; + + uint32_t block_count; + uint16_t block_size; + + tud_msc_capacity_cb(lun, &block_count, &block_size); + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + read_fmt_capa.block_num = tu_htonl(block_count); + read_fmt_capa.block_size_u16 = tu_htons(block_size); + + resplen = sizeof(read_fmt_capa); + memcpy(buffer, &read_fmt_capa, resplen); + } + } + break; + + case SCSI_CMD_INQUIRY: + { + scsi_inquiry_resp_t inquiry_rsp = + { + .is_removable = 1, + .version = 2, + .response_data_format = 2, + }; + + // vendor_id, product_id, product_rev is space padded string + memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); + memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); + memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); + + tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); + + resplen = sizeof(inquiry_rsp); + memcpy(buffer, &inquiry_rsp, resplen); + } + break; + + case SCSI_CMD_MODE_SENSE_6: + { + scsi_mode_sense6_resp_t mode_resp = + { + .data_len = 3, + .medium_type = 0, + .write_protected = false, + .reserved = 0, + .block_descriptor_len = 0 // no block descriptor are included + }; + + bool writable = true; + if (tud_msc_is_writable_cb) { + writable = tud_msc_is_writable_cb(lun); + } + mode_resp.write_protected = !writable; + + resplen = sizeof(mode_resp); + memcpy(buffer, &mode_resp, resplen); + } + break; + + case SCSI_CMD_REQUEST_SENSE: + { + scsi_sense_fixed_resp_t sense_rsp = + { + .response_code = 0x70, + .valid = 1 + }; + + sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; + + sense_rsp.sense_key = _mscd_itf.sense_key; + sense_rsp.add_sense_code = _mscd_itf.add_sense_code; + sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; + + resplen = sizeof(sense_rsp); + memcpy(buffer, &sense_rsp, resplen); + + // Clear sense data after copy + tud_msc_set_sense(lun, 0, 0, 0); + } + break; + + default: resplen = -1; break; + } + + return resplen; +} + static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { msc_cbw_t const * p_cbw = &p_msc->cbw; diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 505542078..22c8366ab 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -102,6 +102,7 @@ #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #elif defined(__ICCARM__) + #include #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index bb631320a..8ed0ad1c0 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -140,6 +140,14 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ +//--------------------------------------------------------------------+ +// Prototypes +//--------------------------------------------------------------------+ +void usbd_control_reset(void); +void usbd_control_set_request(tusb_control_request_t const *request); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void usbd_control_reset(void) { tu_varclr(&_ctrl_xfer); -- cgit v1.3.1 From bdee6397ebf87ba83043fec15ca03e3542deb7a3 Mon Sep 17 00:00:00 2001 From: Yakovenko Andrey Date: Wed, 23 Dec 2020 12:52:51 +0200 Subject: Added MSC read10 and write10 function --- src/class/msc/msc_host.c | 93 ++++++++++++++++++++++++------------------------ src/class/msc/msc_host.h | 22 ++++-------- 2 files changed, 53 insertions(+), 62 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 02ca81e77..9ba41d944 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -192,60 +192,59 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); } -#if 0 - -tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read10_t); + msch_interface_t* p_msc = get_itf(dev_addr); + if ( !p_msc->mounted ){ return false;}; - //------------- SCSI command -------------// - scsi_read10_t cmd_read10 =msch_sem_hdl + msc_cbw_t cbw = { 0 }; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&cbw, lun); + + cbw.total_bytes = 512*block_count; // Number of bytes + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); + + //------------- SCSI command -------------// + scsi_read10_t cmd_read10 = { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; - - memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer)); - - return TUSB_ERROR_NONE; + + memcpy(cbw.command, &cmd_read10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); } - -tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count) + +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_OUT; - p_msch->cbw.cmd_len = sizeof(scsi_write10_t); - - //------------- SCSI command -------------// - scsi_write10_t cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer)); - - return TUSB_ERROR_NONE; + msch_interface_t* p_msc = get_itf(dev_addr); + if ( !p_msc->mounted ){ return false;}; + + msc_cbw_t cbw = { 0 }; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&cbw, lun); + + cbw.total_bytes = 512*block_count; // Number of bytes + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); + + //------------- SCSI command -------------// + scsi_write10_t cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) + }; + + memcpy(cbw.command, &cmd_write10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); } -#endif #if 0 // MSC interface Reset (not used now) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 5913350b8..016e4e21e 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -81,20 +81,16 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms // Carry out SCSI READ CAPACITY (10) command in non-blocking manner. bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); -#if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit - * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) + * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) * \param[in] lba Starting Logical Block Address to be read * \param[in] block_count Number of Block to be read - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \retval true on success + * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function */ -tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count); +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); /** \brief Perform SCSI WRITE 10 command to write data to MassStorage device * \param[in] dev_addr device address @@ -102,14 +98,10 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin * \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) * \param[in] lba Starting Logical Block Address to be written * \param[in] block_count Number of Block to be written - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \retval true on success + * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function */ -tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count); -#endif +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); //------------- Application Callback -------------// -- cgit v1.3.1 From 29f84b16022f9e1162dac959e65e6f7cbe2d5072 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 Jan 2021 11:58:05 +0700 Subject: change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 2d4c59d8f..456b011ba 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -46,7 +46,7 @@ #endif #ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 16 + #define CFG_TUD_HID_EP_BUFSIZE 64 #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 3a3ada0c57013fb64f69178a1c6299abc74e4f40 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:07:15 +0100 Subject: Implement the usage of usbd_edpt_ISO_xfer() --- src/class/audio/audio_device.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8581925e4..8dd1a8fef 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -32,6 +32,8 @@ * * */ +// TODO: Rename CFG_TUD_AUDIO_EPSIZE_IN to CFG_TUD_AUDIO_EP_IN_BUFFER_SIZE + #include "tusb_option.h" #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) @@ -129,6 +131,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_IN CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) + tu_fifo_t epin_ff; #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -531,7 +534,14 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); + // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); + + + TU_VERIFY(usbd_edpt_ISO_xfer(rhport, audio->ep_in, &audio->epin_ff)); + + + + // Inform how many bytes were copied *n_bytes_copied = audio->epin_buf_cnt; @@ -631,7 +641,9 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } - nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); + nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->epin_ff, 0, nByteCount); +// nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); + audio->epin_buf_cnt = nByteCount; return true; @@ -735,6 +747,10 @@ void audiod_init(void) tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } + + // Initialize IN EP FIFO + tu_fifo_config(&audio->epin_ff, &audio->epin_buf, CFG_TUD_AUDIO_EPSIZE_IN, 1, true); + #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE @@ -765,6 +781,10 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); +#if CFG_TUD_AUDIO_EPSIZE_IN + tu_fifo_clear(&audio->epin_ff); +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) { -- cgit v1.3.1 From 56edc2b2618e542b73c284a3116cf88fd70303e2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 19 Jan 2021 10:50:19 +0100 Subject: Change names from edpt_ISO_xfer to edpt_iso_xfer --- src/class/audio/audio_device.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 4 ++-- src/device/usbd_pvt.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8dd1a8fef..616760223 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -537,7 +537,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); - TU_VERIFY(usbd_edpt_ISO_xfer(rhport, audio->ep_in, &audio->epin_ff)); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->epin_ff)); diff --git a/src/device/dcd.h b/src/device/dcd.h index 1b2d2b941..30224e16e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -135,7 +135,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index e0546ac39..c2b5b65d1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,7 +1206,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1220,7 +1220,7 @@ bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff) ) + if ( dcd_edpt_iso_xfer(rhport, ep_addr, ff) ) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 4ae55aecc..1d24957a9 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5f9dc267b..90fcd51e7 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,7 +670,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); -- cgit v1.3.1 From e0aa405d19e35dbf58cf502b8106455c1a3c2a5c Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 19 Jan 2021 19:52:07 -0600 Subject: RP2040 support --- examples/host/cdc_msc_hid/src/keyboard_helper.h | 59 +++ hw/bsp/board.h | 7 + hw/bsp/board_mcu.h | 3 + hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c | 99 ++++ hw/mcu/microchip | 2 +- lib/lwip | 2 +- src/class/hid/hid_host.c | 6 +- src/host/usbh.c | 6 + src/host/usbh.h | 1 + src/osal/osal.h | 2 + src/osal/osal_pico.h | 192 +++++++ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 482 ++++++++++++++++++ src/portable/raspberrypi/rp2040/hcd_rp2040.c | 549 +++++++++++++++++++++ src/portable/raspberrypi/rp2040/rp2040_usb.c | 279 +++++++++++ src/portable/raspberrypi/rp2040/rp2040_usb.h | 124 +++++ src/tusb_option.h | 4 + 16 files changed, 1813 insertions(+), 4 deletions(-) create mode 100644 examples/host/cdc_msc_hid/src/keyboard_helper.h create mode 100644 hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c create mode 100644 src/osal/osal_pico.h create mode 100644 src/portable/raspberrypi/rp2040/dcd_rp2040.c create mode 100644 src/portable/raspberrypi/rp2040/hcd_rp2040.c create mode 100644 src/portable/raspberrypi/rp2040/rp2040_usb.c create mode 100644 src/portable/raspberrypi/rp2040/rp2040_usb.h (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/keyboard_helper.h b/examples/host/cdc_msc_hid/src/keyboard_helper.h new file mode 100644 index 000000000..1fde2768c --- /dev/null +++ b/examples/host/cdc_msc_hid/src/keyboard_helper.h @@ -0,0 +1,59 @@ +#ifndef KEYBOARD_HELPER_H +#define KEYBAORD_HELPER_H + +#include +#include + +#include "tusb.h" + +// look up new key in previous keys +inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) +{ + for(uint8_t i = 0; i < 6; i++) + { + if (p_report->keycode[i] == keycode) return true; + } + + return false; +} + +inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) +{ + return keycode > 128 ? 0 : + hid_keycode_to_ascii_tbl [keycode][modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ? 1 : 0]; +} + +void print_kbd_report(hid_keyboard_report_t *prev_report, hid_keyboard_report_t const *new_report) +{ + + printf("Report: "); + uint8_t c; + + // I assume it's possible to have up to 6 keypress events per report? + for (uint8_t i = 0; i < 6; i++) + { + // Check for key presses + if (new_report->keycode[i]) + { + // If not in prev report then it is newly pressed + if ( !find_key_in_report(prev_report, new_report->keycode[i]) ) + c = keycode_to_ascii(new_report->modifier, new_report->keycode[i]); + printf("press %c ", c); + } + + // Check for key depresses (i.e. was present in prev report but not here) + if (prev_report->keycode[i]) + { + // If not present in the current report then depressed + if (!find_key_in_report(new_report, prev_report->keycode[i])) + { + c = keycode_to_ascii(prev_report->modifier, prev_report->keycode[i]); + printf("depress %c ", c); + } + } + } + + printf("\n"); +} + +#endif \ No newline at end of file diff --git a/hw/bsp/board.h b/hw/bsp/board.h index a8f973a7f..97c80e7c7 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -80,6 +80,13 @@ int board_uart_write(void const * buf, int len); return os_time_ticks_to_ms32( os_time_get() ); } +#elif CFG_TUSB_OS == OPT_OS_PICO +#include "pico/time.h" +static inline uint32_t board_millis(void) + { + return to_ms_since_boot(get_absolute_time()); + } + #else #error "board_millis() is not implemented for this OS" #endif diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index eedae43f7..700183414 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -117,6 +117,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_DA1469X #include "DA1469xAB.h" +#elif CFG_TUSB_MCU == OPT_MCU_RP2040 + #include "pico.h" + #else #error "Missing MCU header" #endif diff --git a/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c b/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c new file mode 100644 index 000000000..efdb54733 --- /dev/null +++ b/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c @@ -0,0 +1,99 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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 file is part of the TinyUSB stack. + */ + +#include "pico/stdlib.h" +#include "../board.h" + +#ifndef LED_PIN +#define LED_PIN PICO_DEFAULT_LED_PIN +#endif + +void board_init(void) +{ + setup_default_uart(); + gpio_init(LED_PIN); + gpio_set_dir(LED_PIN, 1); + + // Button + + // todo probably set up device mode? + +#if TUSB_OPT_HOST_ENABLED + // set portfunc to host !!! +#endif +} + +////--------------------------------------------------------------------+ +//// USB Interrupt Handler +////--------------------------------------------------------------------+ +//void USB_IRQHandler(void) +//{ +//#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST +// tuh_isr(0); +//#endif +// +//#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE +// tud_int_handler(0); +//#endif +//} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + gpio_put(LED_PIN, state); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + for(int i=0;iep_in = p_endpoint_desc->bEndpointAddress; p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->itf_num = interface_number; + p_hid->valid = true; return true; } @@ -246,14 +248,14 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) usbh_driver_set_config_complete(dev_addr, itf_num); #if CFG_TUH_HID_KEYBOARD - if ( keyboardh_data[dev_addr-1].itf_num == itf_num) + if (( keyboardh_data[dev_addr-1].itf_num == itf_num) && keyboardh_data[dev_addr-1].valid) { tuh_hid_keyboard_mounted_cb(dev_addr); } #endif #if CFG_TUH_HID_MOUSE - if ( mouseh_data[dev_addr-1].ep_in == itf_num ) + if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) { tuh_hid_mouse_mounted_cb(dev_addr); } diff --git a/src/host/usbh.c b/src/host/usbh.c index e7347ff56..bf265199d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -151,6 +151,12 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) return (tusb_device_state_t) _usbh_devices[dev_addr].state; } +tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) +{ + TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); + return _usbh_devices[dev_addr].speed; +} + void osal_task_delay(uint32_t msec) { (void) msec; diff --git a/src/host/usbh.h b/src/host/usbh.h index 12c9164dd..a05010b36 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -86,6 +86,7 @@ extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); +tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); static inline bool tuh_device_is_configured(uint8_t dev_addr) { return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; diff --git a/src/osal/osal.h b/src/osal/osal.h index b5057ff4c..eb3bc88d0 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -53,6 +53,8 @@ typedef void (*osal_task_func_t)( void * ); #include "osal_freertos.h" #elif CFG_TUSB_OS == OPT_OS_MYNEWT #include "osal_mynewt.h" +#elif CFG_TUSB_OS == OPT_OS_PICO + #include "osal_pico.h" #elif CFG_TUSB_OS == OPT_OS_CUSTOM #include "tusb_os_custom.h" // implemented by application #else diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h new file mode 100644 index 000000000..1788e5c8d --- /dev/null +++ b/src/osal/osal_pico.h @@ -0,0 +1,192 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_PICO_H_ +#define _TUSB_OSAL_PICO_H_ + +#include "pico/time.h" +#include "pico/sem.h" +#include "pico/mutex.h" +#include "pico/critical_section.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +#ifndef RP2040_USB_HOST_MODE +static inline void osal_task_delay(uint32_t msec) +{ + sleep_ms(msec); +} +#endif + +//--------------------------------------------------------------------+ +// Binary Semaphore API +//--------------------------------------------------------------------+ +typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; + +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + sem_init(semdef, 0, 255); + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + sem_release(sem_hdl); + return true; +} + +static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +{ + return sem_acquire_timeout_ms(sem_hdl, msec); +} + +static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +{ + sem_reset(sem_hdl, 0); +} + +//--------------------------------------------------------------------+ +// MUTEX API +// Within tinyusb, mutex is never used in ISR context +//--------------------------------------------------------------------+ +typedef struct mutex osal_mutex_def_t, *osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + mutex_init(mdef); + return mdef; +} + +static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +{ + return mutex_enter_timeout_ms(mutex_hdl, msec); +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + mutex_exit(mutex_hdl); + return true; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ +#include "common/tusb_fifo.h" + +#if TUSB_OPT_HOST_ENABLED +extern void hcd_int_disable(uint8_t rhport); +extern void hcd_int_enable(uint8_t rhport); +#endif + +typedef struct +{ + tu_fifo_t ff; + struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section +} osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .ff = { \ + .buffer = _name##_buf, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = false, \ + }\ + } + +// lock queue by disable USB interrupt +static inline void _osal_q_lock(osal_queue_t qhdl) +{ + critical_section_enter_blocking(&qhdl->critsec); +} + +// unlock queue +static inline void _osal_q_unlock(osal_queue_t qhdl) +{ + critical_section_exit(&qhdl->critsec); +} + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + critical_section_init(&qdef->critsec); + tu_fifo_clear(&qdef->ff); + return (osal_queue_t) qdef; +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + // TODO: revisit... docs say that mutexes are never used from IRQ context, + // however osal_queue_recieve may be. therefore my assumption is that + // the fifo mutex is not populated for queues used from an IRQ context + assert(!qhdl->ff.mutex); + + _osal_q_lock(qhdl); + bool success = tu_fifo_read(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + return success; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + // TODO: revisit... docs say that mutexes are never used from IRQ context, + // however osal_queue_recieve may be. therefore my assumption is that + // the fifo mutex is not populated for queues used from an IRQ context + assert(!qhdl->ff.mutex); + + _osal_q_lock(qhdl); + bool success = tu_fifo_write(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + TU_ASSERT(success); + + return success; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single + // volatile read. + + // Skip queue lock/unlock since this function is primarily called + // with interrupt disabled before going into low power mode + return tu_fifo_empty(&qhdl->ff); +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c new file mode 100644 index 000000000..80e5d3c4b --- /dev/null +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -0,0 +1,482 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_RP2040 + +#include "pico.h" +#include "rp2040_usb.h" + +#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX +#include "pico/fix/rp2040_usb_device_enumeration.h" +#endif + + +#include "device/dcd.h" + +#include "pico/stdlib.h" + +/*------------------------------------------------------------------*/ +/* Low level controller + *------------------------------------------------------------------*/ + +#define usb_hw_set hw_set_alias(usb_hw) +#define usb_hw_clear hw_clear_alias(usb_hw) + +// Init these in dcd_init +static uint8_t assigned_address; +static uint8_t *next_buffer_ptr; + +// Endpoints 0-15, direction 0 for out and 1 for in. +static struct hw_endpoint hw_endpoints[16][2] = {0}; + +static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) +{ + return &hw_endpoints[num][in]; +} + +static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) +{ + uint8_t num = tu_edpt_number(ep_addr); + uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; + return hw_endpoint_get_by_num(num, in); +} +static void _hw_endpoint_alloc(struct hw_endpoint *ep) +{ + uint size = 64; + if (ep->wMaxPacketSize > 64) + { + size = ep->wMaxPacketSize; + } + + // Assumes single buffered for now + ep->hw_data_buf = next_buffer_ptr; + next_buffer_ptr += size; + // Bits 0-5 are ignored by the controller so make sure these are 0 + if ((uintptr_t)next_buffer_ptr & 0b111111u) + { + // Round up to the next 64 + uint32_t fixptr = (uintptr_t)next_buffer_ptr; + fixptr &= ~0b111111u; + fixptr += 64; + pico_info("Rounding non 64 byte boundary buffer up from %x to %x\n", (uintptr_t)next_buffer_ptr, fixptr); + next_buffer_ptr = (uint8_t*)fixptr; + } + assert(((uintptr_t)next_buffer_ptr & 0b111111u) == 0); + uint dpram_offset = hw_data_offset(ep->hw_data_buf); + assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); + + pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n", + size, + dpram_offset, + ep->hw_data_buf, + ep->num, + ep_dir_string[ep->in]); + + // Fill in endpoint control register with buffer offset + uint32_t reg = EP_CTRL_ENABLE_BITS + | EP_CTRL_INTERRUPT_PER_BUFFER + | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) + | dpram_offset; + + *ep->endpoint_control = reg; +} + +static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type) +{ + uint8_t num = tu_edpt_number(ep_addr); + bool in = ep_addr & TUSB_DIR_IN_MASK; + ep->ep_addr = ep_addr; + ep->in = in; + // For device, IN is a tx transfer and OUT is an rx transfer + ep->rx = in == false; + ep->num = num; + // Response to a setup packet on EP0 starts with pid of 1 + ep->next_pid = num == 0 ? 1u : 0u; + + // Add some checks around the max packet size + if (transfer_type == TUSB_XFER_ISOCHRONOUS) + { + if (wMaxPacketSize > USB_MAX_ISO_PACKET_SIZE) + { + panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize); + } + } + else + { + if (wMaxPacketSize > USB_MAX_PACKET_SIZE) + { + panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize); + } + } + + ep->wMaxPacketSize = wMaxPacketSize; + ep->transfer_type = transfer_type; + + // Every endpoint has a buffer control register in dpram + if (ep->in) + { + ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; + } + else + { + ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; + } + + // Clear existing buffer control state + *ep->buffer_control = 0; + + if (ep->num == 0) + { + // EP0 has no endpoint control register because + // the buffer offsets are fixed + ep->endpoint_control = NULL; + + // Buffer offset is fixed + ep->hw_data_buf = (uint8_t*)&usb_dpram->ep0_buf_a[0]; + } + else + { + // Set the endpoint control register (starts at EP1, hence num-1) + if (in) + { + ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].in; + } + else + { + ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].out; + } + + // Now alloc a buffer and fill in endpoint control register + _hw_endpoint_alloc(ep); + } + + ep->configured = true; +} + +#if 0 // todo unused +static void _hw_endpoint_close(struct hw_endpoint *ep) +{ + // Clear hardware registers and then zero the struct + // Clears endpoint enable + *ep->endpoint_control = 0; + // Clears buffer available, etc + *ep->buffer_control = 0; + // Clear any endpoint state + memset(ep, 0, sizeof(struct hw_endpoint)); +} + +static void hw_endpoint_close(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_close(ep); +} +#endif + +static void hw_endpoint_init(uint8_t ep_addr, uint wMaxPacketSize, uint8_t bmAttributes) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); +} + +static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool start) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_xfer(ep, buffer, total_bytes, start); +} + +static void hw_handle_buff_status(void) +{ + uint32_t remaining_buffers = usb_hw->buf_status; + pico_trace("buf_status 0x%08x\n", remaining_buffers); + uint bit = 1u; + for (uint i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) + { + if (remaining_buffers & bit) + { + uint __unused which = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; + // Should be single buffered + assert(which == 0); + // clear this in advance + usb_hw_clear->buf_status = bit; + // IN transfer for even i, OUT transfer for odd i + struct hw_endpoint *ep = hw_endpoint_get_by_num(i >> 1u, !(i & 1u)); + // Continue xfer + bool done = _hw_endpoint_xfer_continue(ep); + if (done) + { + // Notify + dcd_event_xfer_complete(0, ep->ep_addr, ep->len, XFER_RESULT_SUCCESS, true); + hw_endpoint_reset_transfer(ep); + } + remaining_buffers &= ~bit; + } + bit <<= 1u; + } +} + +static void reset_ep0(void) +{ + // If we have finished this transfer on EP0 set pid back to 1 for next + // setup transfer. Also clear a stall in case + uint8_t addrs[] = {0x0, 0x80}; + for (uint i = 0 ; i < count_of(addrs); i++) + { + struct hw_endpoint *ep = hw_endpoint_get_by_addr(addrs[i]); + ep->next_pid = 1u; + ep->stalled = 0; + } +} + +static void ep0_0len_status(void) +{ + // Send 0len complete response on EP0 IN + reset_ep0(); + hw_endpoint_xfer(0x80, NULL, 0, true); +} + +static void _hw_endpoint_stall(struct hw_endpoint *ep) +{ + assert(!ep->stalled); + if (ep->num == 0) + { + // A stall on EP0 has to be armed so it can be cleared on the next setup packet + usb_hw_set->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + } + _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); + ep->stalled = true; +} + +static void hw_endpoint_stall(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_stall(ep); +} + +static void _hw_endpoint_clear_stall(struct hw_endpoint *ep) +{ + if (ep->num == 0) + { + // Probably already been cleared but no harm + usb_hw_clear->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + } + _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); + ep->stalled = false; +} + +static void hw_endpoint_clear_stall(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_clear_stall(ep); +} + +static void dcd_rp2040_irq(void) +{ + uint32_t status = usb_hw->ints; + uint32_t handled = 0; + + if (status & USB_INTS_SETUP_REQ_BITS) + { + handled |= USB_INTS_SETUP_REQ_BITS; + uint8_t const *setup = (uint8_t const *)&usb_dpram->setup_packet; + // Clear stall bits and reset pid + reset_ep0(); + // Pass setup packet to tiny usb + dcd_event_setup_received(0, setup, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; + } + + if (status & USB_INTS_BUFF_STATUS_BITS) + { + handled |= USB_INTS_BUFF_STATUS_BITS; + hw_handle_buff_status(); + } + + if (status & USB_INTS_BUS_RESET_BITS) + { + pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); + assigned_address = 0; + usb_hw->dev_addr_ctrl = assigned_address; + handled |= USB_INTS_BUS_RESET_BITS; + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; +#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX + rp2040_usb_device_enumeration_fix(); +#endif + } + + if (status ^ handled) + { + panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); + } +} + +#define USB_INTS_ERROR_BITS ( \ + USB_INTS_ERROR_DATA_SEQ_BITS | \ + USB_INTS_ERROR_BIT_STUFF_BITS | \ + USB_INTS_ERROR_CRC_BITS | \ + USB_INTS_ERROR_RX_OVERFLOW_BITS | \ + USB_INTS_ERROR_RX_TIMEOUT_BITS) + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init (uint8_t rhport) +{ + pico_trace("dcd_init %d\n", rhport); + assert(rhport == 0); + + // Reset hardware to default state + rp2040_usb_init(); + + irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); + memset(hw_endpoints, 0, sizeof(hw_endpoints)); + assigned_address = 0; + next_buffer_ptr = &usb_dpram->epx_data[0]; + + // EP0 always exists so init it now + // EP0 OUT + hw_endpoint_init(0x0, 64, 0); + // EP0 IN + hw_endpoint_init(0x80, 64, 0); + + // Initializes the USB peripheral for device mode and enables it. + // Don't need to enable the pull up here. Force VBUS + usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS; + + // Enable individual controller IRQS here. Processor interrupt enable will be used + // for the global interrupt enable... + usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; + usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS; + + dcd_connect(rhport); +} + +void dcd_int_enable(uint8_t rhport) +{ + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, true); +} + +void dcd_int_disable(uint8_t rhport) +{ + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, false); +} + +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); + assert(rhport == 0); + + // Can't set device address in hardware until status xfer has complete + assigned_address = dev_addr; + + ep0_0len_status(); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + panic("dcd_remote_wakeup %d\n", rhport); + assert(rhport == 0); +} + +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + pico_info("dcd_disconnect %d\n", rhport); + assert(rhport == 0); + usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; +} + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + pico_info("dcd_connect %d\n", rhport); + assert(rhport == 0); + usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + pico_trace("dcd_edpt0_status_complete %d\n", rhport); + assert(rhport == 0); + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS) + { + pico_trace("Set HW address %d\n", assigned_address); + usb_hw->dev_addr_ctrl = assigned_address; + } + + reset_ep0(); +} + +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +{ + pico_info("dcd_edpt_open %d %02x\n", rhport, desc_edpt->bEndpointAddress); + assert(rhport == 0); + hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer); + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + assert(rhport == 0); + // True means start new xfer + hw_endpoint_xfer(ep_addr, buffer, total_bytes, true); + return true; +} + +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + pico_trace("dcd_edpt_stall %d %02x\n", rhport, ep_addr); + assert(rhport == 0); + hw_endpoint_stall(ep_addr); +} + +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + pico_trace("dcd_edpt_clear_stall %d %02x\n", rhport, ep_addr); + assert(rhport == 0); + hw_endpoint_clear_stall(ep_addr); +} + + +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + // usbd.c says: In progress transfers on this EP may be delivered after this call + pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr); + +} + +#endif diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c new file mode 100644 index 000000000..c74578c3c --- /dev/null +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -0,0 +1,549 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED && CFG_TUSB_MCU == OPT_MCU_RP2040 + +#include "pico.h" +#include "rp2040_usb.h" + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "osal/osal.h" + +#include "host/hcd.h" +#include "host/usbh.h" +#include "host/usbh_hcd.h" + +#define ROOT_PORT 0 + +//--------------------------------------------------------------------+ +// Low level rp2040 controller functions +//--------------------------------------------------------------------+ + +#ifndef PICO_USB_HOST_INTERRUPT_ENDPOINTS +#define PICO_USB_HOST_INTERRUPT_ENDPOINTS (USB_MAX_ENDPOINTS - 1) +#endif +static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, ""); + +// Host mode uses one shared endpoint register for non-interrupt endpoint +struct hw_endpoint eps[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; +#define epx (eps[0]) + +#define usb_hw_set hw_set_alias(usb_hw) +#define usb_hw_clear hw_clear_alias(usb_hw) + +// Used for hcd pipe busy. +// todo still a bit wasteful +// top bit set if valid +uint8_t dev_ep_map[CFG_TUSB_HOST_DEVICE_MAX][1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS][2]; + +// Flags we set by default in sie_ctrl (we add other bits on top) +static uint32_t sie_ctrl_base = USB_SIE_CTRL_SOF_EN_BITS | + USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | + USB_SIE_CTRL_PULLDOWN_EN_BITS | + USB_SIE_CTRL_EP0_INT_1BUF_BITS; + +static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t num = tu_edpt_number(ep_addr); + if (num == 0) { + return &epx; + } + uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; + uint mapping = dev_ep_map[dev_addr-1][num][in]; + pico_trace("Get dev addr %d ep %d = %d\n", dev_addr, ep_addr, mapping); + return mapping >= 128 ? eps + (mapping & 0x7fu) : NULL; +} + +static void set_dev_ep(uint8_t dev_addr, uint8_t ep_addr, struct hw_endpoint *ep) +{ + uint8_t num = tu_edpt_number(ep_addr); + uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; + uint32_t index = ep - eps; + hard_assert(index < count_of(eps)); + // todo revisit why dev_addr can be 0 here + if (dev_addr) { + dev_ep_map[dev_addr-1][num][in] = 128u | index; + } + pico_trace("Set dev addr %d ep %d = %d\n", dev_addr, ep_addr, index); +} + +static inline uint8_t dev_speed(void) +{ + return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB; +} + +static bool need_pre(uint8_t dev_addr) +{ + // If this device is different to the speed of the root device + // (i.e. is a low speed device on a full speed hub) then need pre + return hcd_port_speed_get(0) != tuh_device_get_speed(dev_addr); +} + +static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result) +{ + // Mark transfer as done before we tell the tinyusb stack + uint8_t dev_addr = ep->dev_addr; + uint8_t ep_addr = ep->ep_addr; + uint total_len = ep->total_len; + hw_endpoint_reset_transfer(ep); + hcd_event_xfer_complete(dev_addr, ep_addr, total_len, xfer_result, true); +} + +static void _handle_buff_status_bit(uint bit, struct hw_endpoint *ep) +{ + usb_hw_clear->buf_status = bit; + bool done = _hw_endpoint_xfer_continue(ep); + if (done) + { + hw_xfer_complete(ep, XFER_RESULT_SUCCESS); + } +} + +static void hw_handle_buff_status(void) +{ + uint32_t remaining_buffers = usb_hw->buf_status; + pico_trace("buf_status 0x%08x\n", remaining_buffers); + + // Check EPX first + uint bit = 0b1; + if (remaining_buffers & bit) + { + remaining_buffers &= ~bit; + struct hw_endpoint *ep = &epx; + _handle_buff_status_bit(bit, ep); + } + + // Check interrupt endpoints + for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++) + { + // EPX is bit 0 + // IEP1 is bit 2 + // IEP2 is bit 4 + // IEP3 is bit 6 + // etc + bit = 1 << (i*2); + + if (remaining_buffers & bit) + { + remaining_buffers &= ~bit; + _handle_buff_status_bit(bit, &eps[i]); + } + } + + if (remaining_buffers) + { + panic("Unhandled buffer %d\n", remaining_buffers); + } +} + +static void hw_trans_complete(void) +{ + struct hw_endpoint *ep = &epx; + assert(ep->active); + + if (ep->sent_setup) + { + pico_trace("Sent setup packet\n"); + hw_xfer_complete(ep, XFER_RESULT_SUCCESS); + } + else + { + // Don't care. Will handle this in buff status + return; + } +} + +static void hcd_rp2040_irq(void) +{ + uint32_t status = usb_hw->ints; + uint32_t handled = 0; + + if (status & USB_INTS_HOST_CONN_DIS_BITS) + { + handled |= USB_INTS_HOST_CONN_DIS_BITS; + + if (dev_speed()) + { + hcd_event_device_attach(ROOT_PORT, true); + } + else + { + hcd_event_device_remove(ROOT_PORT, true); + } + + // Clear speed change interrupt + usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS; + } + + if (status & USB_INTS_TRANS_COMPLETE_BITS) + { + handled |= USB_INTS_TRANS_COMPLETE_BITS; + usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; + hw_trans_complete(); + } + + if (status & USB_INTS_BUFF_STATUS_BITS) + { + handled |= USB_INTS_BUFF_STATUS_BITS; + hw_handle_buff_status(); + } + + if (status & USB_INTS_STALL_BITS) + { + // We have rx'd a stall from the device + pico_trace("Stall REC\n"); + handled |= USB_INTS_STALL_BITS; + usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; + hw_xfer_complete(&epx, XFER_RESULT_STALLED); + } + + if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) + { + handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS; + usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; + } + + if (status & USB_INTS_ERROR_DATA_SEQ_BITS) + { + usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; + panic("Data Seq Error \n"); + } + + if (status ^ handled) + { + panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); + } +} + +static struct hw_endpoint *_next_free_interrupt_ep(void) +{ + struct hw_endpoint *ep = NULL; + for (uint i = 1; i < count_of(eps); i++) + { + ep = &eps[i]; + if (!ep->configured) + { + // Will be configured by _hw_endpoint_init / _hw_endpoint_allocate + ep->interrupt_num = i - 1; + return ep; + } + } + return ep; +} + +static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) +{ + struct hw_endpoint *ep = NULL; + if (transfer_type == TUSB_XFER_INTERRUPT) + { + ep = _next_free_interrupt_ep(); + pico_info("Allocate interrupt ep %d\n", ep->interrupt_num); + assert(ep); + ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; + ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; + // 0x180 for epx + // 0x1c0 for intep0 + // 0x200 for intep1 + // etc + ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 1)]; + } + else + { + ep = &epx; + ep->buffer_control = &usbh_dpram->epx_buf_ctrl; + ep->endpoint_control = &usbh_dpram->epx_ctrl; + ep->hw_data_buf = &usbh_dpram->epx_data[0]; + } + return ep; +} + +static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval) +{ + // Already has data buffer, endpoint control, and buffer control allocated at this point + assert(ep->endpoint_control); + assert(ep->buffer_control); + assert(ep->hw_data_buf); + + uint8_t num = tu_edpt_number(ep_addr); + bool in = ep_addr & TUSB_DIR_IN_MASK; + ep->ep_addr = ep_addr; + ep->dev_addr = dev_addr; + ep->in = in; + // For host, IN to host == RX, anything else rx == false + ep->rx = in == true; + ep->num = num; + // Response to a setup packet on EP0 starts with pid of 1 + ep->next_pid = num == 0 ? 1u : 0u; + ep->wMaxPacketSize = wMaxPacketSize; + ep->transfer_type = transfer_type; + + pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->transfer_type); + pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->hw_data_buf); + uint dpram_offset = hw_data_offset(ep->hw_data_buf); + // Bits 0-5 should be 0 + assert(!(dpram_offset & 0b111111)); + + // Fill in endpoint control register with buffer offset + uint32_t ep_reg = EP_CTRL_ENABLE_BITS + | EP_CTRL_INTERRUPT_PER_BUFFER + | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) + | dpram_offset; + ep_reg |= bmInterval ? (bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB : 0; + *ep->endpoint_control = ep_reg; + pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg); + ep->configured = true; + + if (bmInterval) + { + // This is an interrupt endpoint + // so need to set up interrupt endpoint address control register with: + // device address + // endpoint number / direction + // preamble + uint32_t reg = dev_addr | (ep->num << USB_ADDR_ENDP1_ENDPOINT_LSB); + // Assert the interrupt endpoint is IN_TO_HOST + assert(ep->in); + + if (need_pre(dev_addr)) + { + reg |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; + } + usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = reg; + + // Finally, enable interrupt that endpoint + usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1); + + // If it's an interrupt endpoint we need to set up the buffer control + // register + + } +} + +static void hw_endpoint_init(uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) +{ + // Allocated differently based on if it's an interrupt endpoint or not + struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); + _hw_endpoint_init(ep, + dev_addr, + ep_desc->bEndpointAddress, + ep_desc->wMaxPacketSize.size, + ep_desc->bmAttributes.xfer, + ep_desc->bInterval); + // Map this struct to ep@device address + set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); +} + +//--------------------------------------------------------------------+ +// HCD API +//--------------------------------------------------------------------+ +bool hcd_init(void) +{ + pico_trace("hcd_init\n"); + + // Reset any previous state + rp2040_usb_init(); + + irq_set_exclusive_handler(USBCTRL_IRQ, hcd_rp2040_irq); + + // clear epx and interrupt eps + memset(&eps, 0, sizeof(eps)); + + // Enable in host mode with SOF / Keep alive on + usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS; + usb_hw->sie_ctrl = sie_ctrl_base; + usb_hw->inte = USB_INTE_BUFF_STATUS_BITS | + USB_INTE_HOST_CONN_DIS_BITS | + USB_INTE_HOST_RESUME_BITS | + USB_INTE_STALL_BITS | + USB_INTE_TRANS_COMPLETE_BITS | + USB_INTE_ERROR_RX_TIMEOUT_BITS | + USB_INTE_ERROR_DATA_SEQ_BITS ; + + return true; +} + +void hcd_port_reset(uint8_t rhport) +{ + pico_trace("hcd_port_reset\n"); + assert(rhport == 0); + // TODO: Nothing to do here yet. Perhaps need to reset some state? +} + +bool hcd_port_connect_status(uint8_t rhport) +{ + pico_trace("hcd_port_connect_status\n"); + assert(rhport == 0); + return usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS; +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + pico_trace("hcd_port_speed_get\n"); + assert(rhport == 0); + // TODO: Should enumval this register + switch (dev_speed()) + { + case 1: + return TUSB_SPEED_LOW; + case 2: + return TUSB_SPEED_FULL; + default: + panic("Invalid speed\n"); + } +} + +// Close all opened endpoint belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + pico_trace("hcd_device_close %d\n", dev_addr); +} + +void hcd_int_enable(uint8_t rhport) +{ + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, true); +} + +void hcd_int_disable(uint8_t rhport) +{ + // todo we should check this is disabling from the correct core; note currently this is never called + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, false); +} + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) +{ + pico_info("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); + + // Get appropriate ep. Either EPX or interrupt endpoint + struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); + + if (ep_addr != ep->ep_addr) + { + // Direction has flipped so re init it but with same properties + _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); + } + + // True indicates this is the start of the transfer + _hw_endpoint_xfer(ep, buffer, buflen, true); + + // If a normal transfer (non-interrupt) then initiate using + // sie ctrl registers. Otherwise interrupt ep registers should + // already be configured + if (ep == &epx) { + // That has set up buffer control, endpoint control etc + // for host we have to initiate the transfer + usb_hw->dev_addr_ctrl = dev_addr | ep->num << USB_ADDR_ENDP_ENDPOINT_LSB; + uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base; + flags |= ep->rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS; + // Set pre if we are a low speed device on full speed hub + flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; + usb_hw->sie_ctrl = flags; + } + + return true; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + pico_info("hcd_setup_send dev_addr %d\n", dev_addr); + + // Copy data into setup packet buffer + memcpy((void*)&usbh_dpram->setup_packet[0], setup_packet, 8); + + // Configure EP0 struct with setup info for the trans complete + struct hw_endpoint *ep = _hw_endpoint_allocate(0); + // EP0 out + _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); + assert(ep->configured); + assert(ep->num == 0 && !ep->in); + ep->total_len = 8; + ep->transfer_size = 8; + ep->active = true; + ep->sent_setup = true; + + // Set device address + usb_hw->dev_addr_ctrl = dev_addr; + // Set pre if we are a low speed device on full speed hub + uint32_t flags = sie_ctrl_base | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS; + flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; + usb_hw->sie_ctrl = flags; + return true; +} + +uint32_t hcd_uframe_number(uint8_t rhport) +{ + // Microframe number is (125us) but we are max full speed so return miliseconds * 8 + return usb_hw->sof_rd * 8; +} + +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); + hw_endpoint_init(dev_addr, ep_desc); + return true; +} + +bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + // EPX is shared, so multiple device addresses and endpoint addresses share that + // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own + // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint + // on that device + pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); + struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); + assert(ep); + bool busy = ep->active; + pico_trace("busy == %d\n", busy); + return busy; +} + +bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) +{ + panic("hcd_pipe_stalled"); +} + +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +{ + panic("hcd_clear_stall"); + return true; +} + +bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + pico_trace("hcd_pipe_xfer dev_addr %d, ep_addr 0x%x, total_bytes %d, int_on_complete %d\n", + dev_addr, ep_addr, total_bytes, int_on_complete); + + // Same logic as hcd_edpt_xfer as far as I am concerned + hcd_edpt_xfer(0, dev_addr, ep_addr, buffer, total_bytes); + + return true; +} +#endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c new file mode 100644 index 000000000..a44607e99 --- /dev/null +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -0,0 +1,279 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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 file is part of the TinyUSB stack. + */ + +#include +#include "rp2040_usb.h" +#include "hardware/clocks.h" +#include "tusb_option.h" + +// Direction strings for debug +const char *ep_dir_string[] = { + "out", + "in", +}; + +static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { + // todo add critsec as necessary to prevent issues between worker and IRQ... + // note that this is perhaps as simple as disabling IRQs because it would make + // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. +} + +static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) +{ + ep->last_buf = ep->len + ep->transfer_size == ep->total_len; +} + +void rp2040_usb_init(void) +{ + // Reset usb controller + reset_block(RESETS_RESET_USBCTRL_BITS); + unreset_block_wait(RESETS_RESET_USBCTRL_BITS); + + // Clear any previous state just in case + memset(usb_hw, 0, sizeof(*usb_hw)); + memset(usb_dpram, 0, sizeof(*usb_dpram)); + + // Mux to phy + usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; +} + +void hw_endpoint_reset_transfer(struct hw_endpoint *ep) +{ + ep->stalled = false; + ep->active = false; + ep->sent_setup = false; + ep->total_len = 0; + ep->len = 0; + ep->transfer_size = 0; + ep->user_buf = 0; +} + +void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) { + uint32_t value = 0; + if (and_mask) { + value = *ep->buffer_control & and_mask; + } + if (or_mask) { + value |= or_mask; + if (or_mask & USB_BUF_CTRL_AVAIL) { + if (*ep->buffer_control & USB_BUF_CTRL_AVAIL) { + panic("ep %d %s was already available", ep->num, ep_dir_string[ep->in]); + } + *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; + // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz) + // Don't need delay in host mode as host is in charge +#ifndef RP2040_USB_HOST_MODE + __asm volatile ( + "b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1:\n" + : : : "memory"); +#endif + } + } + *ep->buffer_control = value; +} + +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) +{ + // Prepare buffer control register value + uint32_t val = ep->transfer_size | USB_BUF_CTRL_AVAIL; + + if (!ep->rx) + { + // Copy data from user buffer to hw buffer + memcpy(ep->hw_data_buf, &ep->user_buf[ep->len], ep->transfer_size); + // Mark as full + val |= USB_BUF_CTRL_FULL; + } + + // PID + val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + ep->next_pid ^= 1u; + + // Is this the last buffer? Only really matters for host mode. Will trigger + // the trans complete irq but also stop it polling. We only really care about + // trans complete for setup packets being sent + if (ep->last_buf) + { + pico_trace("Last buf (%d bytes left)\n", ep->transfer_size); + val |= USB_BUF_CTRL_LAST; + } + + // Finally, write to buffer_control which will trigger the transfer + // the next time the controller polls this dpram address + _hw_endpoint_buffer_control_set_value32(ep, val); + pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val); +} + + +void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) +{ + _hw_endpoint_lock_update(ep, 1); + pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, ep->num, ep_dir_string[ep->in]); + if (ep->active) + { + // TODO: Is this acceptable for interrupt packets? + pico_warn("WARN: starting new transfer on already active ep %d %s\n", ep->num, ep_dir_string[ep->in]); + + hw_endpoint_reset_transfer(ep); + } + + // Fill in info now that we're kicking off the hw + ep->total_len = total_len; + ep->len = 0; + // FIXME: What if low speed + ep->transfer_size = total_len > 64 ? 64 : total_len; + ep->active = true; + ep->user_buf = buffer; + // Recalculate if this is the last buffer + _hw_endpoint_update_last_buf(ep); + ep->buf_sel = 0; + + _hw_endpoint_start_next_buffer(ep); + _hw_endpoint_lock_update(ep, -1); +} + +void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) +{ + // Update hw endpoint struct with info from hardware + // after a buff status interrupt + + // Get the buffer state and amount of bytes we have + // transferred + uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + uint transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + +#ifdef RP2040_USB_HOST_MODE + // tag::host_buf_sel_fix[] + if (ep->buf_sel == 1) + { + // Host can erroneously write status to top half of buf_ctrl register + buf_ctrl = buf_ctrl >> 16; + } + // Flip buf sel for host + ep->buf_sel ^= 1u; + // end::host_buf_sel_fix[] +#endif + + // We are continuing a transfer here. If we are TX, we have successfullly + // sent some data can increase the length we have sent + if (!ep->rx) + { + assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); + pico_trace("tx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl); + ep->len += transferred_bytes; + } + else + { + // If we are OUT we have recieved some data, so can increase the length + // we have recieved AFTER we have copied it to the user buffer at the appropriate + // offset + pico_trace("rx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl); + assert(buf_ctrl & USB_BUF_CTRL_FULL); + memcpy(&ep->user_buf[ep->len], ep->hw_data_buf, transferred_bytes); + ep->len += transferred_bytes; + } + + // Sometimes the host will send less data than we expect... + // If this is a short out transfer update the total length of the transfer + // to be the current length + if ((ep->rx) && (transferred_bytes < ep->transfer_size)) + { + pico_trace("Short rx transfer\n"); + // Reduce total length as this is last packet + ep->total_len = ep->len; + } +} + +// Returns true if transfer is complete +bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) +{ + _hw_endpoint_lock_update(ep, 1); + // Part way through a transfer + if (!ep->active) + { + panic("Can't continue xfer on inactive ep %d %s", ep->num, ep_dir_string); + } + + // Update EP struct from hardware state + _hw_endpoint_xfer_sync(ep); + + // Now we have synced our state with the hardware. Is there more data to transfer? + uint remaining_bytes = ep->total_len - ep->len; + ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; + _hw_endpoint_update_last_buf(ep); + + // Can happen because of programmer error so check for it + if (ep->len > ep->total_len) + { + panic("Transferred more data than expected"); + } + + // If we are done then notify tinyusb + if (ep->len == ep->total_len) + { + pico_trace("Completed transfer of %d bytes on ep %d %s\n", + ep->len, ep->num, ep_dir_string[ep->in]); + // Notify caller we are done so it can notify the tinyusb + // stack + _hw_endpoint_lock_update(ep, -1); + return true; + } + else + { + _hw_endpoint_start_next_buffer(ep); + } + + _hw_endpoint_lock_update(ep, -1); + // More work to do + return false; +} + +void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start) +{ + // Trace + pico_trace("hw_endpoint_xfer ep %d %s", ep->num, ep_dir_string[ep->in]); + pico_trace(" total_len %d, start=%d\n", total_len, start); + + assert(ep->configured); + + + if (start) + { + _hw_endpoint_xfer_start(ep, buffer, total_len); + } + else + { + _hw_endpoint_xfer_continue(ep); + } +} + diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h new file mode 100644 index 000000000..7c3234e8d --- /dev/null +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -0,0 +1,124 @@ +#ifndef RP2040_COMMON_H_ +#define RP2040_COMMON_H_ + +#if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE) +#error TinyUSB device and host mode not supported at the same time +#endif + +#include "common/tusb_common.h" + +#include "pico.h" +#include "hardware/structs/usb.h" +#include "hardware/irq.h" +#include "hardware/resets.h" + +#if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) +#define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX +#endif + +// For memset +#include + +#if false && !defined(NDEBUG) +#define pico_trace(format,args...) printf(format, ## args) +#else +#define pico_trace(format,...) ((void)0) +#endif + +#if false && !defined(NDEBUG) +#define pico_info(format,args...) printf(format, ## args) +#else +#define pico_info(format,...) ((void)0) +#endif + +#if false && !defined(NDEBUG) +#define pico_warn(format,args...) printf(format, ## args) +#else +#define pico_warn(format,...) ((void)0) +#endif + +// Hardware information per endpoint +struct hw_endpoint +{ + // Is this a valid struct + bool configured; + // EP direction + bool in; + // EP num (not including direction) + uint8_t num; + + // Transfer direction (i.e. IN is rx for host but tx for device) + // allows us to common up transfer functions + bool rx; + + uint8_t ep_addr; + uint8_t next_pid; + + // Endpoint control register + io_rw_32 *endpoint_control; + // Buffer control register + io_rw_32 *buffer_control; + + // Buffer pointer in usb dpram + uint8_t *hw_data_buf; + + // Have we been stalled + bool stalled; + + // Current transfer information + bool active; + uint total_len; + uint len; + // Amount of data with the hardware + uint transfer_size; + // Only needed for host mode + bool last_buf; + // HOST BUG. Host will incorrect write status to top half of buffer + // control register when doing transfers > 1 packet + uint8_t buf_sel; + // User buffer in main memory + uint8_t *user_buf; + + // Data needed from EP descriptor + uint wMaxPacketSize; + // Interrupt, bulk, etc + uint8_t transfer_type; + + // Only needed for host + uint8_t dev_addr; + bool sent_setup; + // If interrupt endpoint + uint8_t interrupt_num; +}; + +void rp2040_usb_init(void); + +void hw_endpoint_reset_transfer(struct hw_endpoint *ep); +void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start); +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); +void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); +void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); +bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep); +void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); +static inline uint32_t _hw_endpoint_buffer_control_get_value32(struct hw_endpoint *ep) { + return *ep->buffer_control; +} +static inline void _hw_endpoint_buffer_control_set_value32(struct hw_endpoint *ep, uint32_t value) { + return _hw_endpoint_buffer_control_update32(ep, 0, value); +} +static inline void _hw_endpoint_buffer_control_set_mask32(struct hw_endpoint *ep, uint32_t value) { + return _hw_endpoint_buffer_control_update32(ep, ~value, value); +} +static inline void _hw_endpoint_buffer_control_clear_mask32(struct hw_endpoint *ep, uint32_t value) { + return _hw_endpoint_buffer_control_update32(ep, ~value, 0); +} + +static inline uintptr_t hw_data_offset(uint8_t *buf) +{ + // Remove usb base from buffer pointer + return (uintptr_t)buf ^ (uintptr_t)usb_dpram; +} + +extern const char *ep_dir_string[]; + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 2dd2b5841..a4eeeeb7c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -97,6 +97,9 @@ // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x +// Raspberry Pi +#define OPT_MCU_RP2040 1100 ///< Raspberry Pi RP2040 + /** @} */ /** \defgroup group_supported_os Supported RTOS @@ -106,6 +109,7 @@ #define OPT_OS_FREERTOS 2 ///< FreeRTOS #define OPT_OS_MYNEWT 3 ///< Mynewt OS #define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application +#define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK /** @} */ -- cgit v1.3.1 From c4f7ea09f1e5df01eecc2b223728e066c1d8fc02 Mon Sep 17 00:00:00 2001 From: Michael Himing Date: Thu, 28 Jan 2021 20:31:11 +1100 Subject: Fix midi sysex sending bug --- src/class/midi/midi_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index ce4c9cafe..9fff20be2 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -192,6 +192,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u if (midi->write_buffer[0] == 0x4) { if (data == 0xf7) { midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; } else { midi->write_target_length = 4; } -- cgit v1.3.1 From 2a34be2eb0654198f535afced31556d832b4bf58 Mon Sep 17 00:00:00 2001 From: Alexander Golovanov <45916903+homeodor@users.noreply.github.com> Date: Sat, 30 Jan 2021 04:11:08 +0300 Subject: A CDC-like blocking behaviour --- src/class/midi/midi_device.c | 48 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index ce4c9cafe..513f84caf 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -85,6 +85,32 @@ bool tud_midi_n_mounted (uint8_t itf) return midi->ep_in && midi->ep_out; } +static void _prep_out_transaction (midid_interface_t* p_midi) +{ + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_midi->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 >= sizeof(p_midi->epout_buf), ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); + + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_midi->rx_ff); + + if ( available >= sizeof(p_midi->epout_buf) ) { + usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_midi->ep_out); + } +} + //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -135,12 +161,17 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) { (void) jack_id; - tu_fifo_clear(&_midid_itf[itf].rx_ff); + midid_interface_t* p_midi = &_midid_itf[itf]; + tu_fifo_clear(&p_midi->rx_ff); + _prep_out_transaction(p_midi); } bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) { - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); + midid_interface_t* p_midi = &_midid_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); + _prep_out_transaction(p_midi); + return (num_read == 4); } void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { @@ -274,8 +305,8 @@ void midid_init(void) midid_interface_t* midi = &_midid_itf[i]; // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); + tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); @@ -366,11 +397,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } // Prepare for incoming data - if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE) ) - { - TU_LOG1_FAILED(); - TU_BREAKPOINT(); - } + _prep_out_transaction(p_midi); return drv_len; } @@ -391,6 +418,7 @@ bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; + (void) rhport; uint8_t itf; midid_interface_t* p_midi; @@ -414,7 +442,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 // prepare for next // TODO for now ep_out is not used by public API therefore there is no race condition, // and does not need to claim like ep_in - TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); + _prep_out_transaction(p_midi); } else if ( ep_addr == p_midi->ep_in ) { -- cgit v1.3.1 From 84406f1654ca757ecd7294f4b98b56146583be49 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 31 Jan 2021 19:08:23 +0100 Subject: Rework audio driver --- src/class/audio/audio_device.c | 410 ++++++++++++++++---------------- src/class/audio/audio_device.h | 317 +++++++++++++++--------- src/device/dcd.h | 12 +- src/device/usbd.c | 10 +- src/device/usbd_pvt.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 8 +- 6 files changed, 419 insertions(+), 340 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 616760223..07bfe6158 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -32,8 +32,6 @@ * * */ -// TODO: Rename CFG_TUD_AUDIO_EPSIZE_IN to CFG_TUD_AUDIO_EP_IN_BUFFER_SIZE - #include "tusb_option.h" #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) @@ -49,30 +47,17 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT -#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX -#endif -#endif - -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT -#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX -#endif -#endif - typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint16_t epin_buf_cnt; // Count filling status of EP in buffer - this is a shared state currently and is intended to be removed once EP buffers can be implemented as FIFOs! +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + uint8_t ep_in; // TX audio data EP. uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE uint8_t ep_out; // Incoming (into uC) audio data EP. uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) @@ -89,49 +74,60 @@ typedef struct #if CFG_TUD_AUDIO_N_AS_INT uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif + /*------------- From this point, data is not cleared by bus reset -------------*/ // Buffer for control requests CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; - // FIFO -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + // EP Transfer buffers and FIFOs +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; + tu_fifo_t ep_out_ff; + #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT]; + osal_mutex_def_t ep_out_ff_mutex; #endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif + #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE]; +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; + tu_fifo_t ep_in_ff; + #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT]; + osal_mutex_def_t ep_in_ff_mutex; #endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; + // Support FIFOs +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif - // Endpoint Transfer buffers -#if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif - #endif -#if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) - tu_fifo_t epin_ff; +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t int_ctr_ff_mutex; +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -149,11 +145,11 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); #endif @@ -167,34 +163,23 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_AUDIO); audiod_interface_t* audio = &_audiod_itf[itf]; -#if CFG_TUD_AUDIO_EPSIZE_OUT - if (audio->ep_out == 0) - { - return false; - } +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + if (audio->ep_out == 0) return false; #endif -#if CFG_TUD_AUDIO_EPSIZE_IN - if (audio->ep_in == 0) - { - return false; - } +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + if (audio->ep_in == 0) return false; #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) - { - return false; - } + if (audio->ep_int_ctr == 0) return false; #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) - { - return false; - } + if (audio->ep_fb == 0) return false; #endif return true; @@ -204,43 +189,58 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); } -void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) +void tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } -#else -uint16_t tud_audio_n_available(uint8_t itf) + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +// Delete all content in the support RX FIFOs +void tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } -uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } -void tud_audio_n_read_flush (uint8_t itf) +uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } #endif + #endif + + + + + + + + + #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN uint16_t tud_audio_int_ctr_n_available(uint8_t itf) @@ -261,9 +261,9 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) #endif // This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { @@ -281,7 +281,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! @@ -309,11 +309,11 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* return true; } -#endif //CFG_TUD_AUDIO_EPSIZE_OUT +#endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 +// The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_N_CHANNELS_RX > 1 static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -365,13 +365,53 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); return true; } -#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE +#endif // CFG_TUD_AUDIO_N_CHANNELS_RX > 1 +#endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); +} + +void tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); +} + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + audiod_interface_t* audio = &_audiod_itf[itf]; + uint16_t n_bytes_copied; + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); + return n_bytes_copied; +} + +uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); + +uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX, ); + return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); +} +#endif + +#endif + + + + + + /** * \brief Write data to EP in buffer * @@ -383,50 +423,28 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -#if CFG_TUD_AUDIO_EPSIZE_IN -#if !CFG_TUD_AUDIO_TX_FIFO_SIZE -/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } - - // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if audiod_tx_done_cb() is executed in between! - - // FOR SINGLE THREADED OPERATION: - // AS LONG AS THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + if (audio->p_desc == NULL) return 0; - // Determine free space - uint16_t free = CFG_TUD_AUDIO_EPSIZE_IN - audio->epin_buf_cnt; - - // Clip length if needed - if (len > free) len = free; - - // Write data - memcpy((void *) &audio->epin_buf[audio->epin_buf_cnt], data, len); - - audio->epin_buf_cnt += len; - - // Return number of bytes written - return len; + return tu_fifo_write_n(&audio->ep_in_ff, data, len); } -*/ #else -#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1 +#if CFG_TUD_AUDIO_N_CHANNELS_TX == 1 uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) { + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) - { - return 0; - } - return tu_fifo_write_n(&audio->tx_ff[0], data, len); + return 0; } + return tu_fifo_write_n(&audio->tx_ff[0], data, len); } #else uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) @@ -471,11 +489,11 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_EPSIZE_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16_t * n_bytes_copied) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -488,10 +506,10 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP in buffer by use of tud_audio_n_write_ep_in_buffer(). + // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -526,30 +544,11 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } #endif - // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if tud_audio_n_write_ep_in_buffer() is executed in between! - - // THIS IS NOT SOLVED SO FAR! - - // FOR SINGLE THREADED OPERATION: - // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + // Inform how many bytes will be copied + *n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit - // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); - - - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->epin_ff)); - - - - - - // Inform how many bytes were copied - *n_bytes_copied = audio->epin_buf_cnt; - - // Declare EP in buffer empty - audio->epin_buf_cnt = 0; - - // TO HERE + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, *n_bytes_copied)); // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); @@ -557,19 +556,18 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ return true; } -#endif //CFG_TUD_AUDIO_EPSIZE_IN +#endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { - // We encode directly into IN EP's buffer - abort if previous transfer not complete + // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; - uint16_t nBytesToSend; uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) @@ -582,58 +580,47 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* } // Check if there is enough - if (nSamplesPerChannelToSend == 0) - { - audio->epin_buf_cnt = 0; - return true; - } + if (nSamplesPerChannelToSend == 0) return true; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); - nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode uint16_t cntSample; - uint8_t * pBuff = audio->epin_buf; -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 - uint8_t sample; -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 - uint16_t sample; -#else - uint32_t sample; -#endif - // TODO: Big endianess handling for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) { for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - // Get sample from buffer - tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); + // If 8, 16, or 32 bit values are to be copied +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE + tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); +#else + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // Put it into EP's buffer - Let alignment problems be handled by memcpy - memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + // Get sample from buffer + tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); - // Advance pointer - pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); +#endif } } - - audio->epin_buf_cnt = nBytesToSend; - return true; } #else static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { + // TODO GET RID OF SINGLE TX_FIFO! + // We encode directly into IN EP's buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); - nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN); + nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE); // Check if there is enough if (nByteCount == 0) @@ -641,20 +628,17 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } - nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->epin_ff, 0, nByteCount); -// nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); - - audio->epin_buf_cnt = nByteCount; + nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->ep_in_ff, 0, nByteCount); return true; } -#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) +#endif // CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) -#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE +#endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) { uint8_t fb[4]; @@ -738,28 +722,34 @@ void audiod_init(void) { audiod_interface_t* audio = &_audiod_itf[i]; + // Initialize IN EP FIFO if required +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + // Initialize IN EP FIFO + tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#endif + // Initialize TX FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } - - // Initialize IN EP FIFO - tu_fifo_config(&audio->epin_ff, &audio->epin_buf, CFG_TUD_AUDIO_EPSIZE_IN, 1, true); - #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif + + // Initialize OUT EP FIFO + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); + } #endif @@ -781,19 +771,19 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EPSIZE_IN - tu_fifo_clear(&audio->epin_ff); +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); } @@ -891,7 +881,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; @@ -904,7 +894,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) { _audiod_itf[idxDriver].ep_out_as_intf_num = 0; @@ -945,7 +935,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -961,7 +951,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { @@ -973,7 +963,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1242,7 +1232,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE // Data transmission of audio packet finished if (_audiod_itf[idxDriver].ep_in == ep_addr) @@ -1264,16 +1254,16 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); return true; } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5061501ce..fdd4c15d4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -38,9 +38,11 @@ // Class Driver Configuration //--------------------------------------------------------------------+ +// All sizes are in bytes! + // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) #ifndef CFG_TUD_AUDIO_N_AS_INT -#define CFG_TUD_AUDIO_N_AS_INT 0 +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the descriptors! #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors @@ -48,20 +50,6 @@ #error You must define an audio class control request buffer size! #endif -// Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). -// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). -// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. -// Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). -// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and audio_tx_done_cb(). This, however, allows for optimizations. - -#ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel -#endif - -#ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel -#endif - // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX @@ -71,29 +59,90 @@ #define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +// Software EP FIFO buffer sizes - must be >= EP SIZEs! +#if CFG_TUD_AUDIO_EPSIZE_IN +#ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX #endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO_EPSIZE_OUT +#ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX #endif #endif +// General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#endif + +// Use of TX/RX support FIFOs + +// Support FIFOs are not mandatory for the audio driver, rather they are intended to be of use in +// - TX case: CFG_TUD_AUDIO_N_CHANNELS_TX channels need to be encoded into one USB output stream (currently PCM type I is implemented) +// - RX case: CFG_TUD_AUDIO_N_CHANNELS_RX channels need to be decoded from a single USB input stream (currently PCM type I is implemented) +// +// This encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the +// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using +// - tud_audio_n_write() or +// - tud_audio_n_read(). +// To write/read to/from the support FIFOs use +// - tud_audio_n_write_support_ff() or +// - tud_audio_n_read_support_ff(). +// +// The encoding/decoding format type done is defined below. +// +// The encoding/decoding starts when the private callback functions +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// are invoked. If support FIFOs are used the corresponding encoding/decoding functions are called from there. +// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// if you want to get informed what happened. +// +// If you don't use the support FIFOs you may use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. +// +// If you need a different encoding which is not support so far implement it in the +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// functions. + +// Size of support FIFOs - if size > 0 there are as many FIFOs set up as TX/RX channels defined +#ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#endif + +#ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX +#endif + +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -// Audio data format types +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif +#endif + +// Audio data format types - look in audio.h for existing types +// Used in case support FIFOs are used #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif @@ -110,8 +159,8 @@ #define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif #ifndef CFG_TUD_AUDIO_TX_ITEMSIZE @@ -136,8 +185,8 @@ #define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 @@ -170,69 +219,84 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); -void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); -#else -uint16_t tud_audio_n_available (uint8_t itf); -uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_n_read_flush (uint8_t itf); -#endif -#endif +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +uint16_t tud_audio_n_available (uint8_t itf); +uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO -/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +void tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -*/ -#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT -#define CFG_TUD_AUDIO_TX_FIFO_COUNT 1 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); -#else -uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +void tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO +uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif -uint16_t tud_audio_n_write_flush(uint8_t itf); + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_read_flush (uint8_t itf); -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_clear (uint8_t itf); // Delete all content in the AUDIO_INT_CTR FIFO +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ -static inline bool tud_audio_mounted (void); +static inline bool tud_audio_mounted (void); + +// RX API + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -static inline uint16_t tud_audio_available (void); -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline void tud_audio_read_flush (void); +static inline uint16_t tud_audio_available (void); +static inline void tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +static inline void tud_audio_clear_rx_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); -#else -static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize); #endif + +// TX API + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_write (const void * data, uint16_t len); +static inline uint16_t tud_audio_clear_ep_in_ff (void); + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +static inline uint16_t tud_audio_flush_tx_support_ff (void); +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); +#endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -static inline uint32_t tud_audio_int_ctr_available (void); -static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -static inline void tud_audio_int_ctr_read_flush (void); -static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +// INT CTR API + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static inline uint16_t tud_audio_int_ctr_available (void); +static inline uint16_t tud_audio_int_ctr_read (void* buffer, uint16_t bufsize); +static inline void tud_audio_int_ctr_clear (void); +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif // Buffer control EP data and schedule a transmit @@ -247,16 +311,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // User code should call this function with feedback value in 16.16 format for FS and HS. // Value will be corrected for FS to 10.14 format automatically. @@ -302,64 +367,82 @@ static inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN -#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +// RX API + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_available (void) { - return tud_audio_n_write(0, channelId, buffer, n_bytes); + return tud_audio_n_available(0); } -#else -static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used + +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize) { - return tud_audio_n_write(0, buffer, n_bytes); + return tud_audio_n_read(0, buffer, bufsize); } -#endif -static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used +static inline uint16_t tud_audio_clear_ep_out_ff (void) { -#if CFG_TUD_AUDIO_TX_FIFO_SIZE - return tud_audio_n_write_flush(0); -#else - return 0; -#endif + return tud_audio_n_clear_ep_out_ff(0); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_available(uint8_t channelId) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + +static inline void tud_audio_clear_rx_support_ff (uint8_t channelId) { - return tud_audio_n_available(0, channelId); + tud_audio_n_clear_rx_support_ff(0, channelId); } -static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) { - return tud_audio_n_read(0, channelId, buffer, bufsize); + return tud_audio_n_available_support_ff(0, channelId); } -static inline void tud_audio_read_flush(uint8_t channelId) +static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize) { - tud_audio_n_read_flush(0, channelId); + return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); } -#else -static inline uint16_t tud_audio_available(void) + +#endif + +#endif + +// TX API + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_write (const void * data, uint16_t len) { - return tud_audio_n_available(0); + return tud_audio_n_write(0, data, len); } -static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize) +static inline uint16_t tud_audio_clear_ep_in_ff (void) { - return tud_audio_n_read(0, buffer, bufsize); + return tud_audio_n_clear_ep_in_ff(0); } -static inline void tud_audio_read_flush(void) +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + +static inline uint16_t tud_audio_flush_tx_support_ff (void) { - tud_audio_n_read_flush(0); + return tud_audio_n_flush_tx_support_ff(0); } + +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId) +{ + return tud_audio_n_clear_tx_support_ff(0, channelId); +} + +static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len) +{ + return tud_audio_n_write_support_ff(0, channelId, data, len); +} + #endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static inline uint16_t tud_audio_int_ctr_available(void) { return tud_audio_int_ctr_n_available(0); @@ -370,25 +453,25 @@ static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) return tud_audio_int_ctr_n_read(0, buffer, bufsize); } -static inline void tud_audio_int_ctr_read_flush(void) +static inline void tud_audio_int_ctr_clear(void) { - return tud_audio_int_ctr_n_read_flush(0); + return tud_audio_int_ctr_n_clear(0); } -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { - return tud_audio_int_ctr_n_write(0, buffer, bufsize); + return tud_audio_int_ctr_n_write(0, buffer, len); } #endif //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/dcd.h b/src/device/dcd.h index 30224e16e..f0a552434 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -125,23 +125,23 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ // Event API (implemented by stack) diff --git a/src/device/usbd.c b/src/device/usbd.c index 4e18df757..2e2f9cf65 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,12 +1206,16 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, tu_fifo_count(ff)); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, count); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); @@ -1220,7 +1224,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_iso_xfer(rhport, ep_addr, ff) ) + if (dcd_edpt_iso_xfer(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 1d24957a9..412a97a5d 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 90fcd51e7..4cb6028cc 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,13 +670,15 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); - uint16_t total_bytes = tu_fifo_count(ff); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); -- cgit v1.3.1 From b2019e4d719a8b4560714081e5764525308b2924 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 8 Feb 2021 16:10:13 +0700 Subject: enhance gampepad report with dpad/hat support add hid_gamepad_report_t along with GAMEPAD_BUTTON_ and GAMEPAD_HAT_ enum --- src/class/hid/hid.h | 91 ++++++++++++++++++++++++++++++++++++++++++++++ src/class/hid/hid_device.h | 44 ++++++++++++++-------- 2 files changed, 119 insertions(+), 16 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 8803e4b66..cb1bd5835 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -143,6 +143,97 @@ typedef enum /** @} */ +//--------------------------------------------------------------------+ +// GAMEPAD +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Gamepad Gamepad + * @{ */ + +/* From https://www.kernel.org/doc/html/latest/input/gamepad.html + ____________________________ __ + / [__ZL__] [__ZR__] \ | + / [__ TL __] [__ TR __] \ | Front Triggers + __/________________________________\__ __| + / _ \ | + / /\ __ (N) \ | + / || __ |MO| __ _ _ \ | Main Pad + | <===DP===> |SE| |ST| (W) -|- (E) | | + \ || ___ ___ _ / | + /\ \/ / \ / \ (S) /\ __| + / \________ | LS | ____ | RS | ________/ \ | +| / \ \___/ / \ \___/ / \ | | Control Sticks +| / \_____/ \_____/ \ | __| +| / \ | + \_____/ \_____/ + + |________|______| |______|___________| + D-Pad Left Right Action Pad + Stick Stick + + |_____________| + Menu Pad + + Most gamepads have the following features: + - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. + - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. + - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. + - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also + provide a digital button if you press them. + - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons + are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. + - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. + */ + +/// HID Gamepad Protocol Report. +typedef struct TU_ATTR_PACKED +{ + int8_t x; ///< Delta x movement of left analog-stick + int8_t y; ///< Delta y movement of left analog-stick + int8_t z; ///< Delta z movement of right analog-joystick + int8_t rz; ///< Delta Rz movement of right analog-joystick + int8_t rx; ///< Delta Rx movement of analog left trigger + int8_t ry; ///< Delta Ry movement of analog right trigger + uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat + uint16_t buttons; ///< Buttons mask for currently pressed buttons +}hid_gamepad_report_t; + +/// Standard Gamepad Buttons Bitmap (from Linux input event codes) +typedef enum +{ + GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button + GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button + GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button + GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button + GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button + GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button + GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button + GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button + GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button + GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button + GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button + GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button + GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button +//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button +}hid_gamepad_button_bm_t; + +/// Standard Gamepad HAT/DPAD Buttons Bitmap (from Linux input event codes) +typedef enum +{ + GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED + GAMEPAD_HAT_UP = 1, ///< DPAD_UP + GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT + GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT + GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT + GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN + GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT + GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT + GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT +}hid_gamepad_hat_bm_t; + +/// @} + //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 456b011ba..f429d8b9a 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -301,14 +301,37 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 HID_COLLECTION_END \ // Gamepad Report Descriptor Template -// with 16 buttons and 2 joysticks with following layout -// | Button Map (2 bytes) | X | Y | Z | Rz +// with 16 buttons, 2 joysticks and 1 hat/dpad with following layout +// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (2 bytes) | #define TUD_HID_REPORT_DESC_GAMEPAD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ /* Report ID if any */\ __VA_ARGS__ \ + /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT ( 6 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 8 bit DPad/Hat Button Map */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ + HID_LOGICAL_MIN ( 1 ) ,\ + HID_LOGICAL_MAX ( 8 ) ,\ + HID_PHYSICAL_MIN ( 0 ) ,\ + HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ @@ -318,17 +341,6 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 HID_REPORT_COUNT ( 16 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* X, Y, Z, Rz (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_REPORT_COUNT ( 4 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ // HID Generic Input & Output -- cgit v1.3.1 From 72bcc0685c142c512f1d04ff18eaa13b99f62e93 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 8 Feb 2021 19:08:16 +0700 Subject: add tud_hid_n_gamepad_report() helper for gamepad report - Add gamepad to hid_composite example. Though it needs a bit of extra work but it will come later as separated PR. --- examples/device/hid_composite/src/main.c | 29 ++++++++++++++++++++++ .../device/hid_composite/src/usb_descriptors.c | 3 ++- .../device/hid_composite/src/usb_descriptors.h | 1 + .../hid_multiple_interface/src/usb_descriptors.c | 10 ++++---- src/class/hid/hid.h | 4 +-- src/class/hid/hid_device.c | 27 ++++++++++++++------ src/class/hid/hid_device.h | 6 +++++ 7 files changed, 65 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 6a9b6445d..45b8ba674 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -183,6 +183,35 @@ void hid_task(void) if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); has_consumer_key = false; } + + // delay a bit before sending next report + board_delay(10); + } + + /*------------- Gamepad -------------*/ + if ( tud_hid_ready() ) + { + // use to avoid send multiple consecutive zero report for keyboard + static bool has_gamepad_key = false; + + hid_gamepad_report_t report = + { + .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, + .hat = 0, .buttons = 0 + }; + + if ( btn ) + { + report.hat = GAMEPAD_HAT_UP; + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + + has_gamepad_key = true; + }else + { + report.hat = GAMEPAD_HAT_CENTERED; + if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + has_gamepad_key = false; + } } } diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 67ea34c08..fbe0e2550 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -75,7 +75,8 @@ uint8_t const desc_hid_report[] = { TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD )), TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE )), - TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )) + TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )), + TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD )) }; // Invoked when received GET HID REPORT DESCRIPTOR diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h index feda83dcd..7894719fd 100644 --- a/examples/device/hid_composite/src/usb_descriptors.h +++ b/examples/device/hid_composite/src/usb_descriptors.h @@ -30,6 +30,7 @@ enum REPORT_ID_KEYBOARD = 1, REPORT_ID_MOUSE, REPORT_ID_CONSUMER_CONTROL, + REPORT_ID_GAMEPAD }; #endif /* USB_DESCRIPTORS_H_ */ diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index 2354e5c1f..a28e57a2b 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -140,11 +140,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID - "Keyboard Interface", // 4: Interface 1 String - "Mouse Interface", // 5: Interface 2 String + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "Keyboard Interface", // 4: Interface 1 String + "Mouse Interface", // 5: Interface 2 String }; static uint16_t _desc_str[32]; diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index cb1bd5835..a7db087a7 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -218,7 +218,7 @@ typedef enum //GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button }hid_gamepad_button_bm_t; -/// Standard Gamepad HAT/DPAD Buttons Bitmap (from Linux input event codes) +/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) typedef enum { GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED @@ -230,7 +230,7 @@ typedef enum GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT -}hid_gamepad_hat_bm_t; +}hid_gamepad_hat_t; /// @} diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 1f03f8862..5b9735071 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -107,9 +107,6 @@ bool tud_hid_n_boot_mode(uint8_t itf) return _hidd_itf[itf].boot_mode; } -//--------------------------------------------------------------------+ -// KEYBOARD API -//--------------------------------------------------------------------+ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -127,10 +124,8 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } -//--------------------------------------------------------------------+ -// MOUSE APPLICATION API -//--------------------------------------------------------------------+ -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, + uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = { @@ -144,6 +139,24 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } +bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +{ + hid_gamepad_report_t report = + { + .x = x, + .y = y, + .z = z, + .rz = rz, + .rx = rx, + .ry = ry, + .hat = hat, + .buttons = buttons, + }; + + return tud_hid_n_report(itf, report_id, &report, sizeof(report)); +} + //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f429d8b9a..a92dc14e0 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -71,6 +71,10 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, // use template layout report as defined by hid_mouse_report_t bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +// Gamepad: convenient helper to send mouse report if application +// use template layout report TUD_HID_REPORT_DESC_GAMEPAD +bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -119,6 +123,8 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); #endif +// TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, ); + //--------------------------------------------------------------------+ // Inline Functions -- cgit v1.3.1 From d2b8e591f6f939f87c28aaa8b12f67a5072d2b06 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 9 Feb 2021 15:57:29 +0700 Subject: tud_hid_report_complete_cb() API update hid composite to make use of tud_hid_report_complete_cb() for sending reports when possible. --- changelog.md | 6 + examples/device/hid_composite/src/main.c | 189 ++++++++++++--------- .../device/hid_composite/src/usb_descriptors.c | 2 +- .../device/hid_composite/src/usb_descriptors.h | 3 +- src/class/hid/hid_device.c | 20 ++- src/class/hid/hid_device.h | 5 +- 6 files changed, 133 insertions(+), 92 deletions(-) (limited to 'src/class') diff --git a/changelog.md b/changelog.md index 393ca24ca..d645b4fbf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # TinyUSB Changelog +## WIP + +- Fix dropping MIDI sysex message when fifo is full +- Add DPad/Hat support for HID Gamepad +- Add tud_hid_report_complete_cb() API + ## 0.8.0 - 2021.02.05 ### Device Controller Driver diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 45b8ba674..9fb2de88d 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -104,114 +104,135 @@ void tud_resume_cb(void) // USB HID //--------------------------------------------------------------------+ -void hid_task(void) +static void send_hid_report(uint8_t report_id, uint32_t btn) { - // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; - - if ( board_millis() - start_ms < interval_ms) return; // not enough time - start_ms += interval_ms; + // skip if hid is not ready yet + if ( !tud_hid_ready() ) return; - uint32_t const btn = board_button_read(); - - // Remote wakeup - if ( tud_suspended() && btn ) + switch(report_id) { - // Wake up host if we are in suspend mode - // and REMOTE_WAKEUP feature is enabled by host - tud_remote_wakeup(); - } + case REPORT_ID_KEYBOARD: + { + // use to avoid send multiple consecutive zero report for keyboard + static bool has_keyboard_key = false; + + if ( btn ) + { + uint8_t keycode[6] = { 0 }; + keycode[0] = HID_KEY_A; + + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); + has_keyboard_key = true; + }else + { + // send empty key report if previously has key pressed + if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + has_keyboard_key = false; + } + } + break; - /*------------- Mouse -------------*/ - if ( tud_hid_ready() ) - { - if ( btn ) + case REPORT_ID_MOUSE: { int8_t const delta = 5; - // no button, right + down, no scroll pan + // no button, right + down, no scroll, no pan tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); - - // delay a bit before sending keyboard report - board_delay(10); } - } + break; - /*------------- Keyboard -------------*/ - if ( tud_hid_ready() ) - { - // use to avoid send multiple consecutive zero report for keyboard - static bool has_key = false; - - if ( btn ) + case REPORT_ID_CONSUMER_CONTROL: { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_A; - - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); + // use to avoid send multiple consecutive zero report + static bool has_consumer_key = false; + + if ( btn ) + { + // volume down + uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; + tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); + has_consumer_key = true; + }else + { + // send empty key report (release key) if previously has key pressed + uint16_t empty_key = 0; + if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + has_consumer_key = false; + } + } + break; - has_key = true; - }else + case REPORT_ID_GAMEPAD: { - // send empty key report if previously has key pressed - if (has_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); - has_key = false; + // use to avoid send multiple consecutive zero report for keyboard + static bool has_gamepad_key = false; + + hid_gamepad_report_t report = + { + .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, + .hat = 0, .buttons = 0 + }; + + if ( btn ) + { + report.hat = GAMEPAD_HAT_UP; + report.buttons = GAMEPAD_BUTTON_A; + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + + has_gamepad_key = true; + }else + { + report.hat = GAMEPAD_HAT_CENTERED; + report.buttons = 0; + if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + has_gamepad_key = false; + } } + break; - // delay a bit before sending consumer report - board_delay(10); + default: break; } +} - /*------------- Consume Control -------------*/ - if ( tud_hid_ready() ) - { - // use to avoid send multiple consecutive zero report - static bool has_consumer_key = false; - - if ( btn ) - { - // volume down - uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; - tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); +// Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) +// tud_hid_report_complete_cb() is used to send the next report after previous one is complete +void hid_task(void) +{ + // Poll every 10ms + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - has_consumer_key = true; - }else - { - // send empty key report (release key) if previously has key pressed - uint16_t empty_key = 0; - if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); - has_consumer_key = false; - } + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; - // delay a bit before sending next report - board_delay(10); - } + uint32_t const btn = board_button_read(); - /*------------- Gamepad -------------*/ - if ( tud_hid_ready() ) + // Remote wakeup + if ( tud_suspended() && btn ) { - // use to avoid send multiple consecutive zero report for keyboard - static bool has_gamepad_key = false; + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + }else + { + // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() + send_hid_report(REPORT_ID_KEYBOARD, btn); + } +} - hid_gamepad_report_t report = - { - .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, - .hat = 0, .buttons = 0 - }; +// Invoked when sent REPORT successfully to host +// Application can use this to send the next report +// Note: For composite reports, report[0] is report ID +void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) +{ + (void) itf; + (void) len; - if ( btn ) - { - report.hat = GAMEPAD_HAT_UP; - tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + uint8_t next_report_id = report[0] + 1; - has_gamepad_key = true; - }else - { - report.hat = GAMEPAD_HAT_CENTERED; - if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); - has_gamepad_key = false; - } + if (next_report_id < REPORT_ID_COUNT) + { + send_hid_report(next_report_id, board_button_read()); } } diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index fbe0e2550..e5f1ea703 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -107,7 +107,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 2) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h index 7894719fd..ca8925ad9 100644 --- a/examples/device/hid_composite/src/usb_descriptors.h +++ b/examples/device/hid_composite/src/usb_descriptors.h @@ -30,7 +30,8 @@ enum REPORT_ID_KEYBOARD = 1, REPORT_ID_MOUSE, REPORT_ID_CONSUMER_CONTROL, - REPORT_ID_GAMEPAD + REPORT_ID_GAMEPAD, + REPORT_ID_COUNT }; #endif /* USB_DESCRIPTORS_H_ */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 5b9735071..4cdcecc9e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -381,14 +381,24 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ uint8_t itf = 0; hidd_interface_t * p_hid = _hidd_itf; - for ( ; ; itf++, p_hid++) + // Identify which interface to use + for (itf = 0; itf < CFG_TUD_HID; itf++) { - if (itf >= TU_ARRAY_SIZE(_hidd_itf)) return false; - - if ( ep_addr == p_hid->ep_out ) break; + p_hid = &_hidd_itf[itf]; + if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; } + TU_ASSERT(itf < CFG_TUD_HID); - if (ep_addr == p_hid->ep_out) + // Sent report successfully + if (ep_addr == p_hid->ep_in) + { + if (tud_hid_report_complete_cb) + { + tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes); + } + } + // Received report + else if (ep_addr == p_hid->ep_out) { tud_hid_set_report_cb( #if CFG_TUD_HID > 1 diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index a92dc14e0..d5de53221 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -123,7 +123,10 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); #endif -// TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, ); +// Invoked when sent REPORT successfully to host +// Application can use this to send the next report +// Note: For composite reports, report[0] is report ID +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len); //--------------------------------------------------------------------+ -- cgit v1.3.1 From e12c25ec2c6d1cb0dd3c02bdc1947ae351ccad54 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 12:05:22 +0700 Subject: rename dfu_rt to dfu_runtime for easy reading also rename tud_dfu_rt_reboot_to_dfu to tud_dfu_runtime_reboot_to_dfu_cb --- examples/device/dfu_rt/src/main.c | 2 +- examples/device/dfu_rt/src/tusb_config.h | 2 +- src/class/dfu/dfu_rt_device.c | 4 ++-- src/class/dfu/dfu_rt_device.h | 2 +- src/device/usbd.c | 4 ++-- src/tusb.h | 2 +- src/tusb_option.h | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu_rt/src/main.c b/examples/device/dfu_rt/src/main.c index 029ff7312..823c71ae5 100644 --- a/examples/device/dfu_rt/src/main.c +++ b/examples/device/dfu_rt/src/main.c @@ -112,7 +112,7 @@ void tud_resume_cb(void) } // Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_rt_reboot_to_dfu(void) +void tud_dfu_runtime_reboot_to_dfu_cb(void) { blink_interval_ms = BLINK_DFU_MODE; } diff --git a/examples/device/dfu_rt/src/tusb_config.h b/examples/device/dfu_rt/src/tusb_config.h index abdbe7526..bdae1d2e9 100644 --- a/examples/device/dfu_rt/src/tusb_config.h +++ b/examples/device/dfu_rt/src/tusb_config.h @@ -78,7 +78,7 @@ //------------- CLASS -------------// -#define CFG_TUD_DFU_RT 1 +#define CFG_TUD_DFU_RUNTIME 1 #ifdef __cplusplus } diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 38644615a..5700615be 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RT) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" @@ -110,7 +110,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request { case DFU_REQUEST_DETACH: tud_control_status(rhport, request); - tud_dfu_rt_reboot_to_dfu(); + tud_dfu_runtime_reboot_to_dfu_cb(); break; case DFU_REQUEST_GETSTATUS: diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 643e25d8f..cff43d035 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -58,7 +58,7 @@ typedef enum //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention +TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.c b/src/device/usbd.c index d871a53d4..f4e4e08f3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -175,9 +175,9 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_DFU_RT + #if CFG_TUD_DFU_RUNTIME { - DRIVER_NAME("DFU-RT") + DRIVER_NAME("DFU-RUNTIME") .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, diff --git a/src/tusb.h b/src/tusb.h index 8b0dd103c..cc82c440d 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -92,7 +92,7 @@ #include "class/usbtmc/usbtmc_device.h" #endif - #if CFG_TUD_DFU_RT + #if CFG_TUD_DFU_RUNTIME #include "class/dfu/dfu_rt_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 73daf8592..6cbdefbf1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -233,8 +233,8 @@ #define CFG_TUD_USBTMC 0 #endif -#ifndef CFG_TUD_DFU_RT - #define CFG_TUD_DFU_RT 0 +#ifndef CFG_TUD_DFU_RUNTIME + #define CFG_TUD_DFU_RUNTIME 0 #endif #ifndef CFG_TUD_NET -- cgit v1.3.1 From a9fd0a454a96c599cb42f741c2e3e893b6c7306c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 12 Feb 2021 16:28:41 +0100 Subject: Complete redesign of audio driver. --- examples/device/audio_test/src/main.c | 12 +- examples/device/audio_test/src/tusb_config.h | 7 +- examples/device/audio_test/src/usb_descriptors.c | 2 +- examples/device/uac2_headset/src/tusb_config.h | 14 +- src/class/audio/audio_device.c | 524 +++++++++-------------- src/class/audio/audio_device.h | 61 ++- src/portable/st/synopsys/dcd_synopsys.c | 8 - 7 files changed, 235 insertions(+), 393 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 7f0ce3652..c63e64934 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -59,7 +59,7 @@ audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Vol audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_TX_FIFO_SIZE/2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_EPSIZE_IN/2]; uint16_t startVal = 0; void led_blinking_task(void); @@ -73,12 +73,12 @@ int main(void) tusb_init(); // Init values - sampFreq = 44100; + sampFreq = 48000; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = 44100; - sampleFreqRng.subrange[0].bMax = 44100; + sampleFreqRng.subrange[0].bMin = 48000; + sampleFreqRng.subrange[0].bMax = 48000; sampleFreqRng.subrange[0].bRes = 0; while (1) @@ -375,7 +375,7 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_TX_FIFO_SIZE); + tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EPSIZE_IN); return true; } @@ -388,7 +388,7 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_SIZE/2; cnt++) + for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_EPSIZE_IN/2; cnt++) { test_buffer_audio[cnt] = startVal++; } diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 5d94858ea..0744afdf0 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -90,7 +90,6 @@ extern "C" { //-------------------------------------------------------------------- // Audio format type -#define CFG_TUD_AUDIO_USE_TX_FIFO 1 #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I #define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED @@ -100,11 +99,11 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 48*2 // 48 Samples (48 kHz) x 2 Bytes/Sample (1/2 word) +#define CFG_TUD_AUDIO_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + 1; // Just for safety one sample more space // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_N_AS_INT 1 // Size of control request buffer #define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index 02d018823..d4869a940 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -102,7 +102,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 3, /*_nBitsUsedPerSample*/ 24, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ 48*4) + TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EPSIZE_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index d19feeb86..2ecfd59f6 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -112,20 +112,18 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_TX_FIFO_COUNT (CFG_TUD_AUDIO_IN_PATH * 1) -#define CFG_TUD_AUDIO_TX_FIFO_SIZE (CFG_TUD_AUDIO_IN_PATH ? ((CFG_TUD_AUDIO_EPSIZE_IN)) : 0) +#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_RX_FIFO_COUNT (CFG_TUD_AUDIO_OUT_PATH * 1) -#define CFG_TUD_AUDIO_RX_FIFO_SIZE (CFG_TUD_AUDIO_OUT_PATH ? (3 * (CFG_TUD_AUDIO_EPSIZE_OUT / CFG_TUD_AUDIO_RX_FIFO_COUNT)) : 0) +#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT*3 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_N_AS_INT 1 // Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 #ifdef __cplusplus } diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 07bfe6158..d1666056f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -103,6 +103,11 @@ typedef struct osal_mutex_def_t ep_in_ff_mutex; #endif +#endif + + // Audio control interrupt buffer - no FIFO +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif // Support FIFOs @@ -122,18 +127,6 @@ typedef struct #endif #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; -#endif -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; -#endif - } audiod_interface_t; #define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) @@ -146,11 +139,19 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio); +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); @@ -193,80 +194,70 @@ bool tud_audio_n_mounted(uint8_t itf) uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); } uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); } -void tud_audio_n_clear_ep_out_ff(uint8_t itf) +bool tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE // Delete all content in the support RX FIFOs -void tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) +bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } #endif #endif +// This function is called once an audio packet is received by the USB and is responsible for decoding received stream into audio channels. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - - - - - - - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - -uint16_t tud_audio_int_ctr_n_available(uint8_t itf) -{ - return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); -} - -uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) { - return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); -} + uint8_t idxDriver, idxItf; + uint8_t const *dummy2; -void tud_audio_int_ctr_n_read_flush (uint8_t itf) -{ - tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); -} + // If a callback is used determine current alternate setting of + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); + } -#endif + // Get number of bytes in EP OUT SW FIFO + uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); -// This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) -{ switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -280,12 +271,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); -#else -#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! -#endif + TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio)); break; default: @@ -303,8 +289,13 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* break; } - // Call a weak callback here - a possibility for user to get informed RX was completed - if (tud_audio_rx_done_cb) TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); +#endif + + // Prepare for next transmission + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); + + // Call a weak callback here - a possibility for user to get informed decoding was completed + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); return true; } @@ -313,59 +304,42 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* // The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#if CFG_TUD_AUDIO_N_CHANNELS_RX > 1 -static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { (void) rhport; - // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) - { - return false; - } + // We assume there is always the correct number of samples available for decoding - extra checks make no sense here - uint8_t chId = 0; - uint16_t cnt; -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 - uint8_t sample = 0; -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 - uint16_t sample = 0; -#else - uint32_t sample = 0; -#endif + uint16_t const n_bytes = tu_fifo_count(&audio->ep_out_ff); - for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) - { - // Let alignment problems be handled by memcpy - memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); - if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) - { - // Buffer overflow - return false; - } + uint16_t cnt = CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; - if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) - { - chId = 0; - } - } - return true; -} + while (cnt <= n_bytes) + { + for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) + { + // If 8, 16, or 32 bit values are to be copied +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE + // If this aborts then the target buffer is full + TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else -static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *audio, uint8_t *buffer, uint16_t bufsize) -{ - (void) rhport; + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) - { - return false; + // Get sample from buffer + TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); +#endif + } + + cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; } - tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); + // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it + // TU_VERIFY(cnt != n_bytes); + return true; } -#endif // CFG_TUD_AUDIO_N_CHANNELS_RX > 1 #endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE //--------------------------------------------------------------------+ @@ -374,126 +348,89 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +/** + * \brief Write data to EP in buffer + * + * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). + * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. + * + * \param[in] itf: Index of audio function interface + * \param[in] data: Pointer to data array to be copied from + * \param[in] len: # of array elements to copy + * \return Number of bytes actually written + */ uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); } -void tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); - tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + return tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); } #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); audiod_interface_t* audio = &_audiod_itf[itf]; - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); - return n_bytes_copied; -} - -uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); - -uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) -{ - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX, ); - return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); -} -#endif - -#endif - + uint16_t n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); + n_bytes_copied -= tu_fifo_count(&audio->ep_in_ff); + n_bytes_copied = n_bytes_copied*audio->ep_in_ff.item_size; + return n_bytes_copied; +} -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] itf: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) return 0; - - return tu_fifo_write_n(&audio->ep_in_ff, data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); } -#else - -#if CFG_TUD_AUDIO_N_CHANNELS_TX == 1 -uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) +uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) - { - return 0; - } - return tu_fifo_write_n(&audio->tx_ff[0], data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + return tu_fifo_write_n(&_audiod_itf[itf].tx_ff[channelId], data, len); } -#else -uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) -{ - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } +#endif - return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); -} #endif -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_n_write_flush(uint8_t itf) +// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user +uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t len) { - audiod_interface_t *audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); - return n_bytes_copied; -} + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr)); -#endif -#endif + // Check length + TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) -{ - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } + memcpy(_audiod_itf[itf].ep_int_ctr_buf, buffer, len); - return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr, _audiod_itf[itf].ep_int_ctr_buf, len)); + + return true; } #endif // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write. // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16_t * n_bytes_copied) +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -524,7 +461,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16 { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_tx_done_type_I_pcm_ff_cb(rhport, audio)); + TU_VERIFY(audiod_encode_type_I_pcm(rhport, audio)); break; @@ -544,14 +481,14 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16 } #endif - // Inform how many bytes will be copied - *n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); + // Send everything in ISO EP FIFO + uint16_t n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, *n_bytes_copied)); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); return true; } @@ -559,26 +496,29 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16 #endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#if CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) -static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) +// Take samples from the support buffer and encode them into the IN EP software FIFO +static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { uint16_t const count = tu_fifo_count(&audio->tx_ff[cntChannel]); - if (count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) + if (count < nSamplesPerChannelToSend) { - nSamplesPerChannelToSend = count * CFG_TUD_AUDIO_TX_ITEMSIZE; + nSamplesPerChannelToSend = count; } } + // Convert to sample size + nSamplesPerChannelToSend = nSamplesPerChannelToSend / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + // Check if there is enough if (nSamplesPerChannelToSend == 0) return true; @@ -608,106 +548,14 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* } return true; } - -#else -static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) -{ - // TODO GET RID OF SINGLE TX_FIFO! - - // We encode directly into IN EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); - - nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE); - - // Check if there is enough - if (nByteCount == 0) - { - return true; - } - - nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->ep_in_ff, 0, nByteCount); - - return true; -} -#endif // CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) - #endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent +// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) -{ - uint8_t fb[4]; - uint16_t len; - - if (audio->fb_val == 0) - { - len = 0; - return true; - } - else - { - len = 4; - // Here we need to return the feedback value - if (rhport == 0) - { - // For FS format is 10.14 - fb[0] = (audio->fb_val >> 2) & 0xFF; - fb[1] = (audio->fb_val >> 10) & 0xFF; - fb[2] = (audio->fb_val >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - fb[3] = 0; - } - else - { - // For HS format is 16.16 - fb[0] = (audio->fb_val >> 0) & 0xFF; - fb[1] = (audio->fb_val >> 8) & 0xFF; - fb[2] = (audio->fb_val >> 16) & 0xFF; - fb[3] = (audio->fb_val >> 24) & 0xFF; - } - return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len); - } - -} - -//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) -//{ -// (void) rhport; -// (void) audio; -// -// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); -// return 0; -//} - -#endif - -// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) { - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); - - // TODO: Big endianess handling - uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); - - if (cnt > 0) - { - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); - } - - *n_bytes_copied = cnt; - - if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); - - return true; + return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); } #endif @@ -724,11 +572,21 @@ void audiod_init(void) // Initialize IN EP FIFO if required #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - // Initialize IN EP FIFO tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); +#endif #endif - // Initialize TX FIFOs if required + // Initialize OUT EP FIFO if required +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); +#endif +#endif + + // Initialize TX support FIFOs if required #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { @@ -739,6 +597,7 @@ void audiod_init(void) } #endif + // Initialize RX support FIFOs if required #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { @@ -746,18 +605,7 @@ void audiod_init(void) #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif - - // Initialize OUT EP FIFO - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); - } -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 - tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); -#endif #endif } } @@ -775,6 +623,10 @@ void audiod_reset(uint8_t rhport) tu_fifo_clear(&audio->ep_in_ff); #endif +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + tu_fifo_clear(&audio->ep_out_ff); +#endif + #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { @@ -881,7 +733,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; @@ -932,10 +784,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! + //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -946,8 +798,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + // It is necessary to trigger this here since the refill is done with an TX FIFO empty interrupt which can only trigger if something was in there + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } #endif @@ -963,7 +815,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1218,16 +1070,10 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - // Load new data - uint16 *n_bytes_copied; - TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + // I assume here, that things above are handled by PHY + // All transmission is done - what remains to do is to inform job was completed - if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) - { - // There is no data left to send, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); } #endif @@ -1246,8 +1092,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1260,10 +1105,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); - - // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); +// TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); return true; } @@ -1275,14 +1118,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return audio_fb_send(rhport, &_audiod_itf[idxDriver]); + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + return audiod_fb_send(rhport, &_audiod_itf[idxDriver]); } #endif #endif } return false; - } bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) @@ -1458,14 +1301,37 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback) -{ - audiod_interface_t *audio = &_audiod_itf[0]; - - audio->fb_val = feedback; - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true); - return audio_fb_send(rhport, audio); +// Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically +bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + + // Format the feedback value + if (_audiod_itf[itf].rhport == 0) + { + uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + } + else + { + // For HS format is 16.16 as originally demanded + _audiod_itf[itf].fb_val = feedback; + } + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) + { + return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); + } + + return true; } #endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index fdd4c15d4..6e0b3308e 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -136,8 +136,8 @@ #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif #endif @@ -223,10 +223,10 @@ bool tud_audio_n_mounted (uint8_t itf); uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO +bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -void tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs +bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif @@ -236,20 +236,17 @@ uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelI #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); -void tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_clear (uint8_t itf); // Delete all content in the AUDIO_INT_CTR FIFO uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif @@ -264,11 +261,11 @@ static inline bool tud_audio_mounted (void); #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static inline uint16_t tud_audio_available (void); -static inline void tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO +static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static inline void tud_audio_clear_rx_support_ff (uint8_t channelId); +static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif @@ -280,7 +277,7 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static inline uint16_t tud_audio_write (const void * data, uint16_t len); -static inline uint16_t tud_audio_clear_ep_in_ff (void); +static inline bool tud_audio_clear_ep_in_ff (void); #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_flush_tx_support_ff (void); @@ -293,9 +290,6 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_available (void); -static inline uint16_t tud_audio_int_ctr_read (void* buffer, uint16_t bufsize); -static inline void tud_audio_int_ctr_clear (void); static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif @@ -317,8 +311,8 @@ TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_byte #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -327,11 +321,12 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // Value will be corrected for FS to 10.14 format automatically. // (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). // Feedback value will be sent at FB endpoint interval till it's changed. -bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback); +bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback); +static inline bool tud_audio_fb_set(uint32_t feedback); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); #endif // Invoked when audio set interface request received @@ -381,16 +376,16 @@ static inline uint16_t tud_audio_read (void* buffer, uint1 return tud_audio_n_read(0, buffer, bufsize); } -static inline uint16_t tud_audio_clear_ep_out_ff (void) +static inline bool tud_audio_clear_ep_out_ff (void) { return tud_audio_n_clear_ep_out_ff(0); } #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static inline void tud_audio_clear_rx_support_ff (uint8_t channelId) +static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { - tud_audio_n_clear_rx_support_ff(0, channelId); + return tud_audio_n_clear_rx_support_ff(0, channelId); } static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) @@ -416,7 +411,7 @@ static inline uint16_t tud_audio_write (const void * data, return tud_audio_n_write(0, data, len); } -static inline uint16_t tud_audio_clear_ep_in_ff (void) +static inline bool tud_audio_clear_ep_in_ff (void) { return tud_audio_n_clear_ep_in_ff(0); } @@ -443,24 +438,16 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_available(void) -{ - return tud_audio_int_ctr_n_available(0); -} - -static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) -{ - return tud_audio_int_ctr_n_read(0, buffer, bufsize); -} - -static inline void tud_audio_int_ctr_clear(void) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { - return tud_audio_int_ctr_n_clear(0); + return tud_audio_int_ctr_n_write(0, buffer, len); } +#endif -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static inline bool tud_audio_fb_set(uint32_t feedback) { - return tud_audio_int_ctr_n_write(0, buffer, len); + return tud_audio_n_fb_set(0, feedback); } #endif diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4cb6028cc..b6dacd927 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -697,14 +697,6 @@ bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); } - // EP0 can only handle one packet - if(epnum == 0) { - ep0_pending[dir] = total_bytes; - // Schedule the first transaction for EP0 transfer - edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); - return true; - } - uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t const short_packet_size = total_bytes % xfer->max_size; -- cgit v1.3.1 From 185414721ff549058a199ade40966015e6260996 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 12 Feb 2021 18:04:45 +0100 Subject: Formating --- src/class/audio/audio.h | 10 ++-- src/class/audio/audio_device.c | 116 ++++++++++++++++++++--------------------- src/class/audio/audio_device.h | 2 +- 3 files changed, 64 insertions(+), 64 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 05e61f8df..af0e86e21 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -901,7 +901,7 @@ typedef struct TU_ATTR_PACKED { } subrange[numSubRanges] ; \ } - /// 5.2.3.2 2-byte Control RANGE Parameter Block +/// 5.2.3.2 2-byte Control RANGE Parameter Block #define audio_control_range_2_n_t(numSubRanges) \ struct TU_ATTR_PACKED { \ uint16_t wNumSubRanges; \ @@ -912,7 +912,7 @@ typedef struct TU_ATTR_PACKED { } subrange[numSubRanges]; \ } - // 5.2.3.3 4-byte Control RANGE Parameter Block +// 5.2.3.3 4-byte Control RANGE Parameter Block #define audio_control_range_4_n_t(numSubRanges) \ struct TU_ATTR_PACKED { \ uint16_t wNumSubRanges; \ @@ -923,12 +923,12 @@ typedef struct TU_ATTR_PACKED { } subrange[numSubRanges]; \ } - /** @} */ +/** @} */ #ifdef __cplusplus - } +} #endif #endif - /** @} */ +/** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d1666056f..622e6d113 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -240,21 +240,21 @@ uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffe static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) { - uint8_t idxDriver, idxItf; - uint8_t const *dummy2; + uint8_t idxDriver, idxItf; + uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } + // If a callback is used determine current alternate setting of + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); + } - // Get number of bytes in EP OUT SW FIFO - uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); + // Get number of bytes in EP OUT SW FIFO + uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE @@ -316,23 +316,23 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) while (cnt <= n_bytes) { - for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) - { - // If 8, 16, or 32 bit values are to be copied + for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) + { + // If 8, 16, or 32 bit values are to be copied #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE - // If this aborts then the target buffer is full - TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + // If this aborts then the target buffer is full + TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else - // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO - uint32_t sample = 0; + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // Get sample from buffer - TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); - TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); + // Get sample from buffer + TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); #endif - } + } - cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; + cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -389,8 +389,8 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); - return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) @@ -574,15 +574,15 @@ void audiod_init(void) #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); #endif #endif // Initialize OUT EP FIFO if required #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); #endif #endif @@ -1105,8 +1105,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done -// TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); + // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); return true; } @@ -1305,33 +1305,33 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - - // Format the feedback value - if (_audiod_itf[itf].rhport == 0) - { - uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - } - else - { - // For HS format is 16.16 as originally demanded - _audiod_itf[itf].fb_val = feedback; - } - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) - { - return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); - } - - return true; + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + + // Format the feedback value + if (_audiod_itf[itf].rhport == 0) + { + uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + } + else + { + // For HS format is 16.16 as originally demanded + _audiod_itf[itf].fb_val = feedback; + } + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) + { + return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); + } + + return true; } #endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 6e0b3308e..34ba5bb55 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -447,7 +447,7 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) { - return tud_audio_n_fb_set(0, feedback); + return tud_audio_n_fb_set(0, feedback); } #endif -- cgit v1.3.1 From 9e2a1d2e6a22fb1cfb952a62f501403d372bbb45 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 12 Feb 2021 18:31:54 +0100 Subject: Fix CFG_TUD_AUDIO_EP_IN/OUT_SW_BUFFER_SIZE to be defined anyway --- src/class/audio/audio_device.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 34ba5bb55..d1d1157eb 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -64,21 +64,25 @@ #ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE #define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX #endif +#else +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE 0 #endif #if CFG_TUD_AUDIO_EPSIZE_OUT #ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE #define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX #endif +#else +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 #endif // General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 #endif // Use of TX/RX support FIFOs -- cgit v1.3.1 From f8fbc0930bd17b263ca702c0beb9f83af4429d0a Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Tue, 16 Feb 2021 10:40:06 -0500 Subject: Add alternate bitfield padding option Adds configuration option CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT, which substitutes bitfield variable " : 0" padding syntax with an unused variable of size equal to the remaining number of bits. This change resolves aligned access issues for some platforms. Default behavior is original if the option is not explicitly enabled. --- src/class/cdc/cdc.h | 22 +++++++++++++++++++++- src/common/tusb_types.h | 6 +++++- src/host/ehci/ehci.h | 13 ++++++++++--- src/host/hub.h | 8 ++++++-- src/host/ohci/ohci.h | 12 ++++++++++-- src/tusb_option.h | 4 ++++ 6 files changed, 56 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 2c044ac7f..ec31ee4cf 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -277,7 +277,11 @@ typedef struct TU_ATTR_PACKED struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 6; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; uint8_t bDataInterface; @@ -290,7 +294,11 @@ typedef struct TU_ATTR_PACKED uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. uint8_t support_send_break : 1; ///< Device supports the request Send_Break uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 4; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }cdc_acm_capability_t; TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); @@ -316,7 +324,11 @@ typedef struct TU_ATTR_PACKED uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 5; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; }cdc_desc_func_direct_line_management_t; @@ -344,7 +356,11 @@ typedef struct TU_ATTR_PACKED uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 5; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; }cdc_desc_func_telephone_operational_modes_t; @@ -363,7 +379,11 @@ typedef struct TU_ATTR_PACKED uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 26; +#else uint32_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; }cdc_desc_func_telephone_call_state_reporting_capabilities_t; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 2b4ceb69c..e57dc26f5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -342,7 +342,11 @@ typedef struct TU_ATTR_PACKED struct TU_ATTR_PACKED { uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint16_t unused : 3; +#else uint16_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index a6342b2d2..acaf545c1 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -231,7 +231,11 @@ typedef struct TU_ATTR_ALIGNED(32) uint32_t : 1; ///< reserved uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. - uint32_t : 0; // padding to the end of current storage unit +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + ///< All 32 bits are used +#else + uint32_t : 0; // padding to the end of current storage unit +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ // Word 2: Micro-frame Schedule Control uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions @@ -423,7 +427,11 @@ typedef volatile struct uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. uint32_t : 1; uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 4; ///< padding +#else uint32_t : 0; // padding to the boundary of storage unit +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }portsc_bm; }; }ehci_registers_t; @@ -461,4 +469,3 @@ typedef struct /** @} */ /** @} */ - diff --git a/src/host/hub.h b/src/host/hub.h index 35d8ad629..0e3292274 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -163,7 +163,11 @@ typedef struct { uint16_t high_speed : 1; uint16_t port_test_mode : 1; uint16_t port_indicator_control : 1; - uint16_t : 0; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint16_t unused : 3; +#else + uint16_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }; uint16_t value; diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index bfcdaf9a3..76d6fff61 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -208,7 +208,11 @@ typedef volatile struct uint32_t interrupt_routing : 1; uint32_t remote_wakeup_connected : 1; uint32_t remote_wakeup_enale : 1; - uint32_t : 0; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 21; +#else + uint32_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }control_bit; }; @@ -276,7 +280,11 @@ typedef volatile struct uint32_t port_suspend_status_change : 1; uint32_t port_over_current_indicator_change : 1; uint32_t port_reset_status_change : 1; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 11; +#else uint32_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }rhport_status_bit[2]; }; }ohci_registers_t; diff --git a/src/tusb_option.h b/src/tusb_option.h index 6cbdefbf1..b5504d29c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -197,6 +197,10 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +#ifndef CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + #define CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT 0 +#endif + //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From 189b357b54614a770232ac9fa95d56d173efe302 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 21:42:44 +0100 Subject: Implement an evasion linear buffer for MCUs not capable for EP FIFO Also MCUs using DMAs are within this list, however, these can use an EP FIFO. There is just no time for implementation --- src/class/audio/audio_device.c | 55 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 622e6d113..7b7c61750 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -125,6 +125,41 @@ typedef struct #if CFG_FIFO_MUTEX osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif +#endif + + // Evasion buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_RP2040) || /* Don't want to change driver */ \ + CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ + CFG_TUSB_MCU == OPT_MCU_LPC40XX) + +#define USE_EVADE_BUFFER 1 + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#endif + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#endif + +#endif + +#ifndef USE_EVADE_BUFFER +#define USE_EVADE_BUFFER 0 #endif } audiod_interface_t; @@ -292,7 +327,11 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) #endif // Prepare for next transmission +#if USE_EVADE_BUFFER + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, &audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); +#endif // Call a weak callback here - a possibility for user to get informed decoding was completed if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); @@ -485,7 +524,12 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) uint16_t n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit +#if USE_EVADE_BUFFER + tu_fifo_write_n(&audio->ep_in_ff, &audio->evasion_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, &audio->evasion_buf_in, n_bytes_tx)); +#else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); +#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); @@ -815,7 +859,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); +#if USE_EVADE_BUFFER + TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#else + TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#endif } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1106,6 +1154,11 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { // Save into buffer - do whatever has to be done // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); + +#if USE_EVADE_BUFFER + TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, &_audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO +#endif + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); return true; -- cgit v1.3.1 From e407ce463d007231f0d24e55768c1d0ab3b2c049 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 21:47:01 +0100 Subject: Add SAMD MCUs to buffer evasion list --- src/class/audio/audio_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7b7c61750..c93de9380 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -144,7 +144,11 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX) + CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ + CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ + CFG_TUSB_MCU == OPT_MCU_SAME5X) #define USE_EVADE_BUFFER 1 -- cgit v1.3.1 From eee47493a336eb334fdd7f1713903e2131a86650 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 21:59:32 +0100 Subject: Fix bug in evasion buffer list --- src/class/audio/audio_device.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c93de9380..9dd2ee704 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -132,7 +132,7 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_RP2040) || /* Don't want to change driver */ \ + CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ @@ -148,7 +148,7 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ - CFG_TUSB_MCU == OPT_MCU_SAME5X) + CFG_TUSB_MCU == OPT_MCU_SAME5X ) #define USE_EVADE_BUFFER 1 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9d813d4a5..0d25cceb8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -984,7 +984,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN { // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part - void *__restrict src; + void * src; uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA tu_fifo_advance_read_pointer(ff, len); @@ -1064,7 +1064,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB { // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part - void *__restrict dst; + void * dst; uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); tu_fifo_advance_write_pointer(ff, len); -- cgit v1.3.1 From 53a796a92ea853ea5af16431ba2a6bed8a3c7b5a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 22:29:40 +0100 Subject: Fix wrong pointer type. --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 9dd2ee704..2db1e8b58 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -332,7 +332,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) // Prepare for next transmission #if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, &audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); #endif @@ -529,8 +529,8 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Schedule transmit #if USE_EVADE_BUFFER - tu_fifo_write_n(&audio->ep_in_ff, &audio->evasion_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, &audio->evasion_buf_in, n_bytes_tx)); + tu_fifo_write_n(&audio->ep_in_ff, audio->evasion_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->evasion_buf_in, n_bytes_tx)); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); #endif -- cgit v1.3.1 From 681cfd0bf21cc0e977cb3e5294c7a1edbb4f0928 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 11:12:16 +0100 Subject: Correct for wrong pointer type in audio_device.c --- src/class/audio/audio_device.c | 4 ++-- src/common/tusb_fifo.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2db1e8b58..527aecc0d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -864,7 +864,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Prepare for incoming data #if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); #endif @@ -1160,7 +1160,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); #if USE_EVADE_BUFFER - TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, &_audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO + TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, _audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO #endif TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 19f120a33..eb88538ef 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.3.1 From c098da9803a091c4b2402057ece370975850ef53 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 19:25:08 +0100 Subject: Implement left and right justifications for 24 to 32 bit PCM encoding --- src/class/audio/audio_device.c | 10 ++++++++-- src/class/audio/audio_device.h | 12 ++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 527aecc0d..c71ad6b8e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -366,11 +366,15 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) // If this aborts then the target buffer is full TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else - // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO uint32_t sample = 0; // Get sample from buffer TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + +#if CFG_TUD_AUDIO_JUSTIFICATION_RX == CFG_TUD_AUDIO_LEFT_JUSTIFIED + sample = sample << 8; +#endif + TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); #endif } @@ -584,12 +588,14 @@ static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); #else - // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO uint32_t sample = 0; // Get sample from buffer tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); +#if CFG_TUD_AUDIO_JUSTIFICATION_TX == CFG_TUD_AUDIO_LEFT_JUSTIFIED + sample = sample << 8; +#endif tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); #endif } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d1d1157eb..38495f72d 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -203,6 +203,18 @@ #endif +// In case PCM encoding/decoding of 24 into 32 bits, the adjustment needs to be defined +#define CFG_TUD_AUDIO_LEFT_JUSTIFIED +#define CFG_TUD_AUDIO_RIGHT_JUSTIFIED + +#ifndef CFG_TUD_AUDIO_JUSTIFICATION_RX +#define CFG_TUD_AUDIO_JUSTIFICATION_RX CFG_TUD_AUDIO_LEFT_JUSTIFIED +#endif + +#ifndef CFG_TUD_AUDIO_JUSTIFICATION_TX +#define CFG_TUD_AUDIO_JUSTIFICATION_TX CFG_TUD_AUDIO_LEFT_JUSTIFIED +#endif + //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); // Supported types of this driver: -- cgit v1.3.1 From 21f1cd4ec7e2104ac88b26be5c06e81e385cd660 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 18 Feb 2021 13:26:03 -0500 Subject: Implement requested PR changes Removes CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT, and makes the manual padding behavior standard. Replaced unused variable name with TU_RESERVED. --- src/class/cdc/cdc.h | 30 +++++------------------------- src/common/tusb_types.h | 6 +----- src/host/ehci/ehci.h | 11 +---------- src/host/hub.h | 6 +----- src/host/ohci/ohci.h | 12 ++---------- src/tusb_option.h | 4 ---- 6 files changed, 10 insertions(+), 59 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index ec31ee4cf..f59bf0f1a 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -277,11 +277,7 @@ typedef struct TU_ATTR_PACKED struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 6; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 6; } bmCapabilities; uint8_t bDataInterface; @@ -294,11 +290,7 @@ typedef struct TU_ATTR_PACKED uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. uint8_t support_send_break : 1; ///< Device supports the request Send_Break uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 4; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); @@ -324,11 +316,7 @@ typedef struct TU_ATTR_PACKED uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 5; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_direct_line_management_t; @@ -356,11 +344,7 @@ typedef struct TU_ATTR_PACKED uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 5; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_telephone_operational_modes_t; @@ -379,11 +363,7 @@ typedef struct TU_ATTR_PACKED uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 26; -#else - uint32_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 26; } bmCapabilities; }cdc_desc_func_telephone_call_state_reporting_capabilities_t; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index e57dc26f5..ba3fe2c41 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -342,11 +342,7 @@ typedef struct TU_ATTR_PACKED struct TU_ATTR_PACKED { uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint16_t unused : 3; -#else - uint16_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint16_t TU_RESERVED : 3; }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index acaf545c1..d8218a5fd 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -231,11 +231,6 @@ typedef struct TU_ATTR_ALIGNED(32) uint32_t : 1; ///< reserved uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - ///< All 32 bits are used -#else - uint32_t : 0; // padding to the end of current storage unit -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ // Word 2: Micro-frame Schedule Control uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions @@ -427,11 +422,7 @@ typedef volatile struct uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. uint32_t : 1; uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 4; ///< padding -#else - uint32_t : 0; // padding to the boundary of storage unit -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 4; }portsc_bm; }; }ehci_registers_t; diff --git a/src/host/hub.h b/src/host/hub.h index 0e3292274..851bb8e66 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -163,11 +163,7 @@ typedef struct { uint16_t high_speed : 1; uint16_t port_test_mode : 1; uint16_t port_indicator_control : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint16_t unused : 3; -#else - uint16_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint16_t TU_RESERVED : 3; }; uint16_t value; diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index 76d6fff61..2915f8b00 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -208,11 +208,7 @@ typedef volatile struct uint32_t interrupt_routing : 1; uint32_t remote_wakeup_connected : 1; uint32_t remote_wakeup_enale : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 21; -#else - uint32_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 21; }control_bit; }; @@ -280,11 +276,7 @@ typedef volatile struct uint32_t port_suspend_status_change : 1; uint32_t port_over_current_indicator_change : 1; uint32_t port_reset_status_change : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 11; -#else - uint32_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 11; }rhport_status_bit[2]; }; }ohci_registers_t; diff --git a/src/tusb_option.h b/src/tusb_option.h index b5504d29c..6cbdefbf1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -197,10 +197,6 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif -#ifndef CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - #define CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT 0 -#endif - //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From aa850991715e2a6dcaa33a370b0ae702a33c1d54 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Feb 2021 10:51:47 +0700 Subject: fix tud_midi_write24 typo rename jack_id to cable_num in function argument --- src/class/midi/midi_device.c | 18 +++++++++--------- src/class/midi/midi_device.h | 26 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index b9d6b2efc..325fc4669 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -114,15 +114,15 @@ static void _prep_out_transaction (midid_interface_t* p_midi) //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id) +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { - (void) jack_id; + (void) cable_num; return tu_fifo_count(&_midid_itf[itf].rx_ff); } -uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize) +uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { - (void) jack_id; + (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; // Fill empty buffer @@ -158,9 +158,9 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu return n; } -void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) +void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) { - (void) jack_id; + (void) cable_num; midid_interface_t* p_midi = &_midid_itf[itf]; tu_fifo_clear(&p_midi->rx_ff); _prep_out_transaction(p_midi); @@ -205,7 +205,7 @@ static uint32_t write_flush(midid_interface_t* midi) } } -uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) +uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; if (midi->itf_num == 0) { @@ -228,7 +228,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u midi->write_target_length = 4; } } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->write_buffer[0] = jack_id << 4 | msg; + midi->write_buffer[0] = cable_num << 4 | msg; midi->write_target_length = 4; } else if (msg == 0xf) { if (data == 0xf0) { @@ -246,7 +246,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u } } else { // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = jack_id << 4 | 0xf; + midi->write_buffer[0] = cable_num << 4 | 0xf; midi->write_buffer[2] = 0; midi->write_buffer[3] = 0; midi->write_buffer_length = 2; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 9235448f2..5e7df80ae 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -60,13 +60,13 @@ // CFG_TUD_MIDI > 1 //--------------------------------------------------------------------+ bool tud_midi_n_mounted (uint8_t itf); -uint32_t tud_midi_n_available (uint8_t itf, uint8_t jack_id); -uint32_t tud_midi_n_read (uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize); -void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id); -uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize); +uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); +void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline -uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); @@ -78,8 +78,8 @@ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); -static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize); -static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); static inline bool tud_midi_receive (uint8_t packet[4]); static inline bool tud_midi_send (uint8_t const packet[4]); @@ -92,10 +92,10 @@ TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); // Inline Functions //--------------------------------------------------------------------+ -static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3) +static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) { uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_n_write(itf, jack_id, msg, 3); + return tud_midi_n_write(itf, cable_num, msg, 3); } static inline bool tud_midi_mounted (void) @@ -118,15 +118,15 @@ static inline void tud_midi_read_flush (void) tud_midi_n_read_flush(0, 0); } -static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { - return tud_midi_n_write(0, jack_id, buffer, bufsize); + return tud_midi_n_write(0, cable_num, buffer, bufsize); } -static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3) +static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) { uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_write(jack_id, msg, 3); + return tud_midi_write(cable_num, msg, 3); } static inline bool tud_midi_receive (uint8_t packet[4]) -- cgit v1.3.1 From f2ed2ae09a480835eacf049d8959b3c904713be7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 11:14:19 +0700 Subject: rename tuh_msc_scsi_inquiry() to tuh_msc_inquiry() --- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index a45fba737..5e2ea308a 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -82,7 +82,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) block_size = block_count = 0; uint8_t const lun = 0; - tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); + tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // // //------------- file system (only 1 LUN support) -------------// // uint8_t phy_disk = dev_addr-1; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 02ca81e77..9a44d0632 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -139,7 +139,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); } -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) { msc_cbw_t cbw = { 0 }; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 5913350b8..61f6e6a21 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -70,7 +70,7 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); // Carry out SCSI INQUIRY command in non-blocking manner. -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); // Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); -- cgit v1.3.1 From ade4bf74ea7343bcebff4c1b2bbd1ebaac9009c0 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 11:38:15 +0700 Subject: update function comment --- src/class/msc/msc_host.h | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 61f6e6a21..3d1963701 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -51,34 +51,27 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() bool tuh_msc_mounted(uint8_t dev_addr); -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer - * can be scheduled. User needs to make sure the corresponding interface is mounted (by \ref tuh_msc_is_mounted) - * before calling this function - */ -bool tuh_msc_is_busy(uint8_t dev_addr); +// Check if the interface is currently busy transferring data +bool tuh_msc_is_busy(uint8_t dev_addr); // Get Max Lun uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); -// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner. +// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. // `complete_cb` callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI INQUIRY command in non-blocking manner. +// Perform SCSI Inquiry command bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +// Perform SCSI Test Unit Ready command bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +// Perform SCSI Request Sense (10) command bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI READ CAPACITY (10) command in non-blocking manner. +// Perform SCSI Read Capacity (10) command bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 -- cgit v1.3.1 From 386a386345fbaa1a9c63a4346c2d946fe015da72 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 12:20:30 +0700 Subject: clean up host msc --- src/class/msc/msc_host.c | 91 +++++++++++++++++++++++------------------------- src/class/msc/msc_host.h | 38 ++++++++------------ 2 files changed, 57 insertions(+), 72 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ce3693dcb..943dc541f 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -99,11 +99,12 @@ bool tuh_msc_is_busy(uint8_t dev_addr) //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ -static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) +static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) { - p_cbw->signature = MSC_CBW_SIGNATURE; - p_cbw->tag = 0x54555342; // TUSB - p_cbw->lun = lun; + tu_memclr(cbw, sizeof(msc_cbw_t)); + cbw->signature = MSC_CBW_SIGNATURE; + cbw->tag = 0x54555342; // TUSB + cbw->lun = lun; } bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) @@ -126,11 +127,11 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - if ( !p_msc->mounted ) return false; + TU_VERIFY(p_msc->mounted); - msc_cbw_t cbw = { 0 }; + msc_cbw_t cbw; + cbw_init(&cbw, lun); - msc_cbw_add_signature(&cbw, lun); cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_read_capacity10_t); @@ -141,9 +142,9 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msc_cbw_t cbw = { 0 }; + msc_cbw_t cbw; + cbw_init(&cbw, lun); - msc_cbw_add_signature(&cbw, lun); cbw.total_bytes = sizeof(scsi_inquiry_resp_t); cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_inquiry_t); @@ -160,8 +161,8 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { - msc_cbw_t cbw = { 0 }; - msc_cbw_add_signature(&cbw, lun); + msc_cbw_t cbw; + cbw_init(&cbw, lun); cbw.total_bytes = 0; // Number of bytes cbw.dir = TUSB_DIR_OUT; @@ -174,8 +175,8 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) { - msc_cbw_t cbw = { 0 }; - msc_cbw_add_signature(&cbw, lun); + msc_cbw_t cbw; + cbw_init(&cbw, lun); cbw.total_bytes = 18; // TODO sense response cbw.dir = TUSB_DIR_IN_MASK; @@ -192,58 +193,52 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); } -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - if ( !p_msc->mounted ){ return false;}; + TU_VERIFY(p_msc->mounted); - msc_cbw_t cbw = { 0 }; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&cbw, lun); + msc_cbw_t cbw; + cbw_init(&cbw, lun); - cbw.total_bytes = 512*block_count; // Number of bytes + cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_read10_t); - //------------- SCSI command -------------// scsi_read10_t cmd_read10 = { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; memcpy(cbw.command, &cmd_read10, cbw.cmd_len); - return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); + return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb); } -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = get_itf(dev_addr); - if ( !p_msc->mounted ){ return false;}; - - msc_cbw_t cbw = { 0 }; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&cbw, lun); - - cbw.total_bytes = 512*block_count; // Number of bytes - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); - //------------- SCSI command -------------// - scsi_write10_t cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); + + scsi_write10_t cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) + }; + + memcpy(cbw.command, &cmd_write10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, (void*) buffer, complete_cb); } #if 0 diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index d80e3e44d..b6ead28c5 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -58,43 +58,33 @@ bool tuh_msc_is_busy(uint8_t dev_addr); uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); // Perform a full SCSI command (cbw, data, csw) in non-blocking manner. -// `complete_cb` callback is invoked when SCSI op is complete. +// Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); // Perform SCSI Inquiry command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); // Perform SCSI Test Unit Ready command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); -// Perform SCSI Request Sense (10) command +// Perform SCSI Request Sense 10 command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); -// Perform SCSI Read Capacity (10) command +// Perform SCSI Read Capacity 10 command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); -/** \brief Perform SCSI READ 10 command to read data from MassStorage device - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] lba Starting Logical Block Address to be read - * \param[in] block_count Number of Block to be read - * \retval true on success - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function - */ -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); - -/** \brief Perform SCSI WRITE 10 command to write data to MassStorage device - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] lba Starting Logical Block Address to be written - * \param[in] block_count Number of Block to be written - * \retval true on success - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function - */ -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); +// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Write 10 command. Write n blocks starting from LBA to device +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); //------------- Application Callback -------------// -- cgit v1.3.1 From 5108d7613600449c50af9e8ce373571d56bed3cc Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 19:41:11 +0700 Subject: host msc: call read_capacity as part of enumeration - add tuh_msc_get_block_count(), tuh_msc_get_block_size() - rename tuh_msc_mounted_cb/tuh_msc_unmounted_cb to tuh_msc_mount_cb/tuh_msc_unmount_cb to match device stack naming - change tuh_msc_is_busy() to tuh_msc_ready() - add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities - add host msc configured to for state check. --- examples/host/cdc_msc_hid/src/msc_app.c | 46 ++--------- examples/obsolete/host/src/msc_host_app.c | 4 +- lib/fatfs/diskio.c | 2 +- src/class/msc/msc_host.c | 133 ++++++++++++++++++++---------- src/class/msc/msc_host.h | 33 ++++++-- 5 files changed, 125 insertions(+), 93 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 5e2ea308a..623141eaa 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -31,31 +31,6 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ static scsi_inquiry_resp_t inquiry_resp; -static scsi_read_capacity10_resp_t capacity_resp; - -uint32_t block_size; -uint32_t block_count; - -bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - (void) dev_addr; - (void) cbw; - - if (csw->status != 0) - { - printf("Read Capacity (10) failed\r\n"); - return false; - } - - // Capacity response field: Block size and Last LBA are both Big-Endian - block_count = tu_ntohl(capacity_resp.last_lba) + 1; - block_size = tu_ntohl(capacity_resp.block_size); - - printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); - printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); - - return true; -} bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { @@ -68,19 +43,21 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const // Print out Vendor ID, Product ID and Rev printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); - // Read capacity of device - tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb); + // Get capacity of device + uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); + uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); + + printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); return true; } //------------- IMPLEMENTATION -------------// -void tuh_msc_mounted_cb(uint8_t dev_addr) +void tuh_msc_mount_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); - block_size = block_count = 0; - uint8_t const lun = 0; tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // @@ -110,7 +87,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) // } } -void tuh_msc_unmounted_cb(uint8_t dev_addr) +void tuh_msc_unmount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); @@ -133,11 +110,4 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr) // } } -//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -//{ -// (void) dev_addr; -// (void) cbw; -// (void) csw; -//} - #endif diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c index 8afb6ede8..5399e6620 100644 --- a/examples/obsolete/host/src/msc_host_app.c +++ b/examples/obsolete/host/src/msc_host_app.c @@ -48,7 +48,7 @@ CFG_TUSB_MEM_SECTION static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX]; //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ -void tuh_msc_mounted_cb(uint8_t dev_addr) +void tuh_msc_mount_cb(uint8_t dev_addr) { puts("\na MassStorage device is mounted"); @@ -94,7 +94,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) } } -void tuh_msc_unmounted_cb(uint8_t dev_addr) +void tuh_msc_unmount_cb(uint8_t dev_addr) { puts("\na MassStorage device is unmounted"); diff --git a/lib/fatfs/diskio.c b/lib/fatfs/diskio.c index 38503148d..401f583a2 100644 --- a/lib/fatfs/diskio.c +++ b/lib/fatfs/diskio.c @@ -48,7 +48,7 @@ static DSTATUS disk_state[CFG_TUSB_HOST_DEVICE_MAX]; static DRESULT wait_for_io_complete(uint8_t usb_addr) { // TODO with RTOS, this should use semaphore instead of blocking - while ( tuh_msc_is_busy(usb_addr) ) + while ( !tuh_msc_ready(usb_addr) ) { // TODO should have timeout here #if CFG_TUSB_OS != OPT_OS_NONE diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 943dc541f..34dbec2e3 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -47,14 +47,21 @@ enum typedef struct { - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; - uint8_t max_lun; + uint8_t max_lun; - volatile bool mounted; + volatile bool configured; // Receive SET_CONFIGURE + volatile bool mounted; // Enumeration is complete + struct { + uint32_t block_size; + uint32_t block_count; + } capacity[CFG_TUH_MSC_MAXLUN]; + + //------------- SCSI -------------// uint8_t stage; void* buffer; tuh_msc_complete_cb_t complete_cb; @@ -63,14 +70,15 @@ typedef struct msc_csw_t csw; }msch_interface_t; -CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX]; +CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX]; -// buffer used to read scsi information when mounted, largest response data currently is inquiry -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)]; +// buffer used to read scsi information when mounted +// largest response data currently is inquiry TODO Inquiry is not part of enum anymore +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; static inline msch_interface_t* get_itf(uint8_t dev_addr) { - return &msch_data[dev_addr-1]; + return &_msch_itf[dev_addr-1]; } //--------------------------------------------------------------------+ @@ -82,18 +90,28 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) return p_msc->max_lun; } -bool tuh_msc_mounted(uint8_t dev_addr) +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) { msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->capacity[lun].block_count; +} - // is configured can be omitted - return tuh_device_is_configured(dev_addr) && p_msc->mounted; +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->capacity[lun].block_size; +} + +bool tuh_msc_mounted(uint8_t dev_addr) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->mounted; } -bool tuh_msc_is_busy(uint8_t dev_addr) +bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in); + return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ @@ -110,7 +128,7 @@ static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - // TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command + TU_VERIFY(p_msc->configured); // TODO claim endpoint @@ -126,8 +144,8 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -142,6 +160,9 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) { + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); + msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -161,14 +182,17 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); + msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = 0; // Number of bytes - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification + cbw.total_bytes = 0; + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); } @@ -179,8 +203,8 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms cbw_init(&cbw, lun); cbw.total_bytes = 18; // TODO sense response - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_request_sense_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_request_sense_t); scsi_request_sense_t const cmd_request_sense = { @@ -201,11 +225,11 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); + cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); - scsi_read10_t cmd_read10 = + scsi_read10_t const cmd_read10 = { .cmd_code = SCSI_CMD_READ_10, .lba = tu_htonl(lba), @@ -225,11 +249,11 @@ bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_ msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); + cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); - scsi_write10_t cmd_write10 = + scsi_write10_t const cmd_write10 = { .cmd_code = SCSI_CMD_WRITE_10, .lba = tu_htonl(lba), @@ -267,14 +291,14 @@ bool tuh_msc_reset(uint8_t dev_addr) //--------------------------------------------------------------------+ void msch_init(void) { - tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); } void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); tu_memclr(p_msc, sizeof(msch_interface_t)); - tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback + tuh_msc_unmount_cb(dev_addr); // invoke Application Callback } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -331,6 +355,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -369,6 +394,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) msch_interface_t* p_msc = get_itf(dev_addr); TU_ASSERT(p_msc->itf_num == itf_num); + p_msc->configured = true; + //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); tusb_control_request_t request = @@ -396,12 +423,13 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t msch_interface_t* p_msc = get_itf(dev_addr); // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0; p_msc->max_lun++; // MAX LUN is minus 1 by specs // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); - tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete); + uint8_t const lun = 0; + tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); return true; } @@ -410,19 +438,16 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c { if (csw->status == 0) { - msch_interface_t* p_msc = get_itf(dev_addr); - - usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); - - // Unit is ready, Enumeration is complete - p_msc->mounted = true; - tuh_msc_mounted_cb(dev_addr); + // Unit is ready, read its capacity + TU_LOG2("SCSI Read Capacity\r\n"); + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete)); + TU_LOG2("SCSI Request Sense\r\n"); + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete)); } return true; @@ -435,4 +460,24 @@ static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw return true; } +static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + TU_ASSERT(csw->status == 0); + + msch_interface_t* p_msc = get_itf(dev_addr); + + // Capacity response field: Block size and Last LBA are both Big-Endian + scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer; + p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; + p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); + + // Mark enumeration is complete + p_msc->mounted = true; + tuh_msc_mount_cb(dev_addr); + + usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); + + return true; +} + #endif diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index b6ead28c5..8116e729f 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -35,6 +35,15 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_MSC_MAXLUN +#define CFG_TUH_MSC_MAXLUN 4 +#endif + + /** \addtogroup ClassDriver_MSC * @{ * \defgroup MSC_Host Host @@ -51,12 +60,18 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() bool tuh_msc_mounted(uint8_t dev_addr); -// Check if the interface is currently busy transferring data -bool tuh_msc_is_busy(uint8_t dev_addr); +// Check if the interface is currently ready or busy transferring data +bool tuh_msc_ready(uint8_t dev_addr); // Get Max Lun uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); +// Get number of block +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); + +// Get block size in bytes +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); + // Perform a full SCSI command (cbw, data, csw) in non-blocking manner. // Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. @@ -74,10 +89,6 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ // Complete callback is invoked when SCSI op is complete. bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); -// Perform SCSI Read Capacity 10 command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); - // Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer // Complete callback is invoked when SCSI op is complete. bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); @@ -86,13 +97,19 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, // Complete callback is invoked when SCSI op is complete. bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); +// Perform SCSI Read Capacity 10 command +// Complete callback is invoked when SCSI op is complete. +// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by +// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); + //------------- Application Callback -------------// // Invoked when a device with MassStorage interface is mounted -void tuh_msc_mounted_cb(uint8_t dev_addr); +void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -void tuh_msc_unmounted_cb(uint8_t dev_addr); +void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From 313dd1439db037e676429d11646008f143e6bdb9 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 19:41:21 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_da146xx.c BUT WITHOUT DMA SUPPORT --- src/class/audio/audio_device.c | 1 - src/portable/dialog/da146xx/dcd_da146xx.c | 102 +++++++++++++++++++++++++++--- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 3 files changed, 94 insertions(+), 11 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c71ad6b8e..ef533e540 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -135,7 +135,6 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 59f728d08..8e1a5ddfd 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X @@ -196,6 +197,7 @@ typedef struct typedef struct { EPx_REGS * regs; uint8_t * buffer; + tu_fifo_t * ff; // Total length of current transfer uint16_t total_len; // Bytes transferred so far @@ -292,7 +294,6 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); - src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; if (left_to_send > xfer->max_packet_size - xfer->last_packet_size) { @@ -301,12 +302,51 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Loop checks TCOUNT all the time since this value is saturated to 31 // and can't be read just once before. - while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + + if (xfer->ff) { - regs->txd = *src++; - xfer->last_packet_size++; - left_to_send--; + // Since TCOUNT is to be considered, we handle the FIFO reading manually here + // As we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + uint8_t * src; + uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + uint16_t len1 = len; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + len1--; + } + + tu_fifo_advance_read_pointer(ff, len-len1); + left_to_send -= (len-len1); + + // Check for wrapped part + if ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) && left_to_send > 0) + { + len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + len1 = len; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + len1--; + } + tu_fifo_advance_read_pointer(ff, len-len1); + left_to_send -= (len-len1); + } } + else + { + src = &xfer->buffer[xfer->transferred]; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + left_to_send--; + } + } + if (epnum != 0) { if (left_to_send > 0) @@ -363,13 +403,14 @@ static void start_rx_packet(xfer_ctl_t *xfer) xfer->last_packet_size = 0; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) { - if (try_allocate_dma(epnum, TUSB_DIR_OUT)) + if (try_allocate_dma(epnum, TUSB_DIR_OUT) && !xfer->ff) { start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); } else { // Other endpoint is using DMA in that direction, fall back to interrupts. + // Or if an ISO EP transfer was scheduled, currently not handled by DMA! // For endpoint size greater then FIFO size enable FIFO level warning interrupt // when FIFO has less then 17 bytes free. xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; @@ -409,7 +450,7 @@ static void start_tx_packet(xfer_ctl_t *xfer) regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; - if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) + if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN) && !xfer->ff) { // Whole packet will be put in FIFO by DMA. Set LAST bit before start. start_tx_dma(xfer->buffer + xfer->transferred, ®s->txd, size); @@ -430,9 +471,16 @@ static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) if (remaining < bytes_in_fifo) receive_this_time = remaining; - uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; + if (xfer->ff) + { + tu_fifo_write_n(xfer->ff, (const void *) ®s->rxd, receive_this_time); + } + else + { + uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; - for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + } xfer->last_packet_size += receive_this_time; } @@ -918,6 +966,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t (void)rhport; xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->last_packet_size = 0; xfer->transferred = 0; @@ -934,6 +983,41 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + + (void)rhport; + + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->last_packet_size = 0; + xfer->transferred = 0; + + if (dir == TUSB_DIR_IN) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); + } + + if (dir == TUSB_DIR_OUT) + { + start_rx_packet(xfer); + } + else // IN + { + start_tx_packet(xfer); + } + + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5f8c44638..1d0bb5107 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -684,7 +684,7 @@ bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; // Indicates a FIFO shall be used + xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; -- cgit v1.3.1 From a07062672933a5e2ba21db806217ce69243ceabe Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 14:27:20 +0700 Subject: add itf argument to hid API to support multiple instances following API signature is changed: - tud_hid_descriptor_report_cb() - tud_hid_get_report_cb() - tud_hid_set_report_cb() - tud_hid_boot_mode_cb() - tud_hid_set_idle_cb() --- examples/device/hid_composite/src/main.c | 6 ++-- .../device/hid_composite/src/usb_descriptors.c | 3 +- examples/device/hid_composite_freertos/src/main.c | 6 ++-- .../hid_composite_freertos/src/usb_descriptors.c | 2 +- examples/device/hid_generic_inout/src/main.c | 6 ++-- .../device/hid_generic_inout/src/usb_descriptors.c | 3 +- src/class/hid/hid_device.c | 41 ++++------------------ src/class/hid/hid_device.h | 14 -------- 8 files changed, 23 insertions(+), 58 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 9fb2de88d..512f6f9d9 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -239,9 +239,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -252,9 +253,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) itf; (void) report_id; (void) report_type; (void) buffer; diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index ec4976188..ccc1306bd 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -82,8 +82,9 @@ uint8_t const desc_hid_report[] = // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { + (void) itf; return desc_hid_report; } diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index aa006fbea..79dc2ec69 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -299,9 +299,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -312,9 +313,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) itf; (void) report_id; (void) report_type; (void) buffer; diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index ec4976188..da91b71ec 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -82,7 +82,7 @@ uint8_t const desc_hid_report[] = // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { return desc_hid_report; } diff --git a/examples/device/hid_generic_inout/src/main.c b/examples/device/hid_generic_inout/src/main.c index 4573bd7e0..65874f483 100644 --- a/examples/device/hid_generic_inout/src/main.c +++ b/examples/device/hid_generic_inout/src/main.c @@ -121,9 +121,10 @@ void tud_resume_cb(void) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -134,9 +135,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // This example doesn't use multiple report and report ID + (void) itf; (void) report_id; (void) report_type; diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index ef7450e8f..db4ddd76e 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -78,8 +78,9 @@ uint8_t const desc_hid_report[] = // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { + (void) itf; return desc_hid_report; } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4cdcecc9e..18d35bc20 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -251,11 +251,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - uint8_t const * desc_report = tud_hid_descriptor_report_cb( - #if CFG_TUD_HID > 1 - hid_itf // TODO for backward compatible callback, remove later when appropriate - #endif - ); + uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else @@ -275,12 +271,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength - ); + uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -298,12 +289,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength - ); + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength); } break; @@ -314,12 +300,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t if ( tud_hid_set_idle_cb ) { // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->idle_rate) - ); + TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); } tud_control_status(rhport, request); @@ -354,12 +335,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t { if (tud_hid_boot_mode_cb) { - tud_hid_boot_mode_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->boot_mode - ); + tud_hid_boot_mode_cb(hid_itf, p_hid->boot_mode); } } break; @@ -400,12 +376,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Received report else if (ep_addr == p_hid->ep_out) { - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - itf, // TODO for backward compatible callback, remove later when appropriate - #endif - 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes - ); + tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index d5de53221..0c59d5d20 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -88,8 +88,6 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Callbacks (Weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_HID > 1 - // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); @@ -111,18 +109,6 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); -#else - -// TODO for backward compatible callback, remove later when appropriate -uint8_t const * tud_hid_descriptor_report_cb(void); -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); - -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); - -#endif - // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -- cgit v1.3.1 From 07a04255da4442fb0790130ac65c648d0884255a Mon Sep 17 00:00:00 2001 From: amit verma Date: Thu, 25 Feb 2021 23:13:21 +0530 Subject: initial break request handling --- src/class/cdc/cdc_device.c | 11 +++++++++++ src/class/cdc/cdc_device.h | 3 +++ 2 files changed, 14 insertions(+) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 58f485a5d..5a74b4876 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -396,6 +396,17 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; + case CDC_REQUEST_SEND_BREAK: + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + TU_LOG2(" Send Break\r\n"); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + } + break; default: return false; // stall unsupported request } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 62dcd3c0a..d10fe68db 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -133,6 +133,9 @@ static inline bool tud_cdc_write_clear (void); // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t wait_ms); + // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); -- cgit v1.3.1 From 55a46a5c3b7ad3afb70a995954baa6148381b3a5 Mon Sep 17 00:00:00 2001 From: boggyb Date: Fri, 26 Feb 2021 11:00:34 +0530 Subject: Update cdc_device.h Minor api callback change as requested --- src/class/cdc/cdc_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index d10fe68db..0885922c6 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -133,9 +133,6 @@ static inline bool tud_cdc_write_clear (void); // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t wait_ms); - // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); @@ -148,6 +145,9 @@ TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); // Invoked when line coding is change via SET_LINE_CODING TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ -- cgit v1.3.1 From 8ec99694d228d31ee0b4033346498238c6605967 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 1 Mar 2021 09:09:15 +0100 Subject: audio_decive clean up and bootstrapping of linear (formerly evade) buff. --- src/class/audio/audio_device.c | 300 +++++++++++++++++++++++------------------ src/class/audio/audio_device.h | 42 +++--- 2 files changed, 188 insertions(+), 154 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index ef533e540..a29abc496 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -30,6 +30,22 @@ * * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. * + * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host + * + * 1. Input data -> SW-FIFO -> MCU USB + * + * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_iso_xfer() is available) + * + * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB + * + * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. + * + * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB + * + * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. + * + * The same holds in the RX case. + * * */ #include "tusb_option.h" @@ -47,17 +63,45 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ + CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ + CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ + CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ + CFG_TUSB_MCU == OPT_MCU_SAME5X ) + +#define USE_LINEAR_BUFFER 1 + +#else +#define USE_LINEAR_BUFFER 0 +#endif + typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_IN uint8_t ep_in; // TX audio data EP. uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT uint8_t ep_out; // Incoming (into uC) audio data EP. uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) @@ -82,6 +126,8 @@ typedef struct // EP Transfer buffers and FIFOs #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +#if !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; tu_fifo_t ep_out_ff; @@ -89,13 +135,15 @@ typedef struct osal_mutex_def_t ep_out_ff_mutex; #endif +#endif + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). #endif #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; tu_fifo_t ep_in_ff; @@ -112,60 +160,41 @@ typedef struct // Support FIFOs #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif #endif - // Evasion buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically -#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ - CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ - CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ - CFG_TUSB_MCU == OPT_MCU_SAME5X ) - -#define USE_EVADE_BUFFER 1 - -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; + // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used +#if CFG_TUD_AUDIO_EPSIZE_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE) + CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#define USE_LINEAR_BUFFER_RX 1 #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#if CFG_TUD_AUDIO_EPSIZE_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE) + CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#define USE_LINEAR_BUFFER_TX 1 #endif -#endif +} audiod_interface_t; -#ifndef USE_EVADE_BUFFER -#define USE_EVADE_BUFFER 0 +#ifndef USE_LINEAR_BUFFER_TX +#define USE_LINEAR_BUFFER_TX 0 #endif -} audiod_interface_t; +#ifndef USE_LINEAR_BUFFER_RX +#define USE_LINEAR_BUFFER_RX 0 +#endif #define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) @@ -177,19 +206,19 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio); +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); @@ -228,7 +257,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_available(uint8_t itf) { @@ -248,35 +277,35 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif -#endif - -// This function is called once an audio packet is received by the USB and is responsible for decoding received stream into audio channels. +// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). // If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -288,13 +317,10 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); } - // Get number of bytes in EP OUT SW FIFO - uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); - - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) { @@ -309,7 +335,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio)); + TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); break; default: @@ -327,13 +353,22 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) break; } -#endif - // Prepare for next transmission -#if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + +#else + +#if USE_LINEAR_BUFFER_RX + // Data currently is in linear buffer, copy into EP OUT FIFO + TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); + + // Schedule for next receive + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); + // Data is already placed in EP FIFO, schedule for next receive + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#endif + #endif // Call a weak callback here - a possibility for user to get informed decoding was completed @@ -345,37 +380,33 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) #endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE // The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; // We assume there is always the correct number of samples available for decoding - extra checks make no sense here - uint16_t const n_bytes = tu_fifo_count(&audio->ep_out_ff); - uint16_t cnt = CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; + uint16_t idxSample = 0; - while (cnt <= n_bytes) + while (cnt <= n_bytes_received) { for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) { // If 8, 16, or 32 bit values are to be copied #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE // If this aborts then the target buffer is full - TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &audio->lin_buf_out[idxSample], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else - uint32_t sample = 0; - - // Get sample from buffer - TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); - + uint32_t sample = audio->lin_buf_out[idxSample]; #if CFG_TUD_AUDIO_JUSTIFICATION_RX == CFG_TUD_AUDIO_LEFT_JUSTIFIED sample = sample << 8; #endif - TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #endif + idxSample += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; } cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; @@ -392,7 +423,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE /** * \brief Write data to EP in buffer @@ -417,18 +448,20 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete return tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); } -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); audiod_interface_t* audio = &_audiod_itf[itf]; - uint16_t n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); + uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); - n_bytes_copied -= tu_fifo_count(&audio->ep_in_ff); - n_bytes_copied = n_bytes_copied*audio->ep_in_ff.item_size; + n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); + n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; return n_bytes_copied; } @@ -436,17 +469,16 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); - return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); + return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); - return tu_fifo_write_n(&_audiod_itf[itf].tx_ff[channelId], data, len); + return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif -#endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -492,7 +524,11 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + // Send everything in ISO EP FIFO + uint16_t n_bytes_tx; + + // If support FIFOs are used, encode and schedule transmit +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -507,8 +543,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_encode_type_I_pcm(rhport, audio)); - + n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); break; default: @@ -525,17 +560,22 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) TU_BREAKPOINT(); break; } -#endif - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - // Schedule transmit -#if USE_EVADE_BUFFER - tu_fifo_write_n(&audio->ep_in_ff, audio->evasion_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->evasion_buf_in, n_bytes_tx)); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule + + n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + + #if USE_LINEAR_BUFFER_TX + tu_fifo_write_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); + #else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + #endif + #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame @@ -546,21 +586,22 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN // Take samples from the support buffer and encode them into the IN EP software FIFO -static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) +// Returns number of bytes written into linear buffer +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_supp_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - uint16_t const count = tu_fifo_count(&audio->tx_ff[cntChannel]); + uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cntChannel]); if (count < nSamplesPerChannelToSend) { nSamplesPerChannelToSend = count; @@ -571,13 +612,14 @@ static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) nSamplesPerChannelToSend = nSamplesPerChannelToSend / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Check if there is enough - if (nSamplesPerChannelToSend == 0) return true; + if (nSamplesPerChannelToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); // Encode uint16_t cntSample; + uint16_t idxSample = 0; for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) { @@ -585,21 +627,22 @@ static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // If 8, 16, or 32 bit values are to be copied #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE - tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); + tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &audio->lin_buf_in[idxSample], CFG_TUD_AUDIO_TX_ITEMSIZE); #else uint32_t sample = 0; // Get sample from buffer - tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); #if CFG_TUD_AUDIO_JUSTIFICATION_TX == CFG_TUD_AUDIO_LEFT_JUSTIFIED sample = sample << 8; #endif - tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); + audio->lin_buf_in[idxSample] = sample; #endif + idxSample += CFG_TUD_AUDIO_TX_ITEMSIZE; } } - return true; + return nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_TX_ITEMSIZE; } #endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE @@ -624,7 +667,7 @@ void audiod_init(void) audiod_interface_t* audio = &_audiod_itf[i]; // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); @@ -632,7 +675,7 @@ void audiod_init(void) #endif // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); @@ -640,23 +683,23 @@ void audiod_init(void) #endif // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex[cnt])); #endif } #endif // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], osal_mutex_create(&audio->rx_supp_ff_mutex[cnt])); #endif } #endif @@ -672,25 +715,25 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE tu_fifo_clear(&audio->ep_out_ff); #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_clear(&audio->tx_ff[cnt]); + tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_clear(&audio->rx_ff[cnt]); + tu_fifo_clear(&audio->rx_supp_ff[cnt]); } #endif } @@ -731,7 +774,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; @@ -840,7 +882,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_IN if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -856,7 +898,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { @@ -868,8 +910,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data -#if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#if USE_LINEAR_BUFFER_RX + TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); #endif @@ -1161,15 +1203,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) { - // Save into buffer - do whatever has to be done - // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); - -#if USE_EVADE_BUFFER - TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, _audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO -#endif - - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); - + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], (uint16_t) xferred_bytes)); return true; } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 38495f72d..ca74d68f4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -235,26 +235,26 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#endif - #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); @@ -274,35 +274,35 @@ static inline bool tud_audio_mounted (void); // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#endif - // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); #endif -#endif - // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -380,7 +380,7 @@ static inline bool tud_audio_mounted(void) // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_available (void) { @@ -397,7 +397,9 @@ static inline bool tud_audio_clear_ep_out_ff (void) return tud_audio_n_clear_ep_out_ff(0); } -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { @@ -416,11 +418,9 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, #endif -#endif - // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_write (const void * data, uint16_t len) { @@ -432,7 +432,9 @@ static inline bool tud_audio_clear_ep_in_ff (void) return tud_audio_n_clear_ep_in_ff(0); } -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN static inline uint16_t tud_audio_flush_tx_support_ff (void) { @@ -451,8 +453,6 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, #endif -#endif - #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { -- cgit v1.3.1 From fc35b3f72dc2f73ecd9df3e14484ef493803fd7b Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 17:24:58 +0100 Subject: Switch back OPT_MCU_DA1469X to use linear buffers --- src/class/audio/audio_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a29abc496..32745002c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -65,6 +65,7 @@ // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically #if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ -- cgit v1.3.1 From 7b8a08d2e1519afba6045e2a77898afecb1943e1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 20:00:39 +0100 Subject: Rename dcd_edpt_iso_xfer() to dcd_edpt_xfer_fifo() --- src/class/audio/audio_device.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 2 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 4 ++-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/template/dcd_template.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 32745002c..37d6a36a7 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -34,7 +34,7 @@ * * 1. Input data -> SW-FIFO -> MCU USB * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_iso_xfer() is available) + * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) * * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB * diff --git a/src/device/dcd.h b/src/device/dcd.h index f0a552434..89f8760d0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -135,7 +135,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index c087e2b38..1879729e8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1246,7 +1246,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (dcd_edpt_iso_xfer(rhport, ep_addr, ff, total_bytes)) + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 25e54418f..ade79f107 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -357,7 +357,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void)rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 1edbba629..5866e1ce8 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -297,7 +297,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 9ff34e760..0e7157d4c 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -77,7 +77,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -297,7 +297,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 8aa97ad10..65a41463c 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -303,7 +303,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 0a690d84d..0d82a28c0 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -95,7 +95,7 @@ static uint32_t bufseg_addr; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -412,7 +412,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index e2fd48d74..dbd514f86 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -867,7 +867,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 1d0bb5107..6dad05ba1 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -675,7 +675,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 7a9a0ae22..ba656385b 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -106,7 +106,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; (void) ep_addr; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 61cbe1cf7..a8da1ae49 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -347,7 +347,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; -- cgit v1.3.1 From 33a29c9e4ca9aebb3469c8f8114365acc3614321 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 19:30:08 +0700 Subject: add midi comment --- src/class/midi/midi_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 325fc4669..29019cc1d 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -387,6 +387,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint p_midi->ep_out = ep_addr; } + // Class Specific MIDI Stream endpoint descriptor drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); -- cgit v1.3.1 From 7e56f46957452c21a5f6228d0aff2d5544c04b9f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 4 Mar 2021 13:52:14 +0100 Subject: Extend FIFO mutex to use separate write and read mutexes. Adjust all USB drivers using FIFO and mutexes. --- src/class/audio/audio_device.c | 16 +++---- src/class/cdc/cdc_device.c | 4 +- src/class/midi/midi_device.c | 4 +- src/class/vendor/vendor_device.c | 4 +- src/common/tusb_fifo.c | 97 +++++++++++++++++++++++++--------------- src/common/tusb_fifo.h | 8 ++-- 6 files changed, 80 insertions(+), 53 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 37d6a36a7..c0d3e123c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -133,7 +133,7 @@ typedef struct tu_fifo_t ep_out_ff; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex; + osal_mutex_def_t ep_out_ff_mutex_rd; // No need for write mutex as only USB driver writes into FIFO #endif #endif @@ -149,7 +149,7 @@ typedef struct tu_fifo_t ep_in_ff; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex; + osal_mutex_def_t ep_in_ff_mutex_wr; // No need for read mutex as only USB driver reads from FIFO #endif #endif @@ -164,7 +164,7 @@ typedef struct tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_CHANNELS_TX]; // No need for read mutex as only USB driver reads from FIFO #endif #endif @@ -172,7 +172,7 @@ typedef struct tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_CHANNELS_RX]; // No need for write mutex as only USB driver writes into FIFO #endif #endif @@ -671,7 +671,7 @@ void audiod_init(void) #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex_wr), NULL); #endif #endif @@ -679,7 +679,7 @@ void audiod_init(void) #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&audio->ep_out_ff_mutex_rd)); #endif #endif @@ -689,7 +689,7 @@ void audiod_init(void) { tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); #endif } #endif @@ -700,7 +700,7 @@ void audiod_init(void) { tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], osal_mutex_create(&audio->rx_supp_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); #endif } #endif diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 58f485a5d..c679dc71e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -243,8 +243,8 @@ void cdcd_init(void) tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); - tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); #endif } } diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 325fc4669..c61bad17c 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -310,8 +310,8 @@ void midid_init(void) tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); - tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex)); + tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); + tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); #endif } } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 3fcea89c4..9b0a3c25f 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -146,8 +146,8 @@ void vendord_init(void) tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_itf->rx_ff, osal_mutex_create(&p_itf->rx_ff_mutex)); - tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex)); + tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); + tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); #endif } } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d4251abea..44b4a11c0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -39,31 +39,49 @@ // implement mutex lock and unlock #if CFG_FIFO_MUTEX -static void tu_fifo_lock(tu_fifo_t *f) +static void tu_fifo_lock_wr(tu_fifo_t *f) { - if (f->mutex) + if (f->mutex_wr) { - osal_mutex_lock(f->mutex, OSAL_TIMEOUT_WAIT_FOREVER); + osal_mutex_lock(f->mutex_wr, OSAL_TIMEOUT_WAIT_FOREVER); } } -static void tu_fifo_unlock(tu_fifo_t *f) +static void tu_fifo_unlock_wr(tu_fifo_t *f) { - if (f->mutex) + if (f->mutex_wr) { - osal_mutex_unlock(f->mutex); + osal_mutex_unlock(f->mutex_wr); + } +} + +static void tu_fifo_lock_rd(tu_fifo_t *f) +{ + if (f->mutex_rd) + { + osal_mutex_lock(f->mutex_rd, OSAL_TIMEOUT_WAIT_FOREVER); + } +} + +static void tu_fifo_unlock_rd(tu_fifo_t *f) +{ + if (f->mutex_rd) + { + osal_mutex_unlock(f->mutex_rd); } } #else -#define tu_fifo_lock(_ff) -#define tu_fifo_unlock(_ff) +#define tu_fifo_lock_wr(_ff) +#define tu_fifo_unlock_wr(_ff) +#define tu_fifo_lock_rd(_ff) +#define tu_fifo_unlock_rd(_ff) #endif /** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s + * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others */ typedef enum { @@ -75,7 +93,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si { if (depth > 0x8000) return false; // Maximum depth is 2^15 items - tu_fifo_lock(f); + tu_fifo_lock_wr(f); + tu_fifo_lock_rd(f); f->buffer = (uint8_t*) buffer; f->depth = depth; @@ -87,7 +106,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->rd_idx = f->wr_idx = 0; - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); + tu_fifo_lock_rd(f); return true; } @@ -381,7 +401,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu { if ( n == 0 ) return 0; - tu_fifo_lock(f); + tu_fifo_lock_wr(f); uint16_t w = f->wr_idx, r = f->rd_idx; uint8_t const* buf8 = (uint8_t const*) data; @@ -411,14 +431,14 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // Advance pointer f->wr_idx = advance_pointer(f, w, n); - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); return n; } static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); // TODO: Here we may distinguish for read and write pointer mutexes! // Peek the data n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -426,7 +446,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return n; } @@ -533,9 +553,9 @@ bool tu_fifo_overflowed(tu_fifo_t* f) // Only use in case tu_fifo_overflow() returned true! void tu_fifo_correct_read_pointer(tu_fifo_t* f) { - tu_fifo_lock(f); + tu_fifo_lock_rd(f); _tu_fifo_correct_read_pointer(f, f->wr_idx); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); } /******************************************************************************/ @@ -556,7 +576,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); // TODO: Here we may distinguish for read and write pointer mutexes! // Peek the data bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -564,7 +584,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return ret; } @@ -615,7 +635,8 @@ uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) /******************************************************************************/ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); + tu_fifo_lock_wr(f_target); // Conduct copy n = tu_fifo_peek_n_into_other_fifo(f, f_target, offset, n); @@ -623,7 +644,8 @@ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint1 // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); + tu_fifo_unlock_wr(f_target); return n; } @@ -645,9 +667,9 @@ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint1 /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return ret; } @@ -670,9 +692,9 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) /******************************************************************************/ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return ret; } @@ -719,7 +741,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint cnt -= offset; if (cnt < n) n = cnt; - tu_fifo_lock(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified + tu_fifo_lock_wr(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified uint16_t wr_rel_tgt = get_relative_pointer(f_target, f_target->wr_idx, 0); @@ -757,7 +779,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); } - tu_fifo_unlock(f_target); + tu_fifo_unlock_wr(f_target); return n; } @@ -780,7 +802,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint /******************************************************************************/ bool tu_fifo_write(tu_fifo_t* f, const void * data) { - tu_fifo_lock(f); + tu_fifo_lock_wr(f); uint16_t w = f->wr_idx; @@ -794,7 +816,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) // Advance pointer f->wr_idx = advance_pointer(f, w, 1); - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); return true; } @@ -848,12 +870,13 @@ uint16_t tu_fifo_write_n_const_addr(tu_fifo_t* f, const void * data, uint16_t n) /******************************************************************************/ bool tu_fifo_clear(tu_fifo_t *f) { - tu_fifo_lock(f); + tu_fifo_lock_wr(f); + tu_fifo_lock_rd(f); f->rd_idx = f->wr_idx = 0; f->max_pointer_idx = 2*f->depth-1; f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - tu_fifo_unlock(f); - + tu_fifo_unlock_wr(f); + tu_fifo_unlock_rd(f); return true; } @@ -869,11 +892,13 @@ bool tu_fifo_clear(tu_fifo_t *f) /******************************************************************************/ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { - tu_fifo_lock(f); + tu_fifo_lock_wr(f); + tu_fifo_lock_rd(f); f->overwritable = overwritable; - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); + tu_fifo_unlock_rd(f); return true; } @@ -996,9 +1021,9 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, // Check overflow and correct if required if (cnt > f->depth) { - tu_fifo_lock(f); + tu_fifo_lock_rd(f); _tu_fifo_correct_read_pointer(f, w); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); r = f->rd_idx; cnt = f->depth; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index feacc7a12..6e0ecdc82 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -73,7 +73,8 @@ typedef struct volatile uint16_t rd_idx ; ///< read pointer #if CFG_FIFO_MUTEX - tu_fifo_mutex_t mutex; + tu_fifo_mutex_t mutex_wr; + tu_fifo_mutex_t mutex_rd; #endif } tu_fifo_t; @@ -98,9 +99,10 @@ bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if CFG_FIFO_MUTEX -static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t mutex_hdl) +static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) { - f->mutex = mutex_hdl; + f->mutex_wr = write_mutex_hdl; + f->mutex_rd = read_mutex_hdl; } #endif -- cgit v1.3.1 From 7fc99a9e1104703566945ace1b2e1ed59819ba48 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 10 Mar 2021 10:19:45 +0100 Subject: Call One time tu_fifo_write_n on cdcd_xfer_cb Signed-off-by: HiFiPhile --- src/class/cdc/cdc_device.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 5a74b4876..64cb4ab2c 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -432,25 +432,25 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Received new data if ( ep_addr == p_cdc->ep_out ) { + tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); + // TODO search for wanted char first for better performance - for(uint32_t i=0; irx_ff, &p_cdc->epout_buf[i]); - + if (tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1)) { // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1 ) && ( p_cdc->wanted_char == p_cdc->epout_buf[i] ) ) - { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + for (uint32_t i=0; iwanted_char == p_cdc->epout_buf[i] ) { + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + } } } - + // invoke receive callback (if there is still data) if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); - + // prepare for OUT transaction _prep_out_transaction(p_cdc); } - + // Data sent to host, we continue to fetch from tx fifo to send. // Note: This will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! -- cgit v1.3.1 From d5a5a1cab63e8e43b22f13db95df35afdfa6befb Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 10 Mar 2021 19:32:13 +0100 Subject: Implement audio PCM type I enc./decoding acc. to 2.3.1.5 Audio Streams Extending capabilities of support FIFOs Removing copy from to FIFO Adjusting audio examples Remove peek/read into other FIFO --- examples/device/audio_test/src/main.c | 6 +- examples/device/audio_test/src/tusb_config.h | 9 +- examples/device/uac2_headset/src/tusb_config.h | 1 - src/class/audio/audio_device.c | 187 ++++++++++++++++--------- src/class/audio/audio_device.h | 70 ++++----- src/common/tusb_fifo.c | 155 ++------------------ src/common/tusb_fifo.h | 2 - 7 files changed, 168 insertions(+), 262 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index c63e64934..c2406bd23 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -73,12 +73,12 @@ int main(void) tusb_init(); // Init values - sampFreq = 48000; + sampFreq = AUDIO_SAMPLE_RATE; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = 48000; - sampleFreqRng.subrange[0].bMax = 48000; + sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; while (1) diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index c6d786398..6ee5d937c 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -91,9 +91,12 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +#ifndef AUDIO_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE 48000 +#endif + // Audio format type #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // Audio format type I specifications #define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM @@ -101,8 +104,8 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + 1 // Just for safety one sample more space +#define CFG_TUD_AUDIO_EPSIZE_IN 48 * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_N_AS_INT 1 diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 2ad76b7dc..45acf0093 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -110,7 +110,6 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 #define CFG_TUD_AUDIO_N_CHANNELS_RX 2 #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 2 -#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c0d3e123c..00d95ede5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -161,18 +161,18 @@ typedef struct // Support FIFOs #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_CHANNELS_TX]; // No need for read mutex as only USB driver reads from FIFO + osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_CHANNELS_RX]; // No need for write mutex as only USB driver writes into FIFO + osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif @@ -284,19 +284,19 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif @@ -382,35 +382,55 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT + +// Decoding according to 2.3.1.5 Audio Streams static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; - // We assume there is always the correct number of samples available for decoding - extra checks make no sense here + // Determine amount of samples + uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + uint16_t const nSamplesPerFFToRead = n_bytes_received / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint8_t cnt_ff; + + // Decode + void * dst; + uint8_t * src; + uint8_t * dst_end; + uint16_t len; + + for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt_ff++) + { + src = &audio->lin_buf_out[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; - uint16_t cnt = CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; - uint16_t idxSample = 0; + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - while (cnt <= n_bytes_received) - { - for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) - { - // If 8, 16, or 32 bit values are to be copied -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE - // If this aborts then the target buffer is full - TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &audio->lin_buf_out[idxSample], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); -#else - uint32_t sample = audio->lin_buf_out[idxSample]; -#if CFG_TUD_AUDIO_JUSTIFICATION_RX == CFG_TUD_AUDIO_LEFT_JUSTIFIED - sample = sample << 8; -#endif + dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; - TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); -#endif - idxSample += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + while((uint8_t *)dst < dst_end) + { + memcpy(dst, src, nBytesToCopy); + dst = (uint8_t *)dst + nBytesToCopy; + src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; } - cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; + // Handle wrapped part of FIFO + if (len < nSamplesPerFFToRead) + { + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead - len); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); + + dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + + while((uint8_t *)dst < dst_end) + { + memcpy(dst, src, nBytesToCopy); + dst = (uint8_t *)dst + nBytesToCopy; + src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + } + } } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -469,13 +489,13 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif @@ -590,60 +610,91 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN // Take samples from the support buffer and encode them into the IN EP software FIFO // Returns number of bytes written into linear buffer + +/* 2.3.1.7.1 PCM Format +The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio +data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It +is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused +bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the +range [-1, +1) +*/ + +/* + * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples + * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and + * does not change the number of bytes per sample. + * */ + static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { - // We encode directly into IN EP's FIFO - abort if previous transfer not complete + // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_supp_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size - uint8_t cntChannel; + uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t const capSamplesPerFF = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + uint16_t nSamplesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); + uint8_t cnt_ff; - for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + for (cnt_ff = 1; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cntChannel]); - if (count < nSamplesPerChannelToSend) + uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); + if (count < nSamplesPerFFToSend) { - nSamplesPerChannelToSend = count; + nSamplesPerFFToSend = count; } } - // Convert to sample size - nSamplesPerChannelToSend = nSamplesPerChannelToSend / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - // Check if there is enough - if (nSamplesPerChannelToSend == 0) return 0; + if (nSamplesPerFFToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); + nSamplesPerFFToSend = tu_min16(nSamplesPerFFToSend, capSamplesPerFF); + + // Round to full number of samples (flooring) + nSamplesPerFFToSend = (nSamplesPerFFToSend / nChannelsPerFF) * nChannelsPerFF; // Encode - uint16_t cntSample; - uint16_t idxSample = 0; + void * src; + uint8_t * dst; + uint8_t * src_end; + uint16_t len; - for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) { - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + dst = &audio->lin_buf_in[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; + + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); + + src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + + while((uint8_t *)src < src_end) { - // If 8, 16, or 32 bit values are to be copied -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE - tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &audio->lin_buf_in[idxSample], CFG_TUD_AUDIO_TX_ITEMSIZE); -#else - uint32_t sample = 0; + memcpy(dst, src, nBytesToCopy); + src = (uint8_t *)src + nBytesToCopy; + dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + } - // Get sample from buffer - tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + // Handle wrapped part of FIFO + if (len < nSamplesPerFFToSend) + { + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend - len); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); -#if CFG_TUD_AUDIO_JUSTIFICATION_TX == CFG_TUD_AUDIO_LEFT_JUSTIFIED - sample = sample << 8; -#endif - audio->lin_buf_in[idxSample] = sample; -#endif - idxSample += CFG_TUD_AUDIO_TX_ITEMSIZE; + src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + + while((uint8_t *)src < src_end) + { + memcpy(dst, src, nBytesToCopy); + src = (uint8_t *)src + nBytesToCopy; + dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + } } } - return nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_TX_ITEMSIZE; + + return nSamplesPerFFToSend * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; } #endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE @@ -685,9 +736,9 @@ void audiod_init(void) // Initialize TX support FIFOs if required #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) { - tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); #endif @@ -696,9 +747,9 @@ void audiod_init(void) // Initialize RX support FIFOs if required #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) { - tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); #endif @@ -725,14 +776,14 @@ void audiod_reset(uint8_t rhport) #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) { tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) { tu_fifo_clear(&audio->rx_supp_ff[cnt]); } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index ca74d68f4..730d42c38 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -50,7 +50,7 @@ #error You must define an audio class control request buffer size! #endif -// End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 +// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX #endif @@ -76,13 +76,13 @@ #define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 #endif -// General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions +// General information of number of TX and/or RX channels - is used in combination with support FIFOs (see below) and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 #endif // Use of TX/RX support FIFOs @@ -104,7 +104,7 @@ // The encoding/decoding starts when the private callback functions // - audio_tx_done_cb() // - audio_rx_done_cb() -// are invoked. If support FIFOs are used the corresponding encoding/decoding functions are called from there. +// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. // Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions // - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() // - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() @@ -120,13 +120,31 @@ // - audio_rx_done_cb() // functions. -// Size of support FIFOs - if size > 0 there are as many FIFOs set up as TX/RX channels defined +// The number of support FIFOs and number of channels is decoupled. The PCM encoding/decoding works depending on the ratio CFG_TUD_AUDIO_N_CHANNELS_XX / CFG_TUD_AUDIO_N_XX_SUPPORT_SW_FIFO, where currently 1:1 and 2:1 is implemented. The version 2:1 is useful in case of I2S for which usually 2 are channels already interleaved available. + +// Size of support FIFOs IN SAMPLES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO and CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO #ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: // ceil(f_s/1000) * CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO #endif #ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX +#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#endif + +#ifndef CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_TX // default size is equal to number of channels +#else +#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO 0 +#endif +#endif + +#ifndef CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_RX // default size is equal to number of channels +#else +#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO 0 +#endif #endif // Enable/disable feedback EP (required for asynchronous RX applications) @@ -167,20 +185,6 @@ #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif -#ifndef CFG_TUD_AUDIO_TX_ITEMSIZE -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 -#define CFG_TUD_AUDIO_TX_ITEMSIZE 1 -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 -#define CFG_TUD_AUDIO_TX_ITEMSIZE 2 -#else -#define CFG_TUD_AUDIO_TX_ITEMSIZE 4 -#endif -#endif - -#if CFG_TUD_AUDIO_TX_ITEMSIZE < CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX -#error FIFO element size (ITEMSIZE) must not be smaller then sample size -#endif - #endif #if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I @@ -193,26 +197,6 @@ #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 -#define CFG_TUD_AUDIO_RX_ITEMSIZE 1 -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 -#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 -#else -#define CFG_TUD_AUDIO_RX_ITEMSIZE 4 -#endif - -#endif - -// In case PCM encoding/decoding of 24 into 32 bits, the adjustment needs to be defined -#define CFG_TUD_AUDIO_LEFT_JUSTIFIED -#define CFG_TUD_AUDIO_RIGHT_JUSTIFIED - -#ifndef CFG_TUD_AUDIO_JUSTIFICATION_RX -#define CFG_TUD_AUDIO_JUSTIFICATION_RX CFG_TUD_AUDIO_LEFT_JUSTIFIED -#endif - -#ifndef CFG_TUD_AUDIO_JUSTIFICATION_TX -#define CFG_TUD_AUDIO_JUSTIFICATION_TX CFG_TUD_AUDIO_LEFT_JUSTIFIED #endif //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); @@ -256,7 +240,7 @@ bool tud_audio_n_clear_ep_in_ff (uint8_t itf); #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 6a31b6373..4936d5e7d 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -596,42 +596,6 @@ uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST); } -/******************************************************************************/ -/*! - @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. It copies the elements - into another FIFO and as such takes care of wraps etc. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] f_target - Pointer to target FIFO i.e. to copy into - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer - @param[in] n - Number of items to peek - - @returns number of items read from the FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) -{ - tu_fifo_lock(f->mutex_rd); - tu_fifo_lock(f_target->mutex_wr); - - // Conduct copy - n = tu_fifo_peek_n_into_other_fifo(f, f_target, offset, n); - - // Advance read pointer - f->rd_idx = advance_pointer(f, f->rd_idx, n); - - tu_fifo_unlock(f->mutex_rd); - tu_fifo_unlock(f_target->mutex_wr); - - return n; -} - /******************************************************************************/ /*! @brief Read one item without removing it from the FIFO. @@ -680,92 +644,6 @@ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint1 return ret; } -/******************************************************************************/ -/*! - @brief Read n items without removing it from the FIFO and copy them into another FIFO. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] f_target - Pointer to target FIFO i.e. to copy into - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer - @param[in] n - Number of items to peek - - @returns Number of bytes written to p_buffer - */ -/******************************************************************************/ -uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) -{ - // Copy is only possible if both FIFOs have common element size - TU_VERIFY(f->item_size == f_target->item_size); - - // Work on local copies on case any pointer changes in between (only necessary if something is written into FIFO f in the meantime) - uint16_t f_wr_idx = f->wr_idx; - uint16_t f_rd_idx = f->rd_idx; - - uint16_t cnt = _tu_fifo_count(f, f_wr_idx, f_rd_idx); - - // Check overflow and correct if required - if (cnt > f->depth) - { - _tu_fifo_correct_read_pointer(f, f->wr_idx); - f_rd_idx = f->rd_idx; - cnt = f->depth; - } - - // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; - - // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; - if (cnt < n) n = cnt; - - tu_fifo_lock(f_target->mutex_wr); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified - - uint16_t wr_rel_tgt = get_relative_pointer(f_target, f_target->wr_idx, 0); - - if (!f_target->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, tu_fifo_remaining(f_target)); - } - - // Advance write pointer - not required for later - f_target->wr_idx = advance_pointer(f_target, f_target->wr_idx, n); - - if (n >= f_target->depth) - { - offset += n - f_target->depth; - - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - wr_rel_tgt = get_relative_pointer(f_target, f_target->rd_idx, 0); - - n = f_target->depth; - - // Update write pointer - f_target->wr_idx = advance_pointer(f_target, f_target->rd_idx, n); - } - - // Copy linear size - uint16_t sz = f_target->depth - wr_rel_tgt; - _tu_fifo_peek_at_n(f, offset, &f_target->buffer[wr_rel_tgt], sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); - - if (n > sz) - { - // Copy remaining, now wrapped part, into target buffer - _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); - } - - tu_fifo_unlock(f_target->mutex_wr); - - return n; -} - /******************************************************************************/ /*! @brief Write one element into the buffer. @@ -976,7 +854,7 @@ void tu_fifo_backward_read_pointer(tu_fifo_t *f, uint16_t n) Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the corresponding pointer is invalid. The returned length is limited to the number - of BYTES n which the user wants to write into the buffer. + of ITEMS n which the user wants to write into the buffer. The write pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to do so! If the length returned is less than n i.e. lendepth; } - // Convert to bytes - cnt = cnt * f->item_size; - // Skip beginning of buffer if (cnt == 0 || offset >= cnt) return 0; @@ -1027,16 +902,14 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, // Check if there is a wrap around necessary uint16_t len; - if (w >= r) { + if (w > r) { len = w - r; } else { - len = f->depth - r; + len = f->depth - r; // Also the case if FIFO was full } - len = len * f->item_size; - // Limit to required length len = tu_min16(n, len); @@ -1060,31 +933,31 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, @param[in] f Pointer to FIFO @param[in] offset - Number of bytes to ignore before start writing + Number of ITEMS to ignore before start writing @param[out] **ptr Pointer to start writing to @param[in] n - Number of BYTES to write into buffer + Number of ITEMS to write into buffer @return len - Length of linear part IN BYTES, if zero corresponding pointer ptr is invalid + Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; - uint16_t free = _tu_fifo_remaining(f, w, r) * f->item_size; + uint16_t free = _tu_fifo_remaining(f, w, r); if (!f->overwritable) { // Not overwritable limit up to full n = tu_min16(n, free); } - else if (n >= f->depth * f->item_size) + else if (n >= f->depth) { // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - TU_VERIFY(n <= 2*f->depth * f->item_size); + TU_VERIFY(n <= 2*f->depth); - n = f->depth * f->item_size; + n = f->depth; // We start writing at the read pointer's position since we fill the complete // buffer and we do not want to modify the read pointer within a write function! // This would end up in a race condition with read functions! @@ -1108,8 +981,6 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr len = f->depth - w; } - len = len * f->item_size; - // Limit to required length len = tu_min16(n, len); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6e0ecdc82..d31e52f1c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -113,11 +113,9 @@ uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * dat bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr (tu_fifo_t* f, void * buffer, uint16_t n); -uint16_t tu_fifo_read_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); -uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); -- cgit v1.3.1 From 5caad485f199ab6acfa237d84bf3d84cf41dcfdd Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 11 Mar 2021 20:36:46 +0100 Subject: Add fifo empty check. Signed-off-by: HiFiPhile --- src/class/cdc/cdc_device.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 64cb4ab2c..d9b098bb2 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -434,11 +434,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); - // TODO search for wanted char first for better performance + // Check for wanted char and invoke callback if needed if (tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1)) { - // Check for wanted char and invoke callback if needed for (uint32_t i=0; iwanted_char == p_cdc->epout_buf[i] ) { + if ( p_cdc->wanted_char == p_cdc->epout_buf[i] && tu_fifo_count(&p_cdc->rx_ff) ) { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } -- cgit v1.3.1 From 31373fd55cefced35cfaaa61fb8f9aa3e5ec0bc6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Mar 2021 12:55:18 +0700 Subject: use !tu_fifo_empty() instead of tu_fifo_count() --- src/class/cdc/cdc_device.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d9b098bb2..c24edb757 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -95,7 +95,8 @@ static void _prep_out_transaction (cdcd_interface_t* p_cdc) // fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&p_cdc->rx_ff); - if ( available >= sizeof(p_cdc->epout_buf) ) { + if ( available >= sizeof(p_cdc->epout_buf) ) + { usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); }else { @@ -435,16 +436,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if (tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1)) { - for (uint32_t i=0; iwanted_char == p_cdc->epout_buf[i] && tu_fifo_count(&p_cdc->rx_ff) ) { + if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) + { + for ( uint32_t i = 0; i < xferred_bytes; i++ ) + { + if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) + { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); -- cgit v1.3.1 From cd491e296e0c8bce113d5474955d08f4c99b3099 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Mar 2021 18:55:16 +0100 Subject: Intermediate commit --- src/class/audio/audio_device.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 00d95ede5..73f265a8f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -206,6 +206,15 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; +// bSubslotSize for PCM encoding/decoding using support FIFOs +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +extern const tud_audio_n_bytes_per_sample_tx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +extern const tud_audio_n_bytes_per_sample_rx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; +#endif + #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -- cgit v1.3.1 From 62d4652f86516e1fdd7fa79a29535cf39b2ab2f1 Mon Sep 17 00:00:00 2001 From: Michael Bruno Date: Tue, 16 Mar 2021 10:48:42 -0400 Subject: Update usbtmc_device.c Fix buffer alignment in TMC device class --- src/class/usbtmc/usbtmc_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 88776d169..6c9b42449 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -131,9 +131,9 @@ typedef struct uint8_t ep_int_in; // IN buffer is only used for first packet, not the remainder // in order to deal with prepending header - uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; // OUT buffer receives one packet at a time - uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; uint32_t transfer_size_remaining; // also used for requested length for bulk IN. uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) -- cgit v1.3.1 From ec08dcf61a86686da101f480565c6fae2acc3359 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 17 Mar 2021 09:25:01 -0400 Subject: Implement requested changes for PR724 --- src/class/usbtmc/usbtmc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 6c9b42449..d5f8fe41d 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -145,7 +145,7 @@ typedef struct usbtmc_capabilities_specific_t const * capabilities; } usbtmc_interface_state_t; -static usbtmc_interface_state_t usbtmc_state = +CFG_TUSB_MEM_SECTION static usbtmc_interface_state_t usbtmc_state = { .itf_id = 0xFF, }; -- cgit v1.3.1 From 1138f8cc704e09af3335e253e5f244fde90d982f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Fri, 26 Mar 2021 15:30:43 -0400 Subject: Add DFU Class per Version 1.1 Spec --- src/class/dfu/dfu.h | 107 +++++++ src/class/dfu/dfu_rt_device.c | 667 ++++++++++++++++++++++++++++++++++++++++-- src/class/dfu/dfu_rt_device.h | 111 +++++-- src/common/tusb_types.h | 19 ++ src/device/usbd.c | 8 +- src/device/usbd.h | 15 +- src/device/usbd_control.c | 2 +- src/tusb_option.h | 4 + 8 files changed, 875 insertions(+), 58 deletions(-) create mode 100644 src/class/dfu/dfu.h (limited to 'src/class') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h new file mode 100644 index 000000000..39ce567da --- /dev/null +++ b/src/class/dfu/dfu.h @@ -0,0 +1,107 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_H_ +#define _TUSB_DFU_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Common Definitions +//--------------------------------------------------------------------+ +// DFU Protocol +typedef enum +{ + DFU_PROTOCOL_RT = 0x01, + DFU_PROTOCOL_DFU = 0x02, +} dfu_protocol_type_t; + +// DFU Descriptor Type +typedef enum +{ + DFU_DESC_FUNCTIONAL = 0x21, +} dfu_descriptor_type_t; + +// DFU Requests +typedef enum { + DFU_REQUEST_DETACH = 0, + DFU_REQUEST_DNLOAD = 1, + DFU_REQUEST_UPLOAD = 2, + DFU_REQUEST_GETSTATUS = 3, + DFU_REQUEST_CLRSTATUS = 4, + DFU_REQUEST_GETSTATE = 5, + DFU_REQUEST_ABORT = 6, +} dfu_requests_t; + +// DFU States +typedef enum { + APP_IDLE = 0, + APP_DETACH = 1, + DFU_IDLE = 2, + DFU_DNLOAD_SYNC = 3, + DFU_DNBUSY = 4, + DFU_DNLOAD_IDLE = 5, + DFU_MANIFEST_SYNC = 6, + DFU_MANIFEST = 7, + DFU_MANIFEST_WAIT_RESET = 8, + DFU_UPLOAD_IDLE = 9, + DFU_ERROR = 10, +} dfu_mode_state_t; + +// DFU Status +typedef enum { + DFU_STATUS_OK = 0x00, + DFU_STATUS_ERRTARGET = 0x01, + DFU_STATUS_ERRFILE = 0x02, + DFU_STATUS_ERRWRITE = 0x03, + DFU_STATUS_ERRERASE = 0x04, + DFU_STATUS_ERRCHECK_ERASED = 0x05, + DFU_STATUS_ERRPROG = 0x06, + DFU_STATUS_ERRVERIFY = 0x07, + DFU_STATUS_ERRADDRESS = 0x08, + DFU_STATUS_ERRNOTDONE = 0x09, + DFU_STATUS_ERRFIRMWARE = 0x0A, + DFU_STATUS_ERRVENDOR = 0x0B, + DFU_STATUS_ERRUSBR = 0x0C, + DFU_STATUS_ERRPOR = 0x0D, + DFU_STATUS_ERRUNKNOWN = 0x0E, + DFU_STATUS_ERRSTALLEDPKT = 0x0F, +} dfu_mode_device_status_t; + +#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) +#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) +#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) +#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 5700615be..965d1661e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -34,34 +34,176 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef enum { - DFU_REQUEST_DETACH = 0, - DFU_REQUEST_DNLOAD = 1, - DFU_REQUEST_UPLOAD = 2, - DFU_REQUEST_GETSTATUS = 3, - DFU_REQUEST_CLRSTATUS = 4, - DFU_REQUEST_GETSTATE = 5, - DFU_REQUEST_ABORT = 6, -} dfu_requests_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_state_ctx_t; typedef struct TU_ATTR_PACKED { - uint8_t status; - uint8_t poll_timeout[3]; - uint8_t state; - uint8_t istring; -} dfu_status_t; + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_req_payload_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_mode_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), + .items = _dfu_mode_state_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_mode_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), + .items = _dfu_mode_status_lookup +}; + +#endif + +#define dfu_rtd_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ +} //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { + if ( tud_dfu_runtime_init_cb ) { + _dfu_state_ctx.state = (tud_dfu_runtime_init_cb() == DFU_PROTOCOL_DFU) ? APP_DETACH : APP_IDLE; + } else { + _dfu_state_ctx.state = APP_IDLE; + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + + dfu_rtd_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - (void) rhport; + if ( tud_dfu_runtime_usb_reset_cb ) + { + tud_dfu_runtime_usb_reset_cb(rhport, _dfu_state_ctx.state); + } + + switch (_dfu_state_ctx.state) + { + case APP_DETACH: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_runtime_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + dfu_rtd_debug_print_context(); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -69,9 +211,10 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui (void) rhport; (void) max_len; - // Ensure this is DFU Runtime + // Ensure this is DFU Runtime or Mode TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); + ( (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT) + | (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) ), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -90,9 +233,16 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // return false to stall control endpoint (e.g unsupported request) bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - // nothing to do with DATA and ACK stage + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_mode_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage if ( stage != CONTROL_STAGE_SETUP ) return true; + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request @@ -106,34 +256,487 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - switch ( request->bRequest ) + switch (request->bRequest) { case DFU_REQUEST_DETACH: - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - break; - + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: { - // status = OK, poll timeout = 0, state = app idle, istring = 0 - uint8_t status_response[6] = { 0, 0, 0, 0, 0, 0 }; - tud_control_xfer(rhport, request, status_response, sizeof(status_response)); + return dfu_state_machine(rhport, request); } break; - default: return false; // stall unsupported request + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; + } + break; } return true; } +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) +{ + _dfu_state_ctx.status = status; +} -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { - (void) rhport; - (void) ep_addr; - (void) result; - (void) xferred_bytes; + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.epin_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.epin_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); +} + +static void dfu_runtime_start_status_poll_timeout() +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); +} + +void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_runtime_start_status_poll_timeout(); + tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); + _dfu_state_ctx.blk_transfer_in_proc = false; +} + +void tud_dfu_runtime_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case APP_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + { + _dfu_state_ctx.state = APP_DETACH; + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) + { + tud_dfu_runtime_reboot_to_dfu_cb(); + } else { + tud_dfu_runtime_detach_start_timer_cb(request->wValue); + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case APP_DETACH: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = APP_IDLE; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_runtime_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_runtime_abort_cb ) + { + tud_dfu_runtime_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_runtime_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_runtime_abort_cb) + { + tud_dfu_runtime_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + return true; } + #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index cff43d035..0d8f67a9b 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -29,36 +29,106 @@ #include "common/tusb_common.h" #include "device/usbd.h" +#include "dfu.h" #ifdef __cplusplus extern "C" { #endif - //--------------------------------------------------------------------+ -// Common Definitions +// Application Callback API (weak is optional) //--------------------------------------------------------------------+ +// Allow the application to update the status as required. +// Is set to DFU_STATUS_OK during internal initialization and USB reset +// Value is not checked to allow for custom statuses to be used +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 1, - DFU_PROTOCOL_DFU = 2, -} dfu_protocol_type_t; +// Invoked when a DFU_DETACH request is received and bitWillDetatch is set +void tud_dfu_runtime_reboot_to_dfu_cb(); -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; +// Invoked when a DFU_DETACH request is received and bitWillDetatch is not set +// This should start a timer for wTimeout ms +// The application should then look for a USB reset signal to occur before +// the timeout has elapsed. The reset signal will invoke tud_dfu_runtime_usb_reset_cb. +// If this reset signal is received before the timeout, then the application must +// switch to DFU mode. +// If the timer expires, the app does not need to do anything. +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this can will hold up the USB stack +TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_runtime_firmware_valid_check_cb(); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_runtime_init_attrs_cb(); + +// Invoked during initialization of the dfu driver to start as RT or DFU +// This will determine if the internal state machine will begin in +// APP_IDLE or DFU_IDLE +TU_ATTR_WEAK dfu_protocol_type_t tud_dfu_runtime_init_cb(); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); -// Invoked when received new data -TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void); +// Invoked during a USB reset +// Lets the app know that a USB reset has occurred so it can act accordingly, +// See tud_dfu_runtime_detach_start_timer_cb for how to handle the APP_DETACH state +// Other states will be application specific +TU_ATTR_WEAK void tud_dfu_runtime_usb_reset_cb(uint8_t rhport, dfu_mode_state_t state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_runtime_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_runtime_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_runtime_poll_timeout_done(); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_runtime_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_runtime_device_data_done_check_cb(); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_runtime_abort_cb(); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_runtime_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API @@ -67,8 +137,11 @@ void dfu_rtd_init(void); void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +//--------------------------------------------------------------------+ +void dfu_mode_init(void); +void dfu_mode_reset(uint8_t rhport); +void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); #ifdef __cplusplus } #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ba3fe2c41..a462b498f 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -421,6 +421,25 @@ typedef struct TU_ATTR_PACKED char url[]; } tusb_desc_webusb_url_t; +// DFU Functional Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType; + + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +} tusb_desc_dfu_functional_t; + /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ diff --git a/src/device/usbd.c b/src/device/usbd.c index 4fc221888..28c9acdd2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -182,7 +182,7 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_rtd_reset, .open = dfu_rtd_open, .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = dfu_rtd_xfer_cb, + .xfer_cb = NULL, .sof = NULL }, #endif @@ -1270,9 +1270,9 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) /** * usbd_edpt_close will disable an endpoint. - * + * * In progress transfers on this EP may be delivered after this call. - * + * */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { diff --git a/src/device/usbd.h b/src/device/usbd.h index b5f7dceba..f9700811f 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -529,7 +529,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb //------------- DFU Runtime -------------// #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_DFU_APP_SUBCLASS 0x01u +#define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) // Length of template descriptr: 18 bytes #define TUD_DFU_RT_DESC_LEN (9 + 9) @@ -542,6 +542,17 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +// Length of template descriptr: 18 bytes +#define TUD_DFU_MODE_DESC_LEN (9 + 9) + +// DFU runtime descriptor +// Interface number, string index, alternate setting, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _alt_setting, _attr, _timeout, _xfer_size) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt_setting, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + //------------- CDC-ECM -------------// diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index d15380199..724c652e6 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -107,7 +107,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo _ctrl_xfer.buffer = (uint8_t*) buffer; _ctrl_xfer.total_xferred = 0U; _ctrl_xfer.data_len = tu_min16(len, request->wLength); - + if (request->wLength > 0U) { if(_ctrl_xfer.data_len > 0U) diff --git a/src/tusb_option.h b/src/tusb_option.h index 6cbdefbf1..1af3ee672 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -237,6 +237,10 @@ #define CFG_TUD_DFU_RUNTIME 0 #endif +#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE + #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 +#endif + #ifndef CFG_TUD_NET #define CFG_TUD_NET 0 #endif -- cgit v1.3.1 From fb7b47cf07a7a39d39d22502164fec5925fb163e Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Fri, 26 Mar 2021 17:32:03 -0400 Subject: Minor cleanup --- src/class/dfu/dfu_rt_device.c | 20 +++++++++----------- src/class/dfu/dfu_rt_device.h | 4 ---- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 965d1661e..0cbc8eeda 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -66,6 +66,7 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ @@ -280,6 +281,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request return true; } + void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) { _dfu_state_ctx.status = status; @@ -325,21 +327,17 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); } -static void dfu_runtime_start_status_poll_timeout() +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { - uint8_t bwPollTimeout[3] = {0,0,0}; + uint8_t bwPollTimeout[3] = {0,0,0}; - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } - tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); -} + tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); -void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_runtime_start_status_poll_timeout(); tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 0d8f67a9b..9e7ae029e 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -138,10 +138,6 @@ void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -//--------------------------------------------------------------------+ -void dfu_mode_init(void); -void dfu_mode_reset(uint8_t rhport); -void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); #ifdef __cplusplus } #endif -- cgit v1.3.1 From d135825e9ca36bcf50b3476e5dfdc1f74ae1c101 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 21:12:56 +0700 Subject: add hid keys from 0x6B to 0xA4 --- src/class/hid/hid.h | 283 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 171 insertions(+), 112 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index a7db087a7..79b4f48bf 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -303,118 +303,177 @@ typedef enum //--------------------------------------------------------------------+ // HID KEYCODE //--------------------------------------------------------------------+ -#define HID_KEY_NONE 0x00 -#define HID_KEY_A 0x04 -#define HID_KEY_B 0x05 -#define HID_KEY_C 0x06 -#define HID_KEY_D 0x07 -#define HID_KEY_E 0x08 -#define HID_KEY_F 0x09 -#define HID_KEY_G 0x0A -#define HID_KEY_H 0x0B -#define HID_KEY_I 0x0C -#define HID_KEY_J 0x0D -#define HID_KEY_K 0x0E -#define HID_KEY_L 0x0F -#define HID_KEY_M 0x10 -#define HID_KEY_N 0x11 -#define HID_KEY_O 0x12 -#define HID_KEY_P 0x13 -#define HID_KEY_Q 0x14 -#define HID_KEY_R 0x15 -#define HID_KEY_S 0x16 -#define HID_KEY_T 0x17 -#define HID_KEY_U 0x18 -#define HID_KEY_V 0x19 -#define HID_KEY_W 0x1A -#define HID_KEY_X 0x1B -#define HID_KEY_Y 0x1C -#define HID_KEY_Z 0x1D -#define HID_KEY_1 0x1E -#define HID_KEY_2 0x1F -#define HID_KEY_3 0x20 -#define HID_KEY_4 0x21 -#define HID_KEY_5 0x22 -#define HID_KEY_6 0x23 -#define HID_KEY_7 0x24 -#define HID_KEY_8 0x25 -#define HID_KEY_9 0x26 -#define HID_KEY_0 0x27 -#define HID_KEY_RETURN 0x28 -#define HID_KEY_ESCAPE 0x29 -#define HID_KEY_BACKSPACE 0x2A -#define HID_KEY_TAB 0x2B -#define HID_KEY_SPACE 0x2C -#define HID_KEY_MINUS 0x2D -#define HID_KEY_EQUAL 0x2E -#define HID_KEY_BRACKET_LEFT 0x2F -#define HID_KEY_BRACKET_RIGHT 0x30 -#define HID_KEY_BACKSLASH 0x31 -#define HID_KEY_EUROPE_1 0x32 -#define HID_KEY_SEMICOLON 0x33 -#define HID_KEY_APOSTROPHE 0x34 -#define HID_KEY_GRAVE 0x35 -#define HID_KEY_COMMA 0x36 -#define HID_KEY_PERIOD 0x37 -#define HID_KEY_SLASH 0x38 -#define HID_KEY_CAPS_LOCK 0x39 -#define HID_KEY_F1 0x3A -#define HID_KEY_F2 0x3B -#define HID_KEY_F3 0x3C -#define HID_KEY_F4 0x3D -#define HID_KEY_F5 0x3E -#define HID_KEY_F6 0x3F -#define HID_KEY_F7 0x40 -#define HID_KEY_F8 0x41 -#define HID_KEY_F9 0x42 -#define HID_KEY_F10 0x43 -#define HID_KEY_F11 0x44 -#define HID_KEY_F12 0x45 -#define HID_KEY_PRINT_SCREEN 0x46 -#define HID_KEY_SCROLL_LOCK 0x47 -#define HID_KEY_PAUSE 0x48 -#define HID_KEY_INSERT 0x49 -#define HID_KEY_HOME 0x4A -#define HID_KEY_PAGE_UP 0x4B -#define HID_KEY_DELETE 0x4C -#define HID_KEY_END 0x4D -#define HID_KEY_PAGE_DOWN 0x4E -#define HID_KEY_ARROW_RIGHT 0x4F -#define HID_KEY_ARROW_LEFT 0x50 -#define HID_KEY_ARROW_DOWN 0x51 -#define HID_KEY_ARROW_UP 0x52 -#define HID_KEY_NUM_LOCK 0x53 -#define HID_KEY_KEYPAD_DIVIDE 0x54 -#define HID_KEY_KEYPAD_MULTIPLY 0x55 -#define HID_KEY_KEYPAD_SUBTRACT 0x56 -#define HID_KEY_KEYPAD_ADD 0x57 -#define HID_KEY_KEYPAD_ENTER 0x58 -#define HID_KEY_KEYPAD_1 0x59 -#define HID_KEY_KEYPAD_2 0x5A -#define HID_KEY_KEYPAD_3 0x5B -#define HID_KEY_KEYPAD_4 0x5C -#define HID_KEY_KEYPAD_5 0x5D -#define HID_KEY_KEYPAD_6 0x5E -#define HID_KEY_KEYPAD_7 0x5F -#define HID_KEY_KEYPAD_8 0x60 -#define HID_KEY_KEYPAD_9 0x61 -#define HID_KEY_KEYPAD_0 0x62 -#define HID_KEY_KEYPAD_DECIMAL 0x63 -#define HID_KEY_EUROPE_2 0x64 -#define HID_KEY_APPLICATION 0x65 -#define HID_KEY_POWER 0x66 -#define HID_KEY_KEYPAD_EQUAL 0x67 -#define HID_KEY_F13 0x68 -#define HID_KEY_F14 0x69 -#define HID_KEY_F15 0x6A -#define HID_KEY_CONTROL_LEFT 0xE0 -#define HID_KEY_SHIFT_LEFT 0xE1 -#define HID_KEY_ALT_LEFT 0xE2 -#define HID_KEY_GUI_LEFT 0xE3 -#define HID_KEY_CONTROL_RIGHT 0xE4 -#define HID_KEY_SHIFT_RIGHT 0xE5 -#define HID_KEY_ALT_RIGHT 0xE6 -#define HID_KEY_GUI_RIGHT 0xE7 +#define HID_KEY_NONE 0x00 +#define HID_KEY_A 0x04 +#define HID_KEY_B 0x05 +#define HID_KEY_C 0x06 +#define HID_KEY_D 0x07 +#define HID_KEY_E 0x08 +#define HID_KEY_F 0x09 +#define HID_KEY_G 0x0A +#define HID_KEY_H 0x0B +#define HID_KEY_I 0x0C +#define HID_KEY_J 0x0D +#define HID_KEY_K 0x0E +#define HID_KEY_L 0x0F +#define HID_KEY_M 0x10 +#define HID_KEY_N 0x11 +#define HID_KEY_O 0x12 +#define HID_KEY_P 0x13 +#define HID_KEY_Q 0x14 +#define HID_KEY_R 0x15 +#define HID_KEY_S 0x16 +#define HID_KEY_T 0x17 +#define HID_KEY_U 0x18 +#define HID_KEY_V 0x19 +#define HID_KEY_W 0x1A +#define HID_KEY_X 0x1B +#define HID_KEY_Y 0x1C +#define HID_KEY_Z 0x1D +#define HID_KEY_1 0x1E +#define HID_KEY_2 0x1F +#define HID_KEY_3 0x20 +#define HID_KEY_4 0x21 +#define HID_KEY_5 0x22 +#define HID_KEY_6 0x23 +#define HID_KEY_7 0x24 +#define HID_KEY_8 0x25 +#define HID_KEY_9 0x26 +#define HID_KEY_0 0x27 +#define HID_KEY_RETURN 0x28 +#define HID_KEY_ESCAPE 0x29 +#define HID_KEY_BACKSPACE 0x2A +#define HID_KEY_TAB 0x2B +#define HID_KEY_SPACE 0x2C +#define HID_KEY_MINUS 0x2D +#define HID_KEY_EQUAL 0x2E +#define HID_KEY_BRACKET_LEFT 0x2F +#define HID_KEY_BRACKET_RIGHT 0x30 +#define HID_KEY_BACKSLASH 0x31 +#define HID_KEY_EUROPE_1 0x32 +#define HID_KEY_SEMICOLON 0x33 +#define HID_KEY_APOSTROPHE 0x34 +#define HID_KEY_GRAVE 0x35 +#define HID_KEY_COMMA 0x36 +#define HID_KEY_PERIOD 0x37 +#define HID_KEY_SLASH 0x38 +#define HID_KEY_CAPS_LOCK 0x39 +#define HID_KEY_F1 0x3A +#define HID_KEY_F2 0x3B +#define HID_KEY_F3 0x3C +#define HID_KEY_F4 0x3D +#define HID_KEY_F5 0x3E +#define HID_KEY_F6 0x3F +#define HID_KEY_F7 0x40 +#define HID_KEY_F8 0x41 +#define HID_KEY_F9 0x42 +#define HID_KEY_F10 0x43 +#define HID_KEY_F11 0x44 +#define HID_KEY_F12 0x45 +#define HID_KEY_PRINT_SCREEN 0x46 +#define HID_KEY_SCROLL_LOCK 0x47 +#define HID_KEY_PAUSE 0x48 +#define HID_KEY_INSERT 0x49 +#define HID_KEY_HOME 0x4A +#define HID_KEY_PAGE_UP 0x4B +#define HID_KEY_DELETE 0x4C +#define HID_KEY_END 0x4D +#define HID_KEY_PAGE_DOWN 0x4E +#define HID_KEY_ARROW_RIGHT 0x4F +#define HID_KEY_ARROW_LEFT 0x50 +#define HID_KEY_ARROW_DOWN 0x51 +#define HID_KEY_ARROW_UP 0x52 +#define HID_KEY_NUM_LOCK 0x53 +#define HID_KEY_KEYPAD_DIVIDE 0x54 +#define HID_KEY_KEYPAD_MULTIPLY 0x55 +#define HID_KEY_KEYPAD_SUBTRACT 0x56 +#define HID_KEY_KEYPAD_ADD 0x57 +#define HID_KEY_KEYPAD_ENTER 0x58 +#define HID_KEY_KEYPAD_1 0x59 +#define HID_KEY_KEYPAD_2 0x5A +#define HID_KEY_KEYPAD_3 0x5B +#define HID_KEY_KEYPAD_4 0x5C +#define HID_KEY_KEYPAD_5 0x5D +#define HID_KEY_KEYPAD_6 0x5E +#define HID_KEY_KEYPAD_7 0x5F +#define HID_KEY_KEYPAD_8 0x60 +#define HID_KEY_KEYPAD_9 0x61 +#define HID_KEY_KEYPAD_0 0x62 +#define HID_KEY_KEYPAD_DECIMAL 0x63 +#define HID_KEY_EUROPE_2 0x64 +#define HID_KEY_APPLICATION 0x65 +#define HID_KEY_POWER 0x66 +#define HID_KEY_KEYPAD_EQUAL 0x67 +#define HID_KEY_F13 0x68 +#define HID_KEY_F14 0x69 +#define HID_KEY_F15 0x6A +#define HID_KEY_F16 0x6B +#define HID_KEY_F17 0x6C +#define HID_KEY_F18 0x6D +#define HID_KEY_F19 0x6E +#define HID_KEY_F20 0x6F +#define HID_KEY_F21 0x70 +#define HID_KEY_F22 0x71 +#define HID_KEY_F23 0x72 +#define HID_KEY_F24 0x73 +#define HID_KEY_EXECUTE 0x74 +#define HID_KEY_HELP 0x75 +#define HID_KEY_MENU 0x76 +#define HID_KEY_SELECT 0x77 +#define HID_KEY_STOP 0x78 +#define HID_KEY_AGAIN 0x79 +#define HID_KEY_UNDO 0x7A +#define HID_KEY_CUT 0x7B +#define HID_KEY_COPY 0x7C +#define HID_KEY_PASTE 0x7D +#define HID_KEY_FIND 0x7E +#define HID_KEY_MUTE 0x7F +#define HID_KEY_VOLUME_UP 0x80 +#define HID_KEY_VOLUME_DOWN 0x81 +#define HID_KEY_LOCKING_CAPS_LOCK 0x82 +#define HID_KEY_LOCKING_NUM_LOCK 0x83 +#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEY_KEYPAD_COMMA 0x85 +#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEY_KANJI1 0x87 +#define HID_KEY_KANJI2 0x88 +#define HID_KEY_KANJI3 0x89 +#define HID_KEY_KANJI4 0x8A +#define HID_KEY_KANJI5 0x8B +#define HID_KEY_KANJI6 0x8C +#define HID_KEY_KANJI7 0x8D +#define HID_KEY_KANJI8 0x8E +#define HID_KEY_KANJI9 0x8F +#define HID_KEY_LANG1 0x90 +#define HID_KEY_LANG2 0x91 +#define HID_KEY_LANG3 0x92 +#define HID_KEY_LANG4 0x93 +#define HID_KEY_LANG5 0x94 +#define HID_KEY_LANG6 0x95 +#define HID_KEY_LANG7 0x96 +#define HID_KEY_LANG8 0x97 +#define HID_KEY_LANG9 0x98 +#define HID_KEY_ALTERNATE_ERASE 0x99 +#define HID_KEY_SYSREQ_ATTENTION 0x9A +#define HID_KEY_CANCEL 0x9B +#define HID_KEY_CLEAR 0x9C +#define HID_KEY_PRIOR 0x9D +#define HID_KEY_RETURN 0x9E +#define HID_KEY_SEPARATOR 0x9F +#define HID_KEY_OUT 0xA0 +#define HID_KEY_OPER 0xA1 +#define HID_KEY_CLEAR_AGAIN 0xA2 +#define HID_KEY_CRSEL_PROPS 0xA3 +#define HID_KEY_EXSEL 0xA4 +// RESERVED 0xA5-DF +#define HID_KEY_CONTROL_LEFT 0xE0 +#define HID_KEY_SHIFT_LEFT 0xE1 +#define HID_KEY_ALT_LEFT 0xE2 +#define HID_KEY_GUI_LEFT 0xE3 +#define HID_KEY_CONTROL_RIGHT 0xE4 +#define HID_KEY_SHIFT_RIGHT 0xE5 +#define HID_KEY_ALT_RIGHT 0xE6 +#define HID_KEY_GUI_RIGHT 0xE7 //--------------------------------------------------------------------+ -- cgit v1.3.1 From 89a911ee43f2c7a17303b58739dc8b22cbd56294 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 21:26:35 +0700 Subject: correct hid key enter = 0x28, return = 0x9E --- src/class/hid/hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 79b4f48bf..351a4d600 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -340,7 +340,7 @@ typedef enum #define HID_KEY_8 0x25 #define HID_KEY_9 0x26 #define HID_KEY_0 0x27 -#define HID_KEY_RETURN 0x28 +#define HID_KEY_ENTER 0x28 #define HID_KEY_ESCAPE 0x29 #define HID_KEY_BACKSPACE 0x2A #define HID_KEY_TAB 0x2B -- cgit v1.3.1 From c5aa661c892159b2eced9b2e3c1a4a1d8f92b1f6 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 23:54:17 +0700 Subject: rename tud_midi_receive/send to tud_midi_packet_read/write --- src/class/midi/midi_device.c | 6 +++--- src/class/midi/midi_device.h | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 29019cc1d..3772c4759 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -127,7 +127,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t // Fill empty buffer if (midi->read_buffer_length == 0) { - if (!tud_midi_n_receive(itf, midi->read_buffer)) return 0; + if (!tud_midi_n_packet_read(itf, midi->read_buffer)) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. @@ -166,7 +166,7 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) _prep_out_transaction(p_midi); } -bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { midid_interface_t* p_midi = &_midid_itf[itf]; uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); @@ -278,7 +278,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, return i; } -bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) { midid_interface_t* midi = &_midid_itf[itf]; if (midi->itf_num == 0) { diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 5e7df80ae..f76554c70 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -68,8 +68,8 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* b static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); -bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) @@ -80,8 +80,9 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -static inline bool tud_midi_receive (uint8_t packet[4]); -static inline bool tud_midi_send (uint8_t const packet[4]); + +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write(uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -129,14 +130,14 @@ static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t return tud_midi_write(cable_num, msg, 3); } -static inline bool tud_midi_receive (uint8_t packet[4]) +static inline bool tud_midi_packet_read (uint8_t packet[4]) { - return tud_midi_n_receive(0, packet); + return tud_midi_n_packet_read(0, packet); } -static inline bool tud_midi_send (uint8_t const packet[4]) +static inline bool tud_midi_packet_write (uint8_t const packet[4]) { - return tud_midi_n_send(0, packet); + return tud_midi_n_packet_write(0, packet); } //--------------------------------------------------------------------+ -- cgit v1.3.1 From b05084e406b50c6378572974e47d7e2ec15f2045 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 23:56:55 +0700 Subject: remove tud_midi_read_flush() --- src/class/midi/midi_device.c | 8 -------- src/class/midi/midi_device.h | 7 ------- 2 files changed, 15 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 3772c4759..48e5a8e68 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -158,14 +158,6 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t return n; } -void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - midid_interface_t* p_midi = &_midid_itf[itf]; - tu_fifo_clear(&p_midi->rx_ff); - _prep_out_transaction(p_midi); -} - bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { midid_interface_t* p_midi = &_midid_itf[itf]; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index f76554c70..1060fd77a 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -62,7 +62,6 @@ bool tud_midi_n_mounted (uint8_t itf); uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); -void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num); uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline @@ -77,7 +76,6 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); -static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); @@ -114,11 +112,6 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) return tud_midi_n_read(0, 0, buffer, bufsize); } -static inline void tud_midi_read_flush (void) -{ - tud_midi_n_read_flush(0, 0); -} - static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { return tud_midi_n_write(0, cable_num, buffer, bufsize); -- cgit v1.3.1 From 949ff791e0222d9d89fe54b7cab036125997b66e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Mar 2021 00:34:09 +0700 Subject: code format --- src/class/midi/midi_device.c | 131 +++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 54 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 48e5a8e68..1ff81c39a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -200,67 +200,90 @@ static uint32_t write_flush(midid_interface_t* midi) uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; - if (midi->itf_num == 0) { - return 0; - } + TU_VERIFY(midi->itf_num, 0); uint32_t i = 0; - while (i < bufsize) { + while ( i < bufsize ) + { uint8_t data = buffer[i]; - if (midi->write_buffer_length == 0) { - uint8_t msg = data >> 4; - midi->write_buffer[1] = data; - midi->write_buffer_length = 2; - // Check to see if we're still in a SysEx transmit. - if (midi->write_buffer[0] == 0x4) { - if (data == 0xf7) { - midi->write_buffer[0] = 0x5; - midi->write_target_length = 2; - } else { - midi->write_target_length = 4; - } - } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->write_buffer[0] = cable_num << 4 | msg; - midi->write_target_length = 4; - } else if (msg == 0xf) { - if (data == 0xf0) { - midi->write_buffer[0] = 0x4; - midi->write_target_length = 4; - } else if (data == 0xf1 || data == 0xf3) { - midi->write_buffer[0] = 0x2; - midi->write_target_length = 3; - } else if (data == 0xf2) { - midi->write_buffer[0] = 0x3; - midi->write_target_length = 4; - } else { - midi->write_buffer[0] = 0x5; - midi->write_target_length = 2; - } - } else { - // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = cable_num << 4 | 0xf; - midi->write_buffer[2] = 0; - midi->write_buffer[3] = 0; - midi->write_buffer_length = 2; - midi->write_target_length = 2; + if ( midi->write_buffer_length == 0 ) + { + uint8_t msg = data >> 4; + midi->write_buffer[1] = data; + midi->write_buffer_length = 2; + // Check to see if we're still in a SysEx transmit. + if ( midi->write_buffer[0] == 0x4 ) + { + if ( data == 0xf7 ) + { + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; } - } else { - midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length += 1; - // See if this byte ends a SysEx. - if (midi->write_buffer[0] == 0x4 && data == 0xf7) { - midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); - midi->write_target_length = midi->write_buffer_length; + else + { + midi->write_target_length = 4; + } + } + else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) + { + midi->write_buffer[0] = cable_num << 4 | msg; + midi->write_target_length = 4; + } + else if ( msg == 0xf ) + { + if ( data == 0xf0 ) + { + midi->write_buffer[0] = 0x4; + midi->write_target_length = 4; + } + else if ( data == 0xf1 || data == 0xf3 ) + { + midi->write_buffer[0] = 0x2; + midi->write_target_length = 3; } + else if ( data == 0xf2 ) + { + midi->write_buffer[0] = 0x3; + midi->write_target_length = 4; + } + else + { + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; + } + } + else + { + // Pack individual bytes if we don't support packing them into words. + midi->write_buffer[0] = cable_num << 4 | 0xf; + midi->write_buffer[2] = 0; + midi->write_buffer[3] = 0; + midi->write_buffer_length = 2; + midi->write_target_length = 2; + } + } + else + { + TU_ASSERT(midi->write_buffer_length < 4, 0); + midi->write_buffer[midi->write_buffer_length] = data; + midi->write_buffer_length += 1; + // See if this byte ends a SysEx. + if ( midi->write_buffer[0] == 0x4 && data == 0xf7 ) + { + midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_target_length = midi->write_buffer_length; + } } - if (midi->write_buffer_length == midi->write_target_length) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); - if (written < 4) { - TU_ASSERT( written == 0 ); - break; - } - midi->write_buffer_length = 0; + if ( midi->write_buffer_length == midi->write_target_length ) + { + uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + if ( written < 4 ) + { + TU_ASSERT(written == 0); + break; + } + midi->write_buffer_length = 0; } i++; } -- cgit v1.3.1 From 080b14b292251e46b43aac9e1cf7807dc2d3eb2c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 13:26:55 +0700 Subject: fix midi tx fifo overflow cause data corruption rename --- examples/device/dynamic_configuration/src/main.c | 2 +- examples/device/midi_test/src/main.c | 8 +- examples/make.mk | 2 +- src/class/midi/midi.h | 45 ++++++++++ src/class/midi/midi_device.c | 103 ++++++++++++++--------- src/class/midi/midi_device.h | 16 +++- 6 files changed, 127 insertions(+), 49 deletions(-) (limited to 'src/class') diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index acee295f6..ce1f752d0 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -172,7 +172,7 @@ void midi_task(void) // regardless of these being used or not. Therefore incoming traffic should be read // (possibly just discarded) to avoid the sender blocking in IO uint8_t packet[4]; - while(tud_midi_available()) tud_midi_receive(packet); + while( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms if (board_millis() - start_ms < 286) return; // not enough time diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 858a096b6..af10350df 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -132,7 +132,7 @@ void midi_task(void) // regardless of these being used or not. Therefore incoming traffic should be read // (possibly just discarded) to avoid the sender blocking in IO uint8_t packet[4]; - while(tud_midi_available()) tud_midi_receive(packet); + while ( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms if (board_millis() - start_ms < 286) return; // not enough time @@ -146,10 +146,12 @@ void midi_task(void) if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tud_midi_write24(cable_num, 0x90 | channel, note_sequence[note_pos], 127); + uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; + tud_midi_write(cable_num, note_on, 3); // Send Note Off for previous note. - tud_midi_write24(cable_num, 0x80 | channel, note_sequence[previous], 0); + uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; + tud_midi_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/examples/make.mk b/examples/make.mk index e04a2592a..ffcb8ee5c 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -103,7 +103,7 @@ CFLAGS += \ # Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -Og + CFLAGS += -O0 else CFLAGS += -Os endif diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index f758b6e1c..74dc41749 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -61,6 +61,51 @@ typedef enum MIDI_JACK_EXTERNAL = 0x02 } midi_jack_type_t; +typedef enum +{ + MIDI_CIN_MISC = 0, + MIDI_CIN_CABLE_EVENT = 1, + MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect + MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP + MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue + MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message + MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data + MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data + MIDI_CIN_NOTE_ON = 8, + MIDI_CIN_NOTE_OFF = 9, + MIDI_CIN_POLY_KEYPRESS = 10, + MIDI_CIN_CONTROL_CHANGE = 11, + MIDI_CIN_PROGRAM_CHANGE = 12, + MIDI_CIN_CHANNEL_PRESSURE = 13, + MIDI_CIN_PITCH_BEND_CHANGE = 14, + MIDI_CIN_1BYTE_DATA = 15 +} midi_code_index_number_t; + +// MIDI 1.0 status byte +enum +{ + //------------- System Exclusive -------------// + MIDI_STATUS_SYSEX_START = 0xF0, + MIDI_STATUS_SYSEX_END = 0xF7, + + //------------- System Common -------------// + MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, + MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, + MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, + // F4, F5 is undefined + MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, + + //------------- System RealTime -------------// + MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, + // 0xF9 is undefined + MIDI_STATUS_SYSREAL_START = 0xFA, + MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, + MIDI_STATUS_SYSREAL_STOP = 0xFC, + // 0xFD is undefined + MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, + MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, +}; + /// MIDI Interface Header Descriptor typedef struct TU_ATTR_PACKED { diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 1ff81c39a..cba1dcca0 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -38,6 +38,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + typedef struct { uint8_t itf_num; @@ -126,16 +127,19 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t midid_interface_t* midi = &_midid_itf[itf]; // Fill empty buffer - if (midi->read_buffer_length == 0) { - if (!tud_midi_n_packet_read(itf, midi->read_buffer)) return 0; + if ( midi->read_buffer_length == 0 ) + { + if ( !tud_midi_n_packet_read(itf, midi->read_buffer) ) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. uint8_t count = 1; // Ignore subsequent bytes based on the code. - if (code_index != 0x5 && code_index != 0xf) { + if ( code_index != 0x5 && code_index != 0xf ) + { count = 2; - if (code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd) { + if ( code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd ) + { count = 3; } } @@ -150,7 +154,8 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); midi->read_target_length += n; - if (midi->read_target_length == midi->read_buffer_length) { + if ( midi->read_target_length == midi->read_buffer_length ) + { midi->read_buffer_length = 0; midi->read_target_length = 0; } @@ -166,10 +171,6 @@ bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) return (num_read == 4); } -void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { - tu_fifo_write_n(&midi->rx_ff, buffer, bufsize); -} - //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ @@ -185,7 +186,8 @@ static uint32_t write_flush(midid_interface_t* midi) TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - if (count > 0) + + if (count) { TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); return count; @@ -202,21 +204,26 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); + uint32_t written = 0; uint32_t i = 0; while ( i < bufsize ) { - uint8_t data = buffer[i]; + uint8_t const data = buffer[i]; + if ( midi->write_buffer_length == 0 ) { - uint8_t msg = data >> 4; + // new packet + + uint8_t const msg = data >> 4; midi->write_buffer[1] = data; midi->write_buffer_length = 2; + // Check to see if we're still in a SysEx transmit. - if ( midi->write_buffer[0] == 0x4 ) + if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START ) { - if ( data == 0xf7 ) + if ( data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = 0x5; + midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; midi->write_target_length = 2; } else @@ -226,29 +233,31 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, } else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { - midi->write_buffer[0] = cable_num << 4 | msg; + // Channel Voice Messages + midi->write_buffer[0] = (cable_num << 4) | msg; midi->write_target_length = 4; } else if ( msg == 0xf ) { - if ( data == 0xf0 ) + // System message + if ( data == MIDI_STATUS_SYSEX_START ) { - midi->write_buffer[0] = 0x4; + midi->write_buffer[0] = MIDI_CIN_SYSEX_START; midi->write_target_length = 4; } - else if ( data == 0xf1 || data == 0xf3 ) + else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) { - midi->write_buffer[0] = 0x2; + midi->write_buffer[0] = MIDI_CIN_SYSCOM_2BYTE; midi->write_target_length = 3; } - else if ( data == 0xf2 ) + else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) { - midi->write_buffer[0] = 0x3; + midi->write_buffer[0] = MIDI_CIN_SYSCOM_3BYTE; midi->write_target_length = 4; } else { - midi->write_buffer[0] = 0x5; + midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; midi->write_target_length = 2; } } @@ -264,33 +273,44 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, } else { + // On-going packet + TU_ASSERT(midi->write_buffer_length < 4, 0); midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length += 1; + midi->write_buffer_length++; + // See if this byte ends a SysEx. - if ( midi->write_buffer[0] == 0x4 && data == 0xf7 ) + if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_buffer[0] = MIDI_CIN_SYSEX_START + (midi->write_buffer_length - 1); midi->write_target_length = midi->write_buffer_length; } } + // Send out packet if ( midi->write_buffer_length == midi->write_target_length ) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); - if ( written < 4 ) - { - TU_ASSERT(written == 0); - break; - } - midi->write_buffer_length = 0; + // zeroes unused bytes + for(uint8_t idx = midi->write_target_length; idx < 4; idx++) midi->write_buffer[idx] = 0; + + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + + // reset buffer + midi->write_buffer_length = midi->write_target_length = 0; + + // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing + if ( count != 4 ) break; + + // updated written if succeeded + written = i; } + i++; } write_flush(midi); - return i; + return written; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) @@ -300,8 +320,7 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) return 0; } - if (tu_fifo_remaining(&midi->tx_ff) < 4) - return false; + if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; tu_fifo_write_n(&midi->tx_ff, packet, 4); write_flush(midi); @@ -347,9 +366,9 @@ void midid_reset(uint8_t rhport) uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); uint16_t drv_len = tu_desc_len(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf); @@ -365,9 +384,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 1060fd77a..aaceaf62a 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -59,16 +59,28 @@ // Application API (Multiple Interfaces) // CFG_TUD_MIDI > 1 //--------------------------------------------------------------------+ + +// Check if midi interface is mounted bool tud_midi_n_mounted (uint8_t itf); + +// Get the number of bytes available for reading uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); + +// Read byte stream (legacy) uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); + +// Write byte Stream (legacy) uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +// Write good-old 3 bytes data, this use write packet static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); + +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) -- cgit v1.3.1 From 6b04efd443c3299131135849b736a2f2ce5877ac Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 13:55:51 +0700 Subject: refactor midi stream read --- src/class/midi/midi_device.c | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index cba1dcca0..14748f18b 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -39,6 +39,13 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct +{ + uint8_t buffer[4]; + uint8_t index; + uint8_t total; +}midid_stream_t; + typedef struct { uint8_t itf_num; @@ -57,12 +64,15 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif + // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. uint8_t write_buffer[4]; uint8_t write_buffer_length; uint8_t write_target_length; +// midid_stream_t stream_write; + uint8_t read_buffer[4]; uint8_t read_buffer_length; uint8_t read_target_length; @@ -129,26 +139,41 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t // Fill empty buffer if ( midi->read_buffer_length == 0 ) { - if ( !tud_midi_n_packet_read(itf, midi->read_buffer) ) return 0; + TU_VERIFY(tud_midi_n_packet_read(itf, midi->read_buffer), 0); - uint8_t code_index = midi->read_buffer[0] & 0x0f; - // We always copy over the first byte. - uint8_t count = 1; - // Ignore subsequent bytes based on the code. - if ( code_index != 0x5 && code_index != 0xf ) + uint8_t const code_index = midi->read_buffer[0] & 0x0f; + uint8_t count; + + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) { - count = 2; - if ( code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd ) - { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; + + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + count = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + count = 2; + break; + + default: count = 3; - } + break; } midi->read_buffer_length = count; } - uint32_t n = midi->read_buffer_length - midi->read_target_length; - if (bufsize < n) n = bufsize; + uint32_t n = tu_min32(midi->read_buffer_length - midi->read_target_length, bufsize); // Skip the header in the buffer memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); @@ -204,6 +229,8 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); +// midid_stream_t* stream = &midi->stream_write; + uint32_t written = 0; uint32_t i = 0; while ( i < bufsize ) -- cgit v1.3.1 From 08fe16840fcc39e4cb7c1f55fa56762427734753 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:26:55 +0700 Subject: refactor midi write into stream --- src/class/midi/midi_device.c | 77 +++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 40 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 14748f18b..49bf2a27a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -67,11 +67,7 @@ typedef struct // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. - uint8_t write_buffer[4]; - uint8_t write_buffer_length; - uint8_t write_target_length; - -// midid_stream_t stream_write; + midid_stream_t stream_write; uint8_t read_buffer[4]; uint8_t read_buffer_length; @@ -229,7 +225,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); -// midid_stream_t* stream = &midi->stream_write; + midid_stream_t* stream = &midi->stream_write; uint32_t written = 0; uint32_t i = 0; @@ -237,93 +233,94 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, { uint8_t const data = buffer[i]; - if ( midi->write_buffer_length == 0 ) + if ( stream->index == 0 ) { - // new packet + // new event packet uint8_t const msg = data >> 4; - midi->write_buffer[1] = data; - midi->write_buffer_length = 2; + + stream->index = 2; + stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START ) + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) { if ( data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - midi->write_target_length = 2; + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } else { - midi->write_target_length = 4; + stream->total = 4; } } else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { // Channel Voice Messages - midi->write_buffer[0] = (cable_num << 4) | msg; - midi->write_target_length = 4; + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 4; } else if ( msg == 0xf ) { // System message if ( data == MIDI_STATUS_SYSEX_START ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_START; - midi->write_target_length = 4; + stream->buffer[0] = MIDI_CIN_SYSEX_START; + stream->total = 4; } else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) { - midi->write_buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - midi->write_target_length = 3; + stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; + stream->total = 3; } else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) { - midi->write_buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - midi->write_target_length = 4; + stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; + stream->total = 4; } else { - midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - midi->write_target_length = 2; + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } } else { // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = cable_num << 4 | 0xf; - midi->write_buffer[2] = 0; - midi->write_buffer[3] = 0; - midi->write_buffer_length = 2; - midi->write_target_length = 2; + stream->buffer[0] = cable_num << 4 | 0xf; + stream->buffer[2] = 0; + stream->buffer[3] = 0; + stream->index = 2; + stream->total = 2; } } else { - // On-going packet + // On-going (buffering) packet - TU_ASSERT(midi->write_buffer_length < 4, 0); - midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length++; + TU_ASSERT(stream->index < 4, written); + stream->buffer[stream->index] = data; + stream->index++; // See if this byte ends a SysEx. - if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_START + (midi->write_buffer_length - 1); - midi->write_target_length = midi->write_buffer_length; + stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); + stream->total = stream->index; } } // Send out packet - if ( midi->write_buffer_length == midi->write_target_length ) + if ( stream->index == stream->total ) { // zeroes unused bytes - for(uint8_t idx = midi->write_target_length; idx < 4; idx++) midi->write_buffer[idx] = 0; + for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); // reset buffer - midi->write_buffer_length = midi->write_target_length = 0; + stream->index = stream->total = 0; // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing if ( count != 4 ) break; -- cgit v1.3.1 From 99b78e62f2172988ffa3835b7d6bcaaf455cef10 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:34:13 +0700 Subject: removed tud_midi_write24() --- src/class/midi/midi_device.h | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index aaceaf62a..c875748fd 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -72,10 +72,6 @@ uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, ui // Write byte Stream (legacy) uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -// Write good-old 3 bytes data, this use write packet -static inline -uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); - // Read event packet (4 bytes) bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); @@ -87,13 +83,26 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); + static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); static inline bool tud_midi_packet_read (uint8_t packet[4]); static inline bool tud_midi_packet_write(uint8_t const packet[4]); +// TODO remove after 0.10.0 release +TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") +static inline bool tud_midi_send(uint8_t packet[4]) +{ + return tud_midi_packet_write(packet); +} + +TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") +static inline bool tud_midi_receive(uint8_t packet[4]) +{ + return tud_midi_packet_read(packet); +} + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ @@ -103,12 +112,6 @@ TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); // Inline Functions //--------------------------------------------------------------------+ -static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) -{ - uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_n_write(itf, cable_num, msg, 3); -} - static inline bool tud_midi_mounted (void) { return tud_midi_n_mounted(0); @@ -129,12 +132,6 @@ static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, return tud_midi_n_write(0, cable_num, buffer, bufsize); } -static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) -{ - uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_write(cable_num, msg, 3); -} - static inline bool tud_midi_packet_read (uint8_t packet[4]) { return tud_midi_n_packet_read(0, packet); -- cgit v1.3.1 From da59c4ad4434b64691aa7a93e03381702633964d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:43:38 +0700 Subject: rename midi write()/read() to stream_write() stream_read() also add deprecated for warning and rename hint --- examples/device/dynamic_configuration/src/main.c | 6 ++- examples/device/midi_test/src/main.c | 4 +- src/class/midi/midi_device.c | 4 +- src/class/midi/midi_device.h | 55 +++++++++++++++--------- 4 files changed, 43 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index ce1f752d0..4c10f55b0 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -186,10 +186,12 @@ void midi_task(void) if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tud_midi_write24(cable_num, 0x90 | channel, note_sequence[note_pos], 127); + uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; + tud_midi_stream_write(cable_num, note_on, 3); // Send Note Off for previous note. - tud_midi_write24(cable_num, 0x80 | channel, note_sequence[previous], 0); + uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; + tud_midi_stream_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index af10350df..9e0e82a10 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -147,11 +147,11 @@ void midi_task(void) // Send Note On for current position at full velocity (127) on channel 1. uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; - tud_midi_write(cable_num, note_on, 3); + tud_midi_stream_write(cable_num, note_on, 3); // Send Note Off for previous note. uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; - tud_midi_write(cable_num, note_off, 3); + tud_midi_stream_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 49bf2a27a..e76f01db2 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -127,7 +127,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) return tu_fifo_count(&_midid_itf[itf].rx_ff); } -uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; @@ -220,7 +220,7 @@ static uint32_t write_flush(midid_interface_t* midi) } } -uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index c875748fd..67f03930c 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -61,36 +61,51 @@ //--------------------------------------------------------------------+ // Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); +bool tud_midi_n_mounted (uint8_t itf); // Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); -// Read byte stream (legacy) -uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); +// Read byte stream (legacy) +uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); -// Write byte Stream (legacy) -uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +// Write byte Stream (legacy) +uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) //--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); +static inline bool tud_midi_mounted (void); +static inline uint32_t tud_midi_available (void); -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write(uint8_t const packet[4]); +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write (uint8_t const packet[4]); +//------------- Deprecated API name -------------// // TODO remove after 0.10.0 release + +TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") +static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +{ + return tud_midi_stream_read(buffer, bufsize); +} + +TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") +static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + return tud_midi_stream_write(cable_num, buffer, bufsize); +} + + TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") static inline bool tud_midi_send(uint8_t packet[4]) { @@ -122,14 +137,14 @@ static inline uint32_t tud_midi_available (void) return tud_midi_n_available(0, 0); } -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) { - return tud_midi_n_read(0, 0, buffer, bufsize); + return tud_midi_n_stream_read(0, 0, buffer, bufsize); } -static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { - return tud_midi_n_write(0, cable_num, buffer, bufsize); + return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); } static inline bool tud_midi_packet_read (uint8_t packet[4]) -- cgit v1.3.1 From 350eb1127755f3ee0dd3dd186cc31e9492916a0c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:52:44 +0700 Subject: refactor midi read buffer to stream --- src/class/midi/midi_device.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index e76f01db2..a4cc104a8 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -68,10 +68,7 @@ typedef struct // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. midid_stream_t stream_write; - - uint8_t read_buffer[4]; - uint8_t read_buffer_length; - uint8_t read_target_length; + midid_stream_t stream_read; // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; @@ -131,14 +128,16 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui { (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t* stream = &midi->stream_read; + + TU_VERIFY(bufsize, 0); - // Fill empty buffer - if ( midi->read_buffer_length == 0 ) + // Get new packet from fifo + if ( stream->total == 0 ) { - TU_VERIFY(tud_midi_n_packet_read(itf, midi->read_buffer), 0); + TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0); - uint8_t const code_index = midi->read_buffer[0] & 0x0f; - uint8_t count; + uint8_t const code_index = stream->buffer[0] & 0x0f; // MIDI 1.0 Table 4-1: Code Index Number Classifications switch(code_index) @@ -151,34 +150,32 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui case MIDI_CIN_SYSEX_END_1BYTE: case MIDI_CIN_1BYTE_DATA: - count = 1; + stream->total = 1; break; case MIDI_CIN_SYSCOM_2BYTE : case MIDI_CIN_SYSEX_END_2BYTE : case MIDI_CIN_PROGRAM_CHANGE : case MIDI_CIN_CHANNEL_PRESSURE : - count = 2; + stream->total = 2; break; default: - count = 3; + stream->total = 3; break; } - - midi->read_buffer_length = count; } - uint32_t n = tu_min32(midi->read_buffer_length - midi->read_target_length, bufsize); + uint32_t const n = tu_min32(stream->total - stream->index, bufsize); - // Skip the header in the buffer - memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); - midi->read_target_length += n; + // Skip the header (1st byte) in the buffer + memcpy(buffer, stream->buffer + 1 + stream->index, n); + stream->index += n; - if ( midi->read_target_length == midi->read_buffer_length ) + if ( stream->total == stream->index ) { - midi->read_buffer_length = 0; - midi->read_target_length = 0; + stream->index = 0; + stream->total = 0; } return n; -- cgit v1.3.1 From 48bb96f5072a173189d9076c5c2b1f5066327bf6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 15:08:36 +0700 Subject: correct midi stream read behavior to read until user buffer is full or no more data from usb fifo --- src/class/midi/midi_device.c | 111 ++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 49 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a4cc104a8..9ccbb733c 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -52,6 +52,12 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midid_stream_t stream_write; + midid_stream_t stream_read; + /*------------- From this point, data is not cleared by bus reset -------------*/ // FIFO tu_fifo_t rx_ff; @@ -64,12 +70,6 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; @@ -127,58 +127,71 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { (void) cable_num; - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; - TU_VERIFY(bufsize, 0); - // Get new packet from fifo - if ( stream->total == 0 ) - { - TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0); + uint8_t* buf8 = (uint8_t*) buffer; - uint8_t const code_index = stream->buffer[0] & 0x0f; + midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t* stream = &midi->stream_read; - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) + uint32_t total_read = 0; + while( bufsize ) + { + // Get new packet from fifo, then set packet expected bytes + if ( stream->total == 0 ) { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; + // return if there is no more data from fifo + if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; + uint8_t const code_index = stream->buffer[0] & 0x0f; - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) + { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; + + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + stream->total = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + stream->total = 2; + break; - default: - stream->total = 3; - break; + default: + stream->total = 3; + break; + } } - } - uint32_t const n = tu_min32(stream->total - stream->index, bufsize); + // Copy data up to bufsize + uint32_t const count = tu_min32(stream->total - stream->index, bufsize); - // Skip the header (1st byte) in the buffer - memcpy(buffer, stream->buffer + 1 + stream->index, n); - stream->index += n; + // Skip the header (1st byte) in the buffer + memcpy(buf8, stream->buffer + 1 + stream->index, count); - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; + total_read += count; + stream->index += count; + buf8 += count; + bufsize -= count; + + // complete current event packet, reset stream + if ( stream->total == stream->index ) + { + stream->index = 0; + stream->total = 0; + } } - return n; + return total_read; } bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) @@ -224,7 +237,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* midid_stream_t* stream = &midi->stream_write; - uint32_t written = 0; + uint32_t total_written = 0; uint32_t i = 0; while ( i < bufsize ) { @@ -296,7 +309,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* { // On-going (buffering) packet - TU_ASSERT(stream->index < 4, written); + TU_ASSERT(stream->index < 4, total_written); stream->buffer[stream->index] = data; stream->index++; @@ -316,14 +329,14 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - // reset buffer + // complete current event packet, reset stream stream->index = stream->total = 0; // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing if ( count != 4 ) break; // updated written if succeeded - written = i; + total_written = i; } i++; @@ -331,7 +344,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* write_flush(midi); - return written; + return total_written; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -- cgit v1.3.1 From 9b2ddd9cc6401b80350179d26e842557f9b60aaf Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 09:49:27 +0200 Subject: Generalize audio driver for 3 audio functions plus a lot more. - Audio format and parameters are parsed from descriptors thus user no longer needs to give them explicitely - Tested for 4 channel software type I PCM encoding with 16 bit with 1 channel per FIFO and 2 channels per FIFO (this is I2S specific) --- examples/device/audio_test/src/main.c | 8 +- examples/device/audio_test/src/tusb_config.h | 22 +- examples/device/audio_test/src/usb_descriptors.c | 11 +- examples/device/uac2_headset/src/tusb_config.h | 34 +- examples/device/uac2_headset/src/usb_descriptors.c | 2 +- src/class/audio/audio.h | 76 +- src/class/audio/audio_device.c | 1088 ++++++++++++++++---- src/class/audio/audio_device.h | 313 ++++-- src/common/tusb_fifo.c | 4 +- src/device/usbd.h | 59 +- 10 files changed, 1214 insertions(+), 403 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index a631f37b6..7cbf57946 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -53,17 +53,17 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_EPSIZE_IN/2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_EP_SZ_IN/2]; uint16_t startVal = 0; void led_blinking_task(void); diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 557a8b15e..d3b617319 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -91,6 +91,21 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +// Have a look into audio_device.h for all configurations + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! +#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channel +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 + + + // Audio format type #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I @@ -100,14 +115,11 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_EPSIZE_IN 48 * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 -// Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 #ifdef __cplusplus } diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index d4869a940..67dd34d2a 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -79,7 +79,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -89,20 +89,13 @@ enum #define EPNUM_AUDIO 0x01 #endif -// These variables are required by the audio driver in audio_device.c - -// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO - unfortunately this is not possible to determine otherwise -const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_MIC_DESC_LEN}; - -// TAKE CARE - THE NUMBER OF AUDIO STREAMING INTERFACES PER AUDIO FUNCTION MUST NOT EXCEED CFG_TUD_AUDIO_N_AS_INT - IF IT DOES INCREASE CFG_TUD_AUDIO_N_AS_INT IN tusb_config.h! - uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EPSIZE_IN) + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 7795d8405..511e4e558 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -91,35 +91,31 @@ extern "C" { //-------------------------------------------------------------------- // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) - -// Audio format type -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_I +#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) +#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) // Audio format type I specifications -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 -#define CFG_TUD_AUDIO_N_CHANNELS_RX 2 -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 2 -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX 2 +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EPSIZE_IN // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT*3 +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 +#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 #ifdef __cplusplus } diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 940f0fe2b..b69e5a5e0 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -98,7 +98,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EPSIZE_OUT, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EPSIZE_IN) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index af0e86e21..2c6cd260a 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -469,44 +469,44 @@ typedef enum /// Additional Audio Device Class Codes - Source: Audio Data Formats /// A.1 - Audio Class-Format Type Codes UAC2 -//typedef enum -//{ -// AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, -// AUDIO_FORMAT_TYPE_I = 0x01, -// AUDIO_FORMAT_TYPE_II = 0x02, -// AUDIO_FORMAT_TYPE_III = 0x03, -// AUDIO_FORMAT_TYPE_IV = 0x04, -// AUDIO_EXT_FORMAT_TYPE_I = 0x81, -// AUDIO_EXT_FORMAT_TYPE_II = 0x82, -// AUDIO_EXT_FORMAT_TYPE_III = 0x83, -//} audio_format_type_t; - -#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 -#define AUDIO_FORMAT_TYPE_I 0x01 -#define AUDIO_FORMAT_TYPE_II 0x02 -#define AUDIO_FORMAT_TYPE_III 0x03 -#define AUDIO_FORMAT_TYPE_IV 0x04 -#define AUDIO_EXT_FORMAT_TYPE_I 0x81 -#define AUDIO_EXT_FORMAT_TYPE_II 0x82 -#define AUDIO_EXT_FORMAT_TYPE_III 0x83 - -/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -//typedef enum -//{ -// AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), -// AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), -// AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), -// AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), -// AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), -// AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, -//} audio_data_format_type_I_t; - -#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) -#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) -#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) -#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) -#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) -#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +//#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +//#define AUDIO_FORMAT_TYPE_I 0x01 +//#define AUDIO_FORMAT_TYPE_II 0x02 +//#define AUDIO_FORMAT_TYPE_III 0x03 +//#define AUDIO_FORMAT_TYPE_IV 0x04 +//#define AUDIO_EXT_FORMAT_TYPE_I 0x81 +//#define AUDIO_EXT_FORMAT_TYPE_II 0x82 +//#define AUDIO_EXT_FORMAT_TYPE_III 0x83 + +// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, +} audio_data_format_type_I_t; + +//#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) +//#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) +//#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) +//#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) +//#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) +//#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 73f265a8f..5df32c30f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -63,7 +63,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically #if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ @@ -92,18 +92,170 @@ #define USE_LINEAR_BUFFER 0 #endif +// Declaration of buffers + +// Check for maximum supported numbers +#if CFG_TUD_AUDIO > 3 +#error Maximum number of audio functions restricted to three! +#endif + +// EP IN software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + +// Linear buffer TX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// EP OUT software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + +// Linear buffer RX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// Control buffers +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +#if CFG_TUD_AUDIO > 1 +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +#endif +#if CFG_TUD_AUDIO > 2 +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +#endif + +// Active alternate setting of interfaces +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +#endif + +// Software encoding/decoding support FIFOs +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#endif + typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN uint8_t ep_in; // TX audio data EP. + uint16_t ep_in_sz; // Current size of TX EP uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT uint8_t ep_out; // Incoming (into uC) audio data EP. + uint16_t ep_out_sz; // Current size of RX EP uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -116,74 +268,83 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif -#if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + uint8_t * alt_setting_ptr; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif /*------------- From this point, data is not cleared by bus reset -------------*/ + // + uint16_t desc_length; // Length of audio function descriptor + // Buffer for control requests - CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + uint8_t * ctrl_buf; + uint8_t ctrl_buf_sz; // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - -#if !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t ep_out_ff; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd; // No need for write mutex as only USB driver writes into FIFO -#endif - #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). #endif - #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t ep_in_ff; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr; // No need for read mutex as only USB driver reads from FIFO #endif -#endif - - // Audio control interrupt buffer - no FIFO + // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif - // Support FIFOs -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + // Decoding parameters - parameters are set when alternate AS interface is set by host + // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + audio_format_type_t format_type_rx; + uint8_t n_channels_rx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio_data_format_type_I_t format_type_I_rx; + uint8_t n_bytes_per_sampe_rx; #endif #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + // Encoding parameters - parameters are set when alternate AS interface is set by host +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + audio_format_type_t format_type_tx; + uint8_t n_channels_tx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + audio_data_format_type_I_t format_type_I_tx; + uint8_t n_bytes_per_sampe_tx; + uint8_t n_channels_per_ff_tx; +#endif #endif + + // Support FIFOs for software encoding and decoding +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_t * rx_supp_ff; + uint8_t n_rx_supp_ff; + uint8_t n_channels_per_ff_rx; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_t * tx_supp_ff; + uint8_t n_tx_supp_ff; #endif // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_EPSIZE_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE) - CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + uint8_t * lin_buf_out; #define USE_LINEAR_BUFFER_RX 1 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE) - CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) + uint8_t * lin_buf_in; #define USE_LINEAR_BUFFER_TX 1 #endif @@ -204,30 +365,19 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; -extern const uint16_t tud_audio_desc_lengths[]; - -// bSubslotSize for PCM encoding/decoding using support FIFOs -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -extern const tud_audio_n_bytes_per_sample_tx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -extern const tud_audio_n_bytes_per_sample_rx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif @@ -238,17 +388,23 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); + +static inline uint8_t tu_desc_subtype(void const* desc) +{ + return ((uint8_t const*) desc)[2]; +} bool tud_audio_n_mounted(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_AUDIO); audiod_interface_t* audio = &_audiod_itf[itf]; -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (audio->ep_in == 0) return false; #endif @@ -267,7 +423,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING uint16_t tud_audio_n_available(uint8_t itf) { @@ -289,50 +445,46 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif // This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + switch (audio->format_type_rx) { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! @@ -342,7 +494,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + switch (audio->format_type_I_tx) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); @@ -364,7 +516,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else @@ -373,34 +525,108 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); return true; } -#endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT -// The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Decoding according to 2.3.1.5 Audio Streams + +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +{ + + // This function is an optimized version of +// while((uint8_t *)dst < dst_end) +// { +// memcpy(dst, src, nBytesToCopy); +// dst = (uint8_t *)dst + nBytesToCopy; +// src += nBytesToCopy * n_ff_used; +// } + + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)dst < dst_end) + { + *(uint8_t *)dst++ = *src; + src += n_ff_used; + } + break; + + case 2: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + dst += 2; + src += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)dst < dst_end) + { +// memcpy(dst, src, 3); +// dst = (uint8_t *)dst + 3; +// src += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + + src += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + dst += 4; + src += 4 * n_ff_used; + } + break; + } + + return src; +} + static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; // Determine amount of samples - uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; - uint16_t const nSamplesPerFFToRead = n_bytes_received / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint8_t const n_ff_used = audio->n_channels_rx / audio->n_channels_per_ff_rx; + + TU_ASSERT( n_ff_used <= audio->n_rx_supp_ff ); + + uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; + uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; // Decode @@ -409,36 +635,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint8_t * dst_end; uint16_t len; - for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - src = &audio->lin_buf_out[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead); tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + dst_end = dst + len; - while((uint8_t *)dst < dst_end) - { - memcpy(dst, src, nBytesToCopy); - dst = (uint8_t *)dst + nBytesToCopy; - src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - } + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len < nSamplesPerFFToRead) + if (len < nBytesPerFFToRead) { - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead - len); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead - len); tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + dst_end = dst + len; - while((uint8_t *)dst < dst_end) - { - memcpy(dst, src, nBytesToCopy); - dst = (uint8_t *)dst + nBytesToCopy; - src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - } + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); } } @@ -447,13 +663,13 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, return true; } -#endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_DECODING //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING /** * \brief Write data to EP in buffer @@ -480,7 +696,7 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); @@ -498,13 +714,13 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif @@ -534,42 +750,44 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I + // Required in any case regardless if call backs are used - find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); +#else + // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface + if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); +#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN - switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + switch (audio->format_type_tx) { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + switch (audio->format_type_I_tx) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: @@ -580,6 +798,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // YOUR ENCODING IS REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; } break; @@ -588,6 +807,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; } @@ -596,27 +816,27 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #else // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - #if USE_LINEAR_BUFFER_TX - tu_fifo_write_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - #else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); - #endif +#if USE_LINEAR_BUFFER_TX + tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); +#else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); +#endif #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); return true; } -#endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN // Take samples from the support buffer and encode them into the IN EP software FIFO // Returns number of bytes written into linear buffer @@ -626,7 +846,7 @@ data streams. The audio data is not compressed and uses a signed two’s-complem is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the range [-1, +1) -*/ + */ /* * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples @@ -634,35 +854,99 @@ range [-1, +1) * does not change the number of bytes per sample. * */ +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +{ + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)src < src_end) + { + *dst = *(uint8_t *)src++; + dst += n_ff_used; + } + break; + + case 2: + while((uint8_t *)src < src_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + src += 2; + dst += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)src < src_end) + { +// memcpy(dst, src, 3); +// src = (uint8_t *)src + 3; +// dst += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *dst++ = *(uint8_t *)src++; + *dst++ = *(uint8_t *)src++; + *dst++ = *(uint8_t *)src++; + + dst += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)src < src_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + src += 4; + dst += 4 * n_ff_used; + } + break; + } + + return dst; +} + static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t const capSamplesPerFF = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - uint16_t nSamplesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); + uint8_t const n_ff_used = audio->n_channels_tx / audio->n_channels_per_ff_tx; + + TU_ASSERT( n_ff_used <= audio->n_tx_supp_ff ); + + uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; + uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes + uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); uint8_t cnt_ff; - for (cnt_ff = 1; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) { uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nSamplesPerFFToSend) + if (count < nBytesPerFFToSend) { - nSamplesPerFFToSend = count; + nBytesPerFFToSend = count; } } // Check if there is enough - if (nSamplesPerFFToSend == 0) return 0; + if (nBytesPerFFToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerFFToSend = tu_min16(nSamplesPerFFToSend, capSamplesPerFF); + nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); // Round to full number of samples (flooring) - nSamplesPerFFToSend = (nSamplesPerFFToSend / nChannelsPerFF) * nChannelsPerFF; + nBytesPerFFToSend = (nBytesPerFFToSend / audio->n_channels_per_ff_tx) * audio->n_channels_per_ff_tx; // Encode void * src; @@ -670,46 +954,36 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud uint8_t * src_end; uint16_t len; - for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - dst = &audio->lin_buf_in[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; + dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend); tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + src_end = src + len; - while((uint8_t *)src < src_end) - { - memcpy(dst, src, nBytesToCopy); - src = (uint8_t *)src + nBytesToCopy; - dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - } + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len < nSamplesPerFFToSend) + if (len < nBytesPerFFToSend) { - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend - len); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend - len); tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + src_end = src + len; - while((uint8_t *)src < src_end) - { - memcpy(dst, src, nBytesToCopy); - src = (uint8_t *)src + nBytesToCopy; - dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - } + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); } } - return nSamplesPerFFToSend * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + return nBytesPerFFToSend * n_ff_used; } -#endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_ENCODING // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) { return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); @@ -727,43 +1001,304 @@ void audiod_init(void) { audiod_interface_t* audio = &_audiod_itf[i]; + // Initialize control buffers + switch (i) + { + case 0: + audio->ctrl_buf = ctrl_buf_1; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; + break; +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 + case 1: + audio->ctrl_buf = ctrl_buf_2; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 + case 2: + audio->ctrl_buf = ctrl_buf_3; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; + break; +#endif + } + + // Initialize active alternate interface buffers +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 + case 0: + audio->alt_setting_ptr = alt_setting_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 + case 1: + audio->alt_setting_ptr = alt_setting_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + case 2: + audio->alt_setting_ptr = alt_setting_3; + break; +#endif + } +#endif + // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_1), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_2), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex_wr), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_3), NULL); #endif + break; #endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_TX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 + case 0: + audio->lin_buf_in = lin_buf_in_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 + case 1: + audio->lin_buf_in = lin_buf_in_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 + case 2: + audio->lin_buf_in = lin_buf_in_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&audio->ep_out_ff_mutex_rd)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_1)); #endif + break; #endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_2)); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_3)); +#endif + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_RX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 + case 0: + audio->lin_buf_out = lin_buf_out_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 + case 1: + audio->lin_buf_out = lin_buf_out_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 + case 2: + audio->lin_buf_out = lin_buf_out_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) { - tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, true); +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->tx_supp_ff = tx_supp_ff_1; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->tx_supp_ff = tx_supp_ff_2; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->tx_supp_ff = tx_supp_ff_3; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; + break; #endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) { - tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX, true); +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->rx_supp_ff = rx_supp_ff_1; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->rx_supp_ff = rx_supp_ff_2; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->rx_supp_ff = rx_supp_ff_3; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; + break; #endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING } } @@ -776,23 +1311,23 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_clear(&audio->ep_out_ff); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { tu_fifo_clear(&audio->rx_supp_ff[cnt]); } @@ -827,6 +1362,25 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one _audiod_itf[i].rhport = rhport; + + // Setup descriptor lengths + switch (i) + { + case 0: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; + break; +#if CFG_TUD_AUDIO > 1 + case 1: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; + break; +#endif +#if CFG_TUD_AUDIO > 2 + case 2: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; + break; +#endif + } + break; } } @@ -835,14 +1389,14 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { -#if CFG_TUD_AUDIO_N_AS_INT > 0 +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface @@ -850,9 +1404,9 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *dummy; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting_ptr[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting_ptr[idxItf]); return true; @@ -888,41 +1442,60 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *p_desc; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + audiod_interface_t* audio = &_audiod_itf[idxDriver]; + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (audio->ep_in_as_intf_num == itf) { - _audiod_itf[idxDriver].ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + audio->ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_in); // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? + audio->ep_in = 0; // Necessary? + + // Clear support FIFOs if used +#if CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } +#endif + } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (audio->ep_out_as_intf_num == itf) { - _audiod_itf[idxDriver].ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + audio->ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_out); + audio->ep_out = 0; // Necessary? + + // Clear support FIFOs if used +#if CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } +#endif // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + usbd_edpt_close(rhport, audio->ep_fb); + audio->ep_fb = 0; // Necessary? #endif } #endif // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; + audio->alt_setting_ptr[idxItf] = alt; // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; // p_desc starts at required interface with alternate setting zero while (p_desc < p_desc_end) @@ -930,6 +1503,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) { +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING + uint8_t const * p_desc_parse_for_params = p_desc; +#endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; while (foundEPs < nEps && p_desc < p_desc_end) @@ -943,52 +1519,61 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address - _audiod_itf[idxDriver].ep_in = ep_addr; - _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + audio->ep_in = ep_addr; + audio->ep_in_as_intf_num = itf; + audio->ep_in_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; + // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters +#if CFG_TUD_AUDIO_ENABLE_ENCODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); +#endif // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an TX FIFO empty interrupt which can only trigger if something was in there + // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } -#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; - _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + audio->ep_out = ep_addr; + audio->ep_out_as_intf_num = itf; + audio->ep_out_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; +#if CFG_TUD_AUDIO_ENABLE_DECODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); +#endif // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data #if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback { - _audiod_itf[idxDriver].ep_fb = ep_addr; + audio->ep_fb = ep_addr; // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } #endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT -#endif foundEPs += 1; } p_desc = tu_desc_next(p_desc); @@ -1188,7 +1773,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, _audiod_itf[idxDriver].ctrl_buf_sz)); return true; } @@ -1238,7 +1823,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished if (_audiod_itf[idxDriver].ep_in == ep_addr) @@ -1259,7 +1844,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) @@ -1327,7 +1912,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + if (len > _audiod_itf[idxDriver].ctrl_buf_sz) len = _audiod_itf[idxDriver].ctrl_buf_sz; // Copy into buffer memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); @@ -1348,7 +1933,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // Advance past AC descriptors uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1413,7 +1998,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { @@ -1437,7 +2022,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length; // Advance past AC descriptors - EP we look for are streaming EPs uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1457,6 +2042,69 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) return false; } +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +// p_desc points to the AS interface of alternate setting zero +// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter +// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! +static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +{ + p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor + + while (p_desc < p_desc_end) + { + // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; + + // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) + { + if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + + if (itf == audio->ep_in_as_intf_num) + { + audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } + + if (itf == audio->ep_out_as_intf_num) + { + audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } + } + + // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) + { + if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + + if (itf == audio->ep_in_as_intf_num) + { + audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } + + if (itf == audio->ep_out_as_intf_num) + { + audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } + } +#endif + + // Other format types are not supported yet + + p_desc = tu_desc_next(p_desc); + } +} +#endif + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 730d42c38..e68c437ad 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -40,49 +40,151 @@ // All sizes are in bytes! -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) -#ifndef CFG_TUD_AUDIO_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the descriptors! +#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces +#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE +#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ #error You must define an audio class control request buffer size! #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + // End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_EPSIZE_IN -#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX +#endif + +// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation +#if CFG_TUD_AUDIO_ENABLE_EP_IN +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT + +// Software EP FIFO buffer sizes - must be >= max EP SIZEs! +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 +#endif + +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 +#endif + +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#ifndef CFG_TUD_AUDIO_EPSIZE_OUT -#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -// Software EP FIFO buffer sizes - must be >= EP SIZEs! -#if CFG_TUD_AUDIO_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX +#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#else -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE 0 + +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT -#ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX +#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#else -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 + +#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -// General information of number of TX and/or RX channels - is used in combination with support FIFOs (see below) and can be used for descriptor definitions -#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif // Use of TX/RX support FIFOs @@ -120,83 +222,100 @@ // - audio_rx_done_cb() // functions. -// The number of support FIFOs and number of channels is decoupled. The PCM encoding/decoding works depending on the ratio CFG_TUD_AUDIO_N_CHANNELS_XX / CFG_TUD_AUDIO_N_XX_SUPPORT_SW_FIFO, where currently 1:1 and 2:1 is implemented. The version 2:1 is useful in case of I2S for which usually 2 are channels already interleaved available. +// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size +// The actual parameters of active encoding is parsed from the descriptors -// Size of support FIFOs IN SAMPLES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO and CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO -#ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: // ceil(f_s/1000) * CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO +// For PCM encoding/decoding + +#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING +#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 #endif -#ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#ifndef CFG_TUD_AUDIO_ENABLE_DECODING +#define CFG_TUD_AUDIO_ENABLE_DECODING 0 #endif -#ifndef CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_TX // default size is equal to number of channels -#else -#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO 0 +// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 #endif + +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 #endif -#ifndef CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_RX // default size is equal to number of channels -#else -#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO 0 +// Type I Coding parameters not given within UAC2 descriptors +// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif - -// Audio data format types - look in audio.h for existing types -// Used in case support FIFOs are used -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif - -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif #endif -// Audio data format type I specifications -#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I +// Remaining types not support so far -// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface +#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 #endif - -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 #endif - +#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 #endif -#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I - -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO +#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 #endif +#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 #endif //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); @@ -219,33 +338,29 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO - #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +#endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif -#endif - #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif @@ -258,15 +373,13 @@ static inline bool tud_audio_mounted (void); // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); - #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); @@ -274,14 +387,12 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); - #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); @@ -290,7 +401,7 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif // Buffer control EP data and schedule a transmit @@ -305,17 +416,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // User code should call this function with feedback value in 16.16 format for FS and HS. // Value will be corrected for FS to 10.14 format automatically. @@ -364,7 +475,7 @@ static inline bool tud_audio_mounted(void) // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING static inline uint16_t tud_audio_available (void) { @@ -383,7 +494,7 @@ static inline bool tud_audio_clear_ep_out_ff (void) #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { @@ -404,7 +515,7 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len) { @@ -418,7 +529,7 @@ static inline bool tud_audio_clear_ep_in_ff (void) #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void) { @@ -444,7 +555,7 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) { return tud_audio_n_fb_set(0, feedback); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d05549e3e..1b7f64447 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -138,9 +138,7 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi } } -// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address -// Code adapted from dcd_synopsis.c -// TODO generalize with configurable 1 byte or 4 byte each write +// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address in full word copies static void _tu_fifo_write_to_const_dst_ptr_in_full_words(void * dst, const void * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; diff --git a/src/device/usbd.h b/src/device/usbd.h index 56615b081..7c50a6db0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -353,6 +353,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) #define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx +// 4 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx // For more channels, add definitions here @@ -389,7 +393,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -#define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ +#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + TUD_AUDIO_DESC_STD_AC_LEN\ + TUD_AUDIO_DESC_CS_AC_LEN\ + TUD_AUDIO_DESC_CLK_SRC_LEN\ @@ -403,9 +407,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces +#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces -#define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ @@ -435,6 +439,55 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) +// AUDIO simple descriptor (UAC2) for 4 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces + +#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + // AUDIO simple descriptor (UAC2) for mono speaker // - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source -- cgit v1.3.1 From 8b90c08b357ce04aebe093856b954e02624ff0fe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:24:38 +0200 Subject: Fix #define errors in audio_device.h --- src/class/audio/audio_device.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index e68c437ad..9ff74d6c7 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -153,25 +153,33 @@ #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#if CFG_TUD_AUDIO > 1 #if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif +#if CFG_TUD_AUDIO > 2 #if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#if CFG_TUD_AUDIO > 1 #if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif +#if CFG_TUD_AUDIO > 2 #if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif // Enable/disable feedback EP (required for asynchronous RX applications) #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -187,13 +195,16 @@ #define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif -// Use of TX/RX support FIFOs +// Use software encoding/decoding -// Support FIFOs are not mandatory for the audio driver, rather they are intended to be of use in -// - TX case: CFG_TUD_AUDIO_N_CHANNELS_TX channels need to be encoded into one USB output stream (currently PCM type I is implemented) -// - RX case: CFG_TUD_AUDIO_N_CHANNELS_RX channels need to be decoded from a single USB input stream (currently PCM type I is implemented) +// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved +// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. // -// This encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the +// Currently, only PCM type I encoding/decoding is supported! +// +// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. + +// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the // support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using // - tud_audio_n_write() or // - tud_audio_n_read(). @@ -223,7 +234,7 @@ // functions. // Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual parameters of active encoding is parsed from the descriptors +// The actual coding parameters of active AS alternate interface is parsed from the descriptors // For PCM encoding/decoding -- cgit v1.3.1 From 6236effb1415ea509e6283d33f2779eeae7d425e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:29:39 +0200 Subject: Fix #define error in audio_device.h --- src/class/audio/audio_device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 9ff74d6c7..e2208629f 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -149,6 +149,7 @@ #define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif @@ -164,7 +165,9 @@ #error EP software buffer size MUST BE at least as big as maximum EP size #endif #endif +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif @@ -180,6 +183,7 @@ #error EP software buffer size MUST BE at least as big as maximum EP size #endif #endif +#endif // Enable/disable feedback EP (required for asynchronous RX applications) #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -- cgit v1.3.1 From ec6b240de299e24a7fabb54aa2f2d9c72d0eaad4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:44:44 +0200 Subject: Fix #define error in audio_device.h --- src/class/audio/audio_device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index e2208629f..d4793c9d8 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -261,6 +261,7 @@ // Type I Coding parameters not given within UAC2 descriptors // It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING #ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif @@ -274,7 +275,9 @@ #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif #endif +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING #ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif @@ -288,6 +291,7 @@ #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif #endif +#endif // Remaining types not support so far -- cgit v1.3.1 From fc65f39ff224cdfe3c486c95e0c04f1f979fa1b2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:58:41 +0200 Subject: Fix error in #defines in uac2_headset --- examples/device/uac2_headset/src/tusb_config.h | 2 ++ examples/device/uac2_headset/src/usb_descriptors.c | 5 ----- src/class/audio/audio_device.c | 3 +++ 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 511e4e558..cbdd7b3df 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -94,6 +94,8 @@ extern "C" { #define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) #define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN + // Audio format type I specifications #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index b69e5a5e0..cd749eb65 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,11 +87,6 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO 0x01 #endif -// These variables are required by the audio driver in audio_device.c - -// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO -const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_HEADSET_STEREO_DESC_LEN}; - uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 5df32c30f..a39a030e6 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -388,7 +388,10 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); + +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); +#endif static inline uint8_t tu_desc_subtype(void const* desc) { -- cgit v1.3.1 From 475badd0873dda58b507d3dfe5ab74957fcaa3c0 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 16:10:46 +0200 Subject: Add missing #defines in uac2_headset example --- examples/device/uac2_headset/src/tusb_config.h | 2 ++ src/class/audio/audio_device.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index ee6bdd519..5f86ee1a8 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -107,11 +107,13 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 #define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_SZ_OUT // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a39a030e6..8e4f9d218 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -949,7 +949,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / audio->n_channels_per_ff_tx) * audio->n_channels_per_ff_tx; + nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode void * src; -- cgit v1.3.1 From 4af5189492f850615581d3310e20c98f69cf6138 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 16:53:29 +0200 Subject: Fix potential bug in support FIFO sizes --- examples/device/uac2_headset/src/tusb_config.h | 2 -- examples/device/uac2_headset/src/usb_descriptors.c | 2 ++ src/class/audio/audio_device.c | 32 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 514728ac4..00620d9ed 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -94,8 +94,6 @@ extern "C" { #define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) #define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN - // Audio format type I specifications #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index cd749eb65..404863dba 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,6 +87,8 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO 0x01 #endif +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN + uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8e4f9d218..8bd15a8c1 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -310,6 +310,7 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING audio_data_format_type_I_t format_type_I_rx; uint8_t n_bytes_per_sampe_rx; + uint8_t n_channels_per_ff_rx; #endif #endif @@ -329,12 +330,13 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t * rx_supp_ff; uint8_t n_rx_supp_ff; - uint8_t n_channels_per_ff_rx; + uint16_t rx_supp_ff_sz_max; #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t * tx_supp_ff; uint8_t n_tx_supp_ff; + uint16_t tx_supp_ff_sz_max; #endif // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used @@ -920,6 +922,9 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { + // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap + // This is ensured within set_interface, where the FIFOs are reconfigured according to this size + // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); @@ -1164,6 +1169,7 @@ void audiod_init(void) case 0: audio->tx_supp_ff = tx_supp_ff_1; audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); @@ -1179,6 +1185,7 @@ void audiod_init(void) case 1: audio->tx_supp_ff = tx_supp_ff_2; audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); @@ -1194,6 +1201,7 @@ void audiod_init(void) case 2: audio->tx_supp_ff = tx_supp_ff_3; audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); @@ -1238,6 +1246,7 @@ void audiod_init(void) case 0: audio->rx_supp_ff = rx_supp_ff_1; audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); @@ -1253,6 +1262,7 @@ void audiod_init(void) case 1: audio->rx_supp_ff = rx_supp_ff_2; audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); @@ -1268,6 +1278,7 @@ void audiod_init(void) case 2: audio->rx_supp_ff = rx_supp_ff_3; audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); @@ -1533,6 +1544,16 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters #if CFG_TUD_AUDIO_ENABLE_ENCODING audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); + + // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + const uint16_t active_fifo_depth = (audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx; + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); + } +#endif + #endif // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); @@ -1554,6 +1575,15 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_DECODING audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); + + // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); + } +#endif #endif // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); -- cgit v1.3.1 From f6ba58e370cd67b78dcd1758aa9fe010035f13bc Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 17:50:30 +0200 Subject: Fix wrong pointer type in audio_device.c --- examples/device/uac2_headset/src/usb_descriptors.c | 2 -- src/class/audio/audio_device.c | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 404863dba..cd749eb65 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,8 +87,6 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO 0x01 #endif -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN - uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8bd15a8c1..642688876 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1174,7 +1174,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_1[cnt]), NULL); #endif } @@ -1190,7 +1190,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_2[cnt]), NULL); #endif } @@ -1206,7 +1206,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif } @@ -1251,7 +1251,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_1[cnt]), NULL); #endif } @@ -1267,7 +1267,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_2[cnt]), NULL); #endif } @@ -1283,7 +1283,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif } -- cgit v1.3.1 From 1ac9e7e3a70b48e73f150d1e7494eaecd2d34822 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 18:22:19 +0200 Subject: Fix wrong read mutexes in audio_device.c --- src/class/audio/audio_device.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 642688876..dadb66caa 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1061,7 +1061,7 @@ void audiod_init(void) case 0: tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_1), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); #endif break; #endif @@ -1069,7 +1069,7 @@ void audiod_init(void) case 1: tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_2), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); #endif break; #endif @@ -1077,7 +1077,7 @@ void audiod_init(void) case 2: tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_3), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); #endif break; #endif @@ -1115,7 +1115,7 @@ void audiod_init(void) case 0: tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_1)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); #endif break; #endif @@ -1123,7 +1123,7 @@ void audiod_init(void) case 1: tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_2)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); #endif break; #endif @@ -1131,7 +1131,7 @@ void audiod_init(void) case 2: tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_3)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); #endif break; #endif @@ -1174,7 +1174,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_1[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); #endif } @@ -1190,7 +1190,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_2[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); #endif } @@ -1206,7 +1206,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_3[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif } @@ -1251,7 +1251,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_1[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); #endif } @@ -1267,7 +1267,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_2[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); #endif } @@ -1283,7 +1283,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_3[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif } -- cgit v1.3.1 From 164d3e82e32e1039ba8e471fbc949699c396c9fe Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 11:13:42 -0400 Subject: Fix incorrect DNLOAD request len passed to app Fixes bug where the app callback was getting the length of the status request transfer rather than the length of the data stage payload. TODO: Right now this returns the expected length, when it really should be returning the transfer length. --- src/class/dfu/dfu_rt_device.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 0cbc8eeda..7d40d2057 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -46,8 +46,9 @@ typedef struct TU_ATTR_PACKED bool blk_transfer_in_proc; uint8_t itf_num; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; typedef struct TU_ATTR_PACKED @@ -161,6 +162,8 @@ void dfu_rtd_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; dfu_rtd_debug_print_context(); } @@ -204,6 +207,8 @@ void dfu_rtd_reset(uint8_t rhport) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; dfu_rtd_debug_print_context(); } @@ -290,8 +295,8 @@ void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.epin_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.epin_buf, retval); + uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); return retval; } @@ -319,12 +324,14 @@ static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); } static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) @@ -338,8 +345,12 @@ static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t con tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_runtime_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; } void tud_dfu_runtime_poll_timeout_done() -- cgit v1.3.1 From 7ab8da949e6622f59e49d7435a22f52a18940350 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 01:07:32 +0700 Subject: audio driver only use USE_LINEAR_BUFFER = 0 for stm32 synopsys driver --- src/class/audio/audio_device.c | 51 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index dadb66caa..634e9e4d2 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -63,33 +63,32 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically -#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ - CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ - CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ - CFG_TUSB_MCU == OPT_MCU_SAME5X ) - -#define USE_LINEAR_BUFFER 1 - +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer +// is available or driver is would need to be changed dramatically + +// Only STM32 synopsys use non-linear buffer for now +// Synopsys detection copied from dcd_synopsys.c (refactor later on) +#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) +#define STM32F1_SYNOPSYS +#endif + +#if defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define STM32L4_SYNOPSYS +#endif + +#if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + #define USE_LINEAR_BUFFER 0 #else -#define USE_LINEAR_BUFFER 0 + #define USE_LINEAR_BUFFER 1 #endif // Declaration of buffers -- cgit v1.3.1 From 68687ed0f400adc456cd8e4dbda4eb7d8e32d5cd Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 01:16:51 +0700 Subject: fix build --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 634e9e4d2..a85dfddb8 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -85,7 +85,7 @@ CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From c5b8ef15299e9d5787602b39805efbb0ca385110 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 16:32:58 -0400 Subject: Separate DFU RT and Mode. Untested --- src/class/dfu/dfu.h | 91 ++++++ src/class/dfu/dfu_mode_device.c | 598 +++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_mode_device.h | 132 ++++++++ src/class/dfu/dfu_rt_device.c | 670 +++------------------------------------- src/class/dfu/dfu_rt_device.h | 70 +---- src/common/tusb_common.h | 2 +- src/device/usbd.c | 12 + src/tusb.h | 6 +- src/tusb_option.h | 6 +- 9 files changed, 903 insertions(+), 684 deletions(-) create mode 100644 src/class/dfu/dfu_mode_device.c create mode 100644 src/class/dfu/dfu_mode_device.h (limited to 'src/class') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 39ce567da..2040e415c 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -100,6 +100,97 @@ typedef enum { #define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) #define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) +// DFU Status Request Payload +typedef struct TU_ATTR_PACKED +{ + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_req_payload_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_mode_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), + .items = _dfu_mode_state_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_mode_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), + .items = _dfu_mode_status_lookup +}; + +#endif + +#define dfu_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ +} + + #ifdef __cplusplus } #endif diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c new file mode 100644 index 000000000..e66fb823c --- /dev/null +++ b/src/class/dfu/dfu_mode_device.c @@ -0,0 +1,598 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) + +#include "dfu_mode_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_mode_state_ctx_t; + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_mode_state_ctx_t _dfu_state_ctx; + + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request); + + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_mode_init(void) +{ + _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + + dfu_debug_print_context(); +} + +void dfu_mode_reset(uint8_t rhport) +{ + if ( tud_dfu_mode_usb_reset_cb ) + { + tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + } + + if(_dfu_state_ctx.state == APP_IDLE) + { + tud_dfu_mode_reboot_to_rt_cb(); + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + dfu_debug_print_context(); +} + +uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + (void) max_len; + + // Ensure this is DFU Mode + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint16_t drv_len = sizeof(tusb_desc_interface_t); + + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_mode_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: + { + return dfu_mode_state_machine(rhport, request); + } + break; + + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_mode_req_nonstandard_cb ) ? tud_dfu_mode_req_nonstandard_cb(rhport, stage, request) : false; + } + break; + } + + return true; +} + +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) +{ + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_mode_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_mode_get_poll_timeout_cb ) + { + tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_mode_get_status_desc_table_index_cb ) ? tud_dfu_mode_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); +} + +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_mode_get_poll_timeout_cb ) + { + tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_mode_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); + + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_mode_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; +} + +void tud_dfu_mode_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_mode_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_mode_abort_cb ) + { + tud_dfu_mode_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_mode_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_mode_abort_cb) + { + tud_dfu_mode_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + + return true; +} + + +bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) ep_addr; + (void) result; + (void) xferred_bytes; + return true; +} + + + #endif diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h new file mode 100644 index 000000000..32bf58bbd --- /dev/null +++ b/src/class/dfu/dfu_mode_device.h @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_MODE_DEVICE_H_ +#define _TUSB_DFU_MODE_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_mode_firmware_valid_check_cb(); + +// Invoked when the device must reboot to dfu runtime mode +void tud_dfu_mode_reboot_to_rt_cb(); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_mode_init_attrs_cb(); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); + +// Invoked during a USB reset +// Lets the app perform custom behavior on a USB reset. +// If not defined, the default behavior remains the DFU specification of +// Checking the firmware valid and changing to the error state or rebooting to runtime +// Note: If used, the application must perform the reset logic for all states. +// Changing the state to APP_IDLE will result in tud_dfu_mode_reboot_to_rt_cb being called +TU_ATTR_WEAK void tud_dfu_mode_usb_reset_cb(uint8_t rhport, dfu_mode_state_t *state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_mode_poll_timeout_done(); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_mode_device_data_done_check_cb(); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_mode_abort_cb(); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_mode_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); + +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_mode_init(void); +void dfu_mode_reset(uint8_t rhport); +uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 7d40d2057..806bfba2e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -40,176 +40,39 @@ //--------------------------------------------------------------------+ typedef struct TU_ATTR_PACKED { - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; - bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; -} dfu_state_ctx_t; - -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_req_payload_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; +} dfu_rt_state_ctx_t; // Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_mode_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "DFU_IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "DFU_ERROR" }, -}; - -static tu_lookup_table_t const _dfu_mode_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), - .items = _dfu_mode_state_lookup -}; - -static tu_lookup_entry_t const _dfu_mode_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, - { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_mode_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), - .items = _dfu_mode_status_lookup -}; - -#endif +CFG_TUSB_MEM_SECTION static dfu_rt_state_ctx_t _dfu_state_ctx; -#define dfu_rtd_debug_print_context() \ -{ \ - TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ -} +static void dfu_rt_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { - if ( tud_dfu_runtime_init_cb ) { - _dfu_state_ctx.state = (tud_dfu_runtime_init_cb() == DFU_PROTOCOL_DFU) ? APP_DETACH : APP_IDLE; - } else { - _dfu_state_ctx.state = APP_IDLE; - } - + _dfu_state_ctx.state = APP_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - - dfu_rtd_debug_print_context(); + dfu_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - if ( tud_dfu_runtime_usb_reset_cb ) + if (((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 0) + && (_dfu_state_ctx.state == DFU_REQUEST_DETACH)) { - tud_dfu_runtime_usb_reset_cb(rhport, _dfu_state_ctx.state); - } - - switch (_dfu_state_ctx.state) - { - case APP_DETACH: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_runtime_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; + tud_dfu_runtime_reboot_to_dfu_cb(); } + _dfu_state_ctx.state = APP_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - dfu_rtd_debug_print_context(); + dfu_debug_print_context(); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -217,10 +80,9 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui (void) rhport; (void) max_len; - // Ensure this is DFU Runtime or Mode - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - ( (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT) - | (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) ), 0); + // Ensure this is DFU Runtime + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -239,16 +101,9 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // return false to stall control endpoint (e.g unsupported request) bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) - { - dfu_mode_req_dnload_reply(rhport, request); - return true; - } - - // nothing to do with any other DATA or ACK stage + // nothing to do with DATA or ACK stage if ( stage != CONTROL_STAGE_SETUP ) return true; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request @@ -262,490 +117,67 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: - case DFU_REQUEST_DNLOAD: - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - return dfu_state_machine(rhport, request); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; - } - break; - } - - return true; -} - -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) -{ - _dfu_state_ctx.status = status; -} - -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); - return retval; -} - -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_status_req_payload_t resp; - - resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); -} - -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); -} - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); -} - -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_runtime_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); - _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; -} - -void tud_dfu_runtime_poll_timeout_done() -{ - if (_dfu_state_ctx.state == DFU_DNBUSY) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) - { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } -} - -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); - - switch (_dfu_state_ctx.state) - { - case APP_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - _dfu_state_ctx.state = APP_DETACH; - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } else { - tud_dfu_runtime_detach_start_timer_cb(request->wValue); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case APP_DETACH: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = APP_IDLE; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - ; // do nothing, but don't stall so continue on - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_SYNC: { - switch (request->bRequest) + if (_dfu_state_ctx.state == APP_IDLE) { - case DFU_REQUEST_GETSTATUS: + _dfu_state_ctx.state = APP_DETACH; + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) { - if ( _dfu_state_ctx.blk_transfer_in_proc ) - { - _dfu_state_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); - } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); - } + tud_dfu_runtime_reboot_to_dfu_cb(); + } else { + tud_dfu_runtime_detach_start_timer_cb(request->wValue); } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; + } else { + TU_LOG2(" DFU Unexpected request during state %s: %u\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), request->bRequest); + return false; } } break; - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_runtime_device_data_done_check_cb() ) - { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if ( tud_dfu_runtime_abort_cb ) - { - tud_dfu_runtime_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - { - _dfu_state_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); - } else { - if ( tud_dfu_runtime_firmware_valid_check_cb() ) - { - _dfu_state_ctx.state = DFU_IDLE; - } - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST: + case DFU_REQUEST_GETSTATUS: { - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; + dfu_status_req_payload_t resp; + resp.bStatus = _dfu_state_ctx.status; + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); // Value is ignored + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } break; - case DFU_UPLOAD_IDLE: + case DFU_REQUEST_GETSTATE: { - switch (request->bRequest) - { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_state_ctx.state = DFU_IDLE; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if (tud_dfu_runtime_abort_cb) - { - tud_dfu_runtime_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); } break; - case DFU_ERROR: + default: { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_CLRSTATUS: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } + TU_LOG2(" DFU Nonstandard Runtime Request: %u\r\n", request->bRequest); + return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; } break; - - default: - _dfu_state_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error } return true; } +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) +{ + _dfu_state_ctx.status = status; +} + +void tud_dfu_runtime_detach_timer_elapsed() +{ + if (_dfu_state_ctx.state == DFU_REQUEST_DETACH) + { + _dfu_state_ctx.state = APP_IDLE; + } +} #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 9e7ae029e..23703862d 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -43,28 +43,26 @@ // Value is not checked to allow for custom statuses to be used void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); -// Invoked when a DFU_DETACH request is received and bitWillDetatch is set +// Invoked when a DFU_DETACH request is received and bitWillDetach is set void tud_dfu_runtime_reboot_to_dfu_cb(); -// Invoked when a DFU_DETACH request is received and bitWillDetatch is not set +// Invoked when a DFU_DETACH request is received and bitWillDetach is not set // This should start a timer for wTimeout ms -// The application should then look for a USB reset signal to occur before -// the timeout has elapsed. The reset signal will invoke tud_dfu_runtime_usb_reset_cb. -// If this reset signal is received before the timeout, then the application must -// switch to DFU mode. -// If the timer expires, the app does not need to do anything. +// When the timer has elapsed, the app must call tud_dfu_runtime_detach_timer_elapsed +// If a USB reset is called while the timer is running, the class will call +// tud_dfu_runtime_reboot_to_dfu_cb. // NOTE: This callback should return immediately, and not implement the delay // internally, as this can will hold up the USB stack TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); +// Invoke when the dfu runtime detach timer has elapsed +void tud_dfu_runtime_detach_timer_elapsed(); + // Invoked when a nonstandard request is received // Use may be vendor specific. // Return false to stall TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -// Invoked when a reset is received to check if firmware is valid -bool tud_dfu_runtime_firmware_valid_check_cb(); - // Invoked during initialization of the dfu driver to set attributes // Return byte set with bitmasks: // DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK @@ -74,62 +72,10 @@ bool tud_dfu_runtime_firmware_valid_check_cb(); // Note: This should match the USB descriptor uint8_t tud_dfu_runtime_init_attrs_cb(); -// Invoked during initialization of the dfu driver to start as RT or DFU -// This will determine if the internal state machine will begin in -// APP_IDLE or DFU_IDLE -TU_ATTR_WEAK dfu_protocol_type_t tud_dfu_runtime_init_cb(); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); -// Invoked during a USB reset -// Lets the app know that a USB reset has occurred so it can act accordingly, -// See tud_dfu_runtime_detach_start_timer_cb for how to handle the APP_DETACH state -// Other states will be application specific -TU_ATTR_WEAK void tud_dfu_runtime_usb_reset_cb(uint8_t rhport, dfu_mode_state_t state); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_runtime_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_runtime_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_runtime_poll_timeout_done(); - -// Invoked when a DFU_DNLOAD request is received -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_runtime_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_runtime_device_data_done_check_cb(); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_runtime_abort_cb(); - -// Invoked when a DFU_UPLOAD request is received -// This callback must populate data with up to length bytes -// Return the number of bytes to write -uint16_t tud_dfu_runtime_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f10be88ab..859d9d47d 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/device/usbd.c b/src/device/usbd.c index 28c9acdd2..91838b39c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -187,6 +187,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_DFU_MODE + { + DRIVER_NAME("DFU-MODE") + .init = dfu_mode_init, + .reset = dfu_mode_reset, + .open = dfu_mode_open, + .control_xfer_cb = dfu_mode_control_xfer_cb, + .xfer_cb = dfu_mode_xfer_cb, + .sof = NULL + }, + #endif + #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index cc82c440d..c9558515c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -96,6 +96,10 @@ #include "class/dfu/dfu_rt_device.h" #endif + #if CFG_TUD_DFU_MODE + #include "class/dfu/dfu_mode_device.h" + #endif + #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 1af3ee672..3cd3df9f2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -234,7 +234,11 @@ #endif #ifndef CFG_TUD_DFU_RUNTIME - #define CFG_TUD_DFU_RUNTIME 0 + #define CFG_TUD_DFU_RUNTIME 0 +#endif + +#ifndef CFG_TUD_DFU_MODE + #define CFG_TUD_DFU_MODE 0 #endif #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE -- cgit v1.3.1 From fdc91f8d2c3364a9a5cea2b0efff2167c9bf4786 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 16:48:09 -0400 Subject: Fix bug during initialization of DFU Mode --- src/class/dfu/dfu_mode_device.c | 45 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index e66fb823c..68f55510b 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -67,7 +67,7 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ void dfu_mode_init(void) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; @@ -79,31 +79,36 @@ void dfu_mode_init(void) void dfu_mode_reset(uint8_t rhport) { - if ( tud_dfu_mode_usb_reset_cb ) + if (_dfu_state_ctx.state == APP_DETACH) { - tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + _dfu_state_ctx.state = DFU_IDLE; } else { - switch (_dfu_state_ctx.state) + if ( tud_dfu_mode_usb_reset_cb ) { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: + tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) { - _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; } - break; } } -- cgit v1.3.1 From bc2cb99780a0bc0359195a4be8e556f71da5a70b Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 17:06:27 -0400 Subject: Remove unreachable callback --- src/class/dfu/dfu_mode_device.c | 10 ---------- src/class/dfu/dfu_mode_device.h | 1 - src/device/usbd.c | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 68f55510b..59cea7673 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -590,14 +590,4 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const } -bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) ep_addr; - (void) result; - (void) xferred_bytes; - return true; -} - - #endif diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index 32bf58bbd..11b748c3b 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -122,7 +122,6 @@ void dfu_mode_init(void); void dfu_mode_reset(uint8_t rhport); uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 91838b39c..de0e7b0b7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -194,7 +194,7 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_mode_reset, .open = dfu_mode_open, .control_xfer_cb = dfu_mode_control_xfer_cb, - .xfer_cb = dfu_mode_xfer_cb, + .xfer_cb = NULL, .sof = NULL }, #endif -- cgit v1.3.1 From c39b7b8177acbab23e82fee295d5f3205aa9752c Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 17:52:33 -0400 Subject: Add DFU runtime and mode "class" With the runtime and mode portions in separate classes, a single application should only be building with one or the other enabled. In some applications both might be desired at build time. The CFG_TUD_DFU_RUNTIME_AND_MODE option creates a DFU class, which asks the application which mode to initialize to. This allows a runtime change between RT and DFU mode, by just reinitializing tusb. --- src/class/dfu/dfu_mode_device.c | 4 +- src/class/dfu/dfu_rt_and_mode_device.c | 114 +++++++++++++++++++++++++++++++++ src/class/dfu/dfu_rt_and_mode_device.h | 57 +++++++++++++++++ src/class/dfu/dfu_rt_device.c | 2 +- src/device/usbd.c | 12 ++++ src/tusb.h | 6 ++ src/tusb_option.h | 10 +++ 7 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 src/class/dfu/dfu_rt_and_mode_device.c create mode 100644 src/class/dfu/dfu_rt_and_mode_device.h (limited to 'src/class') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 59cea7673..0b80b103d 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) #include "dfu_mode_device.h" #include "device/usbd_pvt.h" @@ -590,4 +590,4 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const } - #endif +#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c new file mode 100644 index 000000000..d555a1d58 --- /dev/null +++ b/src/class/dfu/dfu_rt_and_mode_device.c @@ -0,0 +1,114 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) + +#include "dfu_rt_and_mode_device.h" + +#include "dfu_mode_device.h" +#include "dfu_rt_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct +{ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +} dfu_local_driver_t; + +static dfu_local_driver_t ctx = +{ + .init = NULL, + .reset = NULL, + .open = NULL, + .control_xfer_cb = NULL +}; + +static dfu_protocol_type_t mode = 0x00; + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_init(void) +{ + mode = dfu_init_in_mode_cb(); + + switch (mode) + { + case DFU_PROTOCOL_RT: + { + ctx.init = dfu_rtd_init; + ctx.reset = dfu_rtd_reset; + ctx.open = dfu_rtd_open; + ctx.control_xfer_cb = dfu_rtd_control_xfer_cb; + } + break; + + case DFU_PROTOCOL_DFU: + { + ctx.init = dfu_mode_init; + ctx.reset = dfu_mode_reset; + ctx.open = dfu_mode_open; + ctx.control_xfer_cb = dfu_mode_control_xfer_cb; + } + break; + + default: + { + TU_LOG2(" DFU Unexpected mode: %u\r\n", mode); + } + break; + } + + ctx.init(); +} + +void dfu_reset(uint8_t rhport) +{ + ctx.reset(rhport); +} + +uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + return ctx.open(rhport, itf_desc, max_len); +} + +bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + return ctx.control_xfer_cb(rhport, stage, request); +} + +#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h new file mode 100644 index 000000000..9734a031c --- /dev/null +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_RT_AND_MODE_DEVICE_H_ +#define _TUSB_DFU_RT_AND_MODE_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when the driver needs to determine the callbacks to use +dfu_protocol_type_t dfu_init_in_mode_cb(); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_init(void); +void dfu_reset(uint8_t rhport); +uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_RT_AND_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 806bfba2e..d1d028d69 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index de0e7b0b7..6f2262feb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_DFU_RUNTIME_AND_MODE + { + DRIVER_NAME("DFU-RT-MODE") + .init = dfu_init, + .reset = dfu_reset, + .open = dfu_open, + .control_xfer_cb = dfu_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index c9558515c..6eab4bee2 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -100,6 +100,12 @@ #include "class/dfu/dfu_mode_device.h" #endif + #if CFG_TUD_DFU_RUNTIME_AND_MODE + #include "class/dfu/dfu_rt_and_mode_device.h" + #include "class/dfu/dfu_rt_device.h" + #include "class/dfu/dfu_mode_device.h" + #endif + #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 3cd3df9f2..4c2204964 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -241,6 +241,10 @@ #define CFG_TUD_DFU_MODE 0 #endif +#ifndef CFG_TUD_DFU_RUNTIME_AND_MODE + #define CFG_TUD_DFU_RUNTIME_AND_MODE 0 +#endif + #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 #endif @@ -285,6 +289,12 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif +#if (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_RUNTIME) \ + || (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_MODE) \ + || (CFG_TUD_DFU_RUNTIME && CFG_TUD_DFU_MODE) + #error Only one of CFG_TUD_DFU_RUNTIME_AND_MODE, CFG_TUD_DFU_RUNTIME, and CFG_TUD_DFU_MODE can be enabled in a single build +#endif + #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 8b79040c3864f9d76bba90b8660464f1821209a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 15:34:50 +0700 Subject: code format --- examples/device/audio_test/src/main.c | 142 ++++++++++++++++++---------------- src/class/audio/audio.h | 16 ---- 2 files changed, 77 insertions(+), 81 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index f01a5a183..4de515b3b 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -207,7 +207,6 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; case AUDIO_FU_CTRL_VOLUME: @@ -217,8 +216,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - - return true; + return true; // Unknown/Unsupported control default: @@ -275,96 +273,110 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * // Input terminal (Microphone input) if (entityID == 1) { - switch (ctrlSel) + switch ( ctrlSel ) { - case AUDIO_TE_CTRL_CONNECTOR:; - // The terminal connector control only has a get request with only the CUR attribute. - - audio_desc_channel_cluster_t ret; + case AUDIO_TE_CTRL_CONNECTOR: + { + // The terminal connector control only has a get request with only the CUR attribute. + audio_desc_channel_cluster_t ret; - // Those are dummy values for now - ret.bNrChannels = 1; - ret.bmChannelConfig = 0; - ret.iChannelNames = 0; + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; - TU_LOG2(" Get terminal connector\r\n"); + TU_LOG2(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + } + break; - // Unknown/Unsupported control selector - default: TU_BREAKPOINT(); return false; + // Unknown/Unsupported control selector + default: + TU_BREAKPOINT(); + return false; } } // Feature unit if (entityID == 2) { - switch (ctrlSel) + switch ( ctrlSel ) { case AUDIO_FU_CTRL_MUTE: - // Audio control mute cur parameter block consists of only one byte - we thus can send it right away - // There does not exist a range parameter block for mute - TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - switch (p_request->bRequest) - { - case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); - // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) ret; + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) + ret; - ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; - } + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } } // Clock Source unit - if (entityID == 4) + if ( entityID == 4 ) { - switch (ctrlSel) + switch ( ctrlSel ) { case AUDIO_CS_CTRL_SAM_FREQ: - - // channelNum is always zero in this case - - switch (p_request->bRequest) - { - case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Sample Freq. range\r\n"); - return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; - } - - case AUDIO_CS_CTRL_CLK_VALID: - // Only cur attribute exists for this request - TU_LOG2(" Get Sample Freq. valid\r\n"); - return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); - - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; + // channelNum is always zero in this case + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } } diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 2c6cd260a..936f09104 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -481,15 +481,6 @@ typedef enum AUDIO_EXT_FORMAT_TYPE_III = 0x83, } audio_format_type_t; -//#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 -//#define AUDIO_FORMAT_TYPE_I 0x01 -//#define AUDIO_FORMAT_TYPE_II 0x02 -//#define AUDIO_FORMAT_TYPE_III 0x03 -//#define AUDIO_FORMAT_TYPE_IV 0x04 -//#define AUDIO_EXT_FORMAT_TYPE_I 0x81 -//#define AUDIO_EXT_FORMAT_TYPE_II 0x82 -//#define AUDIO_EXT_FORMAT_TYPE_III 0x83 - // A.2.1 - Audio Class-Audio Data Format Type I UAC2 typedef enum { @@ -501,13 +492,6 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, } audio_data_format_type_I_t; -//#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) -//#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) -//#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) -//#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) -//#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) -//#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 - /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification /// Isochronous End Point Attributes -- cgit v1.3.1 From 58bab86d794aad8979bd2557bdc81f44d0731a97 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 21:09:23 +0700 Subject: minor clean up --- src/class/audio/audio_device.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d4793c9d8..81e0024d7 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -496,17 +496,17 @@ static inline bool tud_audio_mounted(void) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -static inline uint16_t tud_audio_available (void) +static inline uint16_t tud_audio_available(void) { return tud_audio_n_available(0); } -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) { return tud_audio_n_read(0, buffer, bufsize); } -static inline bool tud_audio_clear_ep_out_ff (void) +static inline bool tud_audio_clear_ep_out_ff(void) { return tud_audio_n_clear_ep_out_ff(0); } @@ -515,17 +515,17 @@ static inline bool tud_audio_clear_ep_out_ff (void) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) +static inline bool tud_audio_clear_rx_support_ff(uint8_t channelId) { return tud_audio_n_clear_rx_support_ff(0, channelId); } -static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) +static inline uint16_t tud_audio_available_support_ff(uint8_t channelId) { return tud_audio_n_available_support_ff(0, channelId); } -static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read_support_ff(uint8_t channelId, void* buffer, uint16_t bufsize) { return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); } @@ -536,12 +536,12 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_write (const void * data, uint16_t len) +static inline uint16_t tud_audio_write(const void * data, uint16_t len) { return tud_audio_n_write(0, data, len); } -static inline bool tud_audio_clear_ep_in_ff (void) +static inline bool tud_audio_clear_ep_in_ff(void) { return tud_audio_n_clear_ep_in_ff(0); } @@ -550,17 +550,17 @@ static inline bool tud_audio_clear_ep_in_ff (void) #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void) +static inline uint16_t tud_audio_flush_tx_support_ff(void) { return tud_audio_n_flush_tx_support_ff(0); } -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId) +static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t channelId) { return tud_audio_n_clear_tx_support_ff(0, channelId); } -static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len) +static inline uint16_t tud_audio_write_support_ff(uint8_t channelId, const void * data, uint16_t len) { return tud_audio_n_write_support_ff(0, channelId, data, len); } @@ -584,11 +584,11 @@ static inline bool tud_audio_fb_set(uint32_t feedback) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 8eacdffebdcc10a6fffdc248ef6086b223f3edf3 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 7 Apr 2021 20:07:28 +0200 Subject: Optimize encode/decode - refactor unnecessary repetitive division --- src/class/audio/audio_device.c | 16 ++++++++-------- src/class/audio/audio_device.h | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a85dfddb8..2e9684cb9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -310,6 +310,7 @@ typedef struct audio_data_format_type_I_t format_type_I_rx; uint8_t n_bytes_per_sampe_rx; uint8_t n_channels_per_ff_rx; + uint8_t n_ff_used_rx; #endif #endif @@ -322,6 +323,7 @@ typedef struct audio_data_format_type_I_t format_type_I_tx; uint8_t n_bytes_per_sampe_tx; uint8_t n_channels_per_ff_tx; + uint8_t n_ff_used_tx; #endif #endif @@ -625,10 +627,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, (void) rhport; // Determine amount of samples - uint8_t const n_ff_used = audio->n_channels_rx / audio->n_channels_per_ff_rx; - - TU_ASSERT( n_ff_used <= audio->n_rx_supp_ff ); - + uint8_t const n_ff_used = audio->n_ff_used_rx; uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; @@ -928,10 +927,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint8_t const n_ff_used = audio->n_channels_tx / audio->n_channels_per_ff_tx; - - TU_ASSERT( n_ff_used <= audio->n_tx_supp_ff ); - + uint8_t const n_ff_used = audio->n_ff_used_tx; uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -1551,6 +1547,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); } + audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; + TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); #endif #endif @@ -1582,6 +1580,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); } + audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; + TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); #endif #endif // Invoke callback diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 81e0024d7..f91540b64 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -240,6 +240,9 @@ // Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size // The actual coding parameters of active AS alternate interface is parsed from the descriptors +// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! +// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! + // For PCM encoding/decoding #ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -- cgit v1.3.1 From 2e2dc7bdc5928dfa027291ca8c6d6792698e5b9a Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 7 Apr 2021 17:05:04 -0400 Subject: Revise per initial comments Returns the RT driver to the function state of previous iteration, which did not support the will_detach. Behavior should be fine without this feature. This removes much of the added bloat to track state, and handle requests in the APP_DETACH state which is no longer required. Removes the optional bloat added to the RT driver, such as responding to GETSTATE requests. Fixes the DFU Mode to extract the attr bits from the functional descriptor when opened. Fixes some incorrect bitwise if checks. Also, updates some naming of functions to be consistent with the rest of the library. --- src/class/dfu/dfu_mode_device.c | 19 +++++---- src/class/dfu/dfu_mode_device.h | 8 ++-- src/class/dfu/dfu_rt_and_mode_device.c | 18 ++++---- src/class/dfu/dfu_rt_and_mode_device.h | 10 ++--- src/class/dfu/dfu_rt_device.c | 76 ++++------------------------------ src/class/dfu/dfu_rt_device.h | 35 ---------------- src/class/vendor/vendor_device.c | 2 +- src/common/tusb_types.h | 18 ++++---- src/device/usbd.c | 16 +++---- 9 files changed, 55 insertions(+), 147 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 0b80b103d..7ad0f5168 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -65,11 +65,11 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void dfu_mode_init(void) +void dfu_moded_init(void) { _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.last_block_num = 0; _dfu_state_ctx.last_transfer_len = 0; @@ -77,7 +77,7 @@ void dfu_mode_init(void) dfu_debug_print_context(); } -void dfu_mode_reset(uint8_t rhport) +void dfu_moded_reset(uint8_t rhport) { if (_dfu_state_ctx.state == APP_DETACH) { @@ -118,14 +118,13 @@ void dfu_mode_reset(uint8_t rhport) } _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.last_block_num = 0; _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } -uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; (void) max_len; @@ -139,6 +138,9 @@ uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, u if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { + tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -149,7 +151,7 @@ uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, u // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) { @@ -266,7 +268,7 @@ void tud_dfu_mode_poll_timeout_done() _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -394,7 +396,6 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); } else { if ( tud_dfu_mode_device_data_done_check_cb() ) @@ -447,7 +448,7 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index 11b748c3b..aacb1911c 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -118,10 +118,10 @@ TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_mode_init(void); -void dfu_mode_reset(uint8_t rhport); -uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void dfu_moded_init(void); +void dfu_moded_reset(uint8_t rhport); +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c index d555a1d58..8b6a8a766 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.c +++ b/src/class/dfu/dfu_rt_and_mode_device.c @@ -62,9 +62,9 @@ static dfu_protocol_type_t mode = 0x00; //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void dfu_init(void) +void dfu_d_init(void) { - mode = dfu_init_in_mode_cb(); + mode = tud_dfu_init_in_mode_cb(); switch (mode) { @@ -79,10 +79,10 @@ void dfu_init(void) case DFU_PROTOCOL_DFU: { - ctx.init = dfu_mode_init; - ctx.reset = dfu_mode_reset; - ctx.open = dfu_mode_open; - ctx.control_xfer_cb = dfu_mode_control_xfer_cb; + ctx.init = dfu_moded_init; + ctx.reset = dfu_moded_reset; + ctx.open = dfu_moded_open; + ctx.control_xfer_cb = dfu_moded_control_xfer_cb; } break; @@ -96,17 +96,17 @@ void dfu_init(void) ctx.init(); } -void dfu_reset(uint8_t rhport) +void dfu_d_reset(uint8_t rhport) { ctx.reset(rhport); } -uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { return ctx.open(rhport, itf_desc, max_len); } -bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { return ctx.control_xfer_cb(rhport, stage, request); } diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h index 9734a031c..b6eafbba4 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -39,15 +39,15 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t dfu_init_in_mode_cb(); +dfu_protocol_type_t tud_dfu_init_in_mode_cb(); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_init(void); -void dfu_reset(uint8_t rhport); -uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void dfu_d_init(void); +void dfu_d_reset(uint8_t rhport); +uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d1d028d69..729b8e3e0 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -38,41 +38,17 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; -} dfu_rt_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_rt_state_ctx_t _dfu_state_ctx; - -static void dfu_rt_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { - _dfu_state_ctx.state = APP_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - dfu_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - if (((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 0) - && (_dfu_state_ctx.state == DFU_REQUEST_DETACH)) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } - - _dfu_state_ctx.state = APP_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - dfu_debug_print_context(); + (void) rhport; } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -117,67 +93,29 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU RT Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: { - if (_dfu_state_ctx.state == APP_IDLE) - { - _dfu_state_ctx.state = APP_DETACH; - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } else { - tud_dfu_runtime_detach_start_timer_cb(request->wValue); - } - } else { - TU_LOG2(" DFU Unexpected request during state %s: %u\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), request->bRequest); - return false; - } + tud_control_status(rhport, request); + tud_dfu_runtime_reboot_to_dfu_cb(); } break; case DFU_REQUEST_GETSTATUS: { dfu_status_req_payload_t resp; - resp.bStatus = _dfu_state_ctx.status; - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); // Value is ignored - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - + // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 + memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } break; - case DFU_REQUEST_GETSTATE: - { - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Runtime Request: %u\r\n", request->bRequest); - return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; - } - break; + default: return false; // stall unsupported request } return true; } -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) -{ - _dfu_state_ctx.status = status; -} - -void tud_dfu_runtime_detach_timer_elapsed() -{ - if (_dfu_state_ctx.state == DFU_REQUEST_DETACH) - { - _dfu_state_ctx.state = APP_IDLE; - } -} - #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 23703862d..465bf9d99 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -38,44 +38,9 @@ //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Allow the application to update the status as required. -// Is set to DFU_STATUS_OK during internal initialization and USB reset -// Value is not checked to allow for custom statuses to be used -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); - // Invoked when a DFU_DETACH request is received and bitWillDetach is set void tud_dfu_runtime_reboot_to_dfu_cb(); -// Invoked when a DFU_DETACH request is received and bitWillDetach is not set -// This should start a timer for wTimeout ms -// When the timer has elapsed, the app must call tud_dfu_runtime_detach_timer_elapsed -// If a USB reset is called while the timer is running, the class will call -// tud_dfu_runtime_reboot_to_dfu_cb. -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this can will hold up the USB stack -TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); - -// Invoke when the dfu runtime detach timer has elapsed -void tud_dfu_runtime_detach_timer_elapsed(); - -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_runtime_init_attrs_cb(); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 3fcea89c4..d39830a6a 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a462b498f..7703ebb7b 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -427,13 +427,17 @@ typedef struct TU_ATTR_PACKED uint8_t bLength; uint8_t bDescriptorType; - struct TU_ATTR_PACKED { - uint8_t bitCanDnload : 1; - uint8_t bitCanUpload : 1; - uint8_t bitManifestationTolerant : 1; - uint8_t bitWillDetach : 1; - uint8_t reserved : 4; - } bmAttributes; + union { + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint8_t bAttributes; + }; uint16_t wDetachTimeOut; uint16_t wTransferSize; diff --git a/src/device/usbd.c b/src/device/usbd.c index 6f2262feb..92e521ec9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,10 +190,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_MODE { DRIVER_NAME("DFU-MODE") - .init = dfu_mode_init, - .reset = dfu_mode_reset, - .open = dfu_mode_open, - .control_xfer_cb = dfu_mode_control_xfer_cb, + .init = dfu_moded_init, + .reset = dfu_moded_reset, + .open = dfu_moded_open, + .control_xfer_cb = dfu_moded_control_xfer_cb, .xfer_cb = NULL, .sof = NULL }, @@ -202,10 +202,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RUNTIME_AND_MODE { DRIVER_NAME("DFU-RT-MODE") - .init = dfu_init, - .reset = dfu_reset, - .open = dfu_open, - .control_xfer_cb = dfu_control_xfer_cb, + .init = dfu_d_init, + .reset = dfu_d_reset, + .open = dfu_d_open, + .control_xfer_cb = dfu_d_control_xfer_cb, .xfer_cb = NULL, .sof = NULL }, -- cgit v1.3.1 From ae851bba31781eacfadc7e69b414cd1da6960314 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 7 Apr 2021 17:15:26 -0400 Subject: Resolve gcc warnings for no parameter functions --- src/class/dfu/dfu_mode_device.h | 16 ++++++++-------- src/class/dfu/dfu_rt_and_mode_device.h | 2 +- src/class/dfu/dfu_rt_device.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index aacb1911c..c25910b23 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -40,10 +40,10 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when a reset is received to check if firmware is valid -bool tud_dfu_mode_firmware_valid_check_cb(); +bool tud_dfu_mode_firmware_valid_check_cb(void); // Invoked when the device must reboot to dfu runtime mode -void tud_dfu_mode_reboot_to_rt_cb(); +void tud_dfu_mode_reboot_to_rt_cb(void); // Invoked during initialization of the dfu driver to set attributes // Return byte set with bitmasks: @@ -52,11 +52,11 @@ void tud_dfu_mode_reboot_to_rt_cb(); // DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK // DFU_FUNC_ATTR_WILL_DETACH_BITMASK // Note: This should match the USB descriptor -uint8_t tud_dfu_mode_init_attrs_cb(); +uint8_t tud_dfu_mode_init_attrs_cb(void); // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); // Invoked during a USB reset // Lets the app perform custom behavior on a USB reset. @@ -84,7 +84,7 @@ TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); // Must be called when the poll_timeout has elapsed -void tud_dfu_mode_poll_timeout_done(); +void tud_dfu_mode_poll_timeout_done(void); // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it @@ -97,10 +97,10 @@ void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure -bool tud_dfu_mode_device_data_done_check_cb(); +bool tud_dfu_mode_device_data_done_check_cb(void); // Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_mode_abort_cb(); +TU_ATTR_WEAK void tud_dfu_mode_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes @@ -114,7 +114,7 @@ TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h index b6eafbba4..b311bb7a5 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -39,7 +39,7 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t tud_dfu_init_in_mode_cb(); +dfu_protocol_type_t tud_dfu_init_in_mode_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 465bf9d99..0e5fd005a 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -39,7 +39,7 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when a DFU_DETACH request is received and bitWillDetach is set -void tud_dfu_runtime_reboot_to_dfu_cb(); +void tud_dfu_runtime_reboot_to_dfu_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From 4bebb9ca49bc6fc7ae281d284e009afe276a2948 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 8 Apr 2021 20:11:51 +0200 Subject: Remove depracted defines in audio_device.c --- src/class/audio/audio_device.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2e9684cb9..8c0d563e6 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -762,13 +762,8 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) uint8_t idxDriver, idxItf; uint8_t const *dummy2; -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I - // Required in any case regardless if call backs are used - find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); -#else // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); -#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). -- cgit v1.3.1 From 2134c1a875d57c79cd431a982d67420101d3c656 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 8 Apr 2021 21:48:36 +0200 Subject: Fix defines in audio_device.c --- examples/device/audio_4_channel_mic/src/main.c | 1 - src/class/audio/audio_device.c | 28 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 58fbd401e..6e1ea1e6a 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -429,7 +429,6 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const { (void) rhport; (void) p_request; - startVal = 0; return true; } diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8c0d563e6..753c0ef6c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2085,43 +2085,67 @@ static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_in_as_intf_num) break; +#endif +#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_out_as_intf_num) break; +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; #endif } +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf == audio->ep_out_as_intf_num) { audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; #endif } +#endif } // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_in_as_intf_num) break; +#endif +#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_out_as_intf_num) break; +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (itf == audio->ep_in_as_intf_num) { audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf == audio->ep_out_as_intf_num) { audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } +#endif } #endif -- cgit v1.3.1 From 7b45b38fe4b7d2ebd197463cf12f091a6f68ac91 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 12 Apr 2021 11:17:01 -0400 Subject: Remove DFU mode and rt --- src/class/dfu/dfu_mode_device.c | 2 +- src/class/dfu/dfu_rt_and_mode_device.c | 114 --------------------------------- src/class/dfu/dfu_rt_and_mode_device.h | 57 ----------------- src/class/dfu/dfu_rt_device.c | 2 +- src/device/usbd.c | 12 ---- src/tusb.h | 6 -- src/tusb_option.h | 10 --- 7 files changed, 2 insertions(+), 201 deletions(-) delete mode 100644 src/class/dfu/dfu_rt_and_mode_device.c delete mode 100644 src/class/dfu/dfu_rt_and_mode_device.h (limited to 'src/class') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 7ad0f5168..5f8c714c0 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) #include "dfu_mode_device.h" #include "device/usbd_pvt.h" diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c deleted file mode 100644 index 8b6a8a766..000000000 --- a/src/class/dfu/dfu_rt_and_mode_device.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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 file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) - -#include "dfu_rt_and_mode_device.h" - -#include "dfu_mode_device.h" -#include "dfu_rt_device.h" -#include "device/usbd_pvt.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - void (* init ) (void); - void (* reset ) (uint8_t rhport); - uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -} dfu_local_driver_t; - -static dfu_local_driver_t ctx = -{ - .init = NULL, - .reset = NULL, - .open = NULL, - .control_xfer_cb = NULL -}; - -static dfu_protocol_type_t mode = 0x00; - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_d_init(void) -{ - mode = tud_dfu_init_in_mode_cb(); - - switch (mode) - { - case DFU_PROTOCOL_RT: - { - ctx.init = dfu_rtd_init; - ctx.reset = dfu_rtd_reset; - ctx.open = dfu_rtd_open; - ctx.control_xfer_cb = dfu_rtd_control_xfer_cb; - } - break; - - case DFU_PROTOCOL_DFU: - { - ctx.init = dfu_moded_init; - ctx.reset = dfu_moded_reset; - ctx.open = dfu_moded_open; - ctx.control_xfer_cb = dfu_moded_control_xfer_cb; - } - break; - - default: - { - TU_LOG2(" DFU Unexpected mode: %u\r\n", mode); - } - break; - } - - ctx.init(); -} - -void dfu_d_reset(uint8_t rhport) -{ - ctx.reset(rhport); -} - -uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - return ctx.open(rhport, itf_desc, max_len); -} - -bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - return ctx.control_xfer_cb(rhport, stage, request); -} - -#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h deleted file mode 100644 index b311bb7a5..000000000 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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 file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_RT_AND_MODE_DEVICE_H_ -#define _TUSB_DFU_RT_AND_MODE_DEVICE_H_ - -#include "common/tusb_common.h" -#include "device/usbd.h" -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t tud_dfu_init_in_mode_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_d_init(void); -void dfu_d_reset(uint8_t rhport); -uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_AND_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 729b8e3e0..9da2e1e4f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 92e521ec9..af34e53ac 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,18 +199,6 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_DFU_RUNTIME_AND_MODE - { - DRIVER_NAME("DFU-RT-MODE") - .init = dfu_d_init, - .reset = dfu_d_reset, - .open = dfu_d_open, - .control_xfer_cb = dfu_d_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index 6eab4bee2..c9558515c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -100,12 +100,6 @@ #include "class/dfu/dfu_mode_device.h" #endif - #if CFG_TUD_DFU_RUNTIME_AND_MODE - #include "class/dfu/dfu_rt_and_mode_device.h" - #include "class/dfu/dfu_rt_device.h" - #include "class/dfu/dfu_mode_device.h" - #endif - #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 4c2204964..3cd3df9f2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -241,10 +241,6 @@ #define CFG_TUD_DFU_MODE 0 #endif -#ifndef CFG_TUD_DFU_RUNTIME_AND_MODE - #define CFG_TUD_DFU_RUNTIME_AND_MODE 0 -#endif - #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 #endif @@ -289,12 +285,6 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif -#if (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_RUNTIME) \ - || (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_MODE) \ - || (CFG_TUD_DFU_RUNTIME && CFG_TUD_DFU_MODE) - #error Only one of CFG_TUD_DFU_RUNTIME_AND_MODE, CFG_TUD_DFU_RUNTIME, and CFG_TUD_DFU_MODE can be enabled in a single build -#endif - #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 8d9f60ca5e1b095fd8ab5541bf3190a2035eaf6f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 14 Apr 2021 21:52:54 +0200 Subject: Improve user feedback in case of wrong configuration of audio driver --- src/class/audio/audio_device.c | 71 +++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 42 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 753c0ef6c..4057f5f64 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -81,14 +81,14 @@ #endif #if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) - #define USE_LINEAR_BUFFER 0 +#define USE_LINEAR_BUFFER 0 #else - #define USE_LINEAR_BUFFER 1 +#define USE_LINEAR_BUFFER 1 #endif // Declaration of buffers @@ -182,9 +182,7 @@ CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; -#endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif @@ -267,9 +265,7 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 - uint8_t * alt_setting_ptr; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! -#endif + uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -486,7 +482,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -540,7 +536,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -557,12 +553,12 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const { // This function is an optimized version of -// while((uint8_t *)dst < dst_end) -// { -// memcpy(dst, src, nBytesToCopy); -// dst = (uint8_t *)dst + nBytesToCopy; -// src += nBytesToCopy * n_ff_used; -// } + // while((uint8_t *)dst < dst_end) + // { + // memcpy(dst, src, nBytesToCopy); + // dst = (uint8_t *)dst + nBytesToCopy; + // src += nBytesToCopy * n_ff_used; + // } // Optimize for fast half word copies typedef struct{ @@ -596,9 +592,9 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const case 3: while((uint8_t *)dst < dst_end) { -// memcpy(dst, src, 3); -// dst = (uint8_t *)dst + 3; -// src += 3 * n_ff_used; + // memcpy(dst, src, 3); + // dst = (uint8_t *)dst + 3; + // src += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? *(uint8_t *)dst++ = *src++; @@ -767,7 +763,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; @@ -827,7 +823,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -887,9 +883,9 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const case 3: while((uint8_t *)src < src_end) { -// memcpy(dst, src, 3); -// src = (uint8_t *)src + 3; -// dst += 3 * n_ff_used; + // memcpy(dst, src, 3); + // src = (uint8_t *)src + 3; + // dst += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? *dst++ = *(uint8_t *)src++; @@ -1021,26 +1017,24 @@ void audiod_init(void) } // Initialize active alternate interface buffers -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 switch (i) { #if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 case 0: - audio->alt_setting_ptr = alt_setting_1; + audio->alt_setting = alt_setting_1; break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 case 1: - audio->alt_setting_ptr = alt_setting_2; + audio->alt_setting = alt_setting_2; break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 case 2: - audio->alt_setting_ptr = alt_setting_3; + audio->alt_setting = alt_setting_3; break; #endif } -#endif // Initialize IN EP FIFO if required #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING @@ -1400,7 +1394,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface @@ -1408,17 +1401,11 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *dummy; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting_ptr[idxItf], 1)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting_ptr[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting[idxItf]); return true; - -#else - (void) rhport; - (void) p_request; - return false; -#endif } static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) @@ -1495,7 +1482,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // Save current alternative interface setting - audio->alt_setting_ptr[idxItf] = alt; + audio->alt_setting[idxItf] = alt; // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end -- cgit v1.3.1 From 4408ffce88a46bb7f2b07b99a9df60b24e17700f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 20 Apr 2021 18:44:56 +0200 Subject: Fix pointer alt_setting to be cleared when driver gets initialized --- src/class/audio/audio_device.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4057f5f64..d9d078817 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -265,17 +265,17 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - /*------------- From this point, data is not cleared by bus reset -------------*/ - // uint16_t desc_length; // Length of audio function descriptor // Buffer for control requests uint8_t * ctrl_buf; uint8_t ctrl_buf_sz; + // Current active alternate settings + uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! + // EP Transfer buffers and FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_OUT #if !CFG_TUD_AUDIO_ENABLE_DECODING @@ -759,7 +759,10 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) uint8_t const *dummy2; // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface - if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + + // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications + if (audio->alt_setting[idxItf] == 0) return false; // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). @@ -1424,7 +1427,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // 3. Open new EP uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); + volatile uint8_t const alt = tu_u16_low(p_request->wValue); TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); @@ -1537,7 +1540,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - // Schedule first transmit - in case no sample data is available a ZLP is loaded + // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } @@ -1840,7 +1843,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_itf[idxDriver].ep_in == ep_addr) + if (_audiod_itf[idxDriver].ep_in == ep_addr && _audiod_itf[idxDriver].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." -- cgit v1.3.1 From fef0d54559e957575a5f0adebb1af94b7a81dd4f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 20 Apr 2021 19:56:40 +0200 Subject: Refactor static function for better performance --- src/class/audio/audio_device.c | 272 +++++++++++++++++++++++------------------ 1 file changed, 150 insertions(+), 122 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d9d078817..2504e9c83 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -347,7 +347,7 @@ typedef struct #define USE_LINEAR_BUFFER_TX 1 #endif -} audiod_interface_t; +} audiod_function_t; #ifndef USE_LINEAR_BUFFER_TX #define USE_LINEAR_BUFFER_TX 0 @@ -357,39 +357,41 @@ typedef struct #define USE_LINEAR_BUFFER_RX 0 #endif -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) +#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; +CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); +static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); #endif static inline uint8_t tu_desc_subtype(void const* desc) @@ -400,7 +402,7 @@ static inline uint8_t tu_desc_subtype(void const* desc) bool tud_audio_n_mounted(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_AUDIO); - audiod_interface_t* audio = &_audiod_itf[itf]; + audiod_function_t* audio = &_audiod_fct[itf]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; @@ -429,20 +431,20 @@ bool tud_audio_n_mounted(uint8_t itf) uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[itf].ep_out_ff); } uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[itf].ep_out_ff, buffer, bufsize); } bool tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[itf].ep_out_ff); } #endif @@ -451,20 +453,20 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); - return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif @@ -473,16 +475,20 @@ uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffe #if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) +static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) { - uint8_t idxDriver, idxItf; + uint8_t idxItf; uint8_t const *dummy2; + uint8_t idx_audio_fct = 0; - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); + } // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -536,7 +542,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -618,7 +624,7 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const return src; } -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) { (void) rhport; @@ -683,14 +689,14 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, */ uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[itf].ep_in_ff, data, len); } bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[itf].ep_in_ff); } #endif @@ -698,8 +704,8 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - audiod_interface_t* audio = &_audiod_itf[itf]; + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[itf]; uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -713,14 +719,14 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[itf].tx_supp_ff[channelId], data, len); } #endif @@ -730,18 +736,18 @@ uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr)); + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr)); // Check length TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - memcpy(_audiod_itf[itf].ep_int_ctr_buf, buffer, len); + memcpy(_audiod_fct[itf].ep_int_ctr_buf, buffer, len); // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr, _audiod_itf[itf].ep_int_ctr_buf, len)); + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr, _audiod_fct[itf].ep_int_ctr_buf, len)); return true; } @@ -753,20 +759,20 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) { - uint8_t idxDriver, idxItf; + uint8_t idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications if (audio->alt_setting[idxItf] == 0) return false; // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; @@ -826,7 +832,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -912,7 +918,7 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const return dst; } -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) { // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap // This is ensured within set_interface, where the FIFOs are reconfigured according to this size @@ -981,7 +987,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) +static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) { return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); } @@ -992,11 +998,11 @@ static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) //--------------------------------------------------------------------+ void audiod_init(void) { - tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + tu_memclr(_audiod_fct, sizeof(_audiod_fct)); for(uint8_t i=0; i 1 case 1: - _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; break; #endif #if CFG_TUD_AUDIO > 2 case 2: - _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; break; #endif } @@ -1390,7 +1396,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } @@ -1403,10 +1409,10 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t idxDriver, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[idxDriver].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[idxDriver].alt_setting[idxItf]); return true; } @@ -1434,9 +1440,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find index of audio streaming interface and index of interface uint8_t idxDriver, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &p_desc)); - audiod_interface_t* audio = &_audiod_itf[idxDriver]; + audiod_function_t* audio = &_audiod_fct[idxDriver]; // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1542,7 +1548,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1635,7 +1641,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); } else { @@ -1651,7 +1657,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); } else { @@ -1672,7 +1678,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); } else { @@ -1790,7 +1796,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, _audiod_itf[idxDriver].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf, _audiod_fct[idxDriver].ctrl_buf_sz)); return true; } @@ -1826,7 +1832,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // Data transmission of control interrupt finished - if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + if (_audiod_fct[idxDriver].ep_int_ctr == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? @@ -1843,7 +1849,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_itf[idxDriver].ep_in == ep_addr && _audiod_itf[idxDriver].alt_setting != 0) + if (_audiod_fct[idxDriver].ep_in == ep_addr && _audiod_fct[idxDriver].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." @@ -1854,7 +1860,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1864,21 +1870,21 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received - if (_audiod_itf[idxDriver].ep_out == ep_addr) + if (_audiod_fct[idxDriver].ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], (uint16_t) xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[idxDriver], (uint16_t) xferred_bytes)); return true; } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished - if (_audiod_itf[idxDriver].ep_fb == ep_addr) + if (_audiod_fct[idxDriver].ep_fb == ep_addr) { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_itf[idxDriver]); + return audiod_fb_send(rhport, &_audiod_fct[idxDriver]); } #endif #endif @@ -1929,49 +1935,61 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_itf[idxDriver].ctrl_buf_sz) len = _audiod_itf[idxDriver].ctrl_buf_sz; + if (len > _audiod_fct[idxDriver].ctrl_buf_sz) len = _audiod_fct[idxDriver].ctrl_buf_sz; // Copy into buffer - memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); + memcpy((void *)_audiod_fct[idxDriver].ctrl_buf, data, (size_t)len); // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[idxDriver].ctrl_buf, len); +} + +// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. +static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + if (audio->p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; + + // Advance past AC descriptors + uint8_t const *p_desc = tu_desc_next(audio->p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + return false; } // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_itf[i].p_desc) + if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *idxDriver = i; - *pp_desc_int = p_desc; - return true; - } - - // Increase index, bytes read, and pointer - tmp++; - p_desc = tu_desc_next(p_desc); - } + *idxDriver = i; + return true; } } @@ -1985,10 +2003,10 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * for (i = 0; i < CFG_TUD_AUDIO; i++) { // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor @@ -2011,15 +2029,15 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_itf[i].p_desc) + if (_audiod_fct[i].p_desc) { // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc = _audiod_fct[i].p_desc; + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { *idxDriver = i; return true; @@ -2036,13 +2054,13 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_itf[i].p_desc) + if (_audiod_fct[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length; + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; while (p_desc < p_desc_end) @@ -2063,7 +2081,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) // p_desc points to the AS interface of alternate setting zero // itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter // Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) { p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor @@ -2151,12 +2169,12 @@ static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); // Format the feedback value - if (_audiod_itf[itf].rhport == 0) + if (_audiod_fct[itf].rhport == 0) { - uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; + uint8_t * fb = (uint8_t *) &_audiod_fct[itf].fb_val; // For FS format is 10.14 *(fb++) = (feedback >> 2) & 0xFF; @@ -2168,17 +2186,27 @@ bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) else { // For HS format is 16.16 as originally demanded - _audiod_itf[itf].fb_val = feedback; + _audiod_fct[itf].fb_val = feedback; } // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) + if (!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_fb)) { - return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); + return audiod_fb_send(_audiod_fct[itf].rhport, &_audiod_fct[itf]); } return true; } #endif +// No security checks here - internal function only which should always succeed +uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) +{ + for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) + { + if (&_audiod_fct[cnt] == audio) return cnt; + } + return 0; +} + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO -- cgit v1.3.1 From c7c11b181c05136a1c077dc445f422c7e17edc02 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 20 Apr 2021 20:15:02 +0200 Subject: Clean up old depracted and misleading variable names --- src/class/audio/audio_device.c | 218 ++++++++++++++++++++--------------------- src/class/audio/audio_device.h | 66 ++++++------- 2 files changed, 142 insertions(+), 142 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2504e9c83..4c6c79e30 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -383,15 +383,15 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int); static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx); static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); #endif static inline uint8_t tu_desc_subtype(void const* desc) @@ -399,10 +399,10 @@ static inline uint8_t tu_desc_subtype(void const* desc) return ((uint8_t const*) desc)[2]; } -bool tud_audio_n_mounted(uint8_t itf) +bool tud_audio_n_mounted(uint8_t audio_fct_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[itf]; + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO); + audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; @@ -429,44 +429,44 @@ bool tud_audio_n_mounted(uint8_t itf) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available(uint8_t itf) +uint16_t tud_audio_n_available(uint8_t audio_fct_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[itf].ep_out_ff); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[audio_fct_idx].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t audio_fct_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[itf].ep_out_ff, buffer, bufsize); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].ep_out_ff, buffer, bufsize); } -bool tud_audio_n_clear_ep_out_ff(uint8_t itf) +bool tud_audio_n_clear_ep_out_ff(uint8_t audio_fct_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[itf].ep_out_ff); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_out_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) +bool tud_audio_n_clear_rx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[itf].rx_supp_ff[channelId]); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) +uint16_t tud_audio_n_available_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[itf].rx_supp_ff[channelId]); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[itf].rx_supp_ff[channelId], buffer, bufsize); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx], buffer, bufsize); } #endif @@ -682,30 +682,30 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. * - * \param[in] itf: Index of audio function interface + * \param[in] audio_fct_idx: Index of audio function interface * \param[in] data: Pointer to data array to be copied from * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) +uint16_t tud_audio_n_write(uint8_t audio_fct_idx, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[itf].ep_in_ff, data, len); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].ep_in_ff, data, len); } -bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff(uint8_t audio_fct_idx) // Delete all content in the EP IN FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[itf].ep_in_ff); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_in_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t audio_fct_idx) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[itf]; + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -717,16 +717,16 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a return n_bytes_copied; } -bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) +bool tud_audio_n_clear_tx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[itf].tx_supp_ff[channelId]); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) +uint16_t tud_audio_n_write_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[itf].tx_supp_ff[channelId], data, len); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx], data, len); } #endif @@ -734,20 +734,20 @@ uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t len) +uint16_t tud_audio_int_ctr_n_write(uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr)); + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr)); // Check length TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - memcpy(_audiod_fct[itf].ep_int_ctr_buf, buffer, len); + memcpy(_audiod_fct[audio_fct_idx].ep_int_ctr_buf, buffer, len); // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr, _audiod_fct[itf].ep_int_ctr_buf, len)); + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr, _audiod_fct[audio_fct_idx].ep_int_ctr_buf, len)); return true; } @@ -1406,13 +1406,13 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface - uint8_t idxDriver, idxItf; + uint8_t audio_fct_idx, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[idxDriver].alt_setting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[audio_fct_idx].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[idxDriver].alt_setting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[audio_fct_idx].alt_setting[idxItf]); return true; } @@ -1438,11 +1438,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); // Find index of audio streaming interface and index of interface - uint8_t idxDriver, idxItf; + uint8_t audio_fct_idx, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &p_desc)); - audiod_function_t* audio = &_audiod_fct[idxDriver]; + audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1548,7 +1548,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1624,7 +1624,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) { - uint8_t idxDriver; + uint8_t audio_fct_idx; switch (p_request->bmRequestType_bit.recipient) { @@ -1638,10 +1638,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_entity_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); } else { @@ -1654,10 +1654,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_itf_cb) { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); } else { @@ -1675,10 +1675,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_ep_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); } else { @@ -1719,7 +1719,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t idxDriver; + uint8_t audio_fct_idx; // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) @@ -1732,7 +1732,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1751,7 +1751,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1774,7 +1774,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1796,7 +1796,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf, _audiod_fct[idxDriver].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf, _audiod_fct[audio_fct_idx].ctrl_buf_sz)); return true; } @@ -1825,14 +1825,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 (void) xferred_bytes; // Search for interface belonging to given end point address and proceed as required - uint8_t idxDriver; - for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + uint8_t audio_fct_idx; + for (audio_fct_idx = 0; audio_fct_idx < CFG_TUD_AUDIO; audio_fct_idx++) { #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // Data transmission of control interrupt finished - if (_audiod_fct[idxDriver].ep_int_ctr == ep_addr) + if (_audiod_fct[audio_fct_idx].ep_int_ctr == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? @@ -1849,7 +1849,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_fct[idxDriver].ep_in == ep_addr && _audiod_fct[idxDriver].alt_setting != 0) + if (_audiod_fct[audio_fct_idx].ep_in == ep_addr && _audiod_fct[audio_fct_idx].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." @@ -1860,7 +1860,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1870,21 +1870,21 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received - if (_audiod_fct[idxDriver].ep_out == ep_addr) + if (_audiod_fct[audio_fct_idx].ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[idxDriver], (uint16_t) xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[audio_fct_idx], (uint16_t) xferred_bytes)); return true; } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished - if (_audiod_fct[idxDriver].ep_fb == ep_addr) + if (_audiod_fct[audio_fct_idx].ep_fb == ep_addr) { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[idxDriver]); + return audiod_fb_send(rhport, &_audiod_fct[audio_fct_idx]); } #endif #endif @@ -1899,7 +1899,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; // Get corresponding driver index - uint8_t idxDriver; + uint8_t audio_fct_idx; uint8_t itf = TU_U16_LOW(p_request->wIndex); // Conduct checks which depend on the recipient @@ -1913,12 +1913,12 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); } else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); } break; @@ -1927,7 +1927,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); break; // Unknown/Unsupported recipient @@ -1935,13 +1935,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_fct[idxDriver].ctrl_buf_sz) len = _audiod_fct[idxDriver].ctrl_buf_sz; + if (len > _audiod_fct[audio_fct_idx].ctrl_buf_sz) len = _audiod_fct[audio_fct_idx].ctrl_buf_sz; // Copy into buffer - memcpy((void *)_audiod_fct[idxDriver].ctrl_buf, data, (size_t)len); + memcpy((void *)_audiod_fct[audio_fct_idx].ctrl_buf, data, (size_t)len); // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[idxDriver].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[audio_fct_idx].ctrl_buf, len); } // This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function @@ -1980,7 +1980,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; @@ -1988,7 +1988,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver { if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) { - *idxDriver = i; + *audio_fct_idx = i; return true; } } @@ -1997,7 +1997,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver } // Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver) +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2014,7 +2014,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { - *idxDriver = i; + *audio_fct_idx = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2024,7 +2024,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * return false; } -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2039,7 +2039,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { - *idxDriver = i; + *audio_fct_idx = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2049,7 +2049,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) return false; } -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2067,7 +2067,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { - *idxDriver = i; + *audio_fct_idx = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2081,7 +2081,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) // p_desc points to the AS interface of alternate setting zero // itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter // Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) { p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor @@ -2094,17 +2094,17 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num) break; + if (as_itf != audio->ep_in_as_intf_num) break; #endif #if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_out_as_intf_num) break; + if (as_itf != audio->ep_out_as_intf_num) break; #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (itf == audio->ep_in_as_intf_num) + if (as_itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; @@ -2116,7 +2116,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf == audio->ep_out_as_intf_num) + if (as_itf == audio->ep_out_as_intf_num) { audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; @@ -2132,24 +2132,24 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num) break; + if (as_itf != audio->ep_in_as_intf_num) break; #endif #if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_out_as_intf_num) break; + if (as_itf != audio->ep_out_as_intf_num) break; #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (itf == audio->ep_in_as_intf_num) + if (as_itf == audio->ep_in_as_intf_num) { audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf == audio->ep_out_as_intf_num) + if (as_itf == audio->ep_out_as_intf_num) { audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } @@ -2167,14 +2167,14 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically -bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) +bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); // Format the feedback value - if (_audiod_fct[itf].rhport == 0) + if (_audiod_fct[audio_fct_idx].rhport == 0) { - uint8_t * fb = (uint8_t *) &_audiod_fct[itf].fb_val; + uint8_t * fb = (uint8_t *) &_audiod_fct[audio_fct_idx].fb_val; // For FS format is 10.14 *(fb++) = (feedback >> 2) & 0xFF; @@ -2186,13 +2186,13 @@ bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) else { // For HS format is 16.16 as originally demanded - _audiod_fct[itf].fb_val = feedback; + _audiod_fct[audio_fct_idx].fb_val = feedback; } // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_fb)) + if (!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_fb)) { - return audiod_fb_send(_audiod_fct[itf].rhport, &_audiod_fct[itf]); + return audiod_fb_send(_audiod_fct[audio_fct_idx].rhport, &_audiod_fct[audio_fct_idx]); } return true; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index f91540b64..2dccc11bc 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -358,33 +358,33 @@ extern "C" { // Application API (Multiple Interfaces) // CFG_TUD_AUDIO > 1 //--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t itf); +bool tud_audio_n_mounted (uint8_t audio_fct_idx); #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t itf); -uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO +uint16_t tud_audio_n_available (uint8_t audio_fct_idx); +uint16_t tud_audio_n_read (uint8_t audio_fct_idx, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_ep_out_ff (uint8_t audio_fct_idx); // Delete all content in the EP OUT FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_rx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); +uint16_t tud_audio_n_read_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +uint16_t tud_audio_n_write (uint8_t audio_fct_idx, const void * data, uint16_t len); +bool tud_audio_n_clear_ep_in_ff (uint8_t audio_fct_idx); // Delete all content in the EP IN FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t audio_fct_idx); // Force all content in the support TX FIFOs to be written into EP SW FIFO +bool tud_audio_n_clear_tx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); +uint16_t tud_audio_n_write_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); +uint16_t tud_audio_int_ctr_n_write (uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ @@ -402,9 +402,9 @@ static inline uint16_t tud_audio_read (void* buffer, uint1 #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); -static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); -static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); +static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); #endif // TX API @@ -416,8 +416,8 @@ static inline bool tud_audio_clear_ep_in_ff (void); #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); -static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); #endif // INT CTR API @@ -439,13 +439,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -454,7 +454,7 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // Value will be corrected for FS to 10.14 format automatically. // (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). // Feedback value will be sent at FB endpoint interval till it's changed. -bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback); +bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback); static inline bool tud_audio_fb_set(uint32_t feedback); #endif @@ -518,19 +518,19 @@ static inline bool tud_audio_clear_ep_out_ff(void) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff(uint8_t channelId) +static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) { - return tud_audio_n_clear_rx_support_ff(0, channelId); + return tud_audio_n_clear_rx_support_ff(0, ff_idx); } -static inline uint16_t tud_audio_available_support_ff(uint8_t channelId) +static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) { - return tud_audio_n_available_support_ff(0, channelId); + return tud_audio_n_available_support_ff(0, ff_idx); } -static inline uint16_t tud_audio_read_support_ff(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) { - return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); + return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); } #endif @@ -558,14 +558,14 @@ static inline uint16_t tud_audio_flush_tx_support_ff(void) return tud_audio_n_flush_tx_support_ff(0); } -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t channelId) +static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) { - return tud_audio_n_clear_tx_support_ff(0, channelId); + return tud_audio_n_clear_tx_support_ff(0, ff_idx); } -static inline uint16_t tud_audio_write_support_ff(uint8_t channelId, const void * data, uint16_t len) +static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) { - return tud_audio_n_write_support_ff(0, channelId, data, len); + return tud_audio_n_write_support_ff(0, ff_idx, data, len); } #endif -- cgit v1.3.1 From 29bcc83d0f9bb132eee24a0585ed3565a3e2eaee Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 21 Apr 2021 17:01:38 +0200 Subject: Remove unnecessary volatile and short audio function index to func_id --- src/class/audio/audio_device.c | 196 ++++++++++++++++++++--------------------- src/class/audio/audio_device.h | 36 ++++---- 2 files changed, 116 insertions(+), 116 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4c6c79e30..0a60d9ee5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -383,11 +383,11 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING @@ -399,10 +399,10 @@ static inline uint8_t tu_desc_subtype(void const* desc) return ((uint8_t const*) desc)[2]; } -bool tud_audio_n_mounted(uint8_t audio_fct_idx) +bool tud_audio_n_mounted(uint8_t func_id) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; + TU_VERIFY(func_id < CFG_TUD_AUDIO); + audiod_function_t* audio = &_audiod_fct[func_id]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; @@ -429,44 +429,44 @@ bool tud_audio_n_mounted(uint8_t audio_fct_idx) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available(uint8_t audio_fct_idx) +uint16_t tud_audio_n_available(uint8_t func_id) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[audio_fct_idx].ep_out_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t audio_fct_idx, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].ep_out_ff, buffer, bufsize); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); } -bool tud_audio_n_clear_ep_out_ff(uint8_t audio_fct_idx) +bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_out_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) +bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_available_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) +uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_read_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx], buffer, bufsize); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); } #endif @@ -682,30 +682,30 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. * - * \param[in] audio_fct_idx: Index of audio function interface + * \param[in] func_id: Index of audio function interface * \param[in] data: Pointer to data array to be copied from * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -uint16_t tud_audio_n_write(uint8_t audio_fct_idx, const void * data, uint16_t len) +uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].ep_in_ff, data, len); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); } -bool tud_audio_n_clear_ep_in_ff(uint8_t audio_fct_idx) // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_in_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t audio_fct_idx) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[func_id]; uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -717,16 +717,16 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t audio_fct_idx) return n_bytes_copied; } -bool tud_audio_n_clear_tx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) +bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx]); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_write_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len) +uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx], data, len); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); } #endif @@ -734,20 +734,20 @@ uint16_t tud_audio_n_write_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, con #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len) +uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr)); + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); // Check length TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - memcpy(_audiod_fct[audio_fct_idx].ep_int_ctr_buf, buffer, len); + memcpy(_audiod_fct[func_id].ep_int_ctr_buf, buffer, len); // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr, _audiod_fct[audio_fct_idx].ep_int_ctr_buf, len)); + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); return true; } @@ -1406,13 +1406,13 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface - uint8_t audio_fct_idx, idxItf; + uint8_t func_id, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[audio_fct_idx].alt_setting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[audio_fct_idx].alt_setting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); return true; } @@ -1433,16 +1433,16 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // 3. Open new EP uint8_t const itf = tu_u16_low(p_request->wIndex); - volatile uint8_t const alt = tu_u16_low(p_request->wValue); + uint8_t const alt = tu_u16_low(p_request->wValue); TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); // Find index of audio streaming interface and index of interface - uint8_t audio_fct_idx, idxItf; + uint8_t func_id, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); - audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; + audiod_function_t* audio = &_audiod_fct[func_id]; // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1548,7 +1548,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1624,7 +1624,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) { - uint8_t audio_fct_idx; + uint8_t func_id; switch (p_request->bmRequestType_bit.recipient) { @@ -1638,10 +1638,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_entity_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { @@ -1654,10 +1654,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_itf_cb) { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { @@ -1675,10 +1675,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_ep_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { @@ -1719,7 +1719,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t audio_fct_idx; + uint8_t func_id; // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) @@ -1732,7 +1732,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1751,7 +1751,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1774,7 +1774,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1796,7 +1796,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf, _audiod_fct[audio_fct_idx].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); return true; } @@ -1825,14 +1825,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 (void) xferred_bytes; // Search for interface belonging to given end point address and proceed as required - uint8_t audio_fct_idx; - for (audio_fct_idx = 0; audio_fct_idx < CFG_TUD_AUDIO; audio_fct_idx++) + uint8_t func_id; + for (func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) { #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // Data transmission of control interrupt finished - if (_audiod_fct[audio_fct_idx].ep_int_ctr == ep_addr) + if (_audiod_fct[func_id].ep_int_ctr == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? @@ -1849,7 +1849,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_fct[audio_fct_idx].ep_in == ep_addr && _audiod_fct[audio_fct_idx].alt_setting != 0) + if (_audiod_fct[func_id].ep_in == ep_addr && _audiod_fct[func_id].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." @@ -1860,7 +1860,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1870,21 +1870,21 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received - if (_audiod_fct[audio_fct_idx].ep_out == ep_addr) + if (_audiod_fct[func_id].ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[audio_fct_idx], (uint16_t) xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[func_id], (uint16_t) xferred_bytes)); return true; } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished - if (_audiod_fct[audio_fct_idx].ep_fb == ep_addr) + if (_audiod_fct[func_id].ep_fb == ep_addr) { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[audio_fct_idx]); + return audiod_fb_send(rhport, &_audiod_fct[func_id]); } #endif #endif @@ -1899,7 +1899,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; // Get corresponding driver index - uint8_t audio_fct_idx; + uint8_t func_id; uint8_t itf = TU_U16_LOW(p_request->wIndex); // Conduct checks which depend on the recipient @@ -1913,12 +1913,12 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); } else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); } break; @@ -1927,7 +1927,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); break; // Unknown/Unsupported recipient @@ -1935,13 +1935,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_fct[audio_fct_idx].ctrl_buf_sz) len = _audiod_fct[audio_fct_idx].ctrl_buf_sz; + if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; // Copy into buffer - memcpy((void *)_audiod_fct[audio_fct_idx].ctrl_buf, data, (size_t)len); + memcpy((void *)_audiod_fct[func_id].ctrl_buf, data, (size_t)len); // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[audio_fct_idx].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); } // This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function @@ -1980,7 +1980,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int) +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; @@ -1988,7 +1988,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct { if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) { - *audio_fct_idx = i; + *func_id = i; return true; } } @@ -1997,7 +1997,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct } // Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx) +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2014,7 +2014,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { - *audio_fct_idx = i; + *func_id = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2024,7 +2024,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * return false; } -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2039,7 +2039,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { - *audio_fct_idx = i; + *func_id = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2049,7 +2049,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) return false; } -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx) +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2067,7 +2067,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { - *audio_fct_idx = i; + *func_id = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2167,14 +2167,14 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically -bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback) +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value - if (_audiod_fct[audio_fct_idx].rhport == 0) + if (_audiod_fct[func_id].rhport == 0) { - uint8_t * fb = (uint8_t *) &_audiod_fct[audio_fct_idx].fb_val; + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; // For FS format is 10.14 *(fb++) = (feedback >> 2) & 0xFF; @@ -2186,13 +2186,13 @@ bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback) else { // For HS format is 16.16 as originally demanded - _audiod_fct[audio_fct_idx].fb_val = feedback; + _audiod_fct[func_id].fb_val = feedback; } // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_fb)) + if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) { - return audiod_fb_send(_audiod_fct[audio_fct_idx].rhport, &_audiod_fct[audio_fct_idx]); + return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); } return true; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2dccc11bc..c070e48c2 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -358,33 +358,33 @@ extern "C" { // Application API (Multiple Interfaces) // CFG_TUD_AUDIO > 1 //--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t audio_fct_idx); +bool tud_audio_n_mounted (uint8_t func_id); #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t audio_fct_idx); -uint16_t tud_audio_n_read (uint8_t audio_fct_idx, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t audio_fct_idx); // Delete all content in the EP OUT FIFO +uint16_t tud_audio_n_available (uint8_t func_id); +uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); +uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t audio_fct_idx, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t audio_fct_idx); // Delete all content in the EP IN FIFO +uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); +bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t audio_fct_idx); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len); +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO +bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); +uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len); +uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ @@ -439,13 +439,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -454,7 +454,7 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // Value will be corrected for FS to 10.14 format automatically. // (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). // Feedback value will be sent at FB endpoint interval till it's changed. -bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback); +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); static inline bool tud_audio_fb_set(uint32_t feedback); #endif -- cgit v1.3.1 From 01661b3f281c4e044a370b33bf6617b8d2481407 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 14:56:52 -0400 Subject: Replace dfu_mode with dfu --- src/class/dfu/dfu.h | 24 +- src/class/dfu/dfu_device.c | 594 ++++++++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_device.h | 131 +++++++++ src/class/dfu/dfu_mode_device.c | 594 ---------------------------------------- src/class/dfu/dfu_mode_device.h | 131 --------- src/tusb.h | 2 +- 6 files changed, 738 insertions(+), 738 deletions(-) create mode 100644 src/class/dfu/dfu_device.c create mode 100644 src/class/dfu/dfu_device.h delete mode 100644 src/class/dfu/dfu_mode_device.c delete mode 100644 src/class/dfu/dfu_mode_device.h (limited to 'src/class') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 2040e415c..af08a29f7 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -73,7 +73,7 @@ typedef enum { DFU_MANIFEST_WAIT_RESET = 8, DFU_UPLOAD_IDLE = 9, DFU_ERROR = 10, -} dfu_mode_state_t; +} dfu_state_t; // DFU Status typedef enum { @@ -93,7 +93,7 @@ typedef enum { DFU_STATUS_ERRPOR = 0x0D, DFU_STATUS_ERRUNKNOWN = 0x0E, DFU_STATUS_ERRSTALLEDPKT = 0x0F, -} dfu_mode_device_status_t; +} dfu_device_status_t; #define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) #define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) @@ -134,7 +134,7 @@ static tu_lookup_table_t const _dfu_request_table = .items = _dfu_request_lookup }; -static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +static tu_lookup_entry_t const _dfu_state_lookup[] = { { .key = APP_IDLE , .data = "APP_IDLE" }, { .key = APP_DETACH , .data = "APP_DETACH" }, @@ -149,13 +149,13 @@ static tu_lookup_entry_t const _dfu_mode_state_lookup[] = { .key = DFU_ERROR , .data = "DFU_ERROR" }, }; -static tu_lookup_table_t const _dfu_mode_state_table = +static tu_lookup_table_t const _dfu_state_table = { - .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), - .items = _dfu_mode_state_lookup + .count = TU_ARRAY_SIZE(_dfu_state_lookup), + .items = _dfu_state_lookup }; -static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +static tu_lookup_entry_t const _dfu_status_lookup[] = { { .key = DFU_STATUS_OK , .data = "OK" }, { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, @@ -175,10 +175,10 @@ static tu_lookup_entry_t const _dfu_mode_status_lookup[] = { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, }; -static tu_lookup_table_t const _dfu_mode_status_table = +static tu_lookup_table_t const _dfu_status_table = { - .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), - .items = _dfu_mode_status_lookup + .count = TU_ARRAY_SIZE(_dfu_status_lookup), + .items = _dfu_status_lookup }; #endif @@ -186,8 +186,8 @@ static tu_lookup_table_t const _dfu_mode_status_table = #define dfu_debug_print_context() \ { \ TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ + tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \ } diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c new file mode 100644 index 000000000..98213d320 --- /dev/null +++ b/src/class/dfu/dfu_device.c @@ -0,0 +1,594 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) + +#include "dfu_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_device_status_t status; + dfu_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_state_ctx_t; + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; + + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_moded_init(void) +{ + _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = 0; + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + + dfu_debug_print_context(); +} + +void dfu_moded_reset(uint8_t rhport) +{ + if (_dfu_state_ctx.state == APP_DETACH) + { + _dfu_state_ctx.state = DFU_IDLE; + } else { + if ( tud_dfu_usb_reset_cb ) + { + tud_dfu_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + } + } + + if(_dfu_state_ctx.state == APP_IDLE) + { + tud_dfu_reboot_to_rt_cb(); + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + dfu_debug_print_context(); +} + +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + (void) max_len; + + // Ensure this is DFU Mode + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint16_t drv_len = sizeof(tusb_desc_interface_t); + + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: + { + return dfu_state_machine(rhport, request); + } + break; + + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_req_nonstandard_cb ) ? tud_dfu_req_nonstandard_cb(rhport, stage, request) : false; + } + break; + } + + return true; +} + +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) +{ + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_get_poll_timeout_cb ) + { + tud_dfu_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_get_status_desc_table_index_cb ) ? tud_dfu_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); +} + +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_get_poll_timeout_cb ) + { + tud_dfu_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); + + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; +} + +void tud_dfu_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_abort_cb ) + { + tud_dfu_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_abort_cb) + { + tud_dfu_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + + return true; +} + + +#endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h new file mode 100644 index 000000000..3bc1f4ae4 --- /dev/null +++ b/src/class/dfu/dfu_device.h @@ -0,0 +1,131 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_DEVICE_H_ +#define _TUSB_DFU_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_firmware_valid_check_cb(void); + +// Invoked when the device must reboot to dfu runtime mode +void tud_dfu_reboot_to_rt_cb(void); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_init_attrs_cb(void); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); + +// Invoked during a USB reset +// Lets the app perform custom behavior on a USB reset. +// If not defined, the default behavior remains the DFU specification of +// Checking the firmware valid and changing to the error state or rebooting to runtime +// Note: If used, the application must perform the reset logic for all states. +// Changing the state to APP_IDLE will result in tud_dfu_reboot_to_rt_cb being called +TU_ATTR_WEAK void tud_dfu_usb_reset_cb(uint8_t rhport, dfu_state_t *state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_poll_timeout_done(void); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_device_data_done_check_cb(void); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_abort_cb(void); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); + +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_moded_init(void); +void dfu_moded_reset(uint8_t rhport); +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c deleted file mode 100644 index 5f8c714c0..000000000 --- a/src/class/dfu/dfu_mode_device.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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 file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) - -#include "dfu_mode_device.h" -#include "device/usbd_pvt.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; - bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; -} dfu_mode_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_mode_state_ctx_t _dfu_state_ctx; - - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request); - - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void) -{ - _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = 0; - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - - dfu_debug_print_context(); -} - -void dfu_moded_reset(uint8_t rhport) -{ - if (_dfu_state_ctx.state == APP_DETACH) - { - _dfu_state_ctx.state = DFU_IDLE; - } else { - if ( tud_dfu_mode_usb_reset_cb ) - { - tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); - } else { - switch (_dfu_state_ctx.state) - { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; - } - } - } - - if(_dfu_state_ctx.state == APP_IDLE) - { - tud_dfu_mode_reboot_to_rt_cb(); - } - - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - dfu_debug_print_context(); -} - -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - // Ensure this is DFU Mode - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) - { - dfu_mode_req_dnload_reply(rhport, request); - return true; - } - - // nothing to do with any other DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) - { - tud_control_status(rhport, request); - return true; - } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - case DFU_REQUEST_DNLOAD: - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - return dfu_mode_state_machine(rhport, request); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_mode_req_nonstandard_cb ) ? tud_dfu_mode_req_nonstandard_cb(rhport, stage, request) : false; - } - break; - } - - return true; -} - -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_mode_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); - return retval; -} - -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_status_req_payload_t resp; - - resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_mode_get_poll_timeout_cb ) - { - tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_mode_get_status_desc_table_index_cb ) ? tud_dfu_mode_get_status_desc_table_index_cb() : 0; - - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); -} - -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); -} - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); -} - -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_mode_get_poll_timeout_cb ) - { - tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_mode_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_mode_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); - _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; -} - -void tud_dfu_mode_poll_timeout_done() -{ - if (_dfu_state_ctx.state == DFU_DNBUSY) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) - { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } -} - -static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); - - switch (_dfu_state_ctx.state) - { - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - ; // do nothing, but don't stall so continue on - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ( _dfu_state_ctx.blk_transfer_in_proc ) - { - _dfu_state_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); - } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_mode_device_data_done_check_cb() ) - { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if ( tud_dfu_mode_abort_cb ) - { - tud_dfu_mode_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) - { - _dfu_state_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); - } else { - if ( tud_dfu_mode_firmware_valid_check_cb() ) - { - _dfu_state_ctx.state = DFU_IDLE; - } - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST: - { - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_UPLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_state_ctx.state = DFU_IDLE; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if (tud_dfu_mode_abort_cb) - { - tud_dfu_mode_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_ERROR: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_CLRSTATUS: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - default: - _dfu_state_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error - } - - return true; -} - - -#endif diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h deleted file mode 100644 index c25910b23..000000000 --- a/src/class/dfu/dfu_mode_device.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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 file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_MODE_DEVICE_H_ -#define _TUSB_DFU_MODE_DEVICE_H_ - -#include "common/tusb_common.h" -#include "device/usbd.h" -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when a reset is received to check if firmware is valid -bool tud_dfu_mode_firmware_valid_check_cb(void); - -// Invoked when the device must reboot to dfu runtime mode -void tud_dfu_mode_reboot_to_rt_cb(void); - -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_mode_init_attrs_cb(void); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); - -// Invoked during a USB reset -// Lets the app perform custom behavior on a USB reset. -// If not defined, the default behavior remains the DFU specification of -// Checking the firmware valid and changing to the error state or rebooting to runtime -// Note: If used, the application must perform the reset logic for all states. -// Changing the state to APP_IDLE will result in tud_dfu_mode_reboot_to_rt_cb being called -TU_ATTR_WEAK void tud_dfu_mode_usb_reset_cb(uint8_t rhport, dfu_mode_state_t *state); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_mode_poll_timeout_done(void); - -// Invoked when a DFU_DNLOAD request is received -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_mode_device_data_done_check_cb(void); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_mode_abort_cb(void); - -// Invoked when a DFU_UPLOAD request is received -// This callback must populate data with up to length bytes -// Return the number of bytes to write -uint16_t tud_dfu_mode_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); - -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void); -void dfu_moded_reset(uint8_t rhport); -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/tusb.h b/src/tusb.h index c9558515c..56504550c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -97,7 +97,7 @@ #endif #if CFG_TUD_DFU_MODE - #include "class/dfu/dfu_mode_device.h" + #include "class/dfu/dfu_device.h" #endif #if CFG_TUD_NET -- cgit v1.3.1 From 88dea7a0a8f7cb1bc21eaa45a3abb9a912b030d6 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 15:02:50 -0400 Subject: Move debug from .h to .c --- src/class/dfu/dfu.h | 80 ------------------------------------------- src/class/dfu/dfu_device.c | 77 +++++++++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_rt_device.c | 9 +++-- 3 files changed, 84 insertions(+), 82 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index af08a29f7..18de3bf99 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -111,86 +111,6 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "DFU_IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "DFU_ERROR" }, -}; - -static tu_lookup_table_t const _dfu_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_state_lookup), - .items = _dfu_state_lookup -}; - -static tu_lookup_entry_t const _dfu_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, - { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_status_lookup), - .items = _dfu_status_lookup -}; - -#endif - -#define dfu_debug_print_context() \ -{ \ - TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \ -} - - #ifdef __cplusplus } #endif diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 98213d320..f3763adc7 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -61,6 +61,83 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_state_lookup), + .items = _dfu_state_lookup +}; + +static tu_lookup_entry_t const _dfu_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_status_lookup), + .items = _dfu_status_lookup +}; + +#endif + +#define dfu_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \ +} //--------------------------------------------------------------------+ // USBD Driver API diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 9da2e1e4f..faeae9b68 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -93,11 +93,11 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - TU_LOG2(" DFU RT Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: { + TU_LOG2(" DFU RT Request: DETACH\r\n"); tud_control_status(rhport, request); tud_dfu_runtime_reboot_to_dfu_cb(); } @@ -105,6 +105,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request case DFU_REQUEST_GETSTATUS: { + TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); dfu_status_req_payload_t resp; // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); @@ -112,7 +113,11 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request } break; - default: return false; // stall unsupported request + default: + { + TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); + return false; // stall unsupported request + } } return true; -- cgit v1.3.1 From 0936a76dc905a104f03cd1135fc22a8652ee8c7f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 15:59:49 -0400 Subject: Remove nonstd behaviour --- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f3763adc7..85e884d0d 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -269,7 +269,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque default: { TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_req_nonstandard_cb ) ? tud_dfu_req_nonstandard_cb(rhport, stage, request) : false; + return false; // stall unsupported request } break; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 3bc1f4ae4..28a241b3a 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -107,11 +107,6 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Return the number of bytes to write uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); -- cgit v1.3.1 From 18e9d253e986670f77a0f15f687eec258011605f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:04:09 -0400 Subject: Remove usb reset callback --- src/class/dfu/dfu_device.c | 39 +++++++++++++++++---------------------- src/class/dfu/dfu_device.h | 8 -------- 2 files changed, 17 insertions(+), 30 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 85e884d0d..085c2b455 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -160,32 +160,27 @@ void dfu_moded_reset(uint8_t rhport) { _dfu_state_ctx.state = DFU_IDLE; } else { - if ( tud_dfu_usb_reset_cb ) + switch (_dfu_state_ctx.state) { - tud_dfu_usb_reset_cb(rhport, &_dfu_state_ctx.state); - } else { - switch (_dfu_state_ctx.state) + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; + _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; } + break; } } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 28a241b3a..e92935fd7 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -58,14 +58,6 @@ uint8_t tud_dfu_init_attrs_cb(void); // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); -// Invoked during a USB reset -// Lets the app perform custom behavior on a USB reset. -// If not defined, the default behavior remains the DFU specification of -// Checking the firmware valid and changing to the error state or rebooting to runtime -// Note: If used, the application must perform the reset logic for all states. -// Changing the state to APP_IDLE will result in tud_dfu_reboot_to_rt_cb being called -TU_ATTR_WEAK void tud_dfu_usb_reset_cb(uint8_t rhport, dfu_state_t *state); - // Invoked during a DFU_GETSTATUS request to set the timeout in ms to use // before the subsequent DFU_GETSTATUS requests. // The purpose of this value is to allow the device to tell the host -- cgit v1.3.1 From 289af581bb796f730324ac663b3f20d57d03e487 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:06:06 -0400 Subject: Remove uunused code --- src/class/dfu/dfu_device.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index e92935fd7..322cc6496 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -45,15 +45,6 @@ bool tud_dfu_firmware_valid_check_cb(void); // Invoked when the device must reboot to dfu runtime mode void tud_dfu_reboot_to_rt_cb(void); -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_init_attrs_cb(void); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); -- cgit v1.3.1 From e54d9d10af40f4d83410f1e9cd94c47138c7fe7f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:39:43 -0400 Subject: Add const --- src/class/dfu/dfu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 085c2b455..ed7d381f0 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -158,7 +158,7 @@ void dfu_moded_reset(uint8_t rhport) { if (_dfu_state_ctx.state == APP_DETACH) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.state = DFU_IDLE; } else { switch (_dfu_state_ctx.state) { @@ -210,7 +210,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { - tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; drv_len += tu_desc_len(p_desc); -- cgit v1.3.1 From cc440ade81a72df3a605e0abc427a284b8bbc424 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:47:05 -0400 Subject: Remove custom status description table --- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ed7d381f0..f0a90073b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -292,7 +292,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); } resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_get_status_desc_table_index_cb ) ? tud_dfu_get_status_desc_table_index_cb() : 0; + resp.iString = 0; tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 322cc6496..d19115555 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -90,9 +90,6 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Return the number of bytes to write uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 8c80ddeb542007efd547eced028d9bb3e933d434 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 17:00:57 -0400 Subject: Fix statte check on DATA stage --- src/class/dfu/dfu_device.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f0a90073b..59369a78f 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -58,7 +58,7 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_dnload_reply(void); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ @@ -225,9 +225,9 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + if ( (stage == CONTROL_STAGE_DATA) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC) ) { - dfu_req_dnload_reply(rhport, request); + dfu_req_dnload_reply(); return true; } @@ -314,7 +314,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); } -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +static void dfu_req_dnload_reply(void) { uint8_t bwPollTimeout[3] = {0,0,0}; @@ -333,7 +333,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * _dfu_state_ctx.last_transfer_len = 0; } -void tud_dfu_poll_timeout_done() +void tud_dfu_poll_timeout_done(void) { if (_dfu_state_ctx.state == DFU_DNBUSY) { -- cgit v1.3.1 From b8e5885c2b97725e30ff57e6adc8cb7696711f28 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 17:45:33 -0400 Subject: Removes polltimeout behaviour and restructures Moves dfu_req_dnload_reply to ACK stage of a DNREQUEST. Removes unneeded variables due to other simplifications. --- src/class/dfu/dfu_device.c | 78 ++++++++++++++++++---------------------------- src/class/dfu/dfu_device.h | 28 +++-------------- 2 files changed, 34 insertions(+), 72 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 59369a78f..25588aabc 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -44,10 +44,6 @@ typedef struct TU_ATTR_PACKED dfu_state_t state; uint8_t attrs; bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -58,7 +54,7 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_req_dnload_reply(void); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ @@ -148,8 +144,6 @@ void dfu_moded_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } @@ -191,8 +185,6 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } @@ -225,23 +217,20 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC) ) - { - dfu_req_dnload_reply(); - return true; - } - - // nothing to do with any other DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; + // nothing to do with DATA stage + if ( stage == CONTROL_STAGE_DATA ) return true; TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) + if(stage == CONTROL_STAGE_SETUP) { - tud_control_status(rhport, request); - return true; + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } } // Handle class request only from here @@ -249,15 +238,27 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque switch (request->bRequest) { - case DFU_REQUEST_DETACH: case DFU_REQUEST_DNLOAD: + { + if ( (stage == CONTROL_STAGE_ACK) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) + { + dfu_req_dnload_reply(rhport, request); + return true; + } + } // fallthrough + case DFU_REQUEST_DETACH: case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: case DFU_REQUEST_GETSTATE: case DFU_REQUEST_ABORT: { - return dfu_state_machine(rhport, request); + if(stage == CONTROL_STAGE_SETUP) + { + return dfu_state_machine(rhport, request); + } } break; @@ -285,12 +286,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const dfu_status_req_payload_t resp; resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_get_poll_timeout_cb ) - { - tud_dfu_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); resp.bState = _dfu_state_ctx.state; resp.iString = 0; @@ -304,8 +300,6 @@ static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application @@ -314,26 +308,14 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); } -static void dfu_req_dnload_reply(void) +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_get_poll_timeout_cb ) - { - tud_dfu_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + (void) rhport; + tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; } -void tud_dfu_poll_timeout_done(void) +void tud_dfu_dnload_complete(void) { if (_dfu_state_ctx.state == DFU_DNBUSY) { diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d19115555..0c567ff45 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -45,36 +45,16 @@ bool tud_dfu_firmware_valid_check_cb(void); // Invoked when the device must reboot to dfu runtime mode void tud_dfu_reboot_to_rt_cb(void); -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_poll_timeout_done(void); - // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); +// Must be called when the application is done using the last block of data +// provided by tud_dfu_req_dnload_data_cb +void tud_dfu_dnload_complete(void); + // Invoked during the last DFU_DNLOAD request, signifying that the host believes // it is done transmitting data. // Return true if the application agrees there is no more data -- cgit v1.3.1 From 03f974c9b92bf9e0fc6e74ab4d15ad77a4a8b339 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:27:48 +0200 Subject: Implement functions to allow for DMA usage in audio driver. - Add tud_audio_n_get_ep_out_ff(), tud_audio_n_get_ep_in_ff(), tud_audio_n_get_rx_support_ff(), and tud_audio_n_get_tx_support_ff() - Change get_linear_read/write_info() to return linear and wrapped part at once - Adjusted affected code in audio_device.c and tested with audio_4_channel. --- src/class/audio/audio_device.c | 77 ++++++++++++++++----------- src/class/audio/audio_device.h | 29 ++++++++++ src/common/tusb_fifo.c | 35 +++++++----- src/common/tusb_fifo.h | 6 ++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 +- 5 files changed, 103 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0a60d9ee5..f96878b5b 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -447,27 +447,39 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); } +tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; + return NULL; +} + #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); } + +tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; + return NULL; +} #endif // This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). @@ -635,32 +647,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t cnt_ff; // Decode - void * dst; + void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len; + uint16_t len, len_wrap; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead); - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead, &dst, &len_wrap, &dst_wrap); dst_end = dst + len; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len < nBytesPerFFToRead) + if (len_wrap != 0) { - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead - len); - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - - dst_end = dst + len; - - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); + dst_end = dst_wrap + len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst_wrap, dst_end, src, n_ff_used); } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len + len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -699,9 +705,16 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Del return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); } +tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; + return NULL; +} + #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); @@ -719,15 +732,22 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // For bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); } uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); } + +tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; + return NULL; +} + #endif @@ -751,6 +771,7 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1 return true; } + #endif @@ -952,32 +973,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode - void * src; + void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len; + uint16_t len, len_wrap; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend, &src, &len_wrap, &src_wrap); src_end = src + len; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len < nBytesPerFFToSend) + if (len_wrap != 0) { - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend - len); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - - src_end = src + len; - - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); + src_end = src_wrap + len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src_wrap, src_end, dst, n_ff_used); } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len + len_wrap); } return nBytesPerFFToSend * n_ff_used; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c070e48c2..66cc29739 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,6 +33,7 @@ #include "device/usbd.h" #include "audio.h" +#include "tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration @@ -364,23 +365,27 @@ bool tud_audio_n_mounted (uint8_t func_id); uint16_t tud_audio_n_available (uint8_t func_id); uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO +tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); +tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO +tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); +tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -399,12 +404,14 @@ static inline bool tud_audio_mounted (void); static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); #endif // TX API @@ -412,12 +419,14 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, voi #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); +static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); +static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); #endif // INT CTR API @@ -514,6 +523,11 @@ static inline bool tud_audio_clear_ep_out_ff(void) return tud_audio_n_clear_ep_out_ff(0); } +static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) +{ + return tud_audio_n_get_ep_out_ff(0); +} + #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING @@ -533,6 +547,11 @@ static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, u return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); } +static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_rx_support_ff(0, ff_idx); +} + #endif // TX API @@ -549,6 +568,11 @@ static inline bool tud_audio_clear_ep_in_ff(void) return tud_audio_n_clear_ep_in_ff(0); } +static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) +{ + return tud_audio_n_get_ep_in_ff(0); +} + #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING @@ -568,6 +592,11 @@ static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * d return tud_audio_n_write_support_ff(0, ff_idx, data, len); } +static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_tx_support_ff(0, ff_idx); +} + #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 098d54801..3bca8397b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -905,7 +905,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) +uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -933,23 +933,26 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, w = get_relative_pointer(f, w, 0); r = get_relative_pointer(f, r, offset); + // Copy pointer to buffer to start reading from + *ptr_lin = &f->buffer[r]; + *ptr_wrap = f->buffer; + // Check if there is a wrap around necessary uint16_t len; if (w > r) { + // Non wrapping case len = w - r; + len = tu_min16(n, len); // Limit to required length + *len_wrap = 0; } else { len = f->depth - r; // Also the case if FIFO was full + len = tu_min16(n, len); + *len_wrap = n-len; // n was already limited to what is available } - // Limit to required length - len = tu_min16(n, len); - - // Copy pointer to buffer to start reading from - *ptr = &f->buffer[r]; - return len; } @@ -976,7 +979,7 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) +uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); @@ -1004,22 +1007,26 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr // Get relative pointers w = get_relative_pointer(f, w, offset); r = get_relative_pointer(f, r, 0); + + // Copy pointer to buffer to start writing to + *ptr_lin = &f->buffer[w]; + *ptr_wrap = f->buffer; // Always start of buffer + uint16_t len; if (w < r) { + // Non wrapping case len = r-w; + len = tu_min16(n, len); // Limit to required length + *len_wrap = 0; } else { len = f->depth - w; + len = tu_min16(n, len); // Limit to required length + *len_wrap = n-len; // Remaining length - n already was limited to free or FIFO depth } - // Limit to required length - len = tu_min16(n, len); - - // Copy pointer to buffer to start reading from - *ptr = &f->buffer[w]; - return len; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b2d0b5be9..28998ad24 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -134,8 +134,10 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. // In case not all of your data is available within one read/write, update the read/write pointer by // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation -uint16_t tu_fifo_get_linear_read_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); -uint16_t tu_fifo_get_linear_write_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); +// TODO - update comments + +uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); +uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index b8b0fc104..dd0d76c1f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -993,7 +993,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part void * src; - uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO + uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO - THIS FUNCTION CHANGED!!! TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA tu_fifo_advance_read_pointer(ff, len); @@ -1075,7 +1075,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part void * dst; - uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); + uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); // THIS FUNCTION CHANGED!!!! TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); tu_fifo_advance_write_pointer(ff, len); -- cgit v1.3.1 From 4dd1f1f3b50592d71fefcd8fb149322fad5a8493 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:32:22 +0200 Subject: Fix include path in audio_device.h --- src/class/audio/audio_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 66cc29739..c5f8967e4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,7 @@ #include "device/usbd.h" #include "audio.h" -#include "tusb_fifo.h" +#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration -- cgit v1.3.1 From a98d0217a05129b36d2eef76f36b986c31f84e92 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:47:22 +0200 Subject: Init len_wrap = 0 to fix compiler complains. --- src/class/audio/audio_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f96878b5b..4fdb58333 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -650,7 +650,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len, len_wrap; + uint16_t len, len_wrap = 0; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { @@ -976,7 +976,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len, len_wrap; + uint16_t len, len_wrap = 0; // Give len_wrap a value such that compiler does not complain - although it gets initialized in any case... for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { -- cgit v1.3.1 From 7072f0155e994005d8a0ccf5658f765df8a443b8 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 11:48:54 +0200 Subject: Change tu_fifo_get_linear_write/read_info() to return a struct Compilers always complain that variables set by function via pointer might be uninitialized so to avoid that return values are now delivered via struct. --- src/class/audio/audio_device.c | 36 +++++++++++++++--------------- src/common/tusb_fifo.c | 50 +++++++++++++++++++----------------------- src/common/tusb_fifo.h | 12 ++++++++-- 3 files changed, 51 insertions(+), 47 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4fdb58333..25bf9e2d9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -647,26 +647,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t cnt_ff; // Decode - void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len, len_wrap = 0; + + tu_fifo_linear_wr_info info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead, &dst, &len_wrap, &dst_wrap); + info = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead); - dst_end = dst + len; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len_wrap != 0) + if (info.len_wrap != 0) { - dst_end = dst_wrap + len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst_wrap, dst_end, src, n_ff_used); + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len + len_wrap); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -973,28 +973,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode - void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len, len_wrap = 0; // Give len_wrap a value such that compiler does not complain - although it gets initialized in any case... + + tu_fifo_linear_wr_info info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend, &src, &len_wrap, &src_wrap); + info = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend); - src_end = src + len; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); + src_end = info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len_wrap != 0) + if (info.len_wrap != 0) { - src_end = src_wrap + len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src_wrap, src_end, dst, n_ff_used); + src_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); } - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len + len_wrap); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } return nBytesPerFFToSend * n_ff_used; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 3bca8397b..75dae0906 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -905,7 +905,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) +tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -922,8 +922,10 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, cnt = f->depth; } + tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; + if (cnt == 0 || offset >= cnt) return info; // Check if we can read something at and after offset - if too less is available we read what remains cnt -= offset; @@ -934,26 +936,22 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, r = get_relative_pointer(f, r, offset); // Copy pointer to buffer to start reading from - *ptr_lin = &f->buffer[r]; - *ptr_wrap = f->buffer; + info.ptr_lin = &f->buffer[r]; + info.ptr_wrap = f->buffer; // Check if there is a wrap around necessary - uint16_t len; - if (w > r) { // Non wrapping case - len = w - r; - len = tu_min16(n, len); // Limit to required length - *len_wrap = 0; + info.len_lin = tu_min16(n, w - r); // Limit to required length + info.len_wrap = 0; } else { - len = f->depth - r; // Also the case if FIFO was full - len = tu_min16(n, len); - *len_wrap = n-len; // n was already limited to what is available + info.len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full + info.len_wrap = n-info.len_lin; // n was already limited to what is available } - return len; + return info; } /******************************************************************************/ @@ -979,11 +977,13 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) +tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); + tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + if (!f->overwritable) { // Not overwritable limit up to full @@ -992,7 +992,7 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n else if (n >= f->depth) { // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - TU_VERIFY(n <= 2*f->depth); + if(n > 2*f->depth) return info; n = f->depth; // We start writing at the read pointer's position since we fill the complete @@ -1002,31 +1002,27 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n } // Check if there is room to write to - if (free == 0 || offset >= free) return 0; + if (free == 0 || offset >= free) return info; // Get relative pointers w = get_relative_pointer(f, w, offset); r = get_relative_pointer(f, r, 0); // Copy pointer to buffer to start writing to - *ptr_lin = &f->buffer[w]; - *ptr_wrap = f->buffer; // Always start of buffer - - uint16_t len; + info.ptr_lin = &f->buffer[w]; + info.ptr_wrap = f->buffer; // Always start of buffer if (w < r) { // Non wrapping case - len = r-w; - len = tu_min16(n, len); // Limit to required length - *len_wrap = 0; + info.len_lin = tu_min16(n, r-w); // Limit to required length + info.len_wrap = 0; } else { - len = f->depth - w; - len = tu_min16(n, len); // Limit to required length - *len_wrap = n-len; // Remaining length - n already was limited to free or FIFO depth + info.len_lin = tu_min16(n, f->depth - w); // Limit to required length + info.len_wrap = n-info.len_lin; // Remaining length - n already was limited to free or FIFO depth } - return len; + return info; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 28998ad24..c23f25723 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -80,6 +80,14 @@ typedef struct } tu_fifo_t; +typedef struct +{ + uint16_t len_lin ; ///< linear length in item size + uint16_t len_wrap ; ///< wrapped length in item size + void * ptr_lin ; ///< linear part start pointer + void * ptr_wrap ; ///< wrapped part start pointer +} tu_fifo_linear_wr_info; + #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ { \ .buffer = _buffer, \ @@ -136,8 +144,8 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); +tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n); +tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { -- cgit v1.3.1 From c26875e70d120f564f4e68c1dc79d9e7e3642b70 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 26 Apr 2021 17:42:49 +0700 Subject: add TUP_MCU_STRICT_ALIGN macro that manually pick bytes for lpc55 port1 that is m4 but cannot unaligned acces on usb ram --- src/class/msc/msc_device.c | 19 ++++---------- src/common/tusb_common.h | 63 ++++++++++++++++++++++++++++++++++++++-------- src/tusb_option.h | 11 ++++++++ 3 files changed, 69 insertions(+), 24 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 194f4d3cb..539941935 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -77,28 +77,19 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); static inline uint32_t rdwr10_get_lba(uint8_t const command[]) { - // read10 & write10 has the same format - scsi_write10_t* p_rdwr10 = (scsi_write10_t*) command; + // use offsetof to avoid pointer to the odd/unaligned address + uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); - // copy first to prevent mis-aligned access - uint32_t lba; - // use offsetof to avoid pointer to the odd/misaligned address - memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); - - // lba is in Big Endian format + // lba is in Big Endian return tu_ntohl(lba); } static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) { - // read10 & write10 has the same format - scsi_write10_t* p_rdwr10 = (scsi_write10_t*) command; - - // copy first to prevent mis-aligned access - uint16_t block_count; // use offsetof to avoid pointer to the odd/misaligned address - memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); + uint16_t const block_count = tu_unaligned_read16(command + offsetof(scsi_write10_t, block_count)); + // block count is in Big Endian return tu_ntohs(block_count); } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 705ff867c..2cc12c6be 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -47,13 +47,13 @@ #define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16) #define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16) -#define U32_B1_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB -#define U32_B2_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) -#define U32_B3_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) -#define U32_B4_U8(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB +#define TU_U32_BYTE3(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB +#define TU_U32_BYTE2(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) +#define TU_U32_BYTE1(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) +#define TU_U32_BYTE0(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB -#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32) -#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32) +#define U32_TO_U8S_BE(u32) TU_U32_BYTE3(u32), TU_U32_BYTE2(u32), TU_U32_BYTE1(u32), TU_U32_BYTE0(u32) +#define U32_TO_U8S_LE(u32) TU_U32_BYTE0(u32), TU_U32_BYTE1(u32), TU_U32_BYTE2(u32), TU_U32_BYTE3(u32) #define TU_BIT(n) (1U << (n)) @@ -81,9 +81,9 @@ #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) //------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { - return ( ((uint32_t) b1) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b3) << 8) | b4; + return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) @@ -91,8 +91,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) return (uint16_t) ((((uint16_t) high) << 8) | low); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) (((uint16_t) (u16 >> 8)) & 0x00ff); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t u32) { return TU_U32_BYTE3(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t u32) { return TU_U32_BYTE2(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t u32) { return TU_U32_BYTE1(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t u32) { return TU_U32_BYTE0(u32); } + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return TU_U16_HIGH(u16); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return TU_U16_LOW(u16); } //------------- Bits -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } @@ -141,6 +146,8 @@ static inline uint8_t tu_log2(uint32_t value) //------------- Unaligned Access -------------// #if TUP_ARCH_STRICT_ALIGN +// Rely on compiler to generate correct code for unaligned access + typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; @@ -168,8 +175,44 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_ ua16->val = value; } +#elif TUP_MCU_STRICT_ALIGN + +// MCU such as LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM although it is ARM M4. +// We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code +// NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code +// TODO Big Endian may need minor changes +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) +{ + volatile uint8_t const* buf8 = (uint8_t const*) mem; + return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) +{ + volatile uint8_t* buf8 = (uint8_t*) mem; + buf8[0] = tu_u32_byte0(value); + buf8[1] = tu_u32_byte1(value); + buf8[2] = tu_u32_byte2(value); + buf8[3] = tu_u32_byte3(value); +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) +{ + volatile uint8_t const* buf8 = (uint8_t const*) mem; + return tu_u16(buf8[1], buf8[0]); +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) +{ + volatile uint8_t* buf8 = (uint8_t*) mem; + buf8[0] = tu_u16_low(value); + buf8[1] = tu_u16_high(value); +} + + #else +// MCU that could access unaligned memory natively TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem ) { return *((uint32_t*) mem); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem ) { return *((uint16_t*) mem); } diff --git a/src/tusb_option.h b/src/tusb_option.h index 9fcc6c565..b59c7cb22 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -283,6 +283,7 @@ // TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory + // ARMv7+ (M3-M7, M23-M33) can access unaligned memory #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) #define TUP_ARCH_STRICT_ALIGN 0 @@ -290,6 +291,16 @@ #define TUP_ARCH_STRICT_ALIGN 1 #endif +// TUP_MCU_STRICT_ALIGN will overwrite TUP_ARCH_STRICT_ALIGN. +// In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler +// to generate unaligned access code. +// LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM +#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) + #define TUP_MCU_STRICT_ALIGN 1 +#else + #define TUP_MCU_STRICT_ALIGN 0 +#endif + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -- cgit v1.3.1 From c9177246d25b8bd6972a947da4f6d5a39f86f7c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 28 Apr 2021 12:31:24 +0700 Subject: temporarily fix include recusrive loop --- src/class/audio/audio_device.c | 4 ++-- src/class/audio/audio_device.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 25bf9e2d9..8615b2468 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -55,9 +55,9 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "audio_device.h" -#include "class/audio/audio.h" #include "device/usbd_pvt.h" +#include "audio_device.h" +//#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c5f8967e4..b8e6ef9c0 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,6 @@ #include "device/usbd.h" #include "audio.h" -#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration -- cgit v1.3.1 From f830800d00520ed2a91d9095e77738f4558324b2 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 29 Apr 2021 16:04:18 -0400 Subject: Fix typo and clean up reset --- src/class/dfu/dfu_device.c | 44 ++++++-------------------------------------- src/class/dfu/dfu_device.h | 3 --- 2 files changed, 6 insertions(+), 41 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 25588aabc..da9f189aa 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -140,7 +140,7 @@ static tu_lookup_table_t const _dfu_status_table = //--------------------------------------------------------------------+ void dfu_moded_init(void) { - _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE + _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; @@ -150,39 +150,7 @@ void dfu_moded_init(void) void dfu_moded_reset(uint8_t rhport) { - if (_dfu_state_ctx.state == APP_DETACH) - { - _dfu_state_ctx.state = DFU_IDLE; - } else { - switch (_dfu_state_ctx.state) - { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; - } - } - - if(_dfu_state_ctx.state == APP_IDLE) - { - tud_dfu_reboot_to_rt_cb(); - } - + _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; dfu_debug_print_context(); @@ -276,8 +244,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -305,13 +273,13 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // but this mode would provide zero copy from the class driver to the application // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); + tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 0c567ff45..aa8ee23d4 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -42,9 +42,6 @@ // Invoked when a reset is received to check if firmware is valid bool tud_dfu_firmware_valid_check_cb(void); -// Invoked when the device must reboot to dfu runtime mode -void tud_dfu_reboot_to_rt_cb(void); - // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this -- cgit v1.3.1 From 8f72c97f7b0fa14badbc36497fba2c6d21cb59d0 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 12:59:12 +0200 Subject: Change read infos to pointer type --- src/class/audio/audio_device.c | 50 +++++++++++++----------- src/common/tusb_fifo.c | 88 +++++++++++++++++++++--------------------- src/common/tusb_fifo.h | 6 +-- 3 files changed, 76 insertions(+), 68 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8615b2468..f19f8f6fe 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -650,23 +650,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t * src; uint8_t * dst_end; - tu_fifo_linear_wr_info info; + tu_fifo_buffer_info_t info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - info = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead); + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info, nBytesPerFFToRead); - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) + if (info.len_lin != 0) { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); + + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -976,25 +979,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi uint8_t * dst; uint8_t * src_end; - tu_fifo_linear_wr_info info; + tu_fifo_buffer_info_t info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - info = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend); - - src_end = info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info, nBytesPerFFToSend); - // Handle wrapped part of FIFO - if (info.len_wrap != 0) + if (info.ptr_lin != 0) { - src_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); - } + src_end = info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + src_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); + } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + } } return nBytesPerFFToSend * n_ff_used; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 75dae0906..1c4084882 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -883,7 +883,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) /******************************************************************************/ /*! - @brief Get linear read info + @brief Get read info Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the @@ -895,24 +895,18 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) wrapped part! @param[in] f Pointer to FIFO - @param[in] offset - Number of ITEMS to ignore before start writing - @param[out] **ptr - Pointer to start writing to - @param[in] n - Number of ITEMS to read from buffer - @return len - Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid + @param[out] *info + Pointer to struct which holds the desired infos */ /******************************************************************************/ -tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n) +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t cnt = _tu_fifo_count(f, w, r); - // Check overflow and correct if required + // Check overflow and correct if required - may happen in case a DMA wrote too fast if (cnt > f->depth) { _ff_lock(f->mutex_rd); @@ -922,36 +916,40 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offse cnt = f->depth; } - tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; - // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return info; + if (cnt == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } - // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; if (cnt < n) n = cnt; // Get relative pointers - w = get_relative_pointer(f, w, 0); - r = get_relative_pointer(f, r, offset); + w = get_relative_pointer(f, w,0); + r = get_relative_pointer(f, r,0); // Copy pointer to buffer to start reading from - info.ptr_lin = &f->buffer[r]; - info.ptr_wrap = f->buffer; + info->ptr_lin = &f->buffer[r]; // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info.len_lin = tu_min16(n, w - r); // Limit to required length - info.len_wrap = 0; + info->len_lin = tu_min16(n, w - r); // Limit to required length + info->len_wrap = 0; + info->ptr_wrap = NULL; } else { - info.len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full - info.len_wrap = n-info.len_lin; // n was already limited to what is available + info->len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full + info->len_wrap = n-info->len_lin; + info->ptr_wrap = f->buffer; } - return info; + return; } /******************************************************************************/ @@ -967,22 +965,18 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offse time to get a pointer to the wrapped part! @param[in] f Pointer to FIFO - @param[in] offset - Number of ITEMS to ignore before start writing - @param[out] **ptr - Pointer to start writing to + @param[out] *info + Pointer to struct which holds the desired infos @param[in] n Number of ITEMS to write into buffer - @return len - Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n) +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! if (!f->overwritable) { @@ -1002,27 +996,35 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offs } // Check if there is room to write to - if (free == 0 || offset >= free) return info; + if (free == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } // Get relative pointers - w = get_relative_pointer(f, w, offset); - r = get_relative_pointer(f, r, 0); + w = get_relative_pointer(f, w,0); + r = get_relative_pointer(f, r,0); // Copy pointer to buffer to start writing to - info.ptr_lin = &f->buffer[w]; - info.ptr_wrap = f->buffer; // Always start of buffer + info->ptr_lin = &f->buffer[w]; if (w < r) { // Non wrapping case - info.len_lin = tu_min16(n, r-w); // Limit to required length - info.len_wrap = 0; + info->len_lin = tu_min16(n, r-w); // Limit to required length + info->len_wrap = 0; + info->ptr_wrap = NULL; } else { - info.len_lin = tu_min16(n, f->depth - w); // Limit to required length - info.len_wrap = n-info.len_lin; // Remaining length - n already was limited to free or FIFO depth + info->len_lin = tu_min16(n, f->depth - w); // Limit to required length + info->len_wrap = n-info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->ptr_wrap = f->buffer; // Always start of buffer } - return info; + return; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c23f25723..797a5e728 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -86,7 +86,7 @@ typedef struct uint16_t len_wrap ; ///< wrapped length in item size void * ptr_lin ; ///< linear part start pointer void * ptr_wrap ; ///< wrapped part start pointer -} tu_fifo_linear_wr_info; +} tu_fifo_buffer_info_t; #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ { \ @@ -144,8 +144,8 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n); -tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n); +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { -- cgit v1.3.1 From de933c45bc627f930e1951ee606aa76784af47cf Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 14:56:14 +0200 Subject: Remove all remainings with peek_at --- src/class/cdc/cdc_device.c | 4 ++-- src/class/cdc/cdc_device.h | 2 +- src/class/vendor/vendor_device.c | 4 ++-- src/class/vendor/vendor_device.h | 2 +- src/common/tusb_fifo.c | 16 ++++++++-------- src/common/tusb_fifo.h | 9 ++------- test/test/test_fifo.c | 3 --- 7 files changed, 16 insertions(+), 24 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 0a7691916..f5853fddb 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -146,9 +146,9 @@ uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) return num_read; } -bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr) +bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { - return tu_fifo_peek_at(&_cdcd_itf[itf].rx_ff, pos, chr); + return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); } void tud_cdc_n_read_flush (uint8_t itf) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 0885922c6..2566798c5 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -83,7 +83,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf); void tud_cdc_n_read_flush (uint8_t itf); // Get a byte from FIFO at the specified position without removing it -bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); +bool tud_cdc_n_peek (uint8_t itf, uint8_t* u8); // Write bytes to TX FIFO, data may remain in the FIFO for a while uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 9b0a3c25f..ef1f5d2fe 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -72,9 +72,9 @@ uint32_t tud_vendor_n_available (uint8_t itf) return tu_fifo_count(&_vendord_itf[itf].rx_ff); } -bool tud_vendor_n_peek(uint8_t itf, int pos, uint8_t* u8) +bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) { - return tu_fifo_peek_at(&_vendord_itf[itf].rx_ff, pos, u8); + return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); } //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index a4235bfce..ffa2e3b70 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -45,7 +45,7 @@ bool tud_vendor_n_mounted (uint8_t itf); uint32_t tud_vendor_n_available (uint8_t itf); uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, int pos, uint8_t* u8); +bool tud_vendor_n_peek (uint8_t itf, uint8_t* u8); uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); uint32_t tud_vendor_n_write_available (uint8_t itf); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 323bb6270..92e6bd02c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -396,7 +396,7 @@ static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -420,7 +420,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint1 // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) +static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -496,7 +496,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_at_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -634,7 +634,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek_at(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -684,10 +684,10 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) +bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at(f, p_buffer, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); return ret; } @@ -707,10 +707,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n) +uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + bool ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); return ret; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index fffe87bce..36f0d9302 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -123,8 +123,8 @@ bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); -bool tu_fifo_peek_at (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); @@ -147,11 +147,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); -static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ - return tu_fifo_peek_at(f, p_buffer); -} - static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; diff --git a/test/test/test_fifo.c b/test/test/test_fifo.c index b6c22f569..5ea8de512 100644 --- a/test/test/test_fifo.c +++ b/test/test/test_fifo.c @@ -150,9 +150,6 @@ void test_peek(void) tu_fifo_peek(&ff, &temp); TEST_ASSERT_EQUAL(10, temp); - - tu_fifo_peek_at(&ff, 1, &temp); - TEST_ASSERT_EQUAL(20, temp); } void test_empty(void) -- cgit v1.3.1 From 14e2c004cd9db7d386beb2b91804f8e4dfea55f1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:08:14 +0200 Subject: Remove variable n in tu_fifo_get_read_info() --- src/class/audio/audio_device.c | 10 ++++++++-- src/common/tusb_fifo.c | 10 ++++------ src/common/tusb_fifo.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f19f8f6fe..fc5402834 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -985,13 +985,19 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info, nBytesPerFFToSend); + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - if (info.ptr_lin != 0) + // Limit up to desired length + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); + + if (info.len_lin != 0) { src_end = info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + // Limit up to desired length + info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); + // Handle wrapped part of FIFO if (info.len_wrap != 0) { diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 92e6bd02c..306b68653 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -896,7 +896,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -923,8 +923,6 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n return; } - if (cnt < n) n = cnt; - // Get relative pointers w = get_relative_pointer(f, w); r = get_relative_pointer(f, r); @@ -935,14 +933,14 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info->len_lin = tu_min16(n, w - r); // Limit to required length + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full - info->len_wrap = n-info->len_lin; + info->len_lin = f->depth - r; // Also the case if FIFO was full + info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 36f0d9302..c6bcdaec5 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -144,7 +144,7 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); static inline uint16_t tu_fifo_depth(tu_fifo_t* f) -- cgit v1.3.1 From 54f332fae095c1bc15d631fd3b5ef79f8a707578 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:42:27 +0200 Subject: Fix cdc peeks() --- src/class/cdc/cdc_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2566798c5..614bbf5dc 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -117,7 +117,7 @@ static inline uint32_t tud_cdc_available (void); static inline int32_t tud_cdc_read_char (void); static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (int pos, uint8_t* u8); +static inline bool tud_cdc_peek (uint8_t* u8); static inline uint32_t tud_cdc_write_char (char ch); static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); @@ -207,9 +207,9 @@ static inline void tud_cdc_read_flush (void) tud_cdc_n_read_flush(0); } -static inline bool tud_cdc_peek (int pos, uint8_t* u8) +static inline bool tud_cdc_peek (uint8_t* u8) { - return tud_cdc_n_peek(0, pos, u8); + return tud_cdc_n_peek(u8); } static inline uint32_t tud_cdc_write_char (char ch) -- cgit v1.3.1 From 6acfa14fec1805b6f875f4bdbe00360065e72731 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 17:23:34 +0200 Subject: Fix bug in cdc_peek --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 614bbf5dc..986585c5b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -209,7 +209,7 @@ static inline void tud_cdc_read_flush (void) static inline bool tud_cdc_peek (uint8_t* u8) { - return tud_cdc_n_peek(u8); + return tud_cdc_n_peek(0, u8); } static inline uint32_t tud_cdc_write_char (char ch) -- cgit v1.3.1 From 5add664874f4855491e28c3a869105eb25c5f4d7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 17:37:14 +0200 Subject: Remove n from tu_fifo_get_write_info() and fix bug in vendor class --- src/class/audio/audio_device.c | 8 ++++---- src/class/vendor/vendor_device.h | 6 +++--- src/common/tusb_fifo.c | 33 ++++++++------------------------- src/common/tusb_fifo.h | 2 +- 4 files changed, 16 insertions(+), 33 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fc5402834..76ebc8aba 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -654,15 +654,17 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info, nBytesPerFFToRead); + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); if (info.len_lin != 0) { + info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; dst_end = info.ptr_lin + info.len_lin; src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO + info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; @@ -987,11 +989,9 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - // Limit up to desired length - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); - if (info.len_lin != 0) { + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length src_end = info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index ffa2e3b70..2c3d79a3d 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -59,7 +59,7 @@ uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); static inline bool tud_vendor_mounted (void); static inline uint32_t tud_vendor_available (void); static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (int pos, uint8_t* u8); +static inline bool tud_vendor_peek (uint8_t* u8); static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_vendor_write_str (char const* str); static inline uint32_t tud_vendor_write_available (void); @@ -95,9 +95,9 @@ static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) return tud_vendor_n_read(0, buffer, bufsize); } -static inline bool tud_vendor_peek (int pos, uint8_t* u8) +static inline bool tud_vendor_peek (uint8_t* u8) { - return tud_vendor_n_peek(0, pos, u8); + return tud_vendor_n_peek(0, u8); } static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index c80bb1497..a386273f0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -950,11 +950,9 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Returns the length and pointer to which bytes can be written into FIFO in a linear manner. This is of major interest for DMA transmissions not using circular mode. If a returned length is zero the - corresponding pointer is invalid. The returned length is limited to the number of BYTES n which the user - wants to write into the buffer. - The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! If the length - returned is less than n i.e. lenwr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - if (free == 0 || n > 2*f->depth) // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions + if (free == 0) { info->len_lin = 0; info->len_wrap = 0; @@ -977,21 +975,6 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t return; } - // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, free); - } - else if (n >= f->depth) - { - n = f->depth; - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - // Get relative pointers w = get_relative_pointer(f, w); r = get_relative_pointer(f, r); @@ -1002,14 +985,14 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t if (w < r) { // Non wrapping case - info->len_lin = tu_min16(n, r-w); // Limit to required length + info->len_lin = r-w; // Limit to required length info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = tu_min16(n, f->depth - w); // Limit to required length - info->len_wrap = n-info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->len_lin = f->depth - w; + info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth info->ptr_wrap = f->buffer; // Always start of buffer } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 7bc6b60b9..f8cc282d3 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -142,7 +142,7 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { -- cgit v1.3.1 From dab1ed6b327a41976a2d4968d80747ac35fde113 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 5 May 2021 17:42:38 -0400 Subject: Add example to be tested Update API description. --- examples/device/dfu/CMakeLists.txt | 41 +++++++ examples/device/dfu/Makefile | 12 ++ examples/device/dfu/src/main.c | 188 ++++++++++++++++++++++++++++++ examples/device/dfu/src/tusb_config.h | 90 ++++++++++++++ examples/device/dfu/src/usb_descriptors.c | 167 ++++++++++++++++++++++++++ src/class/dfu/dfu_device.h | 3 +- 6 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 examples/device/dfu/CMakeLists.txt create mode 100644 examples/device/dfu/Makefile create mode 100644 examples/device/dfu/src/main.c create mode 100644 examples/device/dfu/src/tusb_config.h create mode 100644 examples/device/dfu/src/usb_descriptors.c (limited to 'src/class') diff --git a/examples/device/dfu/CMakeLists.txt b/examples/device/dfu/CMakeLists.txt new file mode 100644 index 000000000..f4bf75c26 --- /dev/null +++ b/examples/device/dfu/CMakeLists.txt @@ -0,0 +1,41 @@ +# use directory name for project id +get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME) +set(PROJECT ${BOARD}-${PROJECT}) + +# TOP is absolute path to root directory of TinyUSB git repo +set(TOP "../../..") +get_filename_component(TOP "${TOP}" REALPATH) + +# Check for -DFAMILY= +if(FAMILY STREQUAL "rp2040") + cmake_minimum_required(VERSION 3.12) + set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk) + include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + project(${PROJECT}) + pico_sdk_init() + add_executable(${PROJECT}) + + include(${TOP}/hw/bsp/${FAMILY}/family.cmake) + + # Example source + target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + + # Example include + target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + + # Example defines + target_compile_definitions(${PROJECT} PUBLIC + CFG_TUSB_OS=OPT_OS_PICO + ) + + target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration) + pico_add_extra_outputs(${PROJECT}) + +else() + message(FATAL_ERROR "Invalid FAMILY specified") +endif() diff --git a/examples/device/dfu/Makefile b/examples/device/dfu/Makefile new file mode 100644 index 000000000..69b633fea --- /dev/null +++ b/examples/device/dfu/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c new file mode 100644 index 000000000..3849de44d --- /dev/null +++ b/examples/device/dfu/src/main.c @@ -0,0 +1,188 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + * + */ + + /* + * After device is enumerated in dfu mode run the following commands + * + * To transfer firmware from host to device: + * + * $ dfu-util -D [filename] + * + * To transfer firmware from device to host: + * + * $ dfu-util -U [filename] + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +#ifndef DFU_VERBOSE +#define DFU_VERBOSE 0 +#endif + +/* Blink pattern + * - 1000 ms : device should reboot + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_DFU_MODE = 100, + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked on DFU_DETACH request to reboot to the bootloader +void tud_dfu_runtime_reboot_to_dfu_cb(void) +{ + blink_interval_ms = BLINK_DFU_MODE; +} + +//--------------------------------------------------------------------+ +// Class callbacks +//--------------------------------------------------------------------+ +bool tud_dfu_firmware_valid_check_cb(void) +{ + TU_LOG2(" Firmware check\r\n"); + return true; +} + +void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +{ + TU_LOG2(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + +#if DFU_VERBOSE + for(uint16_t i=0; i 31 ) { + chr_count = 31; + } + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; i Date: Mon, 10 May 2021 17:19:44 +0900 Subject: fix hid report descriptor --- src/class/hid/hid_device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..ce713559e 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -184,9 +184,9 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 /* 6-byte Keycodes */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX ( 255 ) ,\ + HID_USAGE_MAX_N ( 255, 2 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 255 ) ,\ + HID_LOGICAL_MAX_N( 255, 2 ) ,\ HID_REPORT_COUNT ( 6 ) ,\ HID_REPORT_SIZE ( 8 ) ,\ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ @@ -272,7 +272,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 * 0x00 - do nothing * 0x01 - Power Off * 0x02 - Standby - * 0x04 - Wake Host + * 0x03 - Wake Host */ #define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ @@ -285,8 +285,8 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 HID_LOGICAL_MAX ( 3 ) ,\ HID_REPORT_COUNT ( 1 ) ,\ HID_REPORT_SIZE ( 2 ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ /* 6 bit padding */ \ -- cgit v1.3.1 From 74ca1894de12429e1a16d75242889dcd520eea68 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 10 May 2021 15:58:04 +0200 Subject: audio_device: Fix build error ep_in_as_intf_num was incorrectly used to access out interface which is defined for 'in' interface. Code related to 'out' endpoint should use ep_out_as_intf_num instead. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 76ebc8aba..72533013c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -496,7 +496,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) { idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); } // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) -- cgit v1.3.1 From e163f85ee024ff366253478cfd20e3fc35e96819 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:32:20 +0700 Subject: clean up, rename some HID device symbol/API - add tud_hid_n_interface_protocol() - rename tud_hid_n_boot_mode() to tud_hid_n_get_protocol() - rename tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb() - add HID_PROTOCOL_BOOT/REPORT to avoid magic number 0,1 - rename HID_PROTOCOL_NONE/KEYBOARD/MOUSE to HID_ITF_PROTOCOL_ to avoid confusion --- .../device/hid_composite/src/usb_descriptors.c | 2 +- .../hid_composite_freertos/src/usb_descriptors.c | 2 +- .../device/hid_generic_inout/src/usb_descriptors.c | 2 +- .../hid_multiple_interface/src/usb_descriptors.c | 4 +- src/class/hid/hid.h | 29 +++++++---- src/class/hid/hid_device.c | 58 ++++++++++++---------- src/class/hid/hid_device.h | 55 ++++++++++++-------- src/class/hid/hid_host.c | 4 +- 8 files changed, 92 insertions(+), 64 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index ccc1306bd..1aff5e68e 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -108,7 +108,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index ccc1306bd..1aff5e68e 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -108,7 +108,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index db4ddd76e..5a2f5ffdc 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -104,7 +104,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index a28e57a2b..9eef21504 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -119,8 +119,8 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10), - TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10), + TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 351a4d600..6014e54a6 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -62,15 +62,15 @@ typedef enum { HID_SUBCLASS_NONE = 0, ///< No Subclass HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_type_t; +}hid_subclass_enum_t; -/// HID Protocol +/// HID Interface Protocol typedef enum { - HID_PROTOCOL_NONE = 0, ///< None - HID_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_protocol_type_t; + HID_ITF_PROTOCOL_NONE = 0, ///< None + HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard + HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse +}hid_interface_protocol_enum_t; /// HID Descriptor Type typedef enum @@ -78,7 +78,7 @@ typedef enum HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_type_t; +}hid_descriptor_enum_t; /// HID Request Report Type typedef enum @@ -87,7 +87,7 @@ typedef enum HID_REPORT_TYPE_INPUT, ///< Input HID_REPORT_TYPE_OUTPUT, ///< Output HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; +}hid_report_enum_t; /// HID Class Specific Control Request typedef enum @@ -98,9 +98,9 @@ typedef enum HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_type_t; +}hid_request_enum_t; -/// HID Country Code +/// HID Local Code typedef enum { HID_LOCAL_NotSupported = 0 , ///< NotSupported @@ -139,7 +139,14 @@ typedef enum HID_LOCAL_US , ///< US HID_LOCAL_Yugoslavia , ///< Yugoslavia HID_LOCAL_Turkish_F ///< Turkish-F -} hid_country_code_t; +} hid_local_enum_t; + +// HID protocol value used by GetProtocol / SetProtocol +enum +{ + HID_PROTOCOL_BOOT = 0, + HID_PROTOCOL_REPORT = 1 +}; /** @} */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 18d35bc20..62d63e30a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -43,7 +43,8 @@ typedef struct uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; // optional Out endpoint - uint8_t boot_protocol; // Boot mouse or keyboard + uint8_t itf_protocol; // Boot mouse or keyboard + bool boot_mode; // default = false (Report) uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; @@ -51,6 +52,8 @@ typedef struct CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; + // TODO save hid descriptor since host can specifically request this after enumeration + // Note: HID descriptor may be not available from application after enumeration tusb_hid_descriptor_hid_t const * hid_descriptor; } hidd_interface_t; @@ -70,16 +73,16 @@ static inline uint8_t get_index_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t itf) +bool tud_hid_n_ready(uint8_t instance) { - uint8_t const ep_in = _hidd_itf[itf].ep_in; + uint8_t const ep_in = _hidd_itf[instance].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[itf]; + hidd_interface_t * p_hid = &_hidd_itf[instance]; // claim endpoint TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); @@ -102,12 +105,17 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); } -bool tud_hid_n_boot_mode(uint8_t itf) +uint8_t tud_hid_n_interface_protocol(uint8_t instance) +{ + return _hidd_itf[instance].itf_protocol; +} + +bool tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[itf].boot_mode; + return _hidd_itf[instance].boot_mode; } -bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -121,10 +129,10 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, tu_memclr(report.keycode, 6); } - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = @@ -136,10 +144,10 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, .pan = horizontal }; - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) { hid_gamepad_report_t report = @@ -154,7 +162,7 @@ bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, .buttons = buttons, }; - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ @@ -203,7 +211,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_desc = tu_desc_next(p_desc); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol; + if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; @@ -318,8 +326,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_GET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - // 0 is Boot, 1 is Report protocol - uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); + uint8_t protocol = (p_hid->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT); tud_control_xfer(rhport, request, &protocol, 1); } break; @@ -327,15 +334,14 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_SET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - // 0 is Boot, 1 is Report protocol - p_hid->boot_mode = 1 - request->wValue; + p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); tud_control_status(rhport, request); } else if ( stage == CONTROL_STAGE_ACK ) { - if (tud_hid_boot_mode_cb) + if (tud_hid_set_protocol_cb) { - tud_hid_boot_mode_cb(hid_itf, p_hid->boot_mode); + tud_hid_set_protocol_cb(hid_itf, p_hid->boot_mode); } } break; @@ -354,29 +360,29 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { (void) result; - uint8_t itf = 0; + uint8_t instance = 0; hidd_interface_t * p_hid = _hidd_itf; // Identify which interface to use - for (itf = 0; itf < CFG_TUD_HID; itf++) + for (instance = 0; instance < CFG_TUD_HID; instance++) { - p_hid = &_hidd_itf[itf]; + p_hid = &_hidd_itf[instance]; if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; } - TU_ASSERT(itf < CFG_TUD_HID); + TU_ASSERT(instance < CFG_TUD_HID); // Sent report successfully if (ep_addr == p_hid->ep_in) { if (tud_hid_report_complete_cb) { - tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes); + tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint8_t) xferred_bytes); } } // Received report else if (ep_addr == p_hid->ep_out) { - tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..cc34f19ac 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -55,34 +55,39 @@ //--------------------------------------------------------------------+ // Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t itf); +bool tud_hid_n_ready(uint8_t instance); -// Check if current mode is Boot (true) or Report (false) -bool tud_hid_n_boot_mode(uint8_t itf); +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value +uint8_t tud_hid_n_interface_protocol(uint8_t instance); + +// Check if active protocol is Boot (true) or Report (false) +bool tud_hid_n_get_protocol(uint8_t instance); // Send report to host -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); // Gamepad: convenient helper to send mouse report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline bool tud_hid_boot_mode(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_ready(void); +static inline uint8_t tud_hid_interface_protocol(void); +static inline bool tud_hid_get_protocol(void); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -90,29 +95,29 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); +uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +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); // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, bool boot_mode); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len); +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len); //--------------------------------------------------------------------+ @@ -123,9 +128,14 @@ static inline bool tud_hid_ready(void) return tud_hid_n_ready(0); } -static inline bool tud_hid_boot_mode(void) +static inline uint8_t tud_hid_interface_protocol(void) +{ + return tud_hid_n_interface_protocol(0); +} + +static inline bool tud_hid_get_protocol(void) { - return tud_hid_n_boot_mode(0); + return tud_hid_n_get_protocol(0); } static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) @@ -143,6 +153,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); } +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +{ + return tud_hid_n_gamepad_report(0, x, y, z, rz, rx, ry, hat, buttons); +} + /* --------------------------------------------------------------------+ * HID Report Descriptor Template * diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 64d1b8e5d..28440b1b4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -178,7 +178,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) + if ( HID_ITF_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); @@ -186,7 +186,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c #endif #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) + if ( HID_ITF_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); -- cgit v1.3.1 From 7e9e682e09c2629a9575343e4efaf43d328bde33 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:38:11 +0700 Subject: update to use HID spec protocol value for get/set_protocol() --- src/class/hid/hid.h | 4 ++-- src/class/hid/hid_device.c | 6 +++--- src/class/hid/hid_device.h | 11 ++++++----- 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 6014e54a6..5c30f7585 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -142,11 +142,11 @@ typedef enum } hid_local_enum_t; // HID protocol value used by GetProtocol / SetProtocol -enum +typedef enum { HID_PROTOCOL_BOOT = 0, HID_PROTOCOL_REPORT = 1 -}; +} hid_protocol_mode_enum_t; /** @} */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 62d63e30a..4d33c85d3 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -112,7 +112,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) bool tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[instance].boot_mode; + return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) @@ -334,14 +334,14 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_SET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); tud_control_status(rhport, request); } else if ( stage == CONTROL_STAGE_ACK ) { + p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); if (tud_hid_set_protocol_cb) { - tud_hid_set_protocol_cb(hid_itf, p_hid->boot_mode); + tud_hid_set_protocol_cb(hid_itf, (uint8_t) request->wValue); } } break; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index cc34f19ac..2cc4a9546 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -60,8 +60,8 @@ bool tud_hid_n_ready(uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value uint8_t tud_hid_n_interface_protocol(uint8_t instance); -// Check if active protocol is Boot (true) or Report (false) -bool tud_hid_n_get_protocol(uint8_t instance); +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +uint8_t tud_hid_n_get_protocol(uint8_t instance); // Send report to host bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); @@ -83,7 +83,7 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline uint8_t tud_hid_interface_protocol(void); -static inline bool tud_hid_get_protocol(void); +static inline uint8_t tud_hid_get_protocol(void); static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); @@ -106,8 +106,9 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -// Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, bool boot_mode); +// Invoked when received SET_PROTOCOL request +// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication -- cgit v1.3.1 From a26752a93e56b2fb2d683e5a9f9934b432531d9b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:45:59 +0700 Subject: fix build error --- src/class/hid/hid.h | 2 +- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 5c30f7585..c63b6f00b 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -87,7 +87,7 @@ typedef enum HID_REPORT_TYPE_INPUT, ///< Input HID_REPORT_TYPE_OUTPUT, ///< Output HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_enum_t; +}hid_report_type_t; /// HID Class Specific Control Request typedef enum diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4d33c85d3..ab9ef3ad8 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -110,7 +110,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) return _hidd_itf[instance].itf_protocol; } -bool tud_hid_n_get_protocol(uint8_t instance) +uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 2cc4a9546..b3701c7e0 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -134,7 +134,7 @@ static inline uint8_t tud_hid_interface_protocol(void) return tud_hid_n_interface_protocol(0); } -static inline bool tud_hid_get_protocol(void) +static inline uint8_t tud_hid_get_protocol(void) { return tud_hid_n_get_protocol(0); } @@ -156,7 +156,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) { - return tud_hid_n_gamepad_report(0, x, y, z, rz, rx, ry, hat, buttons); + return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } /* --------------------------------------------------------------------+ -- cgit v1.3.1 From 98f5082191e2135ca783a24a39f95ee82639b9fc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:19:32 +0700 Subject: rename var to be consistent --- src/class/hid/hid_host.c | 36 +++++++++++++++++++----------------- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 12 +++++------- src/class/msc/msc_host.h | 2 +- src/host/usbh.c | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 64d1b8e5d..9e41f9f45 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -47,12 +47,12 @@ typedef struct { //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_t *p_hid) +static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *desc_ep, hidh_interface_t *p_hid) { - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, p_endpoint_desc) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - p_hid->ep_in = p_endpoint_desc->bEndpointAddress; - p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor + p_hid->ep_in = desc_ep->bEndpointAddress; + p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->itf_num = interface_number; p_hid->valid = true; @@ -161,34 +161,36 @@ void hidh_init(void) CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; #endif -bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// - p_desc += p_desc[DESC_OFFSET_LEN]; - tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); + p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESC_OFFSET_LEN]; - tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, TUSB_ERROR_INVALID_PARA); - if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) + if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); } else #endif #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) + if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_ASSERT ( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); } else #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 5c77398f8..174601594 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -196,7 +196,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); // Internal Class Driver API //--------------------------------------------------------------------+ void hidh_init(void); -bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 34dbec2e3..3e8573df0 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -357,15 +357,13 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { - TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && + MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); msch_interface_t* p_msc = get_itf(dev_addr); - - //------------- Open Data Pipe -------------// - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { @@ -383,7 +381,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } - p_msc->itf_num = itf_desc->bInterfaceNumber; + p_msc->itf_num = desc_itf->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); return true; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 8116e729f..d99f1204a 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -116,7 +116,7 @@ void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ void msch_init(void); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 3761f279c..86da97bb8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -79,7 +79,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, .init = hidh_init, - .open = hidh_open_subtask, + .open = hidh_open, .set_config = hidh_set_config, .xfer_cb = hidh_xfer_cb, .close = hidh_close -- cgit v1.3.1 From f1148ca5ac8f56774af4b58175d0d61442f86544 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:54:18 +0700 Subject: reworking hid host --- src/class/hid/hid_host.c | 43 +++++++++++++++++++++++++++++++++++-------- src/class/hid/hid_host.h | 8 ++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 9e41f9f45..7ae50e4d7 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,13 +35,40 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard + "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse + "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control + "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control + "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen + "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF + */ typedef struct { - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - bool valid; + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; - uint16_t report_size; + bool valid; + uint16_t report_size; // TODO remove later + + uint8_t boot_protocol; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol + uint8_t report_count; // Number of reports + + struct { + uint8_t in_len; // length of IN report + uint8_t out_len; // length of OUT report + uint8_t usage_page; + uint8_t usage; + }reports[CFG_TUH_HID_MAX_REPORT]; + + // Parsed Report ID for convenient API + uint8_t report_id_keyboard; + uint8_t reprot_id_mouse; + uint8_t report_id_gamepad; + uint8_t report_id_consumer; + uint8_t report_id_vendor; }hidh_interface_t; //--------------------------------------------------------------------+ @@ -51,9 +78,9 @@ static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t { TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + p_hid->itf_num = interface_number; p_hid->ep_in = desc_ep->bEndpointAddress; p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->itf_num = interface_number; p_hid->valid = true; return true; @@ -170,12 +197,12 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 174601594..d43158186 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -38,6 +38,14 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_HID_MAX_REPORT +#define CFG_TUH_HID_MAX_REPORT 8 +#endif + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 68fa17e17ca900ec2800c55c9345a2a0fed3fca9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 14:07:33 +0700 Subject: more API rename --- examples/host/cdc_msc_hid/src/main.c | 4 ++-- src/class/hid/hid_device.h | 4 ++-- src/class/hid/hid_host.c | 8 ++++---- src/class/hid/hid_host.h | 14 ++++++++++++-- 4 files changed, 20 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c6ab54682..84e88e509 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -257,7 +257,7 @@ void hid_task(void) uint8_t const addr = 1; #if CFG_TUH_HID_KEYBOARD - if ( tuh_hid_keyboard_is_mounted(addr) ) + if ( tuh_hid_keyboard_mounted(addr) ) { if ( !tuh_hid_keyboard_is_busy(addr) ) { @@ -268,7 +268,7 @@ void hid_task(void) #endif #if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_is_mounted(addr) ) + if ( tuh_hid_mouse_mounted(addr) ) { if ( !tuh_hid_mouse_is_busy(addr) ) { diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..7520d3453 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -50,7 +50,7 @@ #endif //--------------------------------------------------------------------+ -// Application API (Multiple Ports) +// Application API (Multiple Instances) // CFG_TUD_HID > 1 //--------------------------------------------------------------------+ @@ -76,7 +76,7 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ -// Application API (Single Port) +// Application API (Single Instance) //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline bool tud_hid_boot_mode(void); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 7ae50e4d7..aa6188a24 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -113,7 +113,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// -bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr) +bool tuh_hid_keyboard_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); } @@ -125,7 +125,7 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); + return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); } #endif @@ -138,14 +138,14 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// -bool tuh_hid_mouse_is_mounted(uint8_t dev_addr) +bool tuh_hid_mouse_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); + return tuh_hid_mouse_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index d43158186..f777fe45d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -46,6 +46,16 @@ #define CFG_TUH_HID_MAX_REPORT 8 #endif +//--------------------------------------------------------------------+ +// Application API (Multiple Instances) +// CFG_TUH_HID > 1 +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// Application API (Single Instance) +//--------------------------------------------------------------------+ + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -63,7 +73,7 @@ extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if * \retval true if device supports Keyboard interface * \retval false if device does not support Keyboard interface or is not mounted */ -bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr); +bool tuh_hid_keyboard_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address @@ -128,7 +138,7 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * \retval true if device supports Mouse interface * \retval false if device does not support Mouse interface or is not mounted */ -bool tuh_hid_mouse_is_mounted(uint8_t dev_addr); +bool tuh_hid_mouse_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address -- cgit v1.3.1 From e83bdcdfdc521fef2dd182a5f83cd1c1be673865 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 15:29:17 +0700 Subject: reworking hid host --- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 4 + src/class/hid/hid_host.c | 159 ++++++++++++++++------------ src/class/hid/hid_host.h | 14 ++- src/host/usbh.c | 1 + 5 files changed, 108 insertions(+), 72 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 652a372e9..b3fd1f2af 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -154,7 +154,7 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) +void tuh_hid_mounted_cb(uint8_t dev_addr) { // application set-up printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fabc7765c..82155f1ca 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -73,9 +73,13 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 + +#define CFG_TUH_HID 2 + #define CFG_TUH_HID_KEYBOARD 1 #define CFG_TUH_HID_MOUSE 1 #define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) + #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index aa6188a24..dae20b305 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -44,11 +44,14 @@ "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF */ -typedef struct { +typedef struct +{ uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; + uint16_t report_desc_len; + bool valid; uint16_t report_size; // TODO remove later @@ -61,16 +64,38 @@ typedef struct { uint8_t out_len; // length of OUT report uint8_t usage_page; uint8_t usage; - }reports[CFG_TUH_HID_MAX_REPORT]; + }reports[CFG_TUH_HID_REPORT_MAX]; // Parsed Report ID for convenient API - uint8_t report_id_keyboard; - uint8_t reprot_id_mouse; - uint8_t report_id_gamepad; - uint8_t report_id_consumer; - uint8_t report_id_vendor; + uint8_t rid_keyboard; + uint8_t rid_mouse; + uint8_t rid_gamepad; + uint8_t rid_consumer; }hidh_interface_t; +typedef struct +{ + uint8_t inst_count; + hidh_interface_t instance[CFG_TUH_HID]; +} hidh_device_t; + +static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; + +#if 0 +CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; +#endif + +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t inst) +{ + return &_hidh_dev[dev_addr-1].instance[inst]; +} + + //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ @@ -108,27 +133,32 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -#if CFG_TUH_HID_KEYBOARD -static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 - -//------------- KEYBOARD PUBLIC API (parameter validation required) -------------// -bool tuh_hid_keyboard_mounted(uint8_t dev_addr) +bool tuh_hid_keyboard_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + // TODO check rid_keyboard + return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); } -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) +tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) { - return hidh_interface_get_report(dev_addr, p_report, &keyboardh_data[dev_addr-1]); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + return hidh_interface_get_report(dev_addr, buffer, hid_itf); } bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -#endif //--------------------------------------------------------------------+ // MOUSE @@ -158,36 +188,20 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) //--------------------------------------------------------------------+ // GENERIC //--------------------------------------------------------------------+ -#if CFG_TUSB_HOST_HID_GENERIC -//STATIC_ struct { -// hidh_interface_info_t -//} generic_data[CFG_TUSB_HOST_DEVICE_MAX]; - -#endif //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ void hidh_init(void) { -#if CFG_TUH_HID_KEYBOARD - tu_memclr(&keyboardh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); -#endif + tu_memclr(_hidh_dev, sizeof(_hidh_dev)); #if CFG_TUH_HID_MOUSE tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif - -#if CFG_TUSB_HOST_HID_GENERIC - hidh_generic_init(); -#endif } -#if 0 -CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; -#endif - bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); @@ -199,6 +213,18 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + // not enough interface, try to increase CFG_TUH_HID + // TODO multiple devices + hidh_device_t* hid_dev = get_dev(dev_addr); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); + + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); + hid_dev->inst_count++; + + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->boot_mode = false; // default is report mode + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; @@ -206,11 +232,20 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { + hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; + #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &keyboardh_data[dev_addr-1]) ); - TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, hid_itf) ); + TU_LOG2_HEX(hid_itf->ep_in); + + hid_itf->report_count = 1; + + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; } else #endif @@ -226,13 +261,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // Not supported protocol return false; } - }else - { - // Not supported subclass - return false; } - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t); + *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); return true; } @@ -276,12 +307,13 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) usbh_driver_set_config_complete(dev_addr, itf_num); -#if CFG_TUH_HID_KEYBOARD - if (( keyboardh_data[dev_addr-1].itf_num == itf_num) && keyboardh_data[dev_addr-1].valid) - { - tuh_hid_keyboard_mounted_cb(dev_addr); +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + + + if (itf_num == 0 ) { + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); } -#endif #if CFG_TUH_HID_MOUSE if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) @@ -297,12 +329,15 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 { (void) xferred_bytes; // TODO may need to use this para later +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + #if CFG_TUH_HID_KEYBOARD - if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) - { - tuh_hid_keyboard_isr(dev_addr, event); - return true; - } +// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_keyboard_isr(dev_addr, event); +// return true; +// } #endif #if CFG_TUH_HID_MOUSE @@ -311,10 +346,6 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 tuh_hid_mouse_isr(dev_addr, event); return true; } -#endif - -#if CFG_TUSB_HOST_HID_GENERIC - #endif return true; @@ -322,13 +353,11 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void hidh_close(uint8_t dev_addr) { -#if CFG_TUH_HID_KEYBOARD - if ( keyboardh_data[dev_addr-1].ep_in != 0 ) - { - hidh_interface_close(&keyboardh_data[dev_addr-1]); - tuh_hid_keyboard_unmounted_cb(dev_addr); - } -#endif + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); + hidh_interface_close(hid_itf); #if CFG_TUH_HID_MOUSE if( mouseh_data[dev_addr-1].ep_in != 0 ) @@ -337,12 +366,6 @@ void hidh_close(uint8_t dev_addr) tuh_hid_mouse_unmounted_cb( dev_addr ); } #endif - -#if CFG_TUSB_HOST_HID_GENERIC - hidh_generic_close(dev_addr); -#endif } - - #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index f777fe45d..10ecc457f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -42,8 +42,8 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_HID_MAX_REPORT -#define CFG_TUH_HID_MAX_REPORT 8 +#ifndef CFG_TUH_HID_REPORT_MAX +#define CFG_TUH_HID_REPORT_MAX 4 #endif //--------------------------------------------------------------------+ @@ -56,6 +56,12 @@ // Application API (Single Instance) //--------------------------------------------------------------------+ +// tuh_hid_instance_count() +//bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); + +TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -66,7 +72,9 @@ * The interface API includes status checking function, data transferring function and callback functions * @{ */ -extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled +// TODO used weak attr if build failed without KEYBOARD enabled +// TODO remove +extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; /** \brief Check if device supports Keyboard interface or not * \param[in] dev_addr device address diff --git a/src/host/usbh.c b/src/host/usbh.c index 88e5c02a7..f7cad4640 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -915,6 +915,7 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co // Start the Set Configuration process for interfaces (itf = 0xff) // Since driver can perform control transfer within its set_config, this is done asynchronously. // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + // TODO use separated API instead of usig 0xff usbh_driver_set_config_complete(dev_addr, 0xff); return true; -- cgit v1.3.1 From 510beef9f8f78689424ee8f62d3883b89fe794fa Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:27:34 +0700 Subject: make tuh_msc_mount_cb() tuh_msc_unmount_cb() as weak callback --- src/class/msc/msc_host.c | 9 ++++++--- src/class/msc/msc_host.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 3e8573df0..4869c8c03 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -287,7 +287,7 @@ bool tuh_msc_reset(uint8_t dev_addr) #endif //--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) +// CLASS-USBH API //--------------------------------------------------------------------+ void msch_init(void) { @@ -298,7 +298,9 @@ void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); tu_memclr(p_msc, sizeof(msch_interface_t)); - tuh_msc_unmount_cb(dev_addr); // invoke Application Callback + + // invoke Application Callback + if (tuh_msc_unmount_cb) tuh_msc_unmount_cb(dev_addr); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -471,8 +473,9 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw // Mark enumeration is complete p_msc->mounted = true; - tuh_msc_mount_cb(dev_addr); + if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); + // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); return true; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index d99f1204a..7ebc9b5a8 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -106,10 +106,10 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r //------------- Application Callback -------------// // Invoked when a device with MassStorage interface is mounted -void tuh_msc_mount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -void tuh_msc_unmount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From be165a67134d08f7c32386de041f1a2665e696be Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:36:52 +0700 Subject: reworking host hid API --- examples/host/cdc_msc_hid/src/main.c | 17 +-- src/class/hid/hid_host.c | 274 ++++++++++++++++++++--------------- src/class/hid/hid_host.h | 62 ++++---- 3 files changed, 192 insertions(+), 161 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index b3fd1f2af..5543e9efb 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -162,19 +162,12 @@ void tuh_hid_mounted_cb(uint8_t dev_addr) tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) +void tuh_hid_unmounted_cb(uint8_t dev_addr) { // application tear-down printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); } -// invoked ISR context -void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) -{ - (void) dev_addr; - (void) event; -} - #endif #if CFG_TUH_HID_MOUSE @@ -242,12 +235,6 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } -// invoked ISR context -void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) -{ - (void) dev_addr; - (void) event; -} #endif @@ -257,7 +244,7 @@ void hid_task(void) uint8_t const addr = 1; #if CFG_TUH_HID_KEYBOARD - if ( tuh_hid_keyboard_mounted(addr) ) + if ( tuh_n_hid_n_keyboard_mounted(addr, 0) ) { if ( !tuh_hid_keyboard_is_busy(addr) ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index dae20b305..a5aa33c2c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -50,6 +50,7 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + uint8_t report_desc_type; uint16_t report_desc_len; bool valid; @@ -75,42 +76,51 @@ typedef struct typedef struct { - uint8_t inst_count; - hidh_interface_t instance[CFG_TUH_HID]; + uint8_t itf_count; + hidh_interface_t interface[CFG_TUH_HID]; } hidh_device_t; static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; -#if 0 -CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; -#endif +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _report_desc_buf[256]; +// Get Device by address TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) { return &_hidh_dev[dev_addr-1]; } -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t inst) +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) { - return &_hidh_dev[dev_addr-1].instance[inst]; + return &_hidh_dev[dev_addr-1].interface[instance]; } +// Get Interface by interface number +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +{ + for(uint8_t inst=0; institf_num == itf) && (hid->ep_in != 0) ) return hid; + } + + return NULL; +} //--------------------------------------------------------------------+ -// HID Interface common functions +// Application API //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *desc_ep, hidh_interface_t *p_hid) +uint8_t tuh_n_hid_instance_count(uint8_t daddr) { - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - - p_hid->itf_num = interface_number; - p_hid->ep_in = desc_ep->bEndpointAddress; - p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->valid = true; - - return true; + return get_dev(daddr)->itf_count; } +//--------------------------------------------------------------------+ +// HID Interface common functions +//--------------------------------------------------------------------+ + static inline void hidh_interface_close(hidh_interface_t *p_hid) { tu_memclr(p_hid, sizeof(hidh_interface_t)); @@ -123,7 +133,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int // TODO change to use is configured function TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; @@ -134,10 +144,9 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_hid_keyboard_mounted(uint8_t dev_addr) +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO check rid_keyboard return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); @@ -153,13 +162,12 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + uint8_t instance = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_n_hid_n_keyboard_mounted(dev_addr, instance) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } - //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ @@ -191,17 +199,63 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) //--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) +// USBH API //--------------------------------------------------------------------+ void hidh_init(void) { tu_memclr(_hidh_dev, sizeof(_hidh_dev)); +} + +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + (void) xferred_bytes; // TODO may need to use this para later + +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + +#if CFG_TUH_HID_KEYBOARD +// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_keyboard_isr(dev_addr, event); +// return true; +// } +#endif #if CFG_TUH_HID_MOUSE - tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); +// if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_mouse_isr(dev_addr, event); +// return true; +// } #endif + + return true; } +void hidh_close(uint8_t dev_addr) +{ + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); + hidh_interface_close(hid_itf); + +#if CFG_TUH_HID_MOUSE + if( mouseh_data[dev_addr-1].ep_in != 0 ) + { + hidh_interface_close(&mouseh_data[dev_addr-1]); + tuh_hid_mouse_unmounted_cb( dev_addr ); + } +#endif +} + +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ + +static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); @@ -216,50 +270,59 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); - - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); - hid_dev->inst_count++; - - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->boot_mode = false; // default is report mode - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + TU_ASSERT(hid_dev->itf_count < CFG_TUH_HID); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + // TODO also open endpoint OUT + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->itf_count); + hid_dev->itf_count++; + + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor + hid_itf->valid = true; + + TU_LOG2_HEX(hid_itf->ep_in); + + // Assume bNumDescriptors = 1 + hid_itf->report_desc_type = desc_hid->bReportType; + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + + hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; - #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, hid_itf) ); - TU_LOG2_HEX(hid_itf->ep_in); - + // TODO boot protocol may still have more report in report mode hid_itf->report_count = 1; hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; hid_itf->reports[0].in_len = 8; hid_itf->reports[0].out_len = 1; - } else - #endif - - #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) + } + else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &mouseh_data[dev_addr-1]) ); - TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); - } else - #endif + // TODO boot protocol may still have more report in report mode + hid_itf->report_count = 1; + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; + } + else { - // Not supported protocol - return false; + // Unknown protocol + TU_ASSERT(false); } } @@ -270,23 +333,11 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { -#if 0 - //------------- Get Report Descriptor TODO HID parser -------------// - if ( p_desc_hid->bNumDescriptors ) - { - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), - TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, - p_desc_hid->wReportLength, report_descriptor ), - error - ); - (void) error; // if error in getting report descriptor --> treating like there is none - } -#endif + // Idle rate = 0 mean only report when there is changes + uint16_t const idle_rate = 0; -#if 0 - // SET IDLE = 0 request - // Device can stall if not support this request + // SET IDLE request, device can stall if not support this request + TU_LOG2("Set Idle \r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -296,76 +347,65 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .direction = TUSB_DIR_OUT }, .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, + .wValue = idle_rate, + .wIndex = itf_num, .wLength = 0 }; - // stall is a valid response for SET_IDLE, therefore we could ignore result of this request - tuh_control_xfer(dev_addr, &request, NULL, NULL); -#endif - - usbh_driver_set_config_complete(dev_addr, itf_num); - -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; - - - if (itf_num == 0 ) { - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); - } - -#if CFG_TUH_HID_MOUSE - if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) - { - tuh_hid_mouse_mounted_cb(dev_addr); - } -#endif + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, config_set_idle_complete) ); return true; } -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - (void) xferred_bytes; // TODO may need to use this para later + // Stall is a valid response for SET_IDLE, therefore we could ignore its result + (void) result; -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + uint8_t const itf_num = (uint8_t) request->wIndex; -#if CFG_TUH_HID_KEYBOARD -// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_keyboard_isr(dev_addr, event); -// return true; -// } -#endif + hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); -#if CFG_TUH_HID_MOUSE - if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) + // Get Report Descriptor + // using usbh enumeration buffer since report descriptor can be very long + TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE ); + + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = { - tuh_hid_mouse_isr(dev_addr, event); - return true; - } -#endif + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); return true; } -void hidh_close(uint8_t dev_addr) +bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + uint8_t const itf_num = (uint8_t) request->wIndex; + hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); - if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); - hidh_interface_close(hid_itf); + if (tuh_hid_descriptor_report_cb) tuh_hid_descriptor_report_cb(dev_addr, hid_itf->itf_num, usbh_get_enum_buf(), request->wLength); -#if CFG_TUH_HID_MOUSE - if( mouseh_data[dev_addr-1].ep_in != 0 ) - { - hidh_interface_close(&mouseh_data[dev_addr-1]); - tuh_hid_mouse_unmounted_cb( dev_addr ); - } -#endif + // TODO Report descriptor parser + + // enumeration is complete + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(dev_addr, itf_num); + + return true; } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 10ecc457f..98c652338 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -46,22 +46,51 @@ #define CFG_TUH_HID_REPORT_MAX 4 #endif +#ifndef CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE +#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 +#endif + //--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUH_HID > 1 +// Application API (Multiple devices) +// Note: +// - tud_n : is multiple devices API +// - class_n : is multiple instances API //--------------------------------------------------------------------+ +// Get the number of HID instances +uint8_t tuh_n_hid_instance_count(uint8_t daddr); + +// Check if HID instance support keyboard +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); + + //--------------------------------------------------------------------+ -// Application API (Single Instance) +// Application API (Single device) //--------------------------------------------------------------------+ -// tuh_hid_instance_count() +// Get the number of HID instances +TU_ATTR_ALWAYS_INLINE static inline +uint8_t tuh_hid_instance_count(void) +{ + return tuh_n_hid_instance_count(1); +} + //bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); +//--------------------------------------------------------------------+ +// Callbacks (Weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when report descriptor is received +// Note: enumeration is still not complete yet +TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); + TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); + + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -193,31 +222,6 @@ void tuh_hid_mouse_mounted_cb(uint8_t dev_addr); */ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr); -/** @} */ // Mouse_Host -/** @} */ // ClassDriver_HID_Mouse - -//--------------------------------------------------------------------+ -// GENERIC Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Generic Generic (not supported yet) - * @{ */ - -/** \defgroup Generic_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -bool tuh_hid_generic_is_mounted(uint8_t dev_addr); -tusb_error_t tuh_hid_generic_get_report(uint8_t dev_addr, void* p_report, bool int_on_complete); -tusb_error_t tuh_hid_generic_set_report(uint8_t dev_addr, void* p_report, bool int_on_complete); -tusb_interface_status_t tuh_hid_generic_get_status(uint8_t dev_addr); -tusb_interface_status_t tuh_hid_generic_set_status(uint8_t dev_addr); - -//------------- Application Callback -------------// -void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); - -/** @} */ // Generic_Host -/** @} */ // ClassDriver_HID_Generic - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From a5cd81a2266541c14dfeb2617b2a826296aab688 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 20:04:19 +0700 Subject: correct hid host mount/unmount callback rename HOST_CLASS_HID to CFG_TUH_HID --- examples/host/cdc_msc_hid/src/main.c | 4 +-- src/class/hid/hid_host.c | 64 ++++++++++++++++++++---------------- src/class/hid/hid_host.h | 6 ++-- src/host/usbh.c | 2 +- src/tusb.h | 2 +- src/tusb_option.h | 3 -- 6 files changed, 42 insertions(+), 39 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 5543e9efb..ccc50bbf2 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -154,7 +154,7 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -void tuh_hid_mounted_cb(uint8_t dev_addr) +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { // application set-up printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); @@ -162,7 +162,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr) tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } -void tuh_hid_unmounted_cb(uint8_t dev_addr) +void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { // application tear-down printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a5aa33c2c..6e8ec47c8 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_HOST_ENABLED && HOST_CLASS_HID) +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "common/tusb_common.h" #include "hid_host.h" @@ -76,8 +76,8 @@ typedef struct typedef struct { - uint8_t itf_count; - hidh_interface_t interface[CFG_TUH_HID]; + uint8_t inst_count; + hidh_interface_t instances[CFG_TUH_HID]; } hidh_device_t; static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; @@ -93,15 +93,28 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) // Get Interface by instance number TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) { - return &_hidh_dev[dev_addr-1].interface[instance]; + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + } + + return 0xff; } // Get Interface by interface number static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) { - for(uint8_t inst=0; institf_num == itf) && (hid->ep_in != 0) ) return hid; } @@ -114,18 +127,13 @@ static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) //--------------------------------------------------------------------+ uint8_t tuh_n_hid_instance_count(uint8_t daddr) { - return get_dev(daddr)->itf_count; + return get_dev(daddr)->inst_count; } //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline void hidh_interface_close(hidh_interface_t *p_hid) -{ - tu_memclr(p_hid, sizeof(hidh_interface_t)); -} - // called from public API need to validate parameters tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) { @@ -234,19 +242,13 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void hidh_close(uint8_t dev_addr) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); - - if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); - hidh_interface_close(hid_itf); - -#if CFG_TUH_HID_MOUSE - if( mouseh_data[dev_addr-1].ep_in != 0 ) + hidh_device_t* hid_dev = get_dev(dev_addr); + if (tuh_hid_unmounted_cb) { - hidh_interface_close(&mouseh_data[dev_addr-1]); - tuh_hid_mouse_unmounted_cb( dev_addr ); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_unmounted_cb(dev_addr, inst); } -#endif + + tu_memclr(hid_dev, sizeof(hidh_device_t)); } //--------------------------------------------------------------------+ @@ -270,7 +272,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->itf_count < CFG_TUH_HID); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -280,8 +282,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // TODO also open endpoint OUT TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->itf_count); - hid_dev->itf_count++; + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); + hid_dev->inst_count++; hid_itf->itf_num = desc_itf->bInterfaceNumber; hid_itf->ep_in = desc_ep->bEndpointAddress; @@ -393,14 +395,18 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co { TU_ASSERT(XFER_RESULT_SUCCESS == result); uint8_t const itf_num = (uint8_t) request->wIndex; - hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + uint8_t const inst = get_instance_id(dev_addr, itf_num); + //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - if (tuh_hid_descriptor_report_cb) tuh_hid_descriptor_report_cb(dev_addr, hid_itf->itf_num, usbh_get_enum_buf(), request->wLength); + if (tuh_hid_descriptor_report_cb) + { + tuh_hid_descriptor_report_cb(dev_addr, inst, usbh_get_enum_buf(), request->wLength); + } // TODO Report descriptor parser // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 98c652338..c45ca9bd4 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -60,7 +60,7 @@ // Get the number of HID instances uint8_t tuh_n_hid_instance_count(uint8_t daddr); -// Check if HID instance support keyboard +// Check if HID instance has keyboard bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); @@ -86,8 +86,8 @@ uint8_t tuh_hid_instance_count(void) // Note: enumeration is still not complete yet TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); -TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); diff --git a/src/host/usbh.c b/src/host/usbh.c index fe0b2b987..3008c9b4e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -74,7 +74,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = }, #endif - #if HOST_CLASS_HID + #if CFG_TUH_HID { DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, diff --git a/src/tusb.h b/src/tusb.h index cc82c440d..1678ef5d8 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -42,7 +42,7 @@ #if TUSB_OPT_HOST_ENABLED #include "host/usbh.h" - #if HOST_CLASS_HID + #if CFG_TUH_HID #include "class/hid/hid_host.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 53d3d9d20..97e12806b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -266,9 +266,6 @@ #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif - //------------- HID CLASS -------------// - #define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC ) - #ifndef CFG_TUH_ENUMERATION_BUFSZIE #define CFG_TUH_ENUMERATION_BUFSZIE 256 #endif -- cgit v1.3.1 From 69defb5edc34979c9476533ba3bb49e070879ceb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 20:19:00 +0700 Subject: rename and moving --- src/class/hid/hid_host.c | 87 +++++++++++++++++++++++++----------------------- src/host/usbh.c | 16 +++++---- 2 files changed, 55 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6e8ec47c8..80680894f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -82,45 +82,10 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _report_desc_buf[256]; - -// Get Device by address -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) -{ - return &_hidh_dev[dev_addr-1]; -} - -// Get Interface by instance number -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) -{ - return &_hidh_dev[dev_addr-1].instances[instance]; -} - -// Get instance ID by interface number -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; - } - - return 0xff; -} - -// Get Interface by interface number -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; - } - - return NULL; -} +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf); +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf); //--------------------------------------------------------------------+ // Application API @@ -290,8 +255,6 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor hid_itf->valid = true; - TU_LOG2_HEX(hid_itf->ep_in); - // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); @@ -414,4 +377,46 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +//--------------------------------------------------------------------+ +// Instance helper +//--------------------------------------------------------------------+ + +// Get Device by address +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) +{ + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + } + + return 0xff; +} + +// Get Interface by interface number +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; + } + + return NULL; +} + #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 3008c9b4e..7a021c11c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -282,7 +282,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); } -bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) +bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { tusb_desc_endpoint_t ep0_desc = { @@ -297,9 +297,11 @@ bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); } -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { - bool ret = hcd_edpt_open(rhport, dev_addr, ep_desc); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + + bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep); if (ret) { @@ -315,7 +317,7 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); - uint8_t const ep_addr = ep_desc->bEndpointAddress; + uint8_t const ep_addr = desc_ep->bEndpointAddress; dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; } @@ -526,7 +528,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) if (drv_id != 0xff) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - TU_LOG2("%s set config itf = %u\r\n", driver->name, itf_num); + TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; } @@ -702,7 +704,7 @@ static bool enum_new_device(hcd_event_t* event) static bool enum_request_addr0_device_desc(void) { // TODO probably doesn't need to open/close each enumeration - TU_ASSERT( usbh_pipe_control_open(0, 8) ); + TU_ASSERT( usbh_edpt_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); @@ -786,7 +788,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); -- cgit v1.3.1 From b7a8b278c83b9b8e03a328e17f4b833f925226a2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 21:40:17 +0700 Subject: rename tuh_device_is_configured() to tuh_device_configured() - remove tuh_device_get_state() - more hid mouse clean up --- examples/host/cdc_msc_hid/src/keyboard_helper.h | 59 ------------------------- examples/host/cdc_msc_hid/src/main.c | 12 ++--- src/class/hid/hid_host.c | 38 +++++++++++----- src/class/hid/hid_host.h | 19 +++----- src/host/usbh.c | 5 +-- src/host/usbh.h | 6 +-- 6 files changed, 42 insertions(+), 97 deletions(-) delete mode 100644 examples/host/cdc_msc_hid/src/keyboard_helper.h (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/keyboard_helper.h b/examples/host/cdc_msc_hid/src/keyboard_helper.h deleted file mode 100644 index 1fde2768c..000000000 --- a/examples/host/cdc_msc_hid/src/keyboard_helper.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef KEYBOARD_HELPER_H -#define KEYBAORD_HELPER_H - -#include -#include - -#include "tusb.h" - -// look up new key in previous keys -inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) -{ - for(uint8_t i = 0; i < 6; i++) - { - if (p_report->keycode[i] == keycode) return true; - } - - return false; -} - -inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) -{ - return keycode > 128 ? 0 : - hid_keycode_to_ascii_tbl [keycode][modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ? 1 : 0]; -} - -void print_kbd_report(hid_keyboard_report_t *prev_report, hid_keyboard_report_t const *new_report) -{ - - printf("Report: "); - uint8_t c; - - // I assume it's possible to have up to 6 keypress events per report? - for (uint8_t i = 0; i < 6; i++) - { - // Check for key presses - if (new_report->keycode[i]) - { - // If not in prev report then it is newly pressed - if ( !find_key_in_report(prev_report, new_report->keycode[i]) ) - c = keycode_to_ascii(new_report->modifier, new_report->keycode[i]); - printf("press %c ", c); - } - - // Check for key depresses (i.e. was present in prev report but not here) - if (prev_report->keycode[i]) - { - // If not present in the current report then depressed - if (!find_key_in_report(new_report, prev_report->keycode[i])) - { - c = keycode_to_ascii(prev_report->modifier, prev_report->keycode[i]); - printf("depress %c ", c); - } - } - } - - printf("\n"); -} - -#endif \ No newline at end of file diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index ccc50bbf2..6b2d0affb 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -156,16 +156,18 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { - // application set-up - printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); +// printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + if (instance == 0) { tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); + } } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { - // application tear-down - printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +// printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); } #endif @@ -255,7 +257,7 @@ void hid_task(void) #endif #if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_mounted(addr) ) + if ( tuh_n_hid_n_mouse_mounted(addr, 0) ) { if ( !tuh_hid_mouse_is_busy(addr) ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 80680894f..72cecb8d1 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -104,7 +104,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int { //------------- parameters validation -------------// // TODO change to use is configured function - TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); + TU_ASSERT(tuh_device_configured(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); @@ -113,32 +113,45 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int return TUSB_ERROR_NONE; } +//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +//{ +// +//} + //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(daddr, instance); + + // TODO check rid_keyboard + return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); +} + +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + hidh_interface_t* hid_itf = get_instance(daddr, instance); // TODO check rid_keyboard - return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); + return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); } tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + uint8_t inst = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, inst); return hidh_interface_get_report(dev_addr, buffer, hid_itf); } bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - uint8_t instance = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t inst = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - return tuh_n_hid_n_keyboard_mounted(dev_addr, instance) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_n_hid_n_keyboard_mounted(dev_addr, inst) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } //--------------------------------------------------------------------+ @@ -149,14 +162,15 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// -bool tuh_hid_mouse_mounted(uint8_t dev_addr) +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { - return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return tuh_device_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); + return tuh_n_hid_n_mouse_mounted(dev_addr, 0) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index c45ca9bd4..0052a2b0c 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -60,10 +60,14 @@ // Get the number of HID instances uint8_t tuh_n_hid_instance_count(uint8_t daddr); -// Check if HID instance has keyboard -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); +// Check if HID instance is mounted +//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +// Check if HID instance with Keyboard is mounted +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); +// Check if HID instance with Mouse is mounted +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); //--------------------------------------------------------------------+ // Application API (Single device) @@ -101,10 +105,6 @@ TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -// TODO used weak attr if build failed without KEYBOARD enabled -// TODO remove -extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; - /** \brief Check if device supports Keyboard interface or not * \param[in] dev_addr device address * \retval true if device supports Keyboard interface @@ -170,13 +170,6 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -/** \brief Check if device supports Mouse interface or not - * \param[in] dev_addr device address - * \retval true if device supports Mouse interface - * \retval false if device does not support Mouse interface or is not mounted - */ -bool tuh_hid_mouse_mounted(uint8_t dev_addr); - /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a021c11c..f1c386a4d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -152,10 +152,9 @@ uint8_t* usbh_get_enum_buf(void) //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ -tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) +bool tuh_device_configured(uint8_t dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); - return (tusb_device_state_t) _usbh_devices[dev_addr].state; + return _usbh_devices[dev_addr].configured; } tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) diff --git a/src/host/usbh.h b/src/host/usbh.h index 5e7abe868..e503ef8fb 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -88,13 +88,9 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); -static inline bool tuh_device_is_configured(uint8_t dev_addr) -{ - return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; -} +bool tuh_device_configured(uint8_t dev_addr); bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 7305fec4db13e846aa945b26d18418ec1e5e4ce7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 12:27:09 +0700 Subject: change hid device report len from uint8 to uint16 --- src/class/hid/hid_device.c | 6 +++--- src/class/hid/hid_device.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 18d35bc20..ccd47a290 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -76,7 +76,7 @@ bool tud_hid_n_ready(uint8_t itf) return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint16_t len) { uint8_t const rhport = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; @@ -87,7 +87,7 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ // prepare data if (report_id) { - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); + len = tu_min16(len, CFG_TUD_HID_EP_BUFSIZE-1); p_hid->epin_buf[0] = report_id; memcpy(p_hid->epin_buf+1, report, len); @@ -95,7 +95,7 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ }else { // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); + len = tu_min16(len, CFG_TUD_HID_EP_BUFSIZE); memcpy(p_hid->epin_buf, report, len); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 7520d3453..a36f7e623 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -61,7 +61,7 @@ bool tud_hid_n_ready(uint8_t itf); bool tud_hid_n_boot_mode(uint8_t itf); // Send report to host -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint16_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t @@ -128,7 +128,7 @@ static inline bool tud_hid_boot_mode(void) return tud_hid_n_boot_mode(0); } -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) { return tud_hid_n_report(0, report_id, report, len); } -- cgit v1.3.1 From 9324fd8f2e549434fd2a399500ae1dc766530046 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 13:42:52 +0700 Subject: more hid host API rework --- examples/host/cdc_msc_hid/src/main.c | 28 ++++++----- src/class/hid/hid_host.c | 94 ++++++++++++------------------------ src/class/hid/hid_host.h | 42 +++------------- 3 files changed, 53 insertions(+), 111 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 6b2d0affb..c37cad15d 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -160,7 +160,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); if (instance == 0) { - tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); + tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } @@ -243,28 +243,30 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) void hid_task(void) { - uint8_t const addr = 1; + uint8_t const daddr = 1; + uint8_t const instance = 0; #if CFG_TUH_HID_KEYBOARD - if ( tuh_n_hid_n_keyboard_mounted(addr, 0) ) + if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) { - if ( !tuh_hid_keyboard_is_busy(addr) ) + if ( tuh_n_hid_n_ready(daddr, instance) ) { process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); + tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } #endif #if CFG_TUH_HID_MOUSE - if ( tuh_n_hid_n_mouse_mounted(addr, 0) ) - { - if ( !tuh_hid_mouse_is_busy(addr) ) - { - process_mouse_report(&usb_mouse_report); - tuh_hid_mouse_get_report(addr, &usb_mouse_report); - } - } + (void) usb_mouse_report; +// if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) +// { +// if ( tuh_n_hid_n_ready(daddr, instance) ) +// { +// process_mouse_report(&usb_mouse_report); +// tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); +// } +// } #endif } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 72cecb8d1..83e65dc52 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -52,19 +52,19 @@ typedef struct uint8_t report_desc_type; uint16_t report_desc_len; - - bool valid; - uint16_t report_size; // TODO remove later + uint16_t ep_size; uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol - uint8_t report_count; // Number of reports + uint8_t report_count; // Number of reports struct { - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report uint8_t usage_page; uint8_t usage; + + // TODO just use the endpint size for now + uint8_t in_len; // length of IN report + uint8_t out_len; // length of OUT report }reports[CFG_TUH_HID_REPORT_MAX]; // Parsed Report ID for convenient API @@ -99,59 +99,43 @@ uint8_t tuh_n_hid_instance_count(uint8_t daddr) // HID Interface common functions //--------------------------------------------------------------------+ -// called from public API need to validate parameters -tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) { - //------------- parameters validation -------------// - // TODO change to use is configured function - TU_ASSERT(tuh_device_configured(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); - TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; - - return TUSB_ERROR_NONE; + hidh_interface_t* hid_itf = get_instance(daddr, instance); + return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) -//{ -// -//} - -//--------------------------------------------------------------------+ -// KEYBOARD -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); - // TODO check rid_keyboard - return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len) { + TU_VERIFY( tuh_device_ready(daddr) && report && len); hidh_interface_t* hid_itf = get_instance(daddr, instance); - // TODO check rid_keyboard - return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); -} + // TODO change to claim endpoint + TU_VERIFY( !hcd_edpt_busy(daddr, hid_itf->ep_in) ); -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) -{ - uint8_t inst = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + len = tu_min16(len, hid_itf->ep_size); - return hidh_interface_get_report(dev_addr, buffer, hid_itf); + return usbh_edpt_xfer(daddr, hid_itf->ep_in, report, len); } -bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) +//--------------------------------------------------------------------+ +// KEYBOARD +//--------------------------------------------------------------------+ + +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) { - uint8_t inst = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + hidh_interface_t* hid_itf = get_instance(daddr, instance); - return tuh_n_hid_n_keyboard_mounted(dev_addr, inst) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + // TODO check rid_keyboard + return tuh_device_ready(daddr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -165,26 +149,11 @@ static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { // hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); -} - -bool tuh_hid_mouse_is_busy(uint8_t dev_addr) -{ - return tuh_n_hid_n_mouse_mounted(dev_addr, 0) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); -} - -tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) -{ - return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]); + return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } #endif -//--------------------------------------------------------------------+ -// GENERIC -//--------------------------------------------------------------------+ - - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ @@ -264,10 +233,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - hid_itf->valid = true; + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->ep_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 0052a2b0c..23b23e657 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -61,7 +61,12 @@ uint8_t tuh_n_hid_instance_count(uint8_t daddr); // Check if HID instance is mounted -//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); + +// Check if the interface is ready to use +bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); + +bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len); // Check if HID instance with Keyboard is mounted bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); @@ -69,6 +74,7 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); // Check if HID instance with Mouse is mounted bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); + //--------------------------------------------------------------------+ // Application API (Single device) //--------------------------------------------------------------------+ @@ -119,19 +125,6 @@ bool tuh_hid_keyboard_mounted(uint8_t dev_addr); * \note This function is primarily used for polling/waiting result after \ref tuh_hid_keyboard_get_report. * Alternatively, asynchronous event API can be used */ -bool tuh_hid_keyboard_is_busy(uint8_t dev_addr); - -/** \brief Perform a get report from Keyboard interface - * \param[in] dev_addr device address - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function - */ -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report); //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred @@ -170,27 +163,6 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is primarily used for polling/waiting result after \ref tuh_hid_mouse_get_report. - * Alternatively, asynchronous event API can be used - */ -bool tuh_hid_mouse_is_busy(uint8_t dev_addr); - -/** \brief Perform a get report from Mouse interface - * \param[in] dev_addr device address - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function - */ -tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void* p_report); - //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device -- cgit v1.3.1 From cc1b83412a0263f0f3d5db492f5680f4a9bb179b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 14:09:33 +0700 Subject: continue with hid host rework --- src/class/hid/hid_host.c | 92 +++++++++++++++++----------------- src/class/hid/hid_host.h | 126 ++++++++++------------------------------------- 2 files changed, 72 insertions(+), 146 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83e65dc52..dc29f7322 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -82,26 +82,25 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; +//------------- Internal prototypes -------------// TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf); -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); +static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -uint8_t tuh_n_hid_instance_count(uint8_t daddr) + +uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) { - return get_dev(daddr)->inst_count; + return get_dev(dev_addr)->inst_count; } -//--------------------------------------------------------------------+ -// HID Interface common functions -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } @@ -113,29 +112,29 @@ bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len) +bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len) { - TU_VERIFY( tuh_device_ready(daddr) && report && len); - hidh_interface_t* hid_itf = get_instance(daddr, instance); + TU_VERIFY( tuh_device_ready(dev_addr) && report && len); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO change to claim endpoint - TU_VERIFY( !hcd_edpt_busy(daddr, hid_itf->ep_in) ); + TU_VERIFY( !hcd_edpt_busy(dev_addr, hid_itf->ep_in) ); len = tu_min16(len, hid_itf->ep_size); - return usbh_edpt_xfer(daddr, hid_itf->ep_in, report, len); + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, report, len); } //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO check rid_keyboard - return tuh_device_ready(daddr) && (hid_itf->ep_in != 0); + return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -164,26 +163,16 @@ void hidh_init(void) bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { - (void) xferred_bytes; // TODO may need to use this para later + uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; - -#if CFG_TUH_HID_KEYBOARD -// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_keyboard_isr(dev_addr, event); -// return true; -// } -#endif - -#if CFG_TUH_HID_MOUSE -// if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_mouse_isr(dev_addr, event); -// return true; -// } -#endif + if ( dir == TUSB_DIR_IN ) + { + if (tuh_hid_get_report_complete_cb) tuh_hid_get_report_complete_cb(dev_addr, instance, xferred_bytes); + }else + { + if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); + } return true; } @@ -311,7 +300,7 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r uint8_t const itf_num = (uint8_t) request->wIndex; - hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance_by_itfnum(dev_addr, itf_num); // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long @@ -340,7 +329,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co { TU_ASSERT(XFER_RESULT_SUCCESS == result); uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const inst = get_instance_id(dev_addr, itf_num); + uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num); //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); if (tuh_hid_descriptor_report_cb) @@ -375,30 +364,43 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a return &_hidh_dev[dev_addr-1].instances[instance]; } +// Get instance by interface number +static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return hid; + } + + return NULL; +} + // Get instance ID by interface number -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) { for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) { hidh_interface_t *hid = get_instance(dev_addr, inst); - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return inst; } return 0xff; } -// Get Interface by interface number -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +// Get instance ID by endpoint address +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) { for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) { hidh_interface_t *hid = get_instance(dev_addr, inst); - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; + if ( (ep_addr == hid->ep_in) || ( ep_addr == hid->ep_out) ) return inst; } - return NULL; + return 0xff; } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 23b23e657..45f03a192 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -58,134 +58,58 @@ //--------------------------------------------------------------------+ // Get the number of HID instances -uint8_t tuh_n_hid_instance_count(uint8_t daddr); +uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); // Check if the interface is ready to use bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); -bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len); +// Get Report from device +bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); -// Check if HID instance with Keyboard is mounted -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); - -// Check if HID instance with Mouse is mounted -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); -//--------------------------------------------------------------------+ -// Application API (Single device) -//--------------------------------------------------------------------+ +//------------- -------------// -// Get the number of HID instances -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_hid_instance_count(void) -{ - return tuh_n_hid_instance_count(1); -} +// Check if HID instance with Keyboard is mounted +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance); -//bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); +// Check if HID instance with Mouse is mounted +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ // Invoked when report descriptor is received -// Note: enumeration is still not complete yet -TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +// Note: enumeration is still not complete yet at this time +TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +// Invoked when device with hid interface is mounted TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); - +// Invoked when device with hid interface is un-mounted +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); -//--------------------------------------------------------------------+ -// KEYBOARD Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/** \defgroup Keyboard_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -/** \brief Check if device supports Keyboard interface or not - * \param[in] dev_addr device address - * \retval true if device supports Keyboard interface - * \retval false if device does not support Keyboard interface or is not mounted - */ -bool tuh_hid_keyboard_mounted(uint8_t dev_addr); - -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is primarily used for polling/waiting result after \ref tuh_hid_keyboard_get_report. - * Alternatively, asynchronous event API can be used - */ - -//------------- Application Callback -------------// -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note Application should schedule the next report by calling \ref tuh_hid_keyboard_get_report within this callback - */ -void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event); - -/** \brief Callback function that will be invoked when a device with Keyboard interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ -void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr); - -/** \brief Callback function that will be invoked when a device with Keyboard interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); +// Invoked when received Report from device +TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); -/** @} */ // Keyboard_Host -/** @} */ // ClassDriver_HID_Keyboard +// Invoked when Sent Report to device +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); //--------------------------------------------------------------------+ -// MOUSE Application API +// Application API (Single device) //--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ -/** \defgroup Mouse_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -//------------- Application Callback -------------// -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note Application should schedule the next report by calling \ref tuh_hid_mouse_get_report within this callback - */ -void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event); - -/** \brief Callback function that will be invoked when a device with Mouse interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ -void tuh_hid_mouse_mounted_cb(uint8_t dev_addr); +// Get the number of HID instances +TU_ATTR_ALWAYS_INLINE static inline +uint8_t tuh_hid_instance_count(void) +{ + return tuh_n_hid_instance_count(1); +} -/** \brief Callback function that will be invoked when a device with Mouse interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ -void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From 641f55f1f18234dbcf3f2b5d46d2231a5e9abae3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 15:44:00 +0700 Subject: remove CFG_TUH_HID_KEYBOARD and CFG_TUH_HID_MOUSE --- examples/host/cdc_msc_hid/src/main.c | 30 ++++------------------------- examples/host/cdc_msc_hid/src/tusb_config.h | 6 ------ src/class/hid/hid_host.c | 4 +--- src/host/hcd.h | 5 ++--- 4 files changed, 7 insertions(+), 38 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c37cad15d..17f649aa4 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -51,14 +51,13 @@ int main(void) { // tinyusb host task tuh_task(); - led_blinking_task(); #if CFG_TUH_CDC cdc_task(); #endif -#if CFG_TUH_HID_KEYBOARD || CFG_TUH_HID_MOUSE +#if CFG_TUH_HID hid_task(); #endif } @@ -109,8 +108,6 @@ void cdc_task(void) //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ -#if CFG_TUH_HID_KEYBOARD - CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; @@ -158,6 +155,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); +// printf("A Mouse device (address %d) is mounted\r\n", dev_addr); if (instance == 0) { tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); @@ -168,11 +166,9 @@ void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); // printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); +// printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } -#endif - -#if CFG_TUH_HID_MOUSE CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; @@ -225,28 +221,12 @@ static inline void process_mouse_report(hid_mouse_report_t const * p_report) } -void tuh_hid_mouse_mounted_cb(uint8_t dev_addr) -{ - // application set-up - printf("A Mouse device (address %d) is mounted\r\n", dev_addr); -} - -void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) -{ - // application tear-down - printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); -} - -#endif - - void hid_task(void) { uint8_t const daddr = 1; uint8_t const instance = 0; -#if CFG_TUH_HID_KEYBOARD if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) { if ( tuh_n_hid_n_ready(daddr, instance) ) @@ -255,9 +235,8 @@ void hid_task(void) tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } -#endif -#if CFG_TUH_HID_MOUSE +// #if CFG_TUH_HID_MOUSE (void) usb_mouse_report; // if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) // { @@ -267,7 +246,6 @@ void hid_task(void) // tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); // } // } -#endif } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index e1e02e31e..01296cd26 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -76,13 +76,7 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 - #define CFG_TUH_HID 2 - -#define CFG_TUH_HID_KEYBOARD 1 -#define CFG_TUH_HID_MOUSE 1 -#define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) - #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index dc29f7322..60ee667d0 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -140,8 +140,8 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ -#if CFG_TUH_HID_MOUSE +// TODO remove static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// @@ -151,8 +151,6 @@ bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } -#endif - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ diff --git a/src/host/hcd.h b/src/host/hcd.h index 4810ef8da..a470a45e8 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -85,9 +85,8 @@ typedef struct #if TUSB_OPT_HOST_ENABLED // Max number of endpoints per device enum { - HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC + - CFG_TUH_MSC*2 + CFG_TUH_CDC*3), - + // TODO better computation + HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, }; -- cgit v1.3.1 From 9ddc3bfd6dc1450d30c16c0a1d07240ea74a13bf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 May 2021 01:02:47 +0700 Subject: more host hid API adding hid parser --- examples/host/cdc_msc_hid/src/tusb_config.h | 6 +- src/class/hid/hid.h | 60 +++++++++-- src/class/hid/hid_host.c | 148 +++++++++++++++++++++------- src/class/hid/hid_host.h | 35 +++++-- 4 files changed, 196 insertions(+), 53 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 01296cd26..fd0432799 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -86,11 +86,7 @@ // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports -#define CFG_TUH_HID_REPORT_MAX 4 - -// Max buffer -#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 - +#define CFG_TUH_HID_REPORT_MAX 4 #ifdef __cplusplus } diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 351a4d600..f0ad03603 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -479,6 +479,7 @@ typedef enum //--------------------------------------------------------------------+ // REPORT DESCRIPTOR //--------------------------------------------------------------------+ + //------------- ITEM & TAG -------------// #define HID_REPORT_DATA_0(data) #define HID_REPORT_DATA_1(data) , data @@ -488,18 +489,31 @@ typedef enum #define HID_REPORT_ITEM(data, tag, type, size) \ (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) -#define RI_TYPE_MAIN 0 -#define RI_TYPE_GLOBAL 1 -#define RI_TYPE_LOCAL 2 +// Report Item Types +enum { + RI_TYPE_MAIN = 0, + RI_TYPE_GLOBAL = 1, + RI_TYPE_LOCAL = 2 +}; + +//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// + +// Report Item Main group +enum { + RI_MAIN_INPUT = 8, + RI_MAIN_OUTPUT = 9, + RI_MAIN_COLLECTION = 10, + RI_MAIN_FEATURE = 11, + RI_MAIN_COLLECTION_END = 12 +}; -//------------- MAIN ITEMS 6.2.2.4 -------------// #define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) #define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) #define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) #define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) #define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) -//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------// +//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// #define HID_DATA (0<<0) #define HID_CONSTANT (1<<0) @@ -527,7 +541,7 @@ typedef enum #define HID_BITFIELD (0<<8) #define HID_BUFFERED_BYTES (1<<8) -//------------- COLLECTION ITEM 6.2.2.6 -------------// +//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// enum { HID_COLLECTION_PHYSICAL = 0, HID_COLLECTION_APPLICATION, @@ -538,7 +552,24 @@ enum { HID_COLLECTION_USAGE_MODIFIER }; -//------------- GLOBAL ITEMS 6.2.2.7 -------------// +//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// + +// Report Item Global group +enum { + RI_GLOBAL_USAGE_PAGE = 0, + RI_GLOBAL_LOGICAL_MIN = 1, + RI_GLOBAL_LOGICAL_MAX = 2, + RI_GLOBAL_PHYSICAL_MIN = 3, + RI_GLOBAL_PHYSICAL_MAX = 4, + RI_GLOBAL_UNIT_EXPONENT = 5, + RI_GLOBAL_UNIT = 6, + RI_GLOBAL_REPORT_SIZE = 7, + RI_GLOBAL_REPORT_ID = 8, + RI_GLOBAL_REPORT_COUNT = 9, + RI_GLOBAL_PUSH = 10, + RI_GLOBAL_POP = 11 +}; + #define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) #define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) @@ -573,6 +604,21 @@ enum { #define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) //------------- LOCAL ITEMS 6.2.2.8 -------------// + +enum { + RI_LOCAL_USAGE = 0, + RI_LOCAL_USAGE_MIN = 1, + RI_LOCAL_USAGE_MAX = 2, + RI_LOCAL_DESIGNATOR_INDEX = 3, + RI_LOCAL_DESIGNATOR_MIN = 4, + RI_LOCAL_DESIGNATOR_MAX = 5, + // 6 is reserved + RI_LOCAL_STRING_INDEX = 7, + RI_LOCAL_STRING_MIN = 8, + RI_LOCAL_STRING_MAX = 9, + RI_LOCAL_DELIMITER = 10, +}; + #define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) #define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 60ee667d0..862026b5b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,14 +35,15 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard - "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse - "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control - "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control - "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen - "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF +/* + "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard + "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse + "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control + "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control + "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen + "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF */ typedef struct { @@ -57,22 +58,14 @@ typedef struct uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol - uint8_t report_count; // Number of reports - struct { - uint8_t usage_page; - uint8_t usage; - - // TODO just use the endpint size for now - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report - }reports[CFG_TUH_HID_REPORT_MAX]; + tuh_hid_report_info_t report_info; // Parsed Report ID for convenient API uint8_t rid_keyboard; uint8_t rid_mouse; uint8_t rid_gamepad; uint8_t rid_consumer; -}hidh_interface_t; +} hidh_interface_t; typedef struct { @@ -104,6 +97,23 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } +uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->boot_protocol; +} + +bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->boot_mode; +} + +tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance) +{ + return &get_instance(dev_addr, instance)->report_info; +} + bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) { TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); @@ -190,6 +200,7 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ +static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len); static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -235,23 +246,25 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { + TU_LOG2(" Boot Keyboard\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_count = 1; + hid_itf->report_info.count = 1; - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[0].out_len = 1; + hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; + hid_itf->report_info.info[0].in_len = 8; + hid_itf->report_info.info[0].out_len = 1; } else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { + TU_LOG2(" Boot Mouse\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_count = 1; + hid_itf->report_info.count = 1; - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[0].out_len = 1; + hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; + hid_itf->report_info.info[0].in_len = 5; + hid_itf->report_info.info[0].out_len = 0; } else { @@ -326,19 +339,23 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num); - //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + uint8_t const* desc_report = usbh_get_enum_buf(); + uint16_t const desc_len = request->wLength; if (tuh_hid_descriptor_report_cb) { - tuh_hid_descriptor_report_cb(dev_addr, inst, usbh_get_enum_buf(), request->wLength); + tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len); } - // TODO Report descriptor parser + parse_report_descriptor(hid_itf, desc_report, desc_len); // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst); + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); @@ -346,8 +363,69 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +// Parse Report Descriptor to tuh_hid_report_info_t +static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) +{ + enum + { + USAGE_PAGE = 0x05, + USAGE = 0x09, + USAGE_MIN = 0x19, + USAGE_MAX = 0x29, + LOGICAL_MIN = 0x15, + LOGICAL_MAX = 0x25, + REPORT_SIZE = 0x75, + REPORT_COUNT = 0x95 + }; + + // Short Item 6.2.2.2 USB HID 1.11 + union TU_ATTR_PACKED + { + uint8_t byte; + struct TU_ATTR_PACKED + { + uint8_t size : 2; + uint8_t type : 2; + uint8_t tag : 4; + }; + } header; + + while(desc_len) + { + header.byte = *desc_report++; + + uint8_t const tag = header.tag; + uint8_t const type = header.type; + uint8_t const size = header.size; + + desc_len--; + + TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); + for(uint32_t i=0; i Date: Fri, 14 May 2021 12:23:09 +0700 Subject: adding hid parser --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 ++ src/class/hid/hid_host.c | 55 ++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fd0432799..7c13cbd2f 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,6 +84,8 @@ //------------- HID -------------// +//#define CFG_TUH_HID_EP_BUFSIZE 64 + // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports #define CFG_TUH_HID_REPORT_MAX 4 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 862026b5b..ba9707a69 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -366,19 +366,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // Parse Report Descriptor to tuh_hid_report_info_t static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) { - enum - { - USAGE_PAGE = 0x05, - USAGE = 0x09, - USAGE_MIN = 0x19, - USAGE_MAX = 0x29, - LOGICAL_MIN = 0x15, - LOGICAL_MAX = 0x25, - REPORT_SIZE = 0x75, - REPORT_COUNT = 0x95 - }; - - // Short Item 6.2.2.2 USB HID 1.11 + // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED { uint8_t byte; @@ -407,12 +395,53 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de switch(type) { case RI_TYPE_MAIN: + switch (tag) + { + case RI_MAIN_INPUT: break; + case RI_MAIN_OUTPUT: break; + case RI_MAIN_FEATURE: break; + case RI_MAIN_COLLECTION: break; + case RI_MAIN_COLLECTION_END: break; + + default: break; + } break; case RI_TYPE_GLOBAL: + switch(tag) + { + case RI_GLOBAL_USAGE_PAGE : break; + case RI_GLOBAL_LOGICAL_MIN : break; + case RI_GLOBAL_LOGICAL_MAX : break; + case RI_GLOBAL_PHYSICAL_MIN : break; + case RI_GLOBAL_PHYSICAL_MAX : break; + case RI_GLOBAL_UNIT_EXPONENT : break; + case RI_GLOBAL_UNIT : break; + case RI_GLOBAL_REPORT_SIZE : break; + case RI_GLOBAL_REPORT_ID : break; + case RI_GLOBAL_REPORT_COUNT : break; + case RI_GLOBAL_PUSH : break; + case RI_GLOBAL_POP : break; + + default: break; + } break; case RI_TYPE_LOCAL: + switch(tag) + { + case RI_LOCAL_USAGE : break; + case RI_LOCAL_USAGE_MIN : break; + case RI_LOCAL_USAGE_MAX : break; + case RI_LOCAL_DESIGNATOR_INDEX : break; + case RI_LOCAL_DESIGNATOR_MIN : break; + case RI_LOCAL_DESIGNATOR_MAX : break; + case RI_LOCAL_STRING_INDEX : break; + case RI_LOCAL_STRING_MIN : break; + case RI_LOCAL_STRING_MAX : break; + case RI_LOCAL_DELIMITER : break; + default: break; + } break; // error -- cgit v1.3.1 From 93661042d96d08ad9f0de66fa44d22bdc4faeb08 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 May 2021 17:47:02 +0700 Subject: more API update - remove tuh_n_hid_n_get_report() - usbh auto queue get report and invoke callback when received data --- examples/host/cdc_msc_hid/src/main.c | 35 +++--------------- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/class/hid/hid_host.c | 55 ++++++++++++++--------------- src/class/hid/hid_host.h | 10 +++--- 4 files changed, 38 insertions(+), 64 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 17f649aa4..40642561b 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -108,7 +108,6 @@ void cdc_task(void) //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // look up new key in previous keys @@ -156,10 +155,6 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); // printf("A Mouse device (address %d) is mounted\r\n", dev_addr); - - if (instance == 0) { - tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); - } } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) @@ -169,9 +164,6 @@ void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) // printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } - -CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; - void cursor_movement(int8_t x, int8_t y, int8_t wheel) { //------------- X -------------// @@ -220,32 +212,13 @@ static inline void process_mouse_report(hid_mouse_report_t const * p_report) cursor_movement(p_report->x, p_report->y, p_report->wheel); } - +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + process_kbd_report( (hid_keyboard_report_t*) report ); +} void hid_task(void) { - uint8_t const daddr = 1; - uint8_t const instance = 0; - - if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) - { - if ( tuh_n_hid_n_ready(daddr, instance) ) - { - process_kbd_report(&usb_keyboard_report); - tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); - } - } - -// #if CFG_TUH_HID_MOUSE - (void) usb_mouse_report; -// if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) -// { -// if ( tuh_n_hid_n_ready(daddr, instance) ) -// { -// process_mouse_report(&usb_mouse_report); -// tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); -// } -// } } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 7c13cbd2f..8c82c0fef 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,7 +84,7 @@ //------------- HID -------------// -//#define CFG_TUH_HID_EP_BUFSIZE 64 +#define CFG_TUH_HID_EP_BUFSIZE 64 // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ba9707a69..4c32d9b33 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -53,7 +53,9 @@ typedef struct uint8_t report_desc_type; uint16_t report_desc_len; - uint16_t ep_size; + + uint16_t epin_size; + uint16_t epout_size; uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol @@ -65,6 +67,9 @@ typedef struct uint8_t rid_mouse; uint8_t rid_gamepad; uint8_t rid_consumer; + + uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; + uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; } hidh_interface_t; typedef struct @@ -82,6 +87,11 @@ static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); +TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) +{ + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); +} + //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ @@ -122,19 +132,6 @@ bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len) -{ - TU_VERIFY( tuh_device_ready(dev_addr) && report && len); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // TODO change to claim endpoint - TU_VERIFY( !hcd_edpt_busy(dev_addr, hid_itf->ep_in) ); - - len = tu_min16(len, hid_itf->ep_size); - - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, report, len); -} - //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ @@ -147,18 +144,11 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ - // TODO remove -static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 - -//------------- Public API -------------// bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { -// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -173,10 +163,17 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 { uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); if ( dir == TUSB_DIR_IN ) { - if (tuh_hid_get_report_complete_cb) tuh_hid_get_report_complete_cb(dev_addr, instance, xferred_bytes); + if (tuh_hid_get_report_cb) + { + tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); + } + + // queue next report + hidh_get_report(dev_addr, hid_itf); }else { if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); @@ -233,7 +230,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->itf_num = desc_itf->bInterfaceNumber; hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->ep_size = desc_ep->wMaxPacketSize.size; + hid_itf->epin_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; @@ -357,6 +354,9 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // enumeration is complete if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); + // queue transfer for IN endpoint + hidh_get_report(dev_addr, hid_itf); + // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); @@ -381,13 +381,12 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de while(desc_len) { header.byte = *desc_report++; + desc_len--; - uint8_t const tag = header.tag; + uint8_t const tag = header.tag; uint8_t const type = header.type; uint8_t const size = header.size; - desc_len--; - TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); for(uint32_t i=0; i Date: Fri, 14 May 2021 18:07:58 +0700 Subject: fix compile --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index a36f7e623..6b876ae74 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -80,7 +80,7 @@ bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline bool tud_hid_boot_mode(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -- cgit v1.3.1 From da6a7fb2bbb5ee07914e684a5162a9534c10bbb1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 08:18:25 +0700 Subject: update hid report descriptor macro --- src/class/hid/hid.h | 66 ++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index f0ad03603..42e16b288 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -507,11 +507,11 @@ enum { RI_MAIN_COLLECTION_END = 12 }; -#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) +#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) +#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) +#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) +#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) +#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) //------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// #define HID_DATA (0<<0) @@ -570,38 +570,38 @@ enum { RI_GLOBAL_POP = 11 }; -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) +#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) +#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n) +#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n) +#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n) +#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n) +#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n) +#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) -#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n) +#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n) +#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n), +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n) +#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) -#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) +#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) +#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) //------------- LOCAL ITEMS 6.2.2.8 -------------// @@ -619,14 +619,14 @@ enum { RI_LOCAL_DELIMITER = 10, }; -#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) +#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) +#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n) +#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n) +#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) //--------------------------------------------------------------------+ // Usage Table -- cgit v1.3.1 From ffdcf9a0d00ad8eba544c4404e27275685ef9cab Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 13:54:39 +0700 Subject: move report_info to application update API accordingly, update hid parser for usage, and usage_page. --- examples/host/cdc_msc_hid/src/hid_app.c | 209 ++++++++++++++++++++++++++++++++ examples/host/cdc_msc_hid/src/main.c | 124 +------------------ src/class/hid/hid_host.c | 201 +++++++++++++++++------------- src/class/hid/hid_host.h | 54 ++++----- 4 files changed, 356 insertions(+), 232 deletions(-) create mode 100644 examples/host/cdc_msc_hid/src/hid_app.c (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c new file mode 100644 index 000000000..4f8556274 --- /dev/null +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -0,0 +1,209 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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 "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +#define MAX_REPORT 4 + +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +static uint8_t _report_count[CFG_TUH_HID]; +static tuh_hid_report_info_t _report_info[CFG_TUH_HID][MAX_REPORT]; + +static void process_kbd_report(hid_keyboard_report_t const *report); +static void process_mouse_report(hid_mouse_report_t const * report); + +void hid_app_task(void) +{ +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); + + // Parse report descriptor with built-in parser + _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info[instance], MAX_REPORT, desc_report, desc_len); + + if (_report_count[instance]) + { + printf("Composite with %u reports", _report_count[instance]); + }else + { + printf("Single report"); + } + + // Interface protocol + const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t + uint8_t const interface_protocol = tuh_n_hid_n_interface_protocol(dev_addr, instance); + printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); +} + +void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) +{ + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +} + +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + uint8_t const rpt_count = _report_count[instance]; + tuh_hid_report_info_t* rpt_info; + + if (rpt_count) + { + // Composite report, 1st byte is report ID, data starts from 2nd byte + // Note: report index = report ID - 1 + uint8_t idx = report[0] - 1; + rpt_info = &_report_info[instance][idx]; + + report++; + }else + { + rpt_info = &_report_info[instance][0]; + } + + if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP ) + { + switch (rpt_info->usage) + { + case HID_USAGE_DESKTOP_KEYBOARD: + TU_LOG1("HID receive keyboard report\r\n"); + // Assume keyboard follow boot report layout + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_USAGE_DESKTOP_MOUSE: + TU_LOG1("HID receive mouse report\r\n"); + // Assume mouse follow boot report layout + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// Keyboard +//--------------------------------------------------------------------+ + +// look up new key in previous keys +static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) +{ + for(uint8_t i=0; i<6; i++) + { + if (report->keycode[i] == keycode) return true; + } + + return false; +} + +static void process_kbd_report(hid_keyboard_report_t const *report) +{ + static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released + + //------------- example code ignore control (non-printable) key affects -------------// + for(uint8_t i=0; i<6; i++) + { + if ( report->keycode[i] ) + { + if ( find_key_in_report(&prev_report, report->keycode[i]) ) + { + // exist in previous report means the current key is holding + }else + { + // not existed in previous report means the current key is pressed + bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; + putchar(ch); + if ( ch == '\r' ) putchar('\n'); // added new line for enter key + + fflush(stdout); // flush right away, else nanolib will wait for newline + } + } + // TODO example skips key released + } + + prev_report = *report; +} + +//--------------------------------------------------------------------+ +// Mouse +//--------------------------------------------------------------------+ + +void cursor_movement(int8_t x, int8_t y, int8_t wheel) +{ + // Move X using ansi escape + if ( x < 0) + { + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left + }else if ( x > 0) + { + printf(ANSI_CURSOR_FORWARD(%d), x); // move right + } + + // Move Y using ansi escape + if ( y < 0) + { + printf(ANSI_CURSOR_UP(%d), (-y)); // move up + }else if ( y > 0) + { + printf(ANSI_CURSOR_DOWN(%d), y); // move down + } + + // Scroll using ansi escape + if (wheel < 0) + { + printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up + }else if (wheel > 0) + { + printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down + } +} + +static void process_mouse_report(hid_mouse_report_t const * report) +{ + static hid_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; + if ( button_changed_mask & report->buttons) + { + printf(" %c%c%c ", + report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(report->x, report->y, report->wheel); +} diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 40642561b..7ae814e38 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -37,7 +37,7 @@ void print_greeting(void); void led_blinking_task(void); extern void cdc_task(void); -extern void hid_task(void); +extern void hid_app_task(void); /*------------- MAIN -------------*/ int main(void) @@ -58,7 +58,7 @@ int main(void) #endif #if CFG_TUH_HID - hid_task(); + hid_app_task(); #endif } @@ -106,127 +106,11 @@ void cdc_task(void) #endif //--------------------------------------------------------------------+ -// USB HID -//--------------------------------------------------------------------+ -uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; - -// look up new key in previous keys -static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) -{ - for(uint8_t i=0; i<6; i++) - { - if (p_report->keycode[i] == keycode) return true; - } - - return false; -} - -static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) -{ - static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released - - //------------- example code ignore control (non-printable) key affects -------------// - for(uint8_t i=0; i<6; i++) - { - if ( p_new_report->keycode[i] ) - { - if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) ) - { - // exist in previous report means the current key is holding - }else - { - // not existed in previous report means the current key is pressed - bool const is_shift = p_new_report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); - uint8_t ch = keycode2ascii[p_new_report->keycode[i]][is_shift ? 1 : 0]; - putchar(ch); - if ( ch == '\r' ) putchar('\n'); // added new line for enter key - - fflush(stdout); // flush right away, else nanolib will wait for newline - } - } - // TODO example skips key released - } - - prev_report = *p_new_report; -} - -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) -{ - printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); -// printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); -// printf("A Mouse device (address %d) is mounted\r\n", dev_addr); -} - -void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) -{ - printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); -// printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); -// printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); -} - -void cursor_movement(int8_t x, int8_t y, int8_t wheel) -{ - //------------- X -------------// - if ( x < 0) - { - printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left - }else if ( x > 0) - { - printf(ANSI_CURSOR_FORWARD(%d), x); // move right - }else { } - - //------------- Y -------------// - if ( y < 0) - { - printf(ANSI_CURSOR_UP(%d), (-y)); // move up - }else if ( y > 0) - { - printf(ANSI_CURSOR_DOWN(%d), y); // move down - }else { } - - //------------- wheel -------------// - if (wheel < 0) - { - printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up - }else if (wheel > 0) - { - printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down - }else { } -} - -static inline void process_mouse_report(hid_mouse_report_t const * p_report) -{ - static hid_mouse_report_t prev_report = { 0 }; - - //------------- button state -------------// - uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; - if ( button_changed_mask & p_report->buttons) - { - printf(" %c%c%c ", - p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); - } - - //------------- cursor movement -------------// - cursor_movement(p_report->x, p_report->y, p_report->wheel); -} - -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ - process_kbd_report( (hid_keyboard_report_t*) report ); -} - -void hid_task(void) -{ -} - -//--------------------------------------------------------------------+ -// tinyusb callbacks +// TinyUSB Callbacks //--------------------------------------------------------------------+ //--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ void led_blinking_task(void) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 4c32d9b33..0ffd32617 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -57,16 +57,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t boot_protocol; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol - - tuh_hid_report_info_t report_info; - - // Parsed Report ID for convenient API - uint8_t rid_keyboard; - uint8_t rid_mouse; - uint8_t rid_gamepad; - uint8_t rid_consumer; + uint8_t boot_interface; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; @@ -107,49 +99,30 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_protocol; + return hid_itf->boot_interface; } -bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->boot_mode; } -tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance) -{ - return &get_instance(dev_addr, instance)->report_info; -} - -bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) -{ - TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); - - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); -} - -//--------------------------------------------------------------------+ -// KEYBOARD -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // TODO check rid_keyboard - return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); -} +//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +//{ +// +//} -// TODO remove -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); -} +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) +//{ +// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); +// +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); +// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +//} //--------------------------------------------------------------------+ // USBH API @@ -167,10 +140,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( dir == TUSB_DIR_IN ) { - if (tuh_hid_get_report_cb) - { - tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); - } + TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); + TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); + tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); // queue next report hidh_get_report(dev_addr, hid_itf); @@ -197,7 +169,6 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len); static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -228,40 +199,40 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; hid_itf->epin_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { - hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; + hid_itf->boot_interface = desc_itf->bInterfaceProtocol; if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { TU_LOG2(" Boot Keyboard\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_info.count = 1; +// hid_itf->report_info.count = 1; - hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->report_info.info[0].in_len = 8; - hid_itf->report_info.info[0].out_len = 1; +// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; +// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; +// hid_itf->report_info.info[0].in_len = 8; +// hid_itf->report_info.info[0].out_len = 1; } else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { TU_LOG2(" Boot Mouse\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_info.count = 1; +// hid_itf->report_info.count = 1; - hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; - hid_itf->report_info.info[0].in_len = 5; - hid_itf->report_info.info[0].out_len = 0; +// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; +// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; +// hid_itf->report_info.info[0].in_len = 5; +// hid_itf->report_info.info[0].out_len = 0; } else { @@ -344,15 +315,8 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co uint8_t const* desc_report = usbh_get_enum_buf(); uint16_t const desc_len = request->wLength; - if (tuh_hid_descriptor_report_cb) - { - tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len); - } - - parse_report_descriptor(hid_itf, desc_report, desc_len); - // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); + tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len); // queue transfer for IN endpoint hidh_get_report(dev_addr, hid_itf); @@ -363,8 +327,11 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } -// Parse Report Descriptor to tuh_hid_report_info_t -static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) +//--------------------------------------------------------------------+ +// Report Descriptor Parser +//--------------------------------------------------------------------+ + +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) { // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED @@ -378,7 +345,20 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de }; } header; - while(desc_len) + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info; + + tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t)); + + // current parsed report count & size from descriptor +// uint8_t ri_report_count = 0; +// uint8_t ri_report_size = 0; + + uint8_t ri_collection_depth = 0; + uint16_t ri_usage_page = 0; + uint8_t ri_usage = 0; + + while(desc_len && report_num < arr_count) { header.byte = *desc_report++; desc_len--; @@ -387,6 +367,8 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de uint8_t const type = header.type; uint8_t const size = header.size; + uint8_t const data8 = desc_report[0]; + TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); for(uint32_t i=0; iusage_page = ri_usage_page; + info->usage = ri_usage; + }else + { + TU_LOG2("HID Skip a report with ID (%u) larger than array count (%u)\r\n", data8, arr_count); + } + break; + + case RI_GLOBAL_REPORT_SIZE: +// ri_report_size = data8; + break; + + case RI_GLOBAL_REPORT_COUNT: +// ri_report_count = data8; + break; + case RI_GLOBAL_UNIT_EXPONENT : break; case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_REPORT_SIZE : break; - case RI_GLOBAL_REPORT_ID : break; - case RI_GLOBAL_REPORT_COUNT : break; case RI_GLOBAL_PUSH : break; case RI_GLOBAL_POP : break; @@ -429,7 +450,11 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de case RI_TYPE_LOCAL: switch(tag) { - case RI_LOCAL_USAGE : break; + case RI_LOCAL_USAGE: + // only take in account the "usage" before starting COLLECTION + if ( ri_collection_depth == 0) ri_usage = data8; + break; + case RI_LOCAL_USAGE_MIN : break; case RI_LOCAL_USAGE_MAX : break; case RI_LOCAL_DESIGNATOR_INDEX : break; @@ -448,8 +473,22 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de } desc_report += size; - desc_len -= size; + desc_len -= size; } + + if ( report_num == 0 ) + { + report_info[0].usage_page = ri_usage_page; + report_info[0].usage = ri_usage; + } + + for ( uint8_t i = 0; (i < report_num) || (!i && !report_num); i++ ) + { + info = report_info+i; + TU_LOG2("%u: usage_page = %u, usage = %u\r\n", i, info->usage_page, info->usage); + } + + return report_num; } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index b000cdfcb..122f57088 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -53,17 +53,12 @@ typedef struct { - uint8_t count; // number of info + uint16_t usage_page; + uint8_t usage; - struct - { - uint8_t usage_page; - uint8_t usage; - - // TODO still use the endpoint size for now - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report - } info[CFG_TUH_HID_REPORT_MAX]; + // TODO still use the endpoint size for now +// uint8_t in_len; // length of IN report +// uint8_t out_len; // length of OUT report } tuh_hid_report_info_t; //--------------------------------------------------------------------+ @@ -79,47 +74,44 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); -// Get boot protocol check out hid_protocol_type_t for possible value -uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance); +// Get boot interface protocol check out hid_protocol_type_t for possible value +uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); + +// Get current protocol mode: Boot (true) or Report (false) +// By HID spec, device will be initialized in Report mode +bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); -// Check if current mode is Boot (true) or Report (false) -bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance); +// Set protocol to Boot or Report mode. +// This function is only supported by Boot interface tuh_n_hid_n_boot_interface() +bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode); -// Get Report information parsed from report descriptor. Data must not be modified by application -// If report information does not match the actual device descriptor, that is because the built-in parser -// has its limit. Application could use tuh_hid_descriptor_report_cb() callback to parse descriptor by itself. -tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance); +// Parse report descriptor into array of report_info struct and return number of reports. +// If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. +// For complicated report, application should write its own parser. +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; // Check if the interface is ready to use -bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); // Set Report using control endpoint //bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); //------------- -------------// -// Check if HID instance with Keyboard is mounted -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance); - -// Check if HID instance with Mouse is mounted -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ -// Invoked when report descriptor is received -// Note: enumeration is still not complete yet at this time -TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); - // Invoked when device with hid interface is mounted -TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); // Invoked when received Report from device via either regular or control endpoint -TU_ATTR_WEAK void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when Sent Report to device via either regular or control endpoint TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); -- cgit v1.3.1 From 2df5a5367f6b8a6649d39d3ba7ebc0af56db9ad2 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 13:12:33 +0700 Subject: update hid host get/set protocol to match device --- src/class/hid/hid_device.h | 2 +- src/class/hid/hid_host.c | 12 ++++++------ src/class/hid/hid_host.h | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index bccfb8d4d..bfaa35f7d 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -57,7 +57,7 @@ // Check if the interface is ready to use bool tud_hid_n_ready(uint8_t instance); -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tud_hid_n_interface_protocol(uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8d60ceb71..62e6c4b76 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -57,8 +57,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t boot_interface; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol + uint8_t itf_protocol; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; @@ -102,16 +102,16 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_interface; + return hid_itf->itf_protocol; } bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_mode; + return hid_itf->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } -//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +// bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) //{ // //} @@ -212,7 +212,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { - hid_itf->boot_interface = desc_itf->bInterfaceProtocol; + hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; if ( HID_ITF_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 87b86c90b..677c8c9de 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -74,16 +74,16 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); -// Get boot interface protocol check out hid_protocol_type_t for possible value +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); -// Get current protocol mode: Boot (true) or Report (false) -// By HID spec, device will be initialized in Report mode +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: as HID spec, device will be initialized in Report mode bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); -// Set protocol to Boot or Report mode. +// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface tuh_n_hid_n_boot_interface() -bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode); +bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. // If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. -- cgit v1.3.1 From 99add05aa78a0fd5d462ab822d0c4656c41c59d7 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 16:27:28 +0700 Subject: simplify hid api add hid set_protocol() and set_protocol_complete_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 113 +++++++++++++++----------------- src/class/hid/hid_host.h | 13 ++-- 3 files changed, 61 insertions(+), 67 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index de92ab841..72e7c30db 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -64,7 +64,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_n_hid_n_interface_protocol(dev_addr, instance); + uint8_t const interface_protocol = tuh_n_hid_interface_protocol(dev_addr, instance); printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 62e6c4b76..e35e4e4da 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -51,15 +51,15 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + uint8_t itf_protocol; // None, Keyboard, Mouse + uint8_t protocol_mode; // Boot (0) or Report protocol (1) + uint8_t report_desc_type; uint16_t report_desc_len; uint16_t epin_size; uint16_t epout_size; - uint8_t itf_protocol; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol - uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; } hidh_interface_t; @@ -76,7 +76,6 @@ static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); -static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) @@ -93,28 +92,64 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) return get_dev(dev_addr)->inst_count; } -bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->itf_protocol; } -bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; + return hid_itf->protocol_mode; } -// bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) -//{ -// -//} +static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; + + if (tuh_hid_set_protocol_complete_cb) + { + tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); + } + + return true; +} + +bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); + + TU_LOG2("Set Protocol = %d\r\n", protocol); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = hid_itf->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); + return true; +} //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ @@ -209,39 +244,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - hid_itf->boot_mode = false; // default is report mode - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) - { - hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - - if ( HID_ITF_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) - { - TU_LOG2(" Boot Keyboard\r\n"); - // TODO boot protocol may still have more report in report mode -// hid_itf->report_info.count = 1; - -// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; -// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; -// hid_itf->report_info.info[0].in_len = 8; -// hid_itf->report_info.info[0].out_len = 1; - } - else if ( HID_ITF_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) - { - TU_LOG2(" Boot Mouse\r\n"); - // TODO boot protocol may still have more report in report mode -// hid_itf->report_info.count = 1; - -// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; -// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; -// hid_itf->report_info.info[0].in_len = 5; -// hid_itf->report_info.info[0].out_len = 0; - } - else - { - // Unknown protocol - TU_ASSERT(false); - } - } + hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -279,9 +283,9 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; - uint8_t const itf_num = (uint8_t) request->wIndex; - - hidh_interface_t* hid_itf = get_instance_by_itfnum(dev_addr, itf_num); + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long @@ -509,19 +513,6 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a return &_hidh_dev[dev_addr-1].instances[instance]; } -// Get instance by interface number -static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return hid; - } - - return NULL; -} - // Get instance ID by interface number static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 677c8c9de..dc0d8c935 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -72,18 +72,18 @@ typedef struct uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); +bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); +uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: as HID spec, device will be initialized in Report mode -bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); +bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// This function is only supported by Boot interface tuh_n_hid_n_boot_interface() -bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) +bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. // If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. @@ -116,6 +116,9 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re // Invoked when Sent Report to device via either regular or control endpoint TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); +// Invoked when Set Protocol request is complete +TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); + //--------------------------------------------------------------------+ // Application API (Single device) //--------------------------------------------------------------------+ -- cgit v1.3.1 From 89dad1ad414e36aa3f0d69b35d06ec82c3e0f168 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 16:48:07 +0700 Subject: update app --- examples/host/cdc_msc_hid/src/hid_app.c | 10 ++++++++++ src/class/hid/hid_host.h | 4 +--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 72e7c30db..628ab3e7d 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -29,6 +29,10 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ + +// If your host terminal support ansi escape code, it can be use to simulate mouse cursor +#define USE_ANSI_ESCAPE 0 + #define MAX_REPORT 4 static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; @@ -165,6 +169,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) void cursor_movement(int8_t x, int8_t y, int8_t wheel) { +#if USE_ANSI_ESCAPE // Move X using ansi escape if ( x < 0) { @@ -191,6 +196,11 @@ void cursor_movement(int8_t x, int8_t y, int8_t wheel) { printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down } + + printf("\r\n"); +#else + printf("(%d %d %d)\r\n", x, y, wheel); +#endif } static void process_mouse_report(hid_mouse_report_t const * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index dc0d8c935..1537216bb 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -63,9 +63,7 @@ typedef struct //--------------------------------------------------------------------+ // Application API (Multiple devices) -// Note: -// - tud_n : is multiple devices API -// - class_n : is multiple instances API +// - tud_n : is multiple devices API //--------------------------------------------------------------------+ // Get the number of HID instances -- cgit v1.3.1 From 350dfb2ea37cebc59ef9fd6b63d2aae1b8cb48da Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 18:17:32 +0700 Subject: more hid api rename --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 10 +++++----- src/class/hid/hid_host.h | 27 ++++++--------------------- 3 files changed, 12 insertions(+), 27 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 628ab3e7d..eab555fc1 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -68,7 +68,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_n_hid_interface_protocol(dev_addr, instance); + uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e35e4e4da..90a848fc1 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -87,24 +87,24 @@ TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_ // Application API //--------------------------------------------------------------------+ -uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) +uint8_t tuh_hid_instance_count(uint8_t dev_addr) { return get_dev(dev_addr)->inst_count; } -bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->itf_protocol; } -bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->protocol_mode; @@ -126,7 +126,7 @@ static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const return true; } -bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 1537216bb..3cf8dc70f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -62,26 +62,25 @@ typedef struct } tuh_hid_report_info_t; //--------------------------------------------------------------------+ -// Application API (Multiple devices) -// - tud_n : is multiple devices API +// Application API //--------------------------------------------------------------------+ // Get the number of HID instances -uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); +uint8_t tuh_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance); +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: as HID spec, device will be initialized in Report mode -bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance); +bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. // If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. @@ -94,8 +93,6 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint // Set Report using control endpoint //bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); -//------------- -------------// - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -117,18 +114,6 @@ TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t insta // Invoked when Set Protocol request is complete TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); -//--------------------------------------------------------------------+ -// Application API (Single device) -//--------------------------------------------------------------------+ - -// Get the number of HID instances -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_hid_instance_count(void) -{ - return tuh_n_hid_instance_count(1); -} - - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From ad845db6a50c1d90e4f7cc45ca16a8861ee2da4d Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 20:54:59 +0700 Subject: improve hid parser --- examples/host/cdc_msc_hid/src/hid_app.c | 50 +++++++++++++++++------------ src/class/hid/hid_host.c | 56 ++++++++++----------------------- src/class/hid/hid_host.h | 6 ++-- 3 files changed, 50 insertions(+), 62 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index eab555fc1..71904245a 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -37,14 +37,16 @@ static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; +// Each HID instance can has multiple reports static uint8_t _report_count[CFG_TUH_HID]; -static tuh_hid_report_info_t _report_info[CFG_TUH_HID][MAX_REPORT]; +static tuh_hid_report_info_t _report_info_arr[CFG_TUH_HID][MAX_REPORT]; static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const * report); void hid_app_task(void) { + // nothing to do } //--------------------------------------------------------------------+ @@ -55,21 +57,13 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); - // Parse report descriptor with built-in parser - _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info[instance], MAX_REPORT, desc_report, desc_len); - - if (_report_count[instance]) - { - printf("Composite with %u reports", _report_count[instance]); - }else - { - printf("Single report"); - } - // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); - printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); + + // Parse report descriptor with built-in parser + _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len); + printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) @@ -82,20 +76,36 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re (void) dev_addr; uint8_t const rpt_count = _report_count[instance]; - tuh_hid_report_info_t* rpt_info; + tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance]; + tuh_hid_report_info_t* rpt_info = NULL; - if (rpt_count) + if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) + { + // Simple report without report ID as 1st byte + rpt_info = &rpt_info_arr[0]; + }else { // Composite report, 1st byte is report ID, data starts from 2nd byte - // Note: report index = report ID - 1 - uint8_t idx = report[0] - 1; - rpt_info = &_report_info[instance][idx]; + uint8_t const rpt_id = report[0]; + + // Find report id in the arrray + for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 90a848fc1..15533cf3a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -337,7 +337,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // Report Descriptor Parser //--------------------------------------------------------------------+ -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) { // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED @@ -351,18 +351,16 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint }; } header; - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info; + tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t)); + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info_arr; // current parsed report count & size from descriptor // uint8_t ri_report_count = 0; // uint8_t ri_report_size = 0; uint8_t ri_collection_depth = 0; - uint16_t ri_usage_page = 0; - uint8_t ri_usage = 0; while(desc_len && report_num < arr_count) { @@ -394,6 +392,11 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint case RI_MAIN_COLLECTION_END: ri_collection_depth--; + if (ri_collection_depth == 0) + { + info++; + report_num++; + } break; default: break; @@ -404,11 +407,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint switch(tag) { case RI_GLOBAL_USAGE_PAGE: - // only take in account the "usage page" before starting COLLECTION - if ( ri_collection_depth == 0) - { - memcpy(&ri_usage_page, desc_report, size); - } + // only take in account the "usage page" before REPORT ID + if ( ri_collection_depth == 0 ) memcpy(&info->usage_page, desc_report, size); break; case RI_GLOBAL_LOGICAL_MIN : break; @@ -417,23 +417,7 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint case RI_GLOBAL_PHYSICAL_MAX : break; case RI_GLOBAL_REPORT_ID: - report_num++; - if (data8 <= arr_count) - { - uint8_t const idx = data8 - 1; - if ( info != &report_info[idx] ) - { - // copy info so far to its correct report ID, and update info pointer - report_info[idx] = *info; - info = &report_info[idx]; - } - - info->usage_page = ri_usage_page; - info->usage = ri_usage; - }else - { - TU_LOG2("HID Skip a report with ID (%u) larger than array count (%u)\r\n", data8, arr_count); - } + info->report_id = data8; break; case RI_GLOBAL_REPORT_SIZE: @@ -457,8 +441,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint switch(tag) { case RI_LOCAL_USAGE: - // only take in account the "usage" before starting COLLECTION - if ( ri_collection_depth == 0) ri_usage = data8; + // only take in account the "usage" before starting REPORT ID + if ( ri_collection_depth == 0 ) info->usage = data8; break; case RI_LOCAL_USAGE_MIN : break; @@ -482,16 +466,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint desc_len -= size; } - if ( report_num == 0 ) - { - report_info[0].usage_page = ri_usage_page; - report_info[0].usage = ri_usage; - } - - for ( uint8_t i = 0; (i < report_num) || (!i && !report_num); i++ ) + for ( uint8_t i = 0; i < report_num; i++ ) { - info = report_info+i; - TU_LOG2("%u: usage_page = %u, usage = %u\r\n", i, info->usage_page, info->usage); + info = report_info_arr+i; + TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); } return report_num; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3cf8dc70f..1b8acda05 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -53,8 +53,9 @@ typedef struct { + uint8_t report_id; + uint8_t usage; uint16_t usage_page; - uint8_t usage; // TODO still use the endpoint size for now // uint8_t in_len; // length of IN report @@ -83,9 +84,8 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. -// If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. // For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); -- cgit v1.3.1 From 63c57ed1a4285671ba38d87b8b77fd68c55880e6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 20:55:42 +0700 Subject: clean p --- examples/host/cdc_msc_hid/src/tusb_config.h | 4 ---- src/class/hid/hid_host.h | 4 ---- 2 files changed, 8 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8c82c0fef..8253964c0 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -86,10 +86,6 @@ #define CFG_TUH_HID_EP_BUFSIZE 64 -// Max number of reports per interface -// E.g composite HID with keyboard + mouse + gamepad will have 3 reports -#define CFG_TUH_HID_REPORT_MAX 4 - #ifdef __cplusplus } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 1b8acda05..3ac1f7c69 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -42,10 +42,6 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_HID_REPORT_MAX -#define CFG_TUH_HID_REPORT_MAX 4 -#endif - // TODO Highspeed interrupt can be up to 512 bytes #ifndef CFG_TUH_HID_EP_BUFSIZE #define CFG_TUH_HID_EP_BUFSIZE 64 -- cgit v1.3.1 From df65c35b31581881b2bf49d9e16608d46f98fe4b Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 21:48:42 +0700 Subject: implement hid host set report with control transfer rename mount, umount callback --- examples/host/cdc_msc_hid/src/hid_app.c | 4 +-- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- src/class/hid/hid_host.c | 54 ++++++++++++++++++++++++++++++--- src/class/hid/hid_host.h | 16 +++++----- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- 6 files changed, 63 insertions(+), 17 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 71904245a..79f10251f 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -53,7 +53,7 @@ void hid_app_task(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); @@ -66,7 +66,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } -void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 3a8ef3a07..3657a3d35 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -80,7 +80,7 @@ void tuh_msc_mount_cb(uint8_t dev_addr) // } } -void tuh_msc_unmount_cb(uint8_t dev_addr) +void tuh_msc_umount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 15533cf3a..f15f0b72a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -73,6 +73,8 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; //------------- Internal prototypes -------------// + +// Get HID device & interface TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); @@ -131,7 +133,7 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); - TU_LOG2("Set Protocol = %d\r\n", protocol); + TU_LOG2("HID Set Protocol = %d\r\n", protocol); tusb_control_request_t const request = { @@ -151,6 +153,48 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return true; } +static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_LOG2("HID Set Report complete\r\n"); + + if (tuh_hid_set_report_complete_cb) + { + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); + } + + return true; +} + + +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = hid_itf->itf_num, + .wLength = len + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_report_complete) ); + return true; +} + //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); @@ -185,7 +229,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 hidh_get_report(dev_addr, hid_itf); }else { - if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); +// if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); } return true; @@ -194,9 +238,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 void hidh_close(uint8_t dev_addr) { hidh_device_t* hid_dev = get_dev(dev_addr); - if (tuh_hid_unmounted_cb) + if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_unmounted_cb(dev_addr, inst); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); @@ -322,7 +366,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co uint16_t const desc_len = request->wLength; // enumeration is complete - tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len); + tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); // queue transfer for IN endpoint hidh_get_report(dev_addr, hid_itf); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3ac1f7c69..f962f5b0a 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -79,6 +79,10 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +// Set Report using control endpoint +// report_type is either Intput, Output or Feature, (value from hid_report_type_t) +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); + // Parse report descriptor into array of report_info struct and return number of reports. // For complicated report, application should write its own parser. uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; @@ -86,9 +90,6 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); -// Set Report using control endpoint -//bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -96,16 +97,17 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); +TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); // Invoked when received Report from device via either regular or control endpoint void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); -// Invoked when Sent Report to device via either regular or control endpoint -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); +// Invoked when Sent Report to device via either control endpoint +// len = 0 indicate there is error in the transfer e.g stalled response +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); // Invoked when Set Protocol request is complete TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 4869c8c03..08b4db9e1 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -300,7 +300,7 @@ void msch_close(uint8_t dev_addr) tu_memclr(p_msc, sizeof(msch_interface_t)); // invoke Application Callback - if (tuh_msc_unmount_cb) tuh_msc_unmount_cb(dev_addr); + if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 7ebc9b5a8..b5ffcd401 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -109,7 +109,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_unmount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From b8e019da321512758959f6fb3b2f0192bda698dc Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 21:51:30 +0700 Subject: rename tuh_hid_get_report_cb to tuh_hid_report_received_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 7 ++++++- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 79f10251f..67be8d50f 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -53,6 +53,9 @@ void hid_app_task(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); @@ -66,12 +69,14 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } +// Invoked when device with hid interface is un-mounted void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +// Invoked when received Report from device via either regular endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { (void) dev_addr; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index f15f0b72a..63983ca5f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -223,7 +223,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 { TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); - tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); + tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); // queue next report hidh_get_report(dev_addr, hid_itf); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index f962f5b0a..3f9979f52 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -102,8 +102,8 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_ // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); -// Invoked when received Report from device via either regular or control endpoint -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +// Invoked when received Report from device via either regular endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response -- cgit v1.3.1 From a2c4a48dd627828f5899e5ab70412594b60f37c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 22:03:21 +0700 Subject: add tuh_hid_report_sent_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 5 +++-- src/class/hid/hid_host.h | 10 +++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 67be8d50f..23ab12404 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -75,7 +75,7 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } -// Invoked when received Report from device via either regular endpoint +// Invoked when received report from device via interrupt endpoint void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { (void) dev_addr; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 63983ca5f..778a897be 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -171,7 +171,6 @@ static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * return true; } - bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); @@ -203,6 +202,8 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); //} +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ @@ -229,7 +230,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 hidh_get_report(dev_addr, hid_itf); }else { -// if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); + if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); } return true; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3f9979f52..ea693df69 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -90,6 +90,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +// Send report using interrupt endpoint +// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -102,9 +106,13 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_ // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); -// Invoked when received Report from device via either regular endpoint +// Invoked when received report from device via interrupt endpoint +// Note: if there is report ID (composite), it is 1st byte of report void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +// Invoked when sent report to device successfully via interrupt endpoint +TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); -- cgit v1.3.1 From f13a3c04f790a865472a7ed0b57182f401189977 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 22:43:55 +0700 Subject: fix missing report in tuh_hid_set_report() --- src/class/hid/hid_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 778a897be..6c0c97095 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -190,7 +190,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .wLength = len }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_report_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); return true; } -- cgit v1.3.1 From a1dab1611bad43cfc3c2dcce58c1dce442287eb9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 23:30:41 +0700 Subject: get protocol when enum with hid boot interface --- src/class/hid/hid_host.c | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6c0c97095..e3ae5a155 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -251,8 +251,9 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { @@ -299,11 +300,14 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + // Idle rate = 0 mean only report when there is changes uint16_t const idle_rate = 0; // SET IDLE request, device can stall if not support this request - TU_LOG2("Set Idle \r\n"); + TU_LOG2("HID Set Idle \r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -318,14 +322,42 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, config_set_idle_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) ); return true; } -bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + (void) result; + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + TU_LOG2("HID Get Protocol\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HID_REQ_CONTROL_GET_PROTOCOL, + .wValue = 0, + .wIndex = hid_itf->itf_num, + .wLength = 1 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) ); + return false; +} + +static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE, therefore we could ignore its result + // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; @@ -355,7 +387,7 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r return true; } -bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); -- cgit v1.3.1 From 8cffe4897eb114d65ff60685e111ff3e03d0fd74 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 13:56:32 +0700 Subject: change hid device internal boot_mode to protocol_mode --- src/class/hid/hid_device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ab9ef3ad8..0d9cdb22b 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,7 @@ typedef struct uint8_t ep_out; // optional Out endpoint uint8_t itf_protocol; // Boot mouse or keyboard - bool boot_mode; // default = false (Report) + uint8_t protocol_mode; // Boot (0) or Report protocol (1) uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; @@ -112,7 +112,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) uint8_t tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; + return _hidd_itf[instance].protocol_mode; } bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) @@ -213,7 +213,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - p_hid->boot_mode = false; // default mode is REPORT + p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode p_hid->itf_num = desc_itf->bInterfaceNumber; // Use offsetof to avoid pointer to the odd/misaligned address @@ -326,8 +326,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_GET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - uint8_t protocol = (p_hid->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT); - tud_control_xfer(rhport, request, &protocol, 1); + tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); } break; @@ -338,10 +337,10 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK ) { - p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); + p_hid->protocol_mode = (uint8_t) request->wValue; if (tud_hid_set_protocol_cb) { - tud_hid_set_protocol_cb(hid_itf, (uint8_t) request->wValue); + tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); } } break; -- cgit v1.3.1 From 3654d96e07f63e041f750aafd125c2c8bca27aa5 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 14:11:12 +0700 Subject: only invoke tuh_msc_umount_cb() if needed --- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e3ae5a155..1bc86e4ad 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -241,7 +241,7 @@ void hidh_close(uint8_t dev_addr) hidh_device_t* hid_dev = get_dev(dev_addr); if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_umount_cb(dev_addr, inst); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 08b4db9e1..ca360ca2a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -297,10 +297,11 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - tu_memclr(p_msc, sizeof(msch_interface_t)); // invoke Application Callback - if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + + tu_memclr(p_msc, sizeof(msch_interface_t)); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -- cgit v1.3.1 From f9c542aa52f7f2e5e532343384441234a019e53d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 May 2021 18:16:56 +0700 Subject: fix dfu example build --- examples/device/dfu/.skip.MCU_SAMD11 | 0 examples/device/dfu/CMakeLists.txt | 10 +++------- examples/device/dfu/src/main.c | 15 +++++++-------- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 6 +++--- examples/rules.mk | 3 ++- hw/bsp/rp2040/family.cmake | 1 + hw/bsp/samd11/boards/luna_d11/samd11d14am_flash.ld | 1 + hw/bsp/samd11/boards/samd11_xplained/board.mk | 1 - hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld | 1 + hw/bsp/samd11/family.mk | 3 ++- hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld | 1 + hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld | 1 + src/class/dfu/dfu_device.c | 2 ++ 14 files changed, 25 insertions(+), 22 deletions(-) create mode 100644 examples/device/dfu/.skip.MCU_SAMD11 (limited to 'src/class') diff --git a/examples/device/dfu/.skip.MCU_SAMD11 b/examples/device/dfu/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/dfu/CMakeLists.txt b/examples/device/dfu/CMakeLists.txt index f4bf75c26..4160c0c88 100644 --- a/examples/device/dfu/CMakeLists.txt +++ b/examples/device/dfu/CMakeLists.txt @@ -9,10 +9,9 @@ get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= if(FAMILY STREQUAL "rp2040") cmake_minimum_required(VERSION 3.12) - set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk) - include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + + include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake) project(${PROJECT}) - pico_sdk_init() add_executable(${PROJECT}) include(${TOP}/hw/bsp/${FAMILY}/family.cmake) @@ -33,9 +32,6 @@ if(FAMILY STREQUAL "rp2040") CFG_TUSB_OS=OPT_OS_PICO ) - target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration) - pico_add_extra_outputs(${PROJECT}) - else() - message(FATAL_ERROR "Invalid FAMILY specified") + message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") endif() diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 3849de44d..1c09066a8 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -126,21 +126,20 @@ void tud_dfu_runtime_reboot_to_dfu_cb(void) //--------------------------------------------------------------------+ bool tud_dfu_firmware_valid_check_cb(void) { - TU_LOG2(" Firmware check\r\n"); + printf(" Firmware check\r\n"); return true; } void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) { - TU_LOG2(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + (void) data; + printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; i ram /* stack section */ diff --git a/hw/bsp/samd11/boards/samd11_xplained/board.mk b/hw/bsp/samd11/boards/samd11_xplained/board.mk index 79ad87068..e351cf0b8 100644 --- a/hw/bsp/samd11/boards/samd11_xplained/board.mk +++ b/hw/bsp/samd11/boards/samd11_xplained/board.mk @@ -6,7 +6,6 @@ LD_FILE = $(BOARD_PATH)/samd11d14am_flash.ld # For flash-jlink target JLINK_DEVICE = ATSAMD11D14 - # flash using edbg flash: $(BUILD)/$(PROJECT).bin edbg -b -t samd11 -e -pv -f $< diff --git a/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld b/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld index 2153f5f50..8b3124c0e 100644 --- a/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld +++ b/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld @@ -126,6 +126,7 @@ SECTIONS . = ALIGN(4); _ebss = . ; _ezero = .; + end = .; } > ram /* stack section */ diff --git a/hw/bsp/samd11/family.mk b/hw/bsp/samd11/family.mk index 6fbdc35af..70120ec94 100644 --- a/hw/bsp/samd11/family.mk +++ b/hw/bsp/samd11/family.mk @@ -3,8 +3,9 @@ DEPS_SUBMODULES += hw/mcu/microchip include $(TOP)/$(BOARD_PATH)/board.mk CFLAGS += \ + -flto \ -mthumb \ - -mabi=aapcs-linux \ + -mabi=aapcs \ -mcpu=cortex-m0plus \ -nostdlib -nostartfiles \ -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ diff --git a/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld b/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld index 2e0e1b256..d1aaa44fc 100644 --- a/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld +++ b/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld @@ -128,6 +128,7 @@ SECTIONS . = ALIGN(4); _ebss = . ; _ezero = .; + end = .; } > ram /* stack section */ diff --git a/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld b/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld index 2e0e1b256..d1aaa44fc 100644 --- a/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld +++ b/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld @@ -128,6 +128,7 @@ SECTIONS . = ALIGN(4); _ebss = . ; _ezero = .; + end = .; } > ram /* stack section */ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index da9f189aa..8496cb02b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -150,6 +150,8 @@ void dfu_moded_init(void) void dfu_moded_reset(uint8_t rhport) { + (void) rhport; + _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; -- cgit v1.3.1 From faa31152b4473166e099fc02500534018ce8c465 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 May 2021 20:25:44 +0700 Subject: rename usbd_edpt_iso_xfer to usbd_edpt_xfer_fifo --- src/class/audio/audio_device.c | 6 +++--- src/device/usbd.c | 2 +- src/device/usbd_pvt.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 72533013c..3afe6ce3f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -548,7 +548,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif #endif @@ -852,7 +852,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); #else // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); #endif #endif @@ -1611,7 +1611,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif } diff --git a/src/device/usbd.c b/src/device/usbd.c index 8454a2951..71c5d4e6c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1271,7 +1271,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 44310f022..c42bfd97b 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. -- cgit v1.3.1 From 9736e54734a85c03d9055c24414e23f112a67968 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 17:40:39 +0700 Subject: include clean up --- src/class/audio/audio_device.c | 3 +- src/class/audio/audio_device.h | 4 --- src/class/bth/bth_device.c | 1 - src/class/cdc/cdc_device.c | 4 ++- src/class/cdc/cdc_device.h | 1 - src/class/dfu/dfu_device.c | 4 ++- src/class/dfu/dfu_device.h | 2 -- src/class/dfu/dfu_rt_device.c | 4 ++- src/class/dfu/dfu_rt_device.h | 2 -- src/class/hid/hid_device.c | 5 +-- src/class/hid/hid_device.h | 2 -- src/class/midi/midi_device.c | 5 +-- src/class/midi/midi_device.h | 3 -- src/class/msc/msc_device.c | 5 +-- src/class/msc/msc_device.h | 72 +++++++++++++++++----------------------- src/class/net/net_device.c | 4 ++- src/class/net/net_device.h | 1 - src/class/usbtmc/usbtmc_device.c | 8 ++--- src/class/vendor/vendor_device.c | 4 ++- src/class/vendor/vendor_device.h | 1 - src/common/tusb_common.h | 5 +-- src/device/dcd.h | 1 + 22 files changed, 62 insertions(+), 79 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3afe6ce3f..8e4420ed0 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -55,9 +55,10 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ +#include "device/usbd.h" #include "device/usbd_pvt.h" + #include "audio_device.h" -//#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b8e6ef9c0..5a469523c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -28,10 +28,6 @@ #ifndef _TUSB_AUDIO_DEVICE_H_ #define _TUSB_AUDIO_DEVICE_H_ -#include "assert.h" -#include "common/tusb_common.h" -#include "device/usbd.h" - #include "audio.h" //--------------------------------------------------------------------+ diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 481dc134e..1d27ae7c5 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -32,7 +32,6 @@ // INCLUDE //--------------------------------------------------------------------+ #include "bth_device.h" -#include #include //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f5853fddb..cac811c45 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) -#include "cdc_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "cdc_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 986585c5b..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -28,7 +28,6 @@ #define _TUSB_CDC_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #include "cdc.h" //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8496cb02b..81045ff7b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) -#include "dfu_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "dfu_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c45c436c5..9a09a46b1 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_DFU_DEVICE_H_ #define _TUSB_DFU_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "dfu.h" #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index faeae9b68..07e6f30f3 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) -#include "dfu_rt_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "dfu_rt_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 0e5fd005a..babaa8214 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_DFU_RT_DEVICE_H_ #define _TUSB_DFU_RT_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "dfu.h" #ifdef __cplusplus diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 0d9cdb22b..c7f5d04ec 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -31,10 +31,11 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "hid_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "hid_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 61274be4d..beb755888 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_HID_DEVICE_H_ #define _TUSB_HID_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "hid.h" #ifdef __cplusplus diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 2c50bc4f3..953ca26e6 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -31,10 +31,11 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "midi_device.h" -#include "class/audio/audio.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "midi_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 67f03930c..211edc8d1 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -27,9 +27,6 @@ #ifndef _TUSB_MIDI_DEVICE_H_ #define _TUSB_MIDI_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" - #include "class/audio/audio.h" #include "midi.h" diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 539941935..9b06b7a33 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -28,11 +28,12 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC) -#include "common/tusb_common.h" -#include "msc_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" #include "device/dcd.h" // for faking dcd_event_xfer_complete +#include "msc_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 469f2f2f7..8f90ef4ad 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -28,7 +28,6 @@ #define _TUSB_MSC_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #include "msc.h" #ifdef __cplusplus @@ -51,53 +50,45 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); -/** \addtogroup ClassDriver_MSC - * @{ - * \defgroup MSC_Device Device - * @{ */ +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ +// Set SCSI sense response bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); //--------------------------------------------------------------------+ // Application Callbacks (WEAK is optional) //--------------------------------------------------------------------+ -/** - * Invoked when received \ref SCSI_CMD_READ_10 command - * \param[in] lun Logical unit number - * \param[in] lba Logical Block Address to be read - * \param[in] offset Byte offset from LBA - * \param[out] buffer Buffer which application need to update with the response data. - * \param[in] bufsize Requested bytes - * - * \return Number of byte read, if it is less than requested bytes by \a \b bufsize. Tinyusb will transfer - * this amount first and invoked this again for remaining data. - * - * \retval zero Indicate application is not ready yet to response e.g disk I/O is not complete. - * tinyusb will invoke this callback with the same parameters again some time later. - * - * \retval negative Indicate error e.g reading disk I/O. tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ +// Invoked when received SCSI READ10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If +// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. +// +// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); -/** - * Invoked when received \ref SCSI_CMD_WRITE_10 command - * \param[in] lun Logical unit number - * \param[in] lba Logical Block Address to be write - * \param[in] offset Byte offset from LBA - * \param[out] buffer Buffer which holds written data. - * \param[in] bufsize Requested bytes - * - * \return Number of byte written, if it is less than requested bytes by \a \b bufsize. Tinyusb will proceed with - * other work and invoked this again with adjusted parameters. - * - * \retval zero Indicate application is not ready yet e.g disk I/O is not complete. - * Tinyusb will invoke this callback with the same parameters again some time later. - * - * \retval negative Indicate error writing disk I/O. Tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ +// Invoked when received SCSI WRITE10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If +// - write < bufsize : callback invoked again with remaining data later on. +// +// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. +// +// TODO change buffer to const uint8_t* int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); // Invoked when received SCSI_CMD_INQUIRY @@ -152,9 +143,6 @@ TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[1 // Hook to make a mass storage device read-only. TODO remove TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); -/** @} */ -/** @} */ - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index ce1131223..9d9719ce4 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -29,8 +29,10 @@ #if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) -#include "net_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" + +#include "net_device.h" #include "rndis_protocol.h" void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 38c47d647..f5f0cd8f1 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -28,7 +28,6 @@ #ifndef _TUSB_NET_DEVICE_H_ #define _TUSB_NET_DEVICE_H_ -#include "common/tusb_common.h" #include "device/usbd.h" #include "class/cdc/cdc.h" diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d5f8fe41d..c1ee49f45 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -77,15 +77,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) -#include -#include "usbtmc.h" -#include "usbtmc_device.h" #include "device/usbd.h" -#include "osal/osal.h" - -// FIXME: I shouldn't need to include _pvt headers, but it is necessary for usbd_edpt_xfer, _stall, and _busy #include "device/usbd_pvt.h" +#include "usbtmc_device.h" + #ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 5fc7dd569..081aac9f6 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR) -#include "vendor_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "vendor_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 2c3d79a3d..6d9c784c0 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -28,7 +28,6 @@ #define _TUSB_VENDOR_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #ifndef CFG_TUD_VENDOR_EPSIZE #define CFG_TUD_VENDOR_EPSIZE 64 diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 88e85c9e0..1ebd8dd61 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -72,10 +72,11 @@ #include "tusb_option.h" #include "tusb_compiler.h" #include "tusb_verify.h" -#include "tusb_error.h" // TODO remove -#include "tusb_timeout.h" #include "tusb_types.h" +#include "tusb_error.h" // TODO remove +#include "tusb_timeout.h" // TODO remove + //------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) diff --git a/src/device/dcd.h b/src/device/dcd.h index 71e88054c..e17c62d4e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -28,6 +28,7 @@ #define _TUSB_DCD_H_ #include "common/tusb_common.h" +#include "osal/osal.h" #include "common/tusb_fifo.h" #ifdef __cplusplus -- cgit v1.3.1 From 9ad6fadf6a65363f9873178e7f80c923452bfb47 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 18:18:30 +0700 Subject: more include clean up --- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/cdc_host.h | 2 -- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 7 ------- src/class/msc/msc.h | 10 ---------- src/class/msc/msc_host.c | 5 +---- src/class/msc/msc_host.h | 2 -- src/class/vendor/vendor_host.c | 2 +- src/class/vendor/vendor_host.h | 7 ------- src/host/hub.c | 4 +--- src/host/hub.h | 1 - src/host/usbh.h | 9 +-------- src/portable/sony/cxd56/dcd_cxd56.c | 1 - 13 files changed, 6 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a897fb58a..c22107bbb 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -28,7 +28,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) -#include "common/tusb_common.h" +#include "host/usbh.h" #include "cdc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 66c2f0727..6ff392709 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -27,8 +27,6 @@ #ifndef _TUSB_CDC_HOST_H_ #define _TUSB_CDC_HOST_H_ -#include "common/tusb_common.h" -#include "host/usbh.h" #include "cdc.h" #ifdef __cplusplus diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 1bc86e4ad..83f3f3039 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -28,7 +28,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) -#include "common/tusb_common.h" +#include "host/usbh.h" #include "hid_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index ea693df69..2e4cce600 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -24,14 +24,9 @@ * This file is part of the TinyUSB stack. */ -/** \addtogroup ClassDriver_HID - * @{ */ - #ifndef _TUSB_HID_HOST_H_ #define _TUSB_HID_HOST_H_ -#include "common/tusb_common.h" -#include "host/usbh.h" #include "hid.h" #ifdef __cplusplus @@ -134,5 +129,3 @@ void hidh_close(uint8_t dev_addr); #endif #endif /* _TUSB_HID_HOST_H_ */ - -/** @} */ // ClassDriver_HID diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index 0bdc00692..84b6e4d79 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -24,13 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_class - * \defgroup ClassDriver_MSC MassStorage (MSC) - * @{ */ - -/** \defgroup ClassDriver_MSC_Common Common Definitions - * @{ */ - #ifndef _TUSB_MSC_H_ #define _TUSB_MSC_H_ @@ -387,6 +380,3 @@ TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); #endif #endif /* _TUSB_MSC_H_ */ - -/// @} -/// @} diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ca360ca2a..5a4ffff48 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -28,10 +28,7 @@ #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" +#include "host/usbh.h" #include "msc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index b5ffcd401..ce4fe64dc 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -27,8 +27,6 @@ #ifndef _TUSB_MSC_HOST_H_ #define _TUSB_MSC_HOST_H_ -#include "common/tusb_common.h" -#include "host/usbh.h" #include "msc.h" #ifdef __cplusplus diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 0524cb981..1978ef61c 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -31,7 +31,7 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "common/tusb_common.h" +#include "host/usbh.h" #include "vendor_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_host.h b/src/class/vendor/vendor_host.h index fa1879376..07fa56c61 100644 --- a/src/class/vendor/vendor_host.h +++ b/src/class/vendor/vendor_host.h @@ -24,15 +24,10 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_class - * \defgroup Group_Custom Custom Class (not supported yet) - * @{ */ - #ifndef _TUSB_VENDOR_HOST_H_ #define _TUSB_VENDOR_HOST_H_ #include "common/tusb_common.h" -#include "host/usbh.h" #ifdef __cplusplus extern "C" { @@ -70,5 +65,3 @@ void cush_close(uint8_t dev_addr); #endif #endif /* _TUSB_VENDOR_HOST_H_ */ - -/** @} */ diff --git a/src/host/hub.c b/src/host/hub.c index 2191c4560..4db680f9e 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -28,9 +28,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ +#include "usbh.h" #include "hub.h" //--------------------------------------------------------------------+ diff --git a/src/host/hub.h b/src/host/hub.h index 851bb8e66..2b2f39ee1 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -37,7 +37,6 @@ #define _TUSB_HUB_H_ #include "common/tusb_common.h" -#include "usbh.h" #ifdef __cplusplus extern "C" { diff --git a/src/host/usbh.h b/src/host/usbh.h index 590c8a359..a9790b484 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -34,10 +34,7 @@ extern "C" { #endif -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "osal/osal.h" // TODO refractor move to common.h ? +#include "common/tusb_common.h" #include "hcd.h" //--------------------------------------------------------------------+ @@ -67,10 +64,6 @@ typedef struct { typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 54958182b..834976468 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -33,7 +33,6 @@ #include #include "device/dcd.h" -#include "osal/osal.h" #define CXD56_EPNUM (7) #define CXD56_SETUP_QUEUE_DEPTH (4) -- cgit v1.3.1 From 7c66c5121b862443aacf7eadbef45153a3fa3060 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 19:31:55 +0700 Subject: update doc --- CONTRIBUTORS.md | 10 +++++++- docs/changelog.md | 63 ++++++++++++++++++++++++++++++++++++++++------ src/class/net/net_device.h | 1 - 3 files changed, 64 insertions(+), 10 deletions(-) (limited to 'src/class') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5ce352f57..5fa3e5250 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -25,6 +25,10 @@ - Improve Audio driver and add uac2_headset example - Improve STM32 Synopsys DCD with various PRs +- **[J McCarthy](https://github.com/xmos-jmccarthy)** + - Add new DFU 1.1 class driver + - Add new example for dfu + - **[Kamil Tomaszewski](https://github.com/kamtom480)** - Add new DCD port for **Sony CXD56** (spresnese board) @@ -53,10 +57,14 @@ - **[Raspberry Pi Team](https://github.com/raspberrypi)** - Add new DCD port for **Raspberry Pi RP2040** + - Add new HCD port for **Raspberry Pi RP2040** - **[Reinhard Panhuber](https://github.com/PanRe)** - Add new class driver for **USB Audio Class 2.0 (UAC2)** - - Enhance tu_fifo with unmasked pointer, which better support DMA + - Rework tu_fifo with unmasked pointer, add DMA support, and constant address support + - Add new DCD/USBD edpt_xfer_fifo() API for optimizing endpoint transfer + - Add and greatly improve Isochronous transfer + - Add new audio examples: audio_test and audio_4_channel_mic - **[Scott Shawcroft](https://github.com/tannewt)** - Add new DCD port for **SAMD21 and SAMD51** diff --git a/docs/changelog.md b/docs/changelog.md index 436259cee..fba362904 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,18 +2,65 @@ ## WIP -- Add new port Silabs EFM32GG12, board EFM32GG12 Thunderboard Kit (SLTB009A) -- Add new port Renesas RX63N, board GR-CITRUS -- MIDI - - Fix MIDI buffer overflow issue +- Rework tu_fifo_t with separated mutex for read and write, better support DMA with read/write buffer info. And constant address mode +- Improve audio_test example and add audio_4_channel_mic example +- Add new dfu example +- Remove pico-sdk from submodule + +### Device Controller Driver (DCD) + +- Add new DCD port for Silabs EFM32GG12 with board Thunderboard Kit (SLTB009A) +- Add new DCD port Renesas RX63N, board GR-CITRUS +- Add new (optional) endpoint API dcd_edpt_xfer_fifo +- Fix build with nRF5340 +- Fix build with lpc15 and lpc54 +- Fix build with lpc177x_8x +- STM32 Synopsys: greatly improve Isochronous transfer with edpt_xfer_fifo API +- Support LPC55 port1 highspeed +- Add support for Espressif esp32s3 +- nRF: fix race condition that could cause drop packet of Bulk OUT transfer + +### USB Device Driver (USBD) + +- Add new (optional) endpoint ADPI usbd_edpt_xfer_fifo + +### Device Class Driver + +CDC + +- [Breaking] tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek at random offset. + +DFU + +- Add new DFU 1.1 class driver (WIP) + +HID + +- Fix keyboard report descriptor template +- Add more hid keys constant from 0x6B to 0xA4 +- [Breaking] rename API + - HID_PROTOCOL_NONE/KEYBOARD/MOUST to HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE + - tud_hid_boot_mode() to tud_hid_get_protocol() + - tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb() + +MIDI + +- Fix MIDI buffer overflow issue +- [Breaking] rename API - Rename tud_midi_read() to tud_midi_stream_read() - Rename tud_midi_write() to tud_midi_stream_write() - Rename tud_midi_receive() to tud_midi_packet_read() - Rename tud_midi_send() to tud_midi_packet_write() -- New board stm32f072-eval -- Breaking changes - - tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek - at random offset. + +### Host Controller Driver (HCD) + +### USB Host Driver (USBH) + +### Host Class Driver + +HID + +- Rework host hid driver, basically everything changes ## 0.9.0 - 2021.03.12 diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index f5f0cd8f1..f030f3077 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -28,7 +28,6 @@ #ifndef _TUSB_NET_DEVICE_H_ #define _TUSB_NET_DEVICE_H_ -#include "device/usbd.h" #include "class/cdc/cdc.h" /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -- cgit v1.3.1 From b4f092ec74d85d4e5567ebb45e1bd0dec20f0e02 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Sat, 29 May 2021 21:23:39 +0200 Subject: Adaptations for Renesas CCRX toolchain and Rx72N controller performed --- src/class/cdc/cdc.h | 48 ++++++++++++-- src/class/cdc/cdc_device.c | 23 +++++-- src/class/cdc/cdc_device.h | 57 ++++++++++++++++ src/common/tusb_compiler.h | 92 ++++++++++++++++++++++++-- src/common/tusb_types.h | 39 ++++++++++- src/device/dcd.h | 42 ++++++++++-- src/device/usbd.c | 67 ++++++++++++------- src/device/usbd.h | 74 +++++++++++++++++++-- src/device/usbd_control.c | 15 ++++- src/device/usbd_pvt.h | 11 ++++ src/osal/osal_freertos.h | 25 +++++++ src/portable/renesas/usba/dcd_usba.c | 122 ++++++++++++++++++++++++++++------- src/tusb_option.h | 1 + 13 files changed, 543 insertions(+), 73 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f59bf0f1a..e5af9fc0c 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -216,6 +216,7 @@ typedef enum //--------------------------------------------------------------------+ /// Header Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -223,8 +224,10 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }cdc_desc_func_header_t; +TU_PACK_STRUCT_END /// Union Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -233,17 +236,21 @@ typedef struct TU_ATTR_PACKED uint8_t bControlInterface ; ///< Interface number of Communication Interface uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; +TU_PACK_STRUCT_END #define cdc_desc_func_union_n_t(no_slave)\ - struct TU_ATTR_PACKED { \ + TU_PACK_STRUCT_BEGIN \ + struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ uint8_t bDescriptorSubType ;\ uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ -} +} \ +TU_PACK_STRUCT_END /// Country Selection Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -252,15 +259,18 @@ typedef struct TU_ATTR_PACKED uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; +TU_PACK_STRUCT_END #define cdc_desc_func_country_selection_n_t(no_country) \ - struct TU_ATTR_PACKED {\ + TU_PACK_STRUCT_BEGIN \ + struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ uint8_t bDescriptorSubType ;\ uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ -} +} \ +TU_PACK_STRUCT_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS @@ -268,22 +278,28 @@ typedef struct TU_ATTR_PACKED /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. uint8_t TU_RESERVED : 6; } bmCapabilities; + TU_BIT_FIELD_ORDER_END uint8_t bDataInterface; }cdc_desc_func_call_management_t; +TU_PACK_STRUCT_END +TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. @@ -292,11 +308,14 @@ typedef struct TU_ATTR_PACKED uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; +TU_BIT_FIELD_ORDER_END +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -304,25 +323,31 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ cdc_acm_capability_t bmCapabilities ; }cdc_desc_func_acm_t; +TU_PACK_STRUCT_END /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. uint8_t TU_RESERVED : 5; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_direct_line_management_t; +TU_PACK_STRUCT_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, /// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -331,31 +356,38 @@ typedef struct TU_ATTR_PACKED uint8_t bRingerVolSteps ; uint8_t bNumRingerPatterns ; }cdc_desc_func_telephone_ringer_t; +TU_PACK_STRUCT_END /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; uint8_t TU_RESERVED : 5; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_operational_modes_t; +TU_PACK_STRUCT_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. @@ -365,7 +397,9 @@ typedef struct TU_ATTR_PACKED uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification uint32_t TU_RESERVED : 26; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_call_state_reporting_capabilities_t; +TU_PACK_STRUCT_END static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { @@ -375,6 +409,7 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint32_t bit_rate; @@ -382,15 +417,20 @@ typedef struct TU_ATTR_PACKED uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); +TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. uint16_t half_duplex_carrier_control : 1; uint16_t : 14; } cdc_line_control_state_t; +TU_BIT_FIELD_ORDER_END +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f5853fddb..cf2ec64c8 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -31,6 +31,15 @@ #include "cdc_device.h" #include "device/usbd_pvt.h" +#if defined(TU_HAS_NO_ATTR_WEAK) +static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb))(uint8_t) = TUD_CDC_TX_COMPLETE_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_line_state_cb))(uint8_t, bool, bool) = TUD_CDC_LINE_STATE_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_line_coding_cb))(uint8_t, cdc_line_coding_t const*) = TUD_CDC_LINE_CODING_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_send_break_cb))(uint8_t, uint16_t) = TUD_CDC_SEND_BREAK_CB; +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -359,7 +368,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK) { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + if ( MAKE_WEAK_FUNC(tud_cdc_line_coding_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_coding_cb)(itf, &p_cdc->line_coding); } break; @@ -394,7 +403,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + if ( MAKE_WEAK_FUNC(tud_cdc_line_state_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_state_cb)(itf, dtr, rts); } break; case CDC_REQUEST_SEND_BREAK: @@ -405,7 +414,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t else if (stage == CONTROL_STAGE_ACK) { TU_LOG2(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + if ( MAKE_WEAK_FUNC(tud_cdc_send_break_cb) ) MAKE_WEAK_FUNC(tud_cdc_send_break_cb)(itf, request->wValue); } break; @@ -436,19 +445,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) + if ( MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb) && (((signed char) p_cdc->wanted_char) != -1) ) { for ( uint32_t i = 0; i < xferred_bytes; i++ ) { if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb)(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + if (MAKE_WEAK_FUNC(tud_cdc_rx_cb) && !tu_fifo_empty(&p_cdc->rx_ff) ) MAKE_WEAK_FUNC(tud_cdc_rx_cb)(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -460,7 +469,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( ep_addr == p_cdc->ep_in ) { // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + if ( MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb) ) MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb)(itf); if ( 0 == tud_cdc_n_write_flush(itf) ) { diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 986585c5b..ed816b707 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -130,6 +130,7 @@ static inline bool tud_cdc_write_clear (void); // Application Callback API (weak is optional) //--------------------------------------------------------------------+ +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); @@ -148,6 +149,62 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p // Invoked when received send break TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); +#else + #if ADD_WEAK_FUNC_TUD_CDC_RX_CB + #define TUD_CDC_RX_CB tud_cdc_rx_cb + #endif + #ifndef TUD_CDC_RX_CB + #define TUD_CDC_RX_CB NULL + #else + extern void TUD_CDC_RX_CB(uint8_t itf); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB + #define TUD_CDC_RX_WANTED_CB tud_cdc_rx_wanted_cb + #endif + #ifndef TUD_CDC_RX_WANTED_CB + #define TUD_CDC_RX_WANTED_CB NULL + #else + extern void TUD_CDC_RX_WANTED_CB(uint8_t itf, char wanted_char); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB + #define TUD_CDC_TX_COMPLETE_CB tud_cdc_tx_complete_cb + #endif + #ifndef TUD_CDC_TX_COMPLETE_CB + #define TUD_CDC_TX_COMPLETE_CB NULL + #else + extern void TUD_CDC_TX_COMPLETE_CB(uint8_t itf); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB + #define TUD_CDC_LINE_STATE_CB tud_cdc_line_state_cb + #endif + #ifndef TUD_CDC_LINE_STATE_CB + #define TUD_CDC_LINE_STATE_CB NULL + #else + extern void TUD_CDC_LINE_STATE_CB(uint8_t itf, bool dtr, bool rts); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB + #define TUD_CDC_LINE_CODING_CB tud_cdc_line_coding_cb + #endif + #ifndef TUD_CDC_LINE_CODING_CB + #define TUD_CDC_LINE_CODING_CB NULL + #else + extern void TUD_CDC_LINE_CODING_CB(uint8_t itf, cdc_line_coding_t const* p_line_coding); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB + #define TUD_CDC_SEND_BREAK_CB tud_cdc_send_break_cb + #endif + #ifndef TUD_CDC_SEND_BREAK_CB + #define TUD_CDC_SEND_BREAK_CB NULL + #else + extern void TUD_CDC_SEND_BREAK_CB(uint8_t itf, uint16_t duration_ms); + #endif +#endif + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 679060b20..508bb126e 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -48,6 +48,8 @@ #define TU_VERIFY_STATIC _Static_assert #elif defined (__cplusplus) && __cplusplus >= 201103L #define TU_VERIFY_STATIC static_assert +#elif defined(__CCRX__) + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif @@ -62,6 +64,9 @@ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ +// define the standard definition of this macro to construct a "weak" function name +#define MAKE_WEAK_FUNC(func_name) func_name + // TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -73,9 +78,17 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + #define TU_PACK_STRUCT_BEGIN + #define TU_PACK_STRUCT_END + + #define TU_BIT_FIELD_ORDER_BEGIN + #define TU_BIT_FIELD_ORDER_END + // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN + #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif @@ -123,6 +136,77 @@ #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) + +#elif defined(__CCRX__) + #define TU_ATTR_ALIGNED(Bytes) + #define TU_ATTR_SECTION(sec_name) + #define TU_ATTR_PACKED + #define TU_ATTR_WEAK + #define TU_ATTR_ALWAYS_INLINE + #define TU_ATTR_DEPRECATED(mess) + #define TU_ATTR_UNUSED + #define TU_ATTR_USED + + #define TU_PACK_STRUCT_BEGIN _Pragma("pack") + #define TU_PACK_STRUCT_END _Pragma("packoption") + + #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") + #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") + + // Endian conversion use well-known host to network (big endian) naming + #if defined(__LIT) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN + #define TU_ENDIAN_LITTLE_END + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN _Pragma("endian little") + #define TU_ENDIAN_LITTLE_END _Pragma("endian") + #endif + + #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) + #define TU_BSWAP32(u32) (_builtin_revl(u32)) + + /* activate the "aligned" emulation, because this toolchain does not know + the aligned attribute (or something similar yet) */ + #define TU_HAS_NO_ATTR_ALIGNED + + /* activate the "weak" function emulation, because this toolchain does not + know the weak attribute (or something similar yet) */ + #define TU_HAS_NO_ATTR_WEAK + + // make sure to define away the standard definition of this macro + #undef MAKE_WEAK_FUNC + // Helper macro to construct a "weak" function name + #define MAKE_WEAK_FUNC(func_name) weak_ ## func_name + + #if defined(TU_HAS_NO_ATTR_WEAK) + // "Weak function" emulation defined in cdc_device.h + #define ADD_WEAK_FUNC_TUD_CDC_RX_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB 0 + + // "Weak function" emulation defined in usbd_pvt.h + #define ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB 0 + + // "Weak function" emulation defined in usbd.h + #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB 0 + #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB 0 + #define ADD_WEAK_FUNC_TUD_MOUNT_CB 0 + #define ADD_WEAK_FUNC_TUD_UMOUNT_CB 0 + #define ADD_WEAK_FUNC_TUD_SUSPEND_CB 0 + #define ADD_WEAK_FUNC_TUD_RESUME_CB 0 + #define ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB 0 + + // "Weak function" emulation defined in dcd.h + #define ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE 0 + #define ADD_WEAK_FUNC_DCD_EDPT_CLOSE 0 + #define ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO 0 + #endif + #else #error "Compiler attribute porting is required" #endif @@ -149,11 +233,11 @@ #define tu_htonl(u32) (u32) #define tu_ntohl(u32) (u32) - #define tu_htole16(u16) (tu_bswap16(u16)) - #define tu_le16toh(u16) (tu_bswap16(u16)) + #define tu_htole16(u16) (TU_BSWAP16(u16)) + #define tu_le16toh(u16) (TU_BSWAP16(u16)) - #define tu_htole32(u32) (tu_bswap32(u32)) - #define tu_le32toh(u32) (tu_bswap32(u32)) + #define tu_htole32(u32) (TU_BSWAP32(u32)) + #define tu_le32toh(u32) (TU_BSWAP32(u32)) #else #error Byte order is undefined diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec58a3181..b20ea2974 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -263,6 +263,7 @@ enum //--------------------------------------------------------------------+ /// USB Device Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -283,10 +284,12 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -294,8 +297,10 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total length of data returned for this descriptor uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; +TU_PACK_STRUCT_END /// USB Configuration Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -308,10 +313,10 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); +TU_PACK_STRUCT_END /// USB Interface Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -325,8 +330,10 @@ typedef struct TU_ATTR_PACKED uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; +TU_PACK_STRUCT_END /// USB Endpoint Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -334,23 +341,32 @@ typedef struct TU_ATTR_PACKED uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t xfer : 2; uint8_t sync : 2; uint8_t usage : 2; uint8_t : 2; } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. + TU_BIT_FIELD_ORDER_END struct TU_ATTR_PACKED { +#if defined(__CCRX__) + //FIXME the original defined bit field has a problem with the CCRX toolchain, so only a size field is defined + uint16_t size; +#else uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; uint16_t TU_RESERVED : 3; +#endif }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; +TU_PACK_STRUCT_END /// USB Other Speed Configuration Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -363,8 +379,10 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; +TU_PACK_STRUCT_END /// USB Device Qualifier Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -378,8 +396,10 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; +TU_PACK_STRUCT_END /// USB Interface Association Descriptor (IAD ECN) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -394,16 +414,20 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_PACK_STRUCT_END // USB String Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; +TU_PACK_STRUCT_END // USB Binary Device Object Store (BOS) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -413,8 +437,10 @@ typedef struct TU_ATTR_PACKED uint8_t PlatformCapabilityUUID[16]; uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; +TU_PACK_STRUCT_END // USB WebuSB URL Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -422,14 +448,17 @@ typedef struct TU_ATTR_PACKED uint8_t bScheme; char url[]; } tusb_desc_webusb_url_t; +TU_PACK_STRUCT_END // DFU Functional Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; union { + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t bitCanDnload : 1; uint8_t bitCanUpload : 1; @@ -437,6 +466,7 @@ typedef struct TU_ATTR_PACKED uint8_t bitWillDetach : 1; uint8_t reserved : 4; } bmAttributes; + TU_BIT_FIELD_ORDER_END uint8_t bAttributes; }; @@ -445,17 +475,21 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; +TU_PACK_STRUCT_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED{ union { + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; + TU_BIT_FIELD_ORDER_END uint8_t bmRequestType; }; @@ -465,6 +499,7 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/device/dcd.h b/src/device/dcd.h index 71e88054c..fd87686bf 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -116,24 +116,54 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Endpoint API //--------------------------------------------------------------------+ +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); - // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; +#else + #if ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE + #define DCD_EDPT0_STATUS_COMPLETE dcd_edpt0_status_complete + #endif + #ifndef DCD_EDPT0_STATUS_COMPLETE + #define DCD_EDPT0_STATUS_COMPLETE NULL + #else + extern void DCD_EDPT0_STATUS_COMPLETE(uint8_t rhport, tusb_control_request_t const * request); + #endif + + #if ADD_WEAK_FUNC_DCD_EDPT_CLOSE + #define DCD_EDPT_CLOSE dcd_edpt_close + #endif + #ifndef DCD_EDPT_CLOSE + #define DCD_EDPT_CLOSE NULL + #else + extern void DCD_EDPT_CLOSE(uint8_t rhport, uint8_t ep_addr); + #endif + + #if ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO + #define DCD_EDPT_XFER_FIFO dcd_edpt_xfer_fifo + #endif + #ifndef DCD_EDPT_XFER_FIFO + #define DCD_EDPT_XFER_FIFO NULL + #else + extern void DCD_EDPT_XFER_FIFO(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); + #endif +#endif + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 8454a2951..fa86c28c7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,6 +33,19 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" +#if defined(TU_HAS_NO_ATTR_WEAK) +static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_bos_cb))(void) = TUD_DESCRIPTOR_BOS_CB; +static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb))(void) = TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB; +static void (*const MAKE_WEAK_FUNC(tud_mount_cb))(void) = TUD_MOUNT_CB; +static void (*const MAKE_WEAK_FUNC(tud_umount_cb))(void) = TUD_UMOUNT_CB; +static void (*const MAKE_WEAK_FUNC(tud_suspend_cb))(_Bool) = TUD_SUSPEND_CB; +static void (*const MAKE_WEAK_FUNC(tud_resume_cb))(void) = TUD_RESUME_CB; +static _Bool (*const MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb))(uint8_t, uint8_t, tusb_control_request_t const *) = TUD_RESUME_CB; +static usbd_class_driver_t const* (*const MAKE_WEAK_FUNC(usbd_app_driver_get_cb))(uint8_t*) = USBD_APP_DRIVER_GET_CB; +static bool (*const MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo))(uint8_t, uint8_t, tu_fifo_t *, uint16_t) = DCD_EDPT_XFER_FIFO; +static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT_CLOSE; +#endif + #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -50,6 +63,8 @@ enum { DRVID_INVALID = 0xFFu }; typedef struct { + TU_PACK_STRUCT_BEGIN + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -60,6 +75,8 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; + TU_BIT_FIELD_ORDER_END + TU_PACK_STRUCT_END volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; @@ -67,6 +84,8 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + TU_PACK_STRUCT_BEGIN + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile bool busy : 1; @@ -75,6 +94,8 @@ typedef struct // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUD_EP_MAX][2]; + TU_BIT_FIELD_ORDER_END + TU_PACK_STRUCT_END }usbd_device_t; @@ -236,7 +257,7 @@ static uint8_t _app_driver_count = 0; static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { // Application drivers - if ( usbd_app_driver_get_cb ) + if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) { if ( drvid < _app_driver_count ) return &_app_driver[drvid]; drvid -= _app_driver_count; @@ -408,9 +429,9 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( usbd_app_driver_get_cb ) + if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) { - _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + _app_driver = MAKE_WEAK_FUNC(usbd_app_driver_get_cb)(&_app_driver_count); } // Init class drivers @@ -501,7 +522,7 @@ void tud_task (void) usbd_reset(event.rhport); // invoke callback - if (tud_umount_cb) tud_umount_cb(); + if (MAKE_WEAK_FUNC(tud_umount_cb)) MAKE_WEAK_FUNC(tud_umount_cb)(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -557,12 +578,12 @@ void tud_task (void) case DCD_EVENT_SUSPEND: TU_LOG2("\r\n"); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + if (MAKE_WEAK_FUNC(tud_suspend_cb)) MAKE_WEAK_FUNC(tud_suspend_cb)(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); + if (MAKE_WEAK_FUNC(tud_resume_cb)) MAKE_WEAK_FUNC(tud_resume_cb)(); break; case DCD_EVENT_SOF: @@ -609,10 +630,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_xfer_cb); + TU_VERIFY(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); - usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); - return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); + usbd_control_set_complete_callback(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); + return MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 @@ -831,7 +852,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Parse interface descriptor uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; + uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); while( p_desc < desc_end ) { @@ -892,7 +913,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // invoke callback - if (tud_mount_cb) tud_mount_cb(); + if (MAKE_WEAK_FUNC(tud_mount_cb)) MAKE_WEAK_FUNC(tud_mount_cb)(); return true; } @@ -949,15 +970,15 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!tud_descriptor_bos_cb) return false; + if (!MAKE_WEAK_FUNC(tud_descriptor_bos_cb)) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)MAKE_WEAK_FUNC(tud_descriptor_bos_cb)(); uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); - return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); + return tud_control_xfer(rhport, p_request, (void*) desc_bos, tu_le16toh(total_len)); } break; @@ -972,7 +993,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); + return tud_control_xfer(rhport, p_request, (void*) desc_config, tu_le16toh(total_len)); } break; @@ -995,9 +1016,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Host sends this request to ask why our device with USB BCD from 2.0 // but is running at Full/Low Speed. If not highspeed capable stall this request, // otherwise return the descriptor that could work in highspeed mode - if ( tud_descriptor_device_qualifier_cb ) + if (MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)) { - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + uint8_t const* desc_qualifier = MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)(); TU_ASSERT(desc_qualifier); // first byte of descriptor is its size @@ -1165,18 +1186,18 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(desc_ep->wMaxPacketSize.size == 512); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) == 512); }else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(desc_ep->wMaxPacketSize.size <= 64); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= 64); } break; case TUSB_XFER_INTERRUPT: { uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); } break; @@ -1285,7 +1306,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) + if (MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo)(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; @@ -1348,10 +1369,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(dcd_edpt_close, /**/); + TU_ASSERT(MAKE_WEAK_FUNC(dcd_edpt_close), /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - dcd_edpt_close(rhport, ep_addr); + MAKE_WEAK_FUNC(dcd_edpt_close(rhport, ep_addr)); return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 53519c4de..04597a215 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -103,10 +103,6 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void); -// Invoked when received GET BOS DESCRIPTOR request -// Application return pointer to descriptor -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); - // Invoked when received GET CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index); @@ -115,6 +111,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); +#if !defined(TU_HAS_NO_ATTR_WEAK) +// Invoked when received GET BOS DESCRIPTOR request +// Application return pointer to descriptor +TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); + // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); @@ -135,6 +136,71 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +#else + #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB + #define TUD_DESCRIPTOR_BOS_CB tud_descriptor_bos_cb + #endif + #ifndef TUD_DESCRIPTOR_BOS_CB + #define TUD_DESCRIPTOR_BOS_CB NULL + #else + extern uint8_t const* TUD_DESCRIPTOR_BOS_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB + #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB tud_descriptor_device_qualifier_cb + #endif + #ifndef TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB + #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB NULL + #else + extern uint8_t const* TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_MOUNT_CB + #define TUD_MOUNT_CB tud_mount_cb + #endif + #ifndef TUD_MOUNT_CB + #define TUD_MOUNT_CB NULL + #else + extern void TUD_MOUNT_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_UMOUNT_CB + #define TUD_UMOUNT_CB tud_umount_cb + #endif + #ifndef TUD_UMOUNT_CB + #define TUD_UMOUNT_CB NULL + #else + extern void TUD_UMOUNT_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_SUSPEND_CB + #define TUD_SUSPEND_CB tud_suspend_cb + #endif + #ifndef TUD_SUSPEND_CB + #define TUD_SUSPEND_CB NULL + #else + extern void TUD_SUSPEND_CB(bool remote_wakeup_en); + #endif + + #if ADD_WEAK_FUNC_TUD_RESUME_CB + #define TUD_RESUME_CB tud_resume_cb + #endif + #ifndef TUD_RESUME_CB + #define TUD_RESUME_CB NULL + #else + extern void TUD_RESUME_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB + #define TUD_VENDOR_CONTROL_XFER_CB tud_vendor_control_xfer_cb + #endif + #ifndef TUD_VENDOR_CONTROL_XFER_CB + #define TUD_VENDOR_CONTROL_XFER_CB NULL + #else + extern bool TUD_VENDOR_CONTROL_XFER_CB(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + #endif +#endif + //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 724c652e6..76f999f86 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -36,6 +36,10 @@ extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif +#if defined(TU_HAS_NO_ATTR_WEAK) +static void (*const MAKE_WEAK_FUNC(dcd_edpt0_status_complete))(uint8_t, tusb_control_request_t const *) = DCD_EDPT0_STATUS_COMPLETE; +#endif + enum { EDPT_CTRL_OUT = 0x00, @@ -55,8 +59,17 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; +#if defined(TU_HAS_NO_ATTR_ALIGNED) +// Helper union to overcome the lack of the alignment attribute/pragma +static union { + uint16_t : (sizeof(uint16_t) * 8); // Alignment of at least the size of the used type + uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +} Align_usbd_ctrl_buf_; +static uint8_t *_usbd_ctrl_buf = (uint8_t*)&Align_usbd_ctrl_buf_; +#else CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +#endif //--------------------------------------------------------------------+ // Application API @@ -171,7 +184,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + if (MAKE_WEAK_FUNC(dcd_edpt0_status_complete)) MAKE_WEAK_FUNC(dcd_edpt0_status_complete)(rhport, &_ctrl_xfer.request); if (_ctrl_xfer.complete_cb) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 44310f022..1d60e5ae2 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -51,10 +51,21 @@ typedef struct void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; +#else + #if ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB + #define USBD_APP_DRIVER_GET_CB usbd_app_driver_get_cb + #endif + #ifndef USBD_APP_DRIVER_GET_CB + #define USBD_APP_DRIVER_GET_CB NULL + #else + extern usbd_class_driver_t const* USBD_APP_DRIVER_GET_CB(uint8_t* driver_count); + #endif +#endif typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 66070c273..ec33b317d 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -51,6 +51,7 @@ static inline void osal_task_delay(uint32_t msec) typedef StaticSemaphore_t osal_semaphore_def_t; typedef SemaphoreHandle_t osal_semaphore_t; +#if (configSUPPORT_STATIC_ALLOCATION == 1) //FIXME Only static API supported static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return xSemaphoreCreateBinaryStatic(semdef); @@ -76,6 +77,7 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) return res != 0; } } +#endif static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { @@ -96,7 +98,12 @@ typedef SemaphoreHandle_t osal_mutex_t; static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { +#if (configSUPPORT_STATIC_ALLOCATION == 0) //FIXME Only static API supported + (void)mdef; + return xSemaphoreCreateMutex(); +#else return xSemaphoreCreateMutexStatic(mdef); +#endif } static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) @@ -131,7 +138,11 @@ typedef QueueHandle_t osal_queue_t; static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { +#if defined(__Tx36V5_Maincard__) + return xQueueCreate(qdef->depth, qdef->item_sz); +#else return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); +#endif } static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) @@ -139,6 +150,19 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return xQueueReceive(qhdl, data, portMAX_DELAY); } +#if defined(__Tx36V5_Maincard__) +extern BaseType_t UsbTaskWoken; +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + if (!in_isr) { + return(xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER)); + + } else { + BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &UsbTaskWoken); + return(res != 0); + } +} +#else static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if ( !in_isr ) @@ -159,6 +183,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return res != 0; } } +#endif static inline bool osal_queue_empty(osal_queue_t qhdl) { diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 06ea1a3f9..54410ff0b 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X ) +#if TUSB_OPT_DEVICE_ENABLED && (( CFG_TUSB_MCU == OPT_MCU_RX63X ) || ( CFG_TUSB_MCU == OPT_MCU_RX72N )) #include "device/dcd.h" #include "iodefine.h" @@ -38,6 +38,7 @@ #define SYSTEM_PRCR_PRKEY (0xA5u<<8) #define USB_FIFOSEL_TX ((uint16_t)(1u<<5)) +#define USB_FIFOSEL_BIGEND ((uint16_t)(1u<<8)) #define USB_FIFOSEL_MBW_8 ((uint16_t)(0u<<10)) #define USB_FIFOSEL_MBW_16 ((uint16_t)(1u<<10)) #define USB_IS0_CTSQ ((uint16_t)(7u)) @@ -91,39 +92,47 @@ typedef struct { union { + TU_BIT_FIELD_ORDER_BEGIN struct { uint16_t : 8; uint16_t TRCLR: 1; uint16_t TRENB: 1; uint16_t : 0; }; + TU_BIT_FIELD_ORDER_END uint16_t TRE; }; uint16_t TRN; } reg_pipetre_t; typedef union { + TU_BIT_FIELD_ORDER_BEGIN struct { volatile uint16_t u8: 8; volatile uint16_t : 0; }; + TU_BIT_FIELD_ORDER_END volatile uint16_t u16; } hw_fifo_t; +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ + TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; + TU_BIT_FIELD_ORDER_END } pipe_state_t; +TU_PACK_STRUCT_END typedef struct { - pipe_state_t pipe[9]; + pipe_state_t pipe[10]; uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ } dcd_data_t; @@ -135,14 +144,23 @@ CFG_TUSB_MEM_SECTION static dcd_data_t _dcd; static uint32_t disable_interrupt(void) { uint32_t pswi; +#if defined(__CCRX__) + pswi = get_psw() & 0x010000; + clrpsw_i(); +#else pswi = __builtin_rx_mvfc(0) & 0x010000; __builtin_rx_clrpsw('I'); +#endif return pswi; } static void enable_interrupt(uint32_t pswi) { +#if defined(__CCRX__) + set_psw(get_psw() | pswi); +#else __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi); +#endif } static unsigned find_pipe(unsigned xfer) @@ -226,7 +244,7 @@ static unsigned select_pipe(unsigned num, unsigned attr) { USB0.PIPESEL.WORD = num; USB0.D0FIFOSEL.WORD = num | attr; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; return wait_for_pipe_ready(); } @@ -270,11 +288,11 @@ static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size if (rem < len) len = rem; pipe->remaining = rem - len; - hw_fifo_t *reg = (hw_fifo_t*)fifo; + uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */ uintptr_t addr = pipe->addr; unsigned loop = len; while (loop--) { - *(uint8_t *)addr = reg->u8; + *(uint8_t *)addr = *reg; ++addr; } pipe->addr = addr; @@ -292,6 +310,13 @@ static void process_setup_packet(uint8_t rhport) setup_packet[1] = USB0.USBVAL; setup_packet[2] = USB0.USBINDX; setup_packet[3] = USB0.USBLENG; +#if TU_BYTE_ORDER==TU_BIG_ENDIAN + #if defined(__CCRX__) + setup_packet[0] = tu_le16toh(setup_packet[0]); + #else + //FIXME needs to implemented for other tool chains + #endif +#endif USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); } @@ -317,7 +342,11 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe_state_t *pipe = &_dcd.pipe[0]; /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; +#else USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; +#endif while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; } else { /* OUT, a byte */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; @@ -329,7 +358,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->remaining = total_bytes; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (fifo_write(&USB0.CFIFO.WORD, pipe, 64)) { + if (fifo_write((void*)&USB0.CFIFO.WORD, pipe, 64)) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; } } @@ -350,7 +379,7 @@ static void process_edpt0_bemp(uint8_t rhport) const unsigned rem = pipe->remaining; if (rem > 64) { pipe->remaining = rem - 64; - int r = fifo_write(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + int r = fifo_write((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -363,7 +392,7 @@ static void process_edpt0_bemp(uint8_t rhport) static void process_edpt0_brdy(uint8_t rhport) { size_t len = USB0.CFIFOCTR.BIT.DTLN; - int cplt = fifo_read(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); + int cplt = fifo_read((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); if (cplt || (len < 64)) { if (2 != cplt) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; @@ -392,11 +421,16 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, USB0.PIPESEL.WORD = num; const unsigned mps = USB0.PIPEMAXP.WORD; if (dir) { /* IN */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; +#else USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - int r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); +#endif + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; + int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } else { volatile reg_pipetre_t *pt = get_pipetre(num); if (pt) { @@ -416,19 +450,25 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; if (tu_edpt_dir(pipe->ep)) { /* IN */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + select_pipe(num, USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND); +#else select_pipe(num, USB_FIFOSEL_MBW_16); +#endif const unsigned mps = USB0.PIPEMAXP.WORD; unsigned rem = pipe->remaining; rem -= TU_MIN(rem, mps); pipe->remaining = rem; if (rem) { int r = 0; - r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); + r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ return; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ pipe->addr = 0; pipe->remaining = 0; dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, @@ -437,18 +477,20 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); const unsigned len = ctr & USB_FIFOCTR_DTLN; const unsigned mps = USB0.PIPEMAXP.WORD; - int cplt = fifo_read(&USB0.D0FIFO.WORD, pipe, mps, len); + int cplt = fifo_read((void*)&USB0.D0FIFO.WORD, pipe, mps, len); if (cplt || (len < mps)) { if (2 != cplt) { USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ dcd_event_xfer_complete(rhport, pipe->ep, pipe->length - pipe->remaining, XFER_RESULT_SUCCESS, true); return; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } } @@ -458,7 +500,9 @@ static void process_bus_reset(uint8_t rhport) USB0.BRDYENB.WORD = 1; USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ USB0.D1FIFOSEL.WORD = 0; + while (USB0.D1FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1CTR.WORD)); volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1TRE.WORD)); for (int i = 1; i <= 5; ++i) { @@ -485,13 +529,22 @@ static void process_set_address(uint8_t rhport) { const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; +#if defined(__CCRX__) + tusb_control_request_t setup_packet; + setup_packet.bmRequestType = 0; + setup_packet.bRequest = 5; + setup_packet.wValue = addr; + setup_packet.wIndex = 0; + setup_packet.wLength = 0; +#else const tusb_control_request_t setup_packet = { - .bmRequestType = 0, - .bRequest = 5, - .wValue = addr, - .wIndex = 0, - .wLength = 0, - }; + .bmRequestType = 0, + .bRequest = 5, + .wValue = addr, + .wIndex = 0, + .wLength = 0, + }; +#endif dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true); } @@ -513,7 +566,13 @@ void dcd_init(uint8_t rhport) USB0.SYSCFG.BIT.DCFM = 0; USB0.SYSCFG.BIT.USBE = 1; + USB0.PHYSLEW.LONG = 0x5; + USB.DPUSR0R.BIT.FIXPHY0 = 0u; /* USB0 Transceiver Output fixed */ +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IR(PERIB, INTB185) = 0; +#else IR(USB0, USBI0) = 0; +#endif /* Setup default control pipe */ USB0.DCPMAXP.BIT.MXPS = 64; @@ -529,13 +588,21 @@ void dcd_init(uint8_t rhport) void dcd_int_enable(uint8_t rhport) { (void)rhport; +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IEN(PERIB, INTB185) = 1; +#else IEN(USB0, USBI0) = 1; +#endif } void dcd_int_disable(uint8_t rhport) { (void)rhport; +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IEN(PERIB, INTB185) = 0; +#else IEN(USB0, USBI0) = 0; +#endif } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -574,7 +641,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; - const unsigned mps = ep_desc->wMaxPacketSize.size; + const unsigned mps = tu_le16toh(ep_desc->wMaxPacketSize.size); if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { /* USBa supports up to 256 bytes */ return false; @@ -680,8 +747,8 @@ void dcd_int_handler(uint8_t rhport) (void)rhport; unsigned is0 = USB0.INTSTS0.WORD; - /* clear bits except VALID */ - USB0.INTSTS0.WORD = USB_IS0_VALID; + /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */ + USB0.INTSTS0.WORD = ~((USB_IS0_CTRT | USB_IS0_DVST | USB_IS0_SOFR | USB_IS0_RESM | USB_IS0_VBINT) & is0) | USB_IS0_VALID; if (is0 & USB_IS0_VBINT) { if (USB0.INTSTS0.BIT.VBSTS) { dcd_connect(rhport); @@ -720,13 +787,24 @@ void dcd_int_handler(uint8_t rhport) if (is0 & USB_IS0_BRDY) { const unsigned m = USB0.BRDYENB.WORD; unsigned s = USB0.BRDYSTS.WORD & m; - USB0.BRDYSTS.WORD = 0; + /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */ + USB0.BRDYSTS.WORD = ~s; if (s & 1) { process_edpt0_brdy(rhport); s &= ~1; } while (s) { +#if defined(__CCRX__) + static const int Mod37BitPosition[] = { + -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, + 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, + 20, 8, 19, 18 + }; + + const unsigned num = Mod37BitPosition[(-s & s) % 37]; +#else const unsigned num = __builtin_ctz(s); +#endif process_pipe_brdy(rhport, num); s &= ~TU_BIT(num); } diff --git a/src/tusb_option.h b/src/tusb_option.h index b317f7630..d04542e61 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -112,6 +112,7 @@ // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 +#define OPT_MCU_RX72N 1401 ///< Renesas RX72N /** @} */ -- cgit v1.3.1 From 5cf930d78a9e31924008ac6bd145ddf2af76b42f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 11:11:00 +0700 Subject: fix cast-align warning in msc host --- src/class/msc/msc_host.c | 7 ++++--- src/host/hcd.h | 2 ++ src/portable/ehci/ehci.c | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 5a4ffff48..205f0fd2d 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -71,7 +71,8 @@ CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX] // buffer used to read scsi information when mounted // largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) +static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; static inline msch_interface_t* get_itf(uint8_t dev_addr) { @@ -438,7 +439,7 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c { // Unit is ready, read its capacity TU_LOG2("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete); + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries @@ -465,7 +466,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw msch_interface_t* p_msc = get_itf(dev_addr); // Capacity response field: Block size and Last LBA are both Big-Endian - scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer; + scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); diff --git a/src/host/hcd.h b/src/host/hcd.h index ba6a9c5ca..df19f3e22 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -28,6 +28,8 @@ #define _TUSB_HCD_H_ #include "common/tusb_common.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" #ifdef __cplusplus extern "C" { diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index eab1f8928..a1c12e70d 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -302,7 +302,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - // FIXME control only for now if ( epnum == 0 ) { ehci_qhd_t* qhd = qhd_control(dev_addr); -- cgit v1.3.1 From 3fb80e76ce554018fd81b2922c1db9121f446ac1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 12:08:37 +0700 Subject: remove obsolete hcd_pipe_queue_xfer()/hcd_pipe_xfer() --- src/class/cdc/cdc_host.c | 6 +- src/class/cdc/cdc_rndis_host.c | 2 +- src/class/vendor/vendor_host.c | 4 +- src/host/hcd.h | 11 +--- src/host/hub.c | 2 +- src/portable/ehci/ehci.c | 82 ++++++++-------------------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 10 ---- 7 files changed, 33 insertions(+), 84 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index c22107bbb..facf86d56 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -96,24 +96,26 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify) { + (void) is_notify; TU_VERIFY( tuh_cdc_mounted(dev_addr) ); TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; if ( hcd_edpt_busy(dev_addr, ep_out) ) return false; - return hcd_pipe_xfer(dev_addr, ep_out, (void *) p_data, length, is_notify); + return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); } bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify) { + (void) is_notify; TU_VERIFY( tuh_cdc_mounted(dev_addr) ); TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; if ( hcd_edpt_busy(dev_addr, ep_in) ) return false; - return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify); + return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 767b917a1..42b9993bc 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -239,7 +239,7 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); //------------- waiting for Response Available notification -------------// - (void) hcd_pipe_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8, true); + (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 1978ef61c..f7a6b2bf0 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -66,7 +66,7 @@ tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t pr return TUSB_ERROR_INTERFACE_IS_BUSY; } - (void) hcd_pipe_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length, true); + (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); return TUSB_ERROR_NONE; } @@ -80,7 +80,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p return TUSB_ERROR_INTERFACE_IS_BUSY; } - (void) hcd_pipe_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length, true); + (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); return TUSB_ERROR_NONE; } diff --git a/src/host/hcd.h b/src/host/hcd.h index df19f3e22..0a9f00a0c 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -143,21 +143,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); -// TODO merge with pipe_xfer -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); - -//--------------------------------------------------------------------+ -// PIPE API - TODO remove later -//--------------------------------------------------------------------+ -// TODO control xfer should be used via usbh layer -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); - //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ diff --git a/src/host/hub.c b/src/host/hub.c index 4db680f9e..2d4033a26 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -352,7 +352,7 @@ void hub_close(uint8_t dev_addr) bool hub_status_pipe_queue(uint8_t dev_addr) { usbh_hub_t * p_hub = &hub_data[dev_addr-1]; - return hcd_pipe_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1, true); + return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index a1c12e70d..70a497f0a 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -293,8 +293,31 @@ static void ehci_stop(uint8_t rhport) #endif //--------------------------------------------------------------------+ -// CONTROL PIPE API +// Endpoint API //--------------------------------------------------------------------+ + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void) rhport; + + ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; + ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; + + qtd_init(td, (void*) setup_packet, 8); + td->pid = EHCI_PID_SETUP; + td->int_on_complete = 1; + td->next.terminate = 1; + + // sw region + qhd->p_qtd_list_head = td; + qhd->p_qtd_list_tail = td; + + // attach TD + qhd->qtd_overlay.next.address = (uint32_t) td; + + return true; +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -342,31 +365,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; - ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - - qtd_init(td, (void*) setup_packet, 8); - td->pid = EHCI_PID_SETUP; - td->int_on_complete = 1; - td->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = td; - qhd->p_qtd_list_tail = td; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) td; - - return true; -} - -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; @@ -420,38 +418,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - //------------- set up QTD -------------// - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); - - TU_ASSERT(p_qtd); - - qtd_init(p_qtd, buffer, total_bytes); - p_qtd->pid = p_qhd->pid; - - //------------- insert TD to TD list -------------// - qtd_insert_to_qhd(p_qhd, p_qtd); - - return true; -} - -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) ); - - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - - if ( int_on_complete ) - { // the just added qtd is pointed by list_tail - p_qhd->p_qtd_list_tail->int_on_complete = 1; - } - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach head QTD to QHD start transferring - - return true; -} - bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index c09469ff5..b8833fbec 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -543,14 +543,4 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) return true; } -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - pico_trace("hcd_pipe_xfer dev_addr %d, ep_addr 0x%x, total_bytes %d, int_on_complete %d\n", - dev_addr, ep_addr, total_bytes, int_on_complete); - - // Same logic as hcd_edpt_xfer as far as I am concerned - hcd_edpt_xfer(0, dev_addr, ep_addr, buffer, total_bytes); - - return true; -} #endif -- cgit v1.3.1 From 6e2cf2a3eec141e2714937532320c9fc46b95f9b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jun 2021 00:10:35 +0700 Subject: clean up log --- src/class/hid/hid_device.c | 2 +- src/class/msc/msc_device.c | 2 +- src/class/vendor/vendor_device.c | 2 +- src/common/tusb_common.h | 4 ---- 4 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index c7f5d04ec..151a36225 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -225,7 +225,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 { if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) { - TU_LOG1_FAILED(); + TU_LOG_FAILED(); TU_BREAKPOINT(); } } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9b06b7a33..7f13b4891 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -172,7 +172,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Prepare for Command Block Wrapper if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ) { - TU_LOG1_FAILED(); + TU_LOG_FAILED(); TU_BREAKPOINT(); } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 081aac9f6..6718a97bf 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -195,7 +195,7 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // Prepare for incoming data if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) ) { - TU_LOG1_FAILED(); + TU_LOG_FAILED(); TU_BREAKPOINT(); } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 6f2905697..d9b388916 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -372,8 +372,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG1_VAR(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) - #define TU_LOG1_LOCATION() - #define TU_LOG1_FAILED() #endif #ifndef TU_LOG2 @@ -382,7 +380,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG2_VAR(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) - #define TU_LOG2_LOCATION() #endif #ifndef TU_LOG3 @@ -391,7 +388,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG3_VAR(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) - #define TU_LOG3_LOCATION() #endif #ifdef __cplusplus -- cgit v1.3.1 From d5f8da44d13d3410f6c710432062807b52ebf407 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Mon, 7 Jun 2021 19:04:21 +0200 Subject: Add optional support for 32 gamepad buttons --- src/class/hid/hid.h | 40 ++++++++++++++++++++++++++++++++++++++-- src/class/hid/hid_device.h | 9 ++++----- src/tusb_option.h | 6 ++++++ 3 files changed, 48 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 5cc9233b5..3c45dc6c1 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -33,10 +33,12 @@ #include "common/tusb_common.h" + #ifdef __cplusplus extern "C" { #endif + //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ @@ -150,6 +152,22 @@ typedef enum /** @} */ +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 64 +#endif + +#ifndef CFG_TUSB_MAX_BUTTONS + #define CFG_TUSB_MAX_BUTTONS 16 +#endif + +#if (CFG_TUSB_MAX_BUTTONS == 16) + typedef uint16_t hid_gamepad_buttons_t; +#elif (CFG_TUSB_MAX_BUTTONS == 32) + typedef uint32_t hid_gamepad_buttons_t; +#else + #error "Invalid CFG_TUSB_MAX_BUTTONS value." +#endif + //--------------------------------------------------------------------+ // GAMEPAD //--------------------------------------------------------------------+ @@ -201,7 +219,7 @@ typedef struct TU_ATTR_PACKED int8_t rx; ///< Delta Rx movement of analog left trigger int8_t ry; ///< Delta Ry movement of analog right trigger uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint16_t buttons; ///< Buttons mask for currently pressed buttons + hid_gamepad_buttons_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; /// Standard Gamepad Buttons Bitmap (from Linux input event codes) @@ -222,7 +240,25 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button -//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button + GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 +#ifdef CFG_TUSB_MAX_BUTTONS_32 + GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 + GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 16 + GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 16 + GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 16 + GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 16 + GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 16 + GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 16 + GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 16 + GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 16 + GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 16 + GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 16 + GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 16 + GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 16 + GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 16 + GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 16 + GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 16 +#endif }hid_gamepad_button_bm_t; /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index beb755888..0ff5cab3f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -43,9 +43,8 @@ #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE #endif -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 -#endif + + //--------------------------------------------------------------------+ // Application API (Multiple Instances) @@ -344,10 +343,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 16 ) ,\ + HID_USAGE_MAX ( CFG_TUSB_MAX_BUTTONS ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 16 ) ,\ + HID_REPORT_COUNT ( CFG_TUSB_MAX_BUTTONS ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/tusb_option.h b/src/tusb_option.h index 5cfcc08e2..a7939d9c7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -316,6 +316,12 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif +#ifndef TUD_OPT_GAMEPAD_32_BUTTONS + #define CFG_TUSB_MAX_BUTTONS 16 +#else + #define CFG_TUSB_MAX_BUTTONS 32 +#endif + #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 3842c806a6bd90a3be8431c4fa3fb8c46220a6bf Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Mon, 7 Jun 2021 20:16:05 +0200 Subject: clean up --- src/class/hid/hid.h | 16 ++++++---------- src/class/hid/hid_device.h | 4 ++-- src/tusb_option.h | 17 +++++++++++++---- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 3c45dc6c1..eac30c62e 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -152,20 +152,16 @@ typedef enum /** @} */ -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 +#ifndef CFG_TUD_MAX_BUTTONS + #define CFG_TUD_MAX_BUTTONS 16 #endif -#ifndef CFG_TUSB_MAX_BUTTONS - #define CFG_TUSB_MAX_BUTTONS 16 -#endif - -#if (CFG_TUSB_MAX_BUTTONS == 16) +#if (CFG_TUD_MAX_BUTTONS == 16) typedef uint16_t hid_gamepad_buttons_t; -#elif (CFG_TUSB_MAX_BUTTONS == 32) +#elif (CFG_TUD_MAX_BUTTONS == 32) typedef uint32_t hid_gamepad_buttons_t; #else - #error "Invalid CFG_TUSB_MAX_BUTTONS value." + #error "Invalid CFG_TUD_MAX_BUTTONS value." #endif //--------------------------------------------------------------------+ @@ -241,7 +237,7 @@ typedef enum GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 -#ifdef CFG_TUSB_MAX_BUTTONS_32 +#if (CFG_TUD_MAX_BUTTONS > 16) GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 16 GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 16 diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0ff5cab3f..39ec6be76 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -343,10 +343,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( CFG_TUSB_MAX_BUTTONS ) ,\ + HID_USAGE_MAX ( CFG_TUD_MAX_BUTTONS ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( CFG_TUSB_MAX_BUTTONS ) ,\ + HID_REPORT_COUNT ( CFG_TUD_MAX_BUTTONS ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/tusb_option.h b/src/tusb_option.h index a7939d9c7..3adb4fcf9 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -309,6 +309,16 @@ #define TUP_MCU_STRICT_ALIGN 0 #endif +//--------------------------------------------------------------------+ +// HID Gamepad options +//--------------------------------------------------------------------+ + +// CFG_TUD_MAX_BUTTONS lets you choose if you want 16 or 32 buttons on you HID gamepad +#ifndef CFG_TUD_MAX_BUTTONS + #define CFG_TUD_MAX_BUTTONS 16 +#endif + + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ @@ -316,10 +326,9 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif -#ifndef TUD_OPT_GAMEPAD_32_BUTTONS - #define CFG_TUSB_MAX_BUTTONS 16 -#else - #define CFG_TUSB_MAX_BUTTONS 32 + +#if (CFG_TUD_MAX_BUTTONS != 16 && CFG_TUD_MAX_BUTTONS != 32) + #error "Unsupported CFG_TUD_MAX_BUTTONS" #endif #endif /* _TUSB_OPTION_H_ */ -- cgit v1.3.1 From ce634f226e59cccfb236371f85a62cb610ef80f6 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Mon, 7 Jun 2021 20:44:53 +0200 Subject: remove excess empty lines --- src/class/hid/hid.h | 2 -- src/tusb_option.h | 1 - 2 files changed, 3 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index eac30c62e..0764bc228 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -33,12 +33,10 @@ #include "common/tusb_common.h" - #ifdef __cplusplus extern "C" { #endif - //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index 3adb4fcf9..6a6e31ee9 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -318,7 +318,6 @@ #define CFG_TUD_MAX_BUTTONS 16 #endif - //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -- cgit v1.3.1 From e12195705c2b849379145618691c2e8564762aa7 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:24:50 +0200 Subject: Pull request changes Remove configuration options and just bump number of buttons to 32 Fix button numbereing and comments in --- examples/device/hid_composite/src/tusb_config.h | 4 --- src/class/hid/hid.h | 48 +++++++++---------------- src/class/hid/hid_device.h | 4 +-- src/tusb_option.h | 14 -------- 4 files changed, 19 insertions(+), 51 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index bc9192d13..3e608ed37 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -104,10 +104,6 @@ // HID buffer size Should be sufficient to hold ID (if any) + Data #define CFG_TUD_HID_EP_BUFSIZE 16 -// Number of button on the gamepad 16 or 32 -#define CFG_TUD_MAX_BUTTONS 16 - - #ifdef __cplusplus } #endif diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 0764bc228..a344c9100 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -150,18 +150,6 @@ typedef enum /** @} */ -#ifndef CFG_TUD_MAX_BUTTONS - #define CFG_TUD_MAX_BUTTONS 16 -#endif - -#if (CFG_TUD_MAX_BUTTONS == 16) - typedef uint16_t hid_gamepad_buttons_t; -#elif (CFG_TUD_MAX_BUTTONS == 32) - typedef uint32_t hid_gamepad_buttons_t; -#else - #error "Invalid CFG_TUD_MAX_BUTTONS value." -#endif - //--------------------------------------------------------------------+ // GAMEPAD //--------------------------------------------------------------------+ @@ -213,7 +201,7 @@ typedef struct TU_ATTR_PACKED int8_t rx; ///< Delta Rx movement of analog left trigger int8_t ry; ///< Delta Ry movement of analog right trigger uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - hid_gamepad_buttons_t buttons; ///< Buttons mask for currently pressed buttons + uint32_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; /// Standard Gamepad Buttons Bitmap (from Linux input event codes) @@ -234,25 +222,23 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 -#if (CFG_TUD_MAX_BUTTONS > 16) + GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 15 GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 - GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 16 - GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 16 - GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 16 - GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 16 - GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 16 - GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 16 - GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 16 - GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 16 - GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 16 - GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 16 - GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 16 - GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 16 - GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 16 - GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 16 - GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 16 -#endif + GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 + GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 19 + GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 20 + GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 21 + GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 22 + GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 23 + GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 24 + GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 25 + GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 26 + GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 27 + GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 28 + GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 29 + GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 30 + GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 31 + GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 32 }hid_gamepad_button_bm_t; /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 39ec6be76..543bc3b3b 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -343,10 +343,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( CFG_TUD_MAX_BUTTONS ) ,\ + HID_USAGE_MAX ( 32 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( CFG_TUD_MAX_BUTTONS ) ,\ + HID_REPORT_COUNT ( 32 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/tusb_option.h b/src/tusb_option.h index 6a6e31ee9..5cfcc08e2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -309,15 +309,6 @@ #define TUP_MCU_STRICT_ALIGN 0 #endif -//--------------------------------------------------------------------+ -// HID Gamepad options -//--------------------------------------------------------------------+ - -// CFG_TUD_MAX_BUTTONS lets you choose if you want 16 or 32 buttons on you HID gamepad -#ifndef CFG_TUD_MAX_BUTTONS - #define CFG_TUD_MAX_BUTTONS 16 -#endif - //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ @@ -325,11 +316,6 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif - -#if (CFG_TUD_MAX_BUTTONS != 16 && CFG_TUD_MAX_BUTTONS != 32) - #error "Unsupported CFG_TUD_MAX_BUTTONS" -#endif - #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From de71e72e31ca1d534e5e0413f9da0a0e84a9aa69 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:26:17 +0200 Subject: Fix comment in hid.h --- src/class/hid/hid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index a344c9100..8ab24ab3e 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -217,12 +217,12 @@ typedef enum GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 15 + GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 16 GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 19 -- cgit v1.3.1 From d3b6e28387c63a1519cd1958ee7e21bd2980d099 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:31:40 +0200 Subject: indent fix --- src/class/hid/hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 8ab24ab3e..782a1a552 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -217,7 +217,7 @@ typedef enum GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button -- cgit v1.3.1 From e393fb32a0830e9d371f3e335cc0cca92b75cbbb Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:39:53 +0200 Subject: re-adding ifdef removed accidentally --- src/class/hid/hid_device.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 543bc3b3b..1d1213e3f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -43,8 +43,9 @@ #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE #endif - - +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 64 +#endif //--------------------------------------------------------------------+ // Application API (Multiple Instances) -- cgit v1.3.1 From 2c0947ebb621e3e53933300cbfd1dce7e0f31338 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 10:30:13 +0700 Subject: update gamepad helper --- src/class/hid/hid.h | 1 + src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 782a1a552..b4e8a9c4c 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -222,6 +222,7 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button + // Note: Button number start from 1 on host OS GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 16 GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 151a36225..e44f282c4 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -149,7 +149,7 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, } bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { hid_gamepad_report_t report = { diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1d1213e3f..19e9315f4 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -72,9 +72,9 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi // use template layout report as defined by hid_mouse_report_t bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -// Gamepad: convenient helper to send mouse report if application +// Gamepad: convenient helper to send gamepad report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); //--------------------------------------------------------------------+ // Application API (Single Port) @@ -85,7 +85,7 @@ static inline uint8_t tud_hid_get_protocol(void); static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) -- cgit v1.3.1 From dca9bc97d66fe2912d2643e4f36cb839d08a31da Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 10:45:37 +0700 Subject: miss a helper --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 19e9315f4..e2c950dd1 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -152,7 +152,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); } -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } -- cgit v1.3.1 From a8abbcc34df72ff5a63d5567d26276ce84e6d162 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Wed, 9 Jun 2021 12:14:04 +0200 Subject: Change buttons to start from 0 --- src/class/hid/hid.h | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index b4e8a9c4c..3c616d691 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -222,24 +222,23 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - // Note: Button number start from 1 on host OS - GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 16 - GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 - GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 - GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 19 - GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 20 - GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 21 - GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 22 - GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 23 - GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 24 - GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 25 - GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 26 - GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 27 - GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 28 - GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 29 - GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 30 - GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 31 - GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 32 + GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 + GAMEPAD_BUTTON_16 = TU_BIT(16), ///< Button 16 + GAMEPAD_BUTTON_17 = TU_BIT(17), ///< Button 17 + GAMEPAD_BUTTON_18 = TU_BIT(18), ///< Button 18 + GAMEPAD_BUTTON_19 = TU_BIT(19), ///< Button 19 + GAMEPAD_BUTTON_20 = TU_BIT(20), ///< Button 20 + GAMEPAD_BUTTON_21 = TU_BIT(21), ///< Button 21 + GAMEPAD_BUTTON_22 = TU_BIT(22), ///< Button 22 + GAMEPAD_BUTTON_23 = TU_BIT(23), ///< Button 23 + GAMEPAD_BUTTON_24 = TU_BIT(24), ///< Button 24 + GAMEPAD_BUTTON_25 = TU_BIT(25), ///< Button 25 + GAMEPAD_BUTTON_26 = TU_BIT(26), ///< Button 26 + GAMEPAD_BUTTON_27 = TU_BIT(27), ///< Button 27 + GAMEPAD_BUTTON_28 = TU_BIT(28), ///< Button 28 + GAMEPAD_BUTTON_29 = TU_BIT(29), ///< Button 29 + GAMEPAD_BUTTON_30 = TU_BIT(30), ///< Button 30 + GAMEPAD_BUTTON_31 = TU_BIT(31), ///< Button 31 }hid_gamepad_button_bm_t; /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) -- cgit v1.3.1 From cffa666bd1fd8f0ab45336b36eb79ab1a8f4663d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 17:45:14 +0700 Subject: use alias for button naming --- src/class/hid/hid.h | 93 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 33 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 3c616d691..ec14c9c7c 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -204,43 +204,70 @@ typedef struct TU_ATTR_PACKED uint32_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; -/// Standard Gamepad Buttons Bitmap (from Linux input event codes) +/// Standard Gamepad Buttons Bitmap typedef enum { - GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button - GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button - GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button - GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button - GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button - GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button - GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button - GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button - GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button - GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button - GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button - GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button - GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button - GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 - GAMEPAD_BUTTON_16 = TU_BIT(16), ///< Button 16 - GAMEPAD_BUTTON_17 = TU_BIT(17), ///< Button 17 - GAMEPAD_BUTTON_18 = TU_BIT(18), ///< Button 18 - GAMEPAD_BUTTON_19 = TU_BIT(19), ///< Button 19 - GAMEPAD_BUTTON_20 = TU_BIT(20), ///< Button 20 - GAMEPAD_BUTTON_21 = TU_BIT(21), ///< Button 21 - GAMEPAD_BUTTON_22 = TU_BIT(22), ///< Button 22 - GAMEPAD_BUTTON_23 = TU_BIT(23), ///< Button 23 - GAMEPAD_BUTTON_24 = TU_BIT(24), ///< Button 24 - GAMEPAD_BUTTON_25 = TU_BIT(25), ///< Button 25 - GAMEPAD_BUTTON_26 = TU_BIT(26), ///< Button 26 - GAMEPAD_BUTTON_27 = TU_BIT(27), ///< Button 27 - GAMEPAD_BUTTON_28 = TU_BIT(28), ///< Button 28 - GAMEPAD_BUTTON_29 = TU_BIT(29), ///< Button 29 - GAMEPAD_BUTTON_30 = TU_BIT(30), ///< Button 30 - GAMEPAD_BUTTON_31 = TU_BIT(31), ///< Button 31 + GAMEPAD_BUTTON_0 = TU_BIT(0), + GAMEPAD_BUTTON_1 = TU_BIT(1), + GAMEPAD_BUTTON_2 = TU_BIT(2), + GAMEPAD_BUTTON_3 = TU_BIT(3), + GAMEPAD_BUTTON_4 = TU_BIT(4), + GAMEPAD_BUTTON_5 = TU_BIT(5), + GAMEPAD_BUTTON_6 = TU_BIT(6), + GAMEPAD_BUTTON_7 = TU_BIT(7), + GAMEPAD_BUTTON_8 = TU_BIT(8), + GAMEPAD_BUTTON_9 = TU_BIT(9), + GAMEPAD_BUTTON_10 = TU_BIT(10), + GAMEPAD_BUTTON_11 = TU_BIT(11), + GAMEPAD_BUTTON_12 = TU_BIT(12), + GAMEPAD_BUTTON_13 = TU_BIT(13), + GAMEPAD_BUTTON_14 = TU_BIT(14), + GAMEPAD_BUTTON_15 = TU_BIT(15), + GAMEPAD_BUTTON_16 = TU_BIT(16), + GAMEPAD_BUTTON_17 = TU_BIT(17), + GAMEPAD_BUTTON_18 = TU_BIT(18), + GAMEPAD_BUTTON_19 = TU_BIT(19), + GAMEPAD_BUTTON_20 = TU_BIT(20), + GAMEPAD_BUTTON_21 = TU_BIT(21), + GAMEPAD_BUTTON_22 = TU_BIT(22), + GAMEPAD_BUTTON_23 = TU_BIT(23), + GAMEPAD_BUTTON_24 = TU_BIT(24), + GAMEPAD_BUTTON_25 = TU_BIT(25), + GAMEPAD_BUTTON_26 = TU_BIT(26), + GAMEPAD_BUTTON_27 = TU_BIT(27), + GAMEPAD_BUTTON_28 = TU_BIT(28), + GAMEPAD_BUTTON_29 = TU_BIT(29), + GAMEPAD_BUTTON_30 = TU_BIT(30), + GAMEPAD_BUTTON_31 = TU_BIT(31), }hid_gamepad_button_bm_t; +/// Standard Gamepad Buttons Naming from Linux input event codes +/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h +#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 +#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 + +#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 +#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 + +#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 + +#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 +#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 + +#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 +#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 + +#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 +#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 +#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 +#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 +#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 +#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 +#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 +#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 +#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 +#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 + /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) typedef enum { -- cgit v1.3.1 From 13cb0160421a6a66429e99ed103afba4f1c345ce Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 16:48:20 +0700 Subject: add usbh_classdriver.h --- src/class/cdc/cdc_host.c | 2 ++ src/class/hid/hid_host.c | 2 ++ src/class/msc/msc_host.c | 2 ++ src/device/usbd_pvt.h | 2 +- src/host/hub.c | 1 + src/host/usbh.c | 7 ++--- src/host/usbh.h | 43 ++----------------------- src/host/usbh_classdriver.h | 76 +++++++++++++++++++++++++++++++++++++++++++++ src/host/usbh_hcd.h | 6 ---- 9 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 src/host/usbh_classdriver.h (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index facf86d56..dbe5341e9 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "cdc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83f3f3039..ec50f55f9 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "hid_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 205f0fd2d..176403e86 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -29,6 +29,8 @@ #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "msc_host.h" //--------------------------------------------------------------------+ diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 65fdadf51..b8d34d7b6 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -34,7 +34,7 @@ #endif //--------------------------------------------------------------------+ -// Class Drivers +// Class Driver API //--------------------------------------------------------------------+ typedef struct diff --git a/src/host/hub.c b/src/host/hub.c index f921027c7..b2761184d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -29,6 +29,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) #include "usbh.h" +#include "usbh_classdriver.h" #include "hub.h" //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ca0653409..ff66d5afd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -24,7 +24,7 @@ * This file is part of the TinyUSB stack. */ -#include "common/tusb_common.h" +#include "tusb_option.h" #if TUSB_OPT_HOST_ENABLED @@ -32,10 +32,9 @@ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include "tusb.h" +#include "host/usbh.h" +#include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" diff --git a/src/host/usbh.h b/src/host/usbh.h index a9790b484..edc9e0808 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -40,27 +40,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef enum tusb_interface_status_{ - TUSB_INTERFACE_STATUS_READY = 0, - TUSB_INTERFACE_STATUS_BUSY, - TUSB_INTERFACE_STATUS_COMPLETE, - TUSB_INTERFACE_STATUS_ERROR, - TUSB_INTERFACE_STATUS_INVALID_PARA -} tusb_interface_status_t; - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - uint8_t class_code; - - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -101,30 +80,12 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, //--------------------------------------------------------------------+ //TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); -/** Callback invoked when device is mounted (configured) */ +// Invoked when device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); -/** Callback invoked when device is unmounted (bus reset/unplugged) */ +/// Invoked when device is unmounted (bus reset/unplugged) TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); -//--------------------------------------------------------------------+ -// CLASS-USBH & INTERNAL API -// TODO move to usbh_pvt.h -//--------------------------------------------------------------------+ - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - #ifdef __cplusplus } #endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h new file mode 100644 index 000000000..2b1523855 --- /dev/null +++ b/src/host/usbh_classdriver.h @@ -0,0 +1,76 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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 file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBH_CLASSDRIVER_H_ +#define _TUSB_USBH_CLASSDRIVER_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + uint8_t class_code; + + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); +} usbh_class_driver_t; + +//--------------------------------------------------------------------+ +// USBH Endpoint API +//--------------------------------------------------------------------+ + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index abc7fd250..b3856d6b7 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -97,12 +97,6 @@ typedef struct { extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -//--------------------------------------------------------------------+ -// callback from HCD ISR -//--------------------------------------------------------------------+ - - - #ifdef __cplusplus } #endif -- cgit v1.3.1 From c7f51cde40afbefe3f1d57b9dbdaaca0abed424e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 17:19:21 +0700 Subject: implement usbh_edpt_busy (WIP), remove hcd_edpt_busy --- src/class/cdc/cdc_host.c | 10 +++--- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 4 +-- src/host/hcd.h | 2 -- src/host/usbh.c | 46 ++++++++++++++++++++++++++-- src/host/usbh_classdriver.h | 19 ++++++++---- src/portable/ehci/ehci.c | 6 ---- src/portable/ohci/ohci.c | 6 ---- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 26 ++++++++-------- 11 files changed, 79 insertions(+), 46 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index dbe5341e9..33f1a8ad3 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -73,13 +73,13 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) switch (pipeid) { case CDC_PIPE_NOTIFICATION: - return hcd_edpt_busy(dev_addr, p_cdc->ep_notif ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); case CDC_PIPE_DATA_IN: - return hcd_edpt_busy(dev_addr, p_cdc->ep_in ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); case CDC_PIPE_DATA_OUT: - return hcd_edpt_busy(dev_addr, p_cdc->ep_out ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); default: return false; @@ -103,7 +103,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; - if ( hcd_edpt_busy(dev_addr, ep_out) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); } @@ -115,7 +115,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; - if ( hcd_edpt_busy(dev_addr, ep_in) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ec50f55f9..cde5e23a5 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -201,7 +201,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); // // hidh_interface_t* hid_itf = get_instance(dev_addr, instance); -// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); //} //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 176403e86..7f98ef9b1 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -111,7 +111,7 @@ bool tuh_msc_mounted(uint8_t dev_addr) bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in); + return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index e17c62d4e..63e97df96 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -122,7 +122,7 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. diff --git a/src/device/usbd.c b/src/device/usbd.c index 71c5d4e6c..2935defd0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1248,8 +1248,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return - // and usbd task can preempt and clear the busy + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() + // could return and USBD task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) diff --git a/src/host/hcd.h b/src/host/hcd.h index 8cb5b3772..7a9aadc73 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -137,8 +137,6 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); - -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ff66d5afd..59246a663 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -314,8 +314,11 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//------------- Endpoint API -------------// +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +// TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -343,6 +346,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -368,11 +372,36 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + usbh_device_t* dev = &_usbh_devices[dev_addr]; - TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); - return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } } bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) @@ -419,6 +448,17 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return ret; } +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 2b1523855..07480fe8e 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -52,22 +52,29 @@ typedef struct { void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; +// Call by class driver to tell USBH that it has complete the enumeration +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +// Open an endpoint +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); + +// Submit a usb transfer bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); +// Check if endpoint transferring is complete +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); #ifdef __cplusplus } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index be3030676..48788ba06 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -440,12 +440,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index cbb72c726..73489c764 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -489,12 +489,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index aeee93324..b575c6afc 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -515,19 +515,19 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - // EPX is shared, so multiple device addresses and endpoint addresses share that - // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own - // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint - // on that device - pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); - struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); - assert(ep); - bool busy = ep->active; - pico_trace("busy == %d\n", busy); - return busy; -} +//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +//{ +// // EPX is shared, so multiple device addresses and endpoint addresses share that +// // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own +// // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint +// // on that device +// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); +// struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); +// assert(ep); +// bool busy = ep->active; +// pico_trace("busy == %d\n", busy); +// return busy; +//} bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { -- cgit v1.3.1 From 572d986a0260543ada22592e3f2216a152ac632d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 17:14:22 +0700 Subject: improve usbh --- examples/host/cdc_msc_hid/src/hid_app.c | 12 +++++- src/class/hid/hid_host.c | 10 ----- src/common/tusb_common.h | 4 +- src/host/usbh.c | 74 ++++++++++++++++++--------------- src/host/usbh_control.c | 4 +- 5 files changed, 54 insertions(+), 50 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 23ab12404..817646dab 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -30,7 +30,8 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ -// If your host terminal support ansi escape code, it can be use to simulate mouse cursor +// If your host terminal support ansi escape code such as TeraTerm +// it can be use to simulate mouse cursor movement within terminal #define USE_ANSI_ESCAPE 0 #define MAX_REPORT 4 @@ -113,6 +114,13 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons return; } + // For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples: + // - Keyboard : Desktop, Keyboard + // - Mouse : Desktop, Mouse + // - Gamepad : Desktop, Gamepad + // - Consumer Control (Media Key) : Consumer, Consumer Control + // - System Control (Power key) : Desktop, System Control + // - Generic (vendor) : 0xFFxx, xx if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP ) { switch (rpt_info->usage) @@ -164,7 +172,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) }else { // not existed in previous report means the current key is pressed - bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; putchar(ch); if ( ch == '\r' ) putchar('\n'); // added new line for enter key diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index cde5e23a5..a227c2a86 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -37,16 +37,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -/* - "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard - "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse - "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control - "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control - "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen - "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF - */ typedef struct { uint8_t itf_num; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 889ad7b25..fe5bf5f41 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -317,8 +317,8 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem #define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x))) -#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) ) -#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) ) +#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (uint32_t) (_x) ) +#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (uint32_t) (_x) ) // Log Level 2: Warn #if CFG_TUSB_DEBUG >= 2 diff --git a/src/host/usbh.c b/src/host/usbh.c index 59246a663..81b9e84af 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -795,6 +795,8 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r return false; } + TU_ASSERT(tu_desc_type(_usbh_ctrl_buf) == TUSB_DESC_DEVICE); + // Reset device again before Set Address TU_LOG2("Port reset \r\n"); @@ -938,7 +940,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet - parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); tusb_control_request_t const new_request = @@ -988,49 +990,53 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura // parse each interfaces while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) { - // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) + tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + + // Class will always starts with Interface Association (if any) and then Interface descriptor + if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length - }else + desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to Interface + } + + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + + // Check if class is supported + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; + } - // Check if class is supported - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + // skip unsupported class + p_desc = tu_desc_next(p_desc); + } + else + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + // Interface number must not be used already TODO alternate interface + TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); + dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) { - // skip unsupported class + // TODO Attach hub to Hub is not currently supported + // skip this interface p_desc = tu_desc_next(p_desc); } else { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - - // Interface number must not be used already TODO alternate interface - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + TU_LOG2("%s open\r\n", driver->name); - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - p_desc = tu_desc_next(p_desc); - } - else - { - TU_LOG2("%s open\r\n", driver->name); - - uint16_t itf_len = 0; - TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); - p_desc += itf_len; - } + uint16_t itf_len = 0; + TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); + p_desc += itf_len; } } } diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index aa82f14ba..91dbdfe99 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -68,7 +68,7 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, _ctrl_xfer.stage = STAGE_SETUP; _ctrl_xfer.complete_cb = complete_cb; - TU_LOG2("Send Setup to address %u: ", dev_addr); + TU_LOG2("Control Setup (addr = %u): ", dev_addr); TU_LOG2_VAR(request); TU_LOG2("\r\n"); @@ -119,7 +119,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu if (request->wLength) { - TU_LOG2("Control data:\r\n"); + TU_LOG2("Control data (addr = %u):\r\n", dev_addr); TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); } -- cgit v1.3.1 From dfe5a727c6b236c1b05b5447cdf0535545a6d32e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 18:53:56 +0700 Subject: log clean up --- src/class/hid/hid_host.c | 6 +++--- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a227c2a86..7444c10fe 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -442,9 +442,9 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t const data8 = desc_report[0]; - TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iendpoint_control; if (ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS) { - TU_LOG(2, "Double Buffered "); + TU_LOG(3, "Double Buffered: "); }else { - TU_LOG(2, "Single Buffered "); + TU_LOG(3, "Single Buffered: "); } - if (ep_ctrl & EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER) TU_LOG(2, "Interrupt per double "); - if (ep_ctrl & EP_CTRL_INTERRUPT_PER_BUFFER) TU_LOG(2, "Interrupt per single "); - TU_LOG_HEX(2, ep_ctrl); + TU_LOG_HEX(3, ep_ctrl); _handle_buff_status_bit(bit, ep); } -- cgit v1.3.1 From 1c23462b43f47685cf0051568f4bfea5de37d563 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Fri, 11 Jun 2021 22:25:36 +0200 Subject: weak atrribute work around removed from CCRX_Port --- src/class/cdc/cdc.h | 54 ++++++++++++----------------- src/class/cdc/cdc_device.c | 23 ++++--------- src/class/cdc/cdc_device.h | 57 ------------------------------- src/common/tusb_compiler.h | 39 --------------------- src/common/tusb_types.h | 42 ++++++----------------- src/device/dcd.h | 30 ---------------- src/device/usbd.c | 61 +++++++++++++-------------------- src/device/usbd.h | 66 ------------------------------------ src/device/usbd_control.c | 6 +--- src/device/usbd_pvt.h | 12 ------- src/portable/renesas/usba/dcd_usba.c | 33 ++++++------------ 11 files changed, 74 insertions(+), 349 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index e5af9fc0c..f59690835 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,8 +215,9 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// Header Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -224,10 +225,8 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }cdc_desc_func_header_t; -TU_PACK_STRUCT_END /// Union Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -236,7 +235,8 @@ typedef struct TU_ATTR_PACKED uint8_t bControlInterface ; ///< Interface number of Communication Interface uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_union_n_t(no_slave)\ TU_PACK_STRUCT_BEGIN \ @@ -249,8 +249,10 @@ TU_PACK_STRUCT_END } \ TU_PACK_STRUCT_END + +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// Country Selection Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -259,7 +261,8 @@ typedef struct TU_ATTR_PACKED uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_country_selection_n_t(no_country) \ TU_PACK_STRUCT_BEGIN \ @@ -276,29 +279,28 @@ TU_PACK_STRUCT_END // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. uint8_t TU_RESERVED : 6; } bmCapabilities; - TU_BIT_FIELD_ORDER_END uint8_t bDataInterface; }cdc_desc_func_call_management_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { @@ -309,13 +311,11 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -323,31 +323,27 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ cdc_acm_capability_t bmCapabilities ; }cdc_desc_func_acm_t; -TU_PACK_STRUCT_END /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. uint8_t TU_RESERVED : 5; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_direct_line_management_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, /// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -356,38 +352,34 @@ typedef struct TU_ATTR_PACKED uint8_t bRingerVolSteps ; uint8_t bNumRingerPatterns ; }cdc_desc_func_telephone_ringer_t; -TU_PACK_STRUCT_END /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; uint8_t TU_RESERVED : 5; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_operational_modes_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. @@ -397,9 +389,8 @@ typedef struct TU_ATTR_PACKED uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification uint32_t TU_RESERVED : 26; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_call_state_reporting_capabilities_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { @@ -409,7 +400,6 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint32_t bit_rate; @@ -417,11 +407,9 @@ typedef struct TU_ATTR_PACKED uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; -TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -TU_PACK_STRUCT_BEGIN TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { @@ -430,7 +418,9 @@ typedef struct TU_ATTR_PACKED uint16_t : 14; } cdc_line_control_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) + TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 57bb804a8..cac811c45 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -33,15 +33,6 @@ #include "cdc_device.h" -#if defined(TU_HAS_NO_ATTR_WEAK) -static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb))(uint8_t) = TUD_CDC_TX_COMPLETE_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_line_state_cb))(uint8_t, bool, bool) = TUD_CDC_LINE_STATE_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_line_coding_cb))(uint8_t, cdc_line_coding_t const*) = TUD_CDC_LINE_CODING_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_send_break_cb))(uint8_t, uint16_t) = TUD_CDC_SEND_BREAK_CB; -#endif - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -370,7 +361,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK) { - if ( MAKE_WEAK_FUNC(tud_cdc_line_coding_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_coding_cb)(itf, &p_cdc->line_coding); + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); } break; @@ -405,7 +396,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( MAKE_WEAK_FUNC(tud_cdc_line_state_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_state_cb)(itf, dtr, rts); + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; case CDC_REQUEST_SEND_BREAK: @@ -416,7 +407,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t else if (stage == CONTROL_STAGE_ACK) { TU_LOG2(" Send Break\r\n"); - if ( MAKE_WEAK_FUNC(tud_cdc_send_break_cb) ) MAKE_WEAK_FUNC(tud_cdc_send_break_cb)(itf, request->wValue); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); } break; @@ -447,19 +438,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if ( MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb) && (((signed char) p_cdc->wanted_char) != -1) ) + if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) { for ( uint32_t i = 0; i < xferred_bytes; i++ ) { if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) { - MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb)(itf, p_cdc->wanted_char); + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (MAKE_WEAK_FUNC(tud_cdc_rx_cb) && !tu_fifo_empty(&p_cdc->rx_ff) ) MAKE_WEAK_FUNC(tud_cdc_rx_cb)(itf); + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -471,7 +462,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( ep_addr == p_cdc->ep_in ) { // invoke transmit callback to possibly refill tx fifo - if ( MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb) ) MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb)(itf); + if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); if ( 0 == tud_cdc_n_write_flush(itf) ) { diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 389516883..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -129,7 +129,6 @@ static inline bool tud_cdc_write_clear (void); // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); @@ -148,62 +147,6 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p // Invoked when received send break TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); -#else - #if ADD_WEAK_FUNC_TUD_CDC_RX_CB - #define TUD_CDC_RX_CB tud_cdc_rx_cb - #endif - #ifndef TUD_CDC_RX_CB - #define TUD_CDC_RX_CB NULL - #else - extern void TUD_CDC_RX_CB(uint8_t itf); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB - #define TUD_CDC_RX_WANTED_CB tud_cdc_rx_wanted_cb - #endif - #ifndef TUD_CDC_RX_WANTED_CB - #define TUD_CDC_RX_WANTED_CB NULL - #else - extern void TUD_CDC_RX_WANTED_CB(uint8_t itf, char wanted_char); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB - #define TUD_CDC_TX_COMPLETE_CB tud_cdc_tx_complete_cb - #endif - #ifndef TUD_CDC_TX_COMPLETE_CB - #define TUD_CDC_TX_COMPLETE_CB NULL - #else - extern void TUD_CDC_TX_COMPLETE_CB(uint8_t itf); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB - #define TUD_CDC_LINE_STATE_CB tud_cdc_line_state_cb - #endif - #ifndef TUD_CDC_LINE_STATE_CB - #define TUD_CDC_LINE_STATE_CB NULL - #else - extern void TUD_CDC_LINE_STATE_CB(uint8_t itf, bool dtr, bool rts); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB - #define TUD_CDC_LINE_CODING_CB tud_cdc_line_coding_cb - #endif - #ifndef TUD_CDC_LINE_CODING_CB - #define TUD_CDC_LINE_CODING_CB NULL - #else - extern void TUD_CDC_LINE_CODING_CB(uint8_t itf, cdc_line_coding_t const* p_line_coding); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB - #define TUD_CDC_SEND_BREAK_CB tud_cdc_send_break_cb - #endif - #ifndef TUD_CDC_SEND_BREAK_CB - #define TUD_CDC_SEND_BREAK_CB NULL - #else - extern void TUD_CDC_SEND_BREAK_CB(uint8_t itf, uint16_t duration_ms); - #endif -#endif - //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 508bb126e..f77cf94ee 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -64,9 +64,6 @@ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ -// define the standard definition of this macro to construct a "weak" function name -#define MAKE_WEAK_FUNC(func_name) func_name - // TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -171,42 +168,6 @@ the aligned attribute (or something similar yet) */ #define TU_HAS_NO_ATTR_ALIGNED - /* activate the "weak" function emulation, because this toolchain does not - know the weak attribute (or something similar yet) */ - #define TU_HAS_NO_ATTR_WEAK - - // make sure to define away the standard definition of this macro - #undef MAKE_WEAK_FUNC - // Helper macro to construct a "weak" function name - #define MAKE_WEAK_FUNC(func_name) weak_ ## func_name - - #if defined(TU_HAS_NO_ATTR_WEAK) - // "Weak function" emulation defined in cdc_device.h - #define ADD_WEAK_FUNC_TUD_CDC_RX_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB 0 - - // "Weak function" emulation defined in usbd_pvt.h - #define ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB 0 - - // "Weak function" emulation defined in usbd.h - #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB 0 - #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB 0 - #define ADD_WEAK_FUNC_TUD_MOUNT_CB 0 - #define ADD_WEAK_FUNC_TUD_UMOUNT_CB 0 - #define ADD_WEAK_FUNC_TUD_SUSPEND_CB 0 - #define ADD_WEAK_FUNC_TUD_RESUME_CB 0 - #define ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB 0 - - // "Weak function" emulation defined in dcd.h - #define ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE 0 - #define ADD_WEAK_FUNC_DCD_EDPT_CLOSE 0 - #define ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO 0 - #endif - #else #error "Compiler attribute porting is required" #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b20ea2974..a8a4d21e5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,8 +262,9 @@ enum // USB Descriptors //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// USB Device Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -284,12 +285,10 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; -TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -297,10 +296,8 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total length of data returned for this descriptor uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; -TU_PACK_STRUCT_END /// USB Configuration Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -313,10 +310,8 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; -TU_PACK_STRUCT_END /// USB Interface Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -330,10 +325,9 @@ typedef struct TU_ATTR_PACKED uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; -TU_PACK_STRUCT_END /// USB Endpoint Descriptor -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -341,14 +335,12 @@ typedef struct TU_ATTR_PACKED uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t xfer : 2; uint8_t sync : 2; uint8_t usage : 2; uint8_t : 2; } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. - TU_BIT_FIELD_ORDER_END struct TU_ATTR_PACKED { #if defined(__CCRX__) @@ -363,10 +355,9 @@ typedef struct TU_ATTR_PACKED uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// USB Other Speed Configuration Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -379,10 +370,8 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; -TU_PACK_STRUCT_END /// USB Device Qualifier Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -396,10 +385,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; -TU_PACK_STRUCT_END /// USB Interface Association Descriptor (IAD ECN) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -414,20 +401,16 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; -TU_PACK_STRUCT_END // USB String Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; -TU_PACK_STRUCT_END // USB Binary Device Object Store (BOS) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -437,10 +420,8 @@ typedef struct TU_ATTR_PACKED uint8_t PlatformCapabilityUUID[16]; uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -TU_PACK_STRUCT_END // USB WebuSB URL Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -448,17 +429,15 @@ typedef struct TU_ATTR_PACKED uint8_t bScheme; char url[]; } tusb_desc_webusb_url_t; -TU_PACK_STRUCT_END // DFU Functional Descriptor -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; union { - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t bitCanDnload : 1; uint8_t bitCanUpload : 1; @@ -466,7 +445,6 @@ typedef struct TU_ATTR_PACKED uint8_t bitWillDetach : 1; uint8_t reserved : 4; } bmAttributes; - TU_BIT_FIELD_ORDER_END uint8_t bAttributes; }; @@ -475,21 +453,19 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED{ union { - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; - TU_BIT_FIELD_ORDER_END uint8_t bmRequestType; }; @@ -499,7 +475,9 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/device/dcd.h b/src/device/dcd.h index d68f9baa7..25cfafc4b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -117,7 +117,6 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Endpoint API //--------------------------------------------------------------------+ -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; @@ -130,35 +129,6 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; -#else - #if ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE - #define DCD_EDPT0_STATUS_COMPLETE dcd_edpt0_status_complete - #endif - #ifndef DCD_EDPT0_STATUS_COMPLETE - #define DCD_EDPT0_STATUS_COMPLETE NULL - #else - extern void DCD_EDPT0_STATUS_COMPLETE(uint8_t rhport, tusb_control_request_t const * request); - #endif - - #if ADD_WEAK_FUNC_DCD_EDPT_CLOSE - #define DCD_EDPT_CLOSE dcd_edpt_close - #endif - #ifndef DCD_EDPT_CLOSE - #define DCD_EDPT_CLOSE NULL - #else - extern void DCD_EDPT_CLOSE(uint8_t rhport, uint8_t ep_addr); - #endif - - #if ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO - #define DCD_EDPT_XFER_FIFO dcd_edpt_xfer_fifo - #endif - #ifndef DCD_EDPT_XFER_FIFO - #define DCD_EDPT_XFER_FIFO NULL - #else - extern void DCD_EDPT_XFER_FIFO(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); - #endif -#endif - // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); diff --git a/src/device/usbd.c b/src/device/usbd.c index 389ba4a4e..49c9279bf 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,19 +33,6 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" -#if defined(TU_HAS_NO_ATTR_WEAK) -static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_bos_cb))(void) = TUD_DESCRIPTOR_BOS_CB; -static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb))(void) = TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB; -static void (*const MAKE_WEAK_FUNC(tud_mount_cb))(void) = TUD_MOUNT_CB; -static void (*const MAKE_WEAK_FUNC(tud_umount_cb))(void) = TUD_UMOUNT_CB; -static void (*const MAKE_WEAK_FUNC(tud_suspend_cb))(_Bool) = TUD_SUSPEND_CB; -static void (*const MAKE_WEAK_FUNC(tud_resume_cb))(void) = TUD_RESUME_CB; -static _Bool (*const MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb))(uint8_t, uint8_t, tusb_control_request_t const *) = TUD_RESUME_CB; -static usbd_class_driver_t const* (*const MAKE_WEAK_FUNC(usbd_app_driver_get_cb))(uint8_t*) = USBD_APP_DRIVER_GET_CB; -static bool (*const MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo))(uint8_t, uint8_t, tu_fifo_t *, uint16_t) = DCD_EDPT_XFER_FIFO; -static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT_CLOSE; -#endif - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -61,10 +48,11 @@ static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT // Invalid driver ID in itf2drv[] ep2drv[][] mapping enum { DRVID_INVALID = 0xFFu }; +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + +TU_BIT_FIELD_ORDER_BEGIN typedef struct { - TU_PACK_STRUCT_BEGIN - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -75,8 +63,6 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; - TU_BIT_FIELD_ORDER_END - TU_PACK_STRUCT_END volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; @@ -84,8 +70,6 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - TU_PACK_STRUCT_BEGIN - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile bool busy : 1; @@ -94,10 +78,11 @@ typedef struct // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUD_EP_MAX][2]; - TU_BIT_FIELD_ORDER_END - TU_PACK_STRUCT_END }usbd_device_t; +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) static usbd_device_t _usbd_dev; @@ -257,7 +242,7 @@ static uint8_t _app_driver_count = 0; static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { // Application drivers - if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) + if ( usbd_app_driver_get_cb ) { if ( drvid < _app_driver_count ) return &_app_driver[drvid]; drvid -= _app_driver_count; @@ -429,9 +414,9 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) + if ( usbd_app_driver_get_cb ) { - _app_driver = MAKE_WEAK_FUNC(usbd_app_driver_get_cb)(&_app_driver_count); + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); } // Init class drivers @@ -522,7 +507,7 @@ void tud_task (void) usbd_reset(event.rhport); // invoke callback - if (MAKE_WEAK_FUNC(tud_umount_cb)) MAKE_WEAK_FUNC(tud_umount_cb)(); + if (tud_umount_cb) tud_umount_cb(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -578,12 +563,12 @@ void tud_task (void) case DCD_EVENT_SUSPEND: TU_LOG2("\r\n"); - if (MAKE_WEAK_FUNC(tud_suspend_cb)) MAKE_WEAK_FUNC(tud_suspend_cb)(_usbd_dev.remote_wakeup_en); + if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: TU_LOG2("\r\n"); - if (MAKE_WEAK_FUNC(tud_resume_cb)) MAKE_WEAK_FUNC(tud_resume_cb)(); + if (tud_resume_cb) tud_resume_cb(); break; case DCD_EVENT_SOF: @@ -630,10 +615,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); + TU_VERIFY(tud_vendor_control_xfer_cb); - usbd_control_set_complete_callback(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); - return MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)(rhport, CONTROL_STAGE_SETUP, p_request); + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 @@ -913,7 +898,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // invoke callback - if (MAKE_WEAK_FUNC(tud_mount_cb)) MAKE_WEAK_FUNC(tud_mount_cb)(); + if (tud_mount_cb) tud_mount_cb(); return true; } @@ -970,9 +955,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!MAKE_WEAK_FUNC(tud_descriptor_bos_cb)) return false; + if (!tud_descriptor_bos_cb) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)MAKE_WEAK_FUNC(tud_descriptor_bos_cb)(); + tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)tud_descriptor_bos_cb(); uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address @@ -1016,9 +1001,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Host sends this request to ask why our device with USB BCD from 2.0 // but is running at Full/Low Speed. If not highspeed capable stall this request, // otherwise return the descriptor that could work in highspeed mode - if (MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)) + if (tud_descriptor_device_qualifier_cb) { - uint8_t const* desc_qualifier = MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)(); + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); TU_ASSERT(desc_qualifier); // first byte of descriptor is its size @@ -1306,7 +1291,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo)(rhport, ep_addr, ff, total_bytes)) + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; @@ -1369,10 +1354,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(MAKE_WEAK_FUNC(dcd_edpt_close), /**/); + TU_ASSERT(dcd_edpt_close, /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - MAKE_WEAK_FUNC(dcd_edpt_close(rhport, ep_addr)); + dcd_edpt_close(rhport, ep_addr); return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 67f1e2913..57c80fed1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -111,7 +111,6 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received GET BOS DESCRIPTOR request // Application return pointer to descriptor TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); @@ -136,71 +135,6 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -#else - #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB - #define TUD_DESCRIPTOR_BOS_CB tud_descriptor_bos_cb - #endif - #ifndef TUD_DESCRIPTOR_BOS_CB - #define TUD_DESCRIPTOR_BOS_CB NULL - #else - extern uint8_t const* TUD_DESCRIPTOR_BOS_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB - #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB tud_descriptor_device_qualifier_cb - #endif - #ifndef TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB - #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB NULL - #else - extern uint8_t const* TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_MOUNT_CB - #define TUD_MOUNT_CB tud_mount_cb - #endif - #ifndef TUD_MOUNT_CB - #define TUD_MOUNT_CB NULL - #else - extern void TUD_MOUNT_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_UMOUNT_CB - #define TUD_UMOUNT_CB tud_umount_cb - #endif - #ifndef TUD_UMOUNT_CB - #define TUD_UMOUNT_CB NULL - #else - extern void TUD_UMOUNT_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_SUSPEND_CB - #define TUD_SUSPEND_CB tud_suspend_cb - #endif - #ifndef TUD_SUSPEND_CB - #define TUD_SUSPEND_CB NULL - #else - extern void TUD_SUSPEND_CB(bool remote_wakeup_en); - #endif - - #if ADD_WEAK_FUNC_TUD_RESUME_CB - #define TUD_RESUME_CB tud_resume_cb - #endif - #ifndef TUD_RESUME_CB - #define TUD_RESUME_CB NULL - #else - extern void TUD_RESUME_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB - #define TUD_VENDOR_CONTROL_XFER_CB tud_vendor_control_xfer_cb - #endif - #ifndef TUD_VENDOR_CONTROL_XFER_CB - #define TUD_VENDOR_CONTROL_XFER_CB NULL - #else - extern bool TUD_VENDOR_CONTROL_XFER_CB(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - #endif -#endif - //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 76f999f86..b3bab2e32 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -36,10 +36,6 @@ extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif -#if defined(TU_HAS_NO_ATTR_WEAK) -static void (*const MAKE_WEAK_FUNC(dcd_edpt0_status_complete))(uint8_t, tusb_control_request_t const *) = DCD_EDPT0_STATUS_COMPLETE; -#endif - enum { EDPT_CTRL_OUT = 0x00, @@ -184,7 +180,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (MAKE_WEAK_FUNC(dcd_edpt0_status_complete)) MAKE_WEAK_FUNC(dcd_edpt0_status_complete)(rhport, &_ctrl_xfer.request); + if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); if (_ctrl_xfer.complete_cb) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index c814353ae..bb2267d40 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -51,22 +51,10 @@ typedef struct void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; -#else - #if ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB - #define USBD_APP_DRIVER_GET_CB usbd_app_driver_get_cb - #endif - #ifndef USBD_APP_DRIVER_GET_CB - #define USBD_APP_DRIVER_GET_CB NULL - #else - extern usbd_class_driver_t const* USBD_APP_DRIVER_GET_CB(uint8_t* driver_count); - #endif -#endif - typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0e7881383..13fc50ae5 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -90,45 +90,47 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) +TU_BIT_FIELD_ORDER_BEGIN typedef struct { union { - TU_BIT_FIELD_ORDER_BEGIN struct { uint16_t : 8; uint16_t TRCLR: 1; uint16_t TRENB: 1; uint16_t : 0; }; - TU_BIT_FIELD_ORDER_END uint16_t TRE; }; uint16_t TRN; } reg_pipetre_t; +TU_BIT_FIELD_ORDER_END +TU_BIT_FIELD_ORDER_BEGIN typedef union { - TU_BIT_FIELD_ORDER_BEGIN struct { volatile uint16_t u8: 8; volatile uint16_t : 0; }; - TU_BIT_FIELD_ORDER_END volatile uint16_t u16; } hw_fifo_t; +TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ - TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; - TU_BIT_FIELD_ORDER_END } pipe_state_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) typedef struct { @@ -259,12 +261,6 @@ static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps) hw_fifo_t *reg = (hw_fifo_t*)fifo; uintptr_t addr = pipe->addr + pipe->length - rem; - if (addr & 1u) { - /* addr is not 2-byte aligned */ - reg->u8 = *(const uint8_t *)addr; - ++addr; - --len; - } while (len >= 2) { reg->u16 = *(const uint16_t *)addr; addr += 2; @@ -306,17 +302,10 @@ static void process_setup_packet(uint8_t rhport) uint16_t setup_packet[4]; if (0 == (USB0.INTSTS0.WORD & USB_IS0_VALID)) return; USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; - setup_packet[0] = USB0.USBREQ.WORD; + setup_packet[0] = tu_le16toh(USB0.USBREQ.WORD); setup_packet[1] = USB0.USBVAL; setup_packet[2] = USB0.USBINDX; setup_packet[3] = USB0.USBLENG; -#if TU_BYTE_ORDER==TU_BIG_ENDIAN - #if defined(__CCRX__) - setup_packet[0] = tu_le16toh(setup_packet[0]); - #else - //FIXME needs to implemented for other tool chains - #endif -#endif USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); } -- cgit v1.3.1 From 8433f638e64ce1b13fead28b4395d9a32c480548 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 20 Jun 2021 15:38:20 +0200 Subject: Add bracket to switch case, fix warning. --- src/class/audio/audio_device.c | 209 +++++++++++++++++++++-------------------- 1 file changed, 107 insertions(+), 102 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8e4420ed0..7ad7edf9e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -393,12 +393,12 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); -#endif static inline uint8_t tu_desc_subtype(void const* desc) { return ((uint8_t const*) desc)[2]; } +#endif bool tud_audio_n_mounted(uint8_t func_id) { @@ -1658,64 +1658,65 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - if (tud_audio_set_req_entity_cb) + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + if (entityID != 0) { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + if (tud_audio_set_req_entity_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } else { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } } - else + break; + + case TUSB_REQ_RCPT_ENDPOINT: { - if (tud_audio_set_req_itf_cb) + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + if (tud_audio_set_req_ep_cb) { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it } } - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - // Unknown/Unsupported recipient default: TU_BREAKPOINT(); return false; } @@ -1754,73 +1755,75 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + // Verify if entity is present + if (entityID != 0) { - if (tud_audio_get_req_entity_cb) + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_entity_cb(rhport, p_request); + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } } - else + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } } } } - else + break; + + case TUSB_REQ_RCPT_ENDPOINT: { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_itf_cb) + if (tud_audio_get_req_ep_cb) { - return tud_audio_get_req_itf_cb(rhport, p_request); + return tud_audio_get_req_ep_cb(rhport, p_request); } else { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall } } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - break; - // Unknown/Unsupported recipient default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; } @@ -1935,29 +1938,31 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + } } break; case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + { + uint8_t ep = TU_U16_LOW(p_request->wIndex); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + } break; // Unknown/Unsupported recipient -- cgit v1.3.1 From 9323a9d094684a25e65fcae964e7ee91c9746f57 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 21 Jun 2021 00:00:46 +0700 Subject: fix issue when calling midi API when not enumerated yet --- src/class/midi/midi_device.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 953ca26e6..4eac0de48 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -197,9 +197,11 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { - midid_interface_t* p_midi = &_midid_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); - _prep_out_transaction(p_midi); + midid_interface_t* midi = &_midid_itf[itf]; + TU_VERIFY(midi->ep_out); + + uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); + _prep_out_transaction(midi); return (num_read == 4); } @@ -234,7 +236,7 @@ static uint32_t write_flush(midid_interface_t* midi) uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->itf_num, 0); + TU_VERIFY(midi->ep_in, 0); midid_stream_t* stream = &midi->stream_write; @@ -351,9 +353,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) { midid_interface_t* midi = &_midid_itf[itf]; - if (midi->itf_num == 0) { - return 0; - } + TU_VERIFY(midi->ep_in); if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; @@ -435,6 +435,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } p_midi->itf_num = desc_midi->bInterfaceNumber; + (void) p_midi->itf_num; // next descriptor drv_len += tu_desc_len(p_desc); -- cgit v1.3.1 From 264dc35b95a2313201845f3612d3e807afad62c3 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 21 Jun 2021 05:32:43 +0200 Subject: Fix typo in TUH configuration define --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/class/hid/hid_host.c | 2 +- src/host/usbh.c | 4 ++-- src/host/usbh_control.c | 2 +- src/tusb_option.h | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8253964c0..cc77b6554 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -72,7 +72,7 @@ //-------------------------------------------------------------------- // Size of buffer to hold descriptors and other data used for enumeration -#define CFG_TUH_ENUMERATION_BUFSZIE 256 +#define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index cde5e23a5..761258f1b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -368,7 +368,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long - TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE ); + TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE ); TU_LOG2("HID Get Report Descriptor\r\n"); tusb_control_request_t const new_request = diff --git a/src/host/usbh.c b/src/host/usbh.c index 59246a663..8ecc87488 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -130,7 +130,7 @@ CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); @@ -907,7 +907,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSZIE); + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); // Get full configuration descriptor TU_LOG2("Get Configuration Descriptor\r\n"); diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 4dbf8592a..53413b6e5 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -50,7 +50,7 @@ typedef struct static usbh_control_xfer_t _ctrl_xfer; //CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; +//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/src/tusb_option.h b/src/tusb_option.h index d5776c029..815e588de 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -278,8 +278,8 @@ #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif - #ifndef CFG_TUH_ENUMERATION_BUFSZIE - #define CFG_TUH_ENUMERATION_BUFSZIE 256 + #ifndef CFG_TUH_ENUMERATION_BUFSIZE + #define CFG_TUH_ENUMERATION_BUFSIZE 256 #endif //------------- CLASS -------------// -- cgit v1.3.1 From f5f087b2f85ebf4ff41c84c5f1a70a598d32cb21 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 23 Jun 2021 10:58:18 -0400 Subject: Add dfu function memory access protection Adds TU_VERIFY to dfu internal buffer access from host. Adds TU_ASSERT to dfu internal buffer access by application. --- src/class/dfu/dfu_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 81045ff7b..df731ee50 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -249,6 +249,7 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + TU_ASSERT( retval <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -276,6 +277,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); // setup for data phase tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } @@ -283,6 +285,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } -- cgit v1.3.1 From 5811122cfd04b84c8760991e287e29fc424453fd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 11:58:34 +0700 Subject: change usbh open driver to have max_len and return driver len --- src/class/cdc/cdc_device.c | 10 +++----- src/class/cdc/cdc_host.c | 62 ++++++++++++++++++++++----------------------- src/class/cdc/cdc_host.h | 10 ++++---- src/class/hid/hid_host.c | 20 +++++++++------ src/class/hid/hid_host.h | 10 ++++---- src/class/msc/msc_host.c | 13 ++++++---- src/class/msc/msc_host.h | 20 ++++----------- src/host/hub.c | 31 +++++++++++++---------- src/host/hub.h | 10 ++++---- src/host/usbh.c | 15 ++++++----- src/host/usbh_classdriver.h | 10 ++++---- 11 files changed, 104 insertions(+), 107 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cac811c45..e622bd616 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -273,9 +273,6 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); - // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); - // Find available interface cdcd_interface_t * p_cdc = NULL; for(uint8_t cdc_id=0; cdc_idep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 33f1a8ad3..fc7100e81 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,29 +149,27 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // Only support ACM - TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + (void) max_len; - // Only support AT commands, no protocol and vendor specific commands. - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - 0xff == itf_desc->bInterfaceProtocol); + // Only support ACM subclass + // Protocol 0xFF can be RNDIS device for windows XP + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0xFF != itf_desc->bInterfaceProtocol, 0); - uint8_t const * p_desc; - cdch_data_t * p_cdc; - - p_desc = tu_desc_next(itf_desc); - p_cdc = get_itf(dev_addr); + cdch_data_t * p_cdc = get_itf(dev_addr); - p_cdc->itf_num = itf_desc->bInterfaceNumber; - p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com + p_cdc->itf_num = itf_desc->bInterfaceNumber; + p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; //------------- Communication Interface -------------// - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t drv_len = tu_desc_len(itf_desc); + uint8_t const * p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors - while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] ) + while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) { @@ -179,52 +177,52 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) ); - p_cdc->ep_notif = ep_desc->bEndpointAddress; + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { - (*p_length) += p_desc[DESC_OFFSET_LEN]; + // next to endpoint descriptor + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs for(uint32_t i=0; i<2; i++) { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0); - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { - p_cdc->ep_in = ep_desc->bEndpointAddress; + p_cdc->ep_in = desc_ep->bEndpointAddress; }else { - p_cdc->ep_out = ep_desc->bEndpointAddress; + p_cdc->ep_out = desc_ep->bEndpointAddress; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next( p_desc ); } } - return true; + return drv_len; } bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 6ff392709..edcd258a8 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init(void); -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close(uint8_t dev_addr); +void cdch_init (void); +uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 16d908a5d..81ed6e8b6 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -247,29 +247,33 @@ static bool config_get_protocol (uint8_t dev_addr, tusb_control_requ static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + (void) max_len; + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0); // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); //------------- Endpoint Descriptor -------------// + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); // TODO also open endpoint OUT - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; @@ -285,9 +289,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 2e4cce600..6ae7c6721 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -118,11 +118,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init(void); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close(uint8_t dev_addr); +void hidh_init (void); +uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7f98ef9b1..83cbe7c89 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -360,18 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); + msch_interface_t* p_msc = get_itf(dev_addr); tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { @@ -385,9 +389,8 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de } p_msc->itf_num = desc_itf->bInterfaceNumber; - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index ce4fe64dc..9e4217ba5 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -41,13 +41,6 @@ #define CFG_TUH_MSC_MAXLUN 4 #endif - -/** \addtogroup ClassDriver_MSC - * @{ - * \defgroup MSC_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); //--------------------------------------------------------------------+ @@ -113,17 +106,14 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init(void); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void msch_close(uint8_t dev_addr); +void msch_init (void); +uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void msch_close (uint8_t dev_addr); #ifdef __cplusplus } #endif #endif /* _TUSB_MSC_HOST_H_ */ - -/// @} -/// @} diff --git a/src/host/hub.c b/src/host/hub.c index b2761184d..2ead5bed1 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -144,29 +144,32 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con //--------------------------------------------------------------------+ void hub_init(void) { - tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof( hub_interface_t)); + tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(hub_interface_t)); } -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // not support multiple TT yet - if ( itf_desc->bInterfaceProtocol > 1 ) return false; + // hub driver does not support multiple TT yet + TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && + 0 == itf_desc->bInterfaceSubClass && + 1 <= itf_desc->bInterfaceProtocol, 0); - //------------- Open Interrupt Status Pipe -------------// - tusb_desc_endpoint_t const *ep_desc; - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer); + //------------- Interrupt Status endpoint -------------// + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && + TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; - hub_data[dev_addr-1].ep_in = ep_desc->bEndpointAddress; - - (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + hub_data[dev_addr-1].ep_in = desc_ep->bEndpointAddress; - return true; + return drv_len; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index a5111b8e7..c9ffe4985 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -181,11 +181,11 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hub_init(void); -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close(uint8_t dev_addr); +void hub_init (void); +uint16_t hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh.c b/src/host/usbh.c index bad1aa61a..93621c42a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -984,11 +984,12 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; - uint8_t const* p_desc = (uint8_t const*) desc_cfg; - p_desc = tu_desc_next(p_desc); + + uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint8_t const* p_desc = tu_desc_next(desc_cfg); // parse each interfaces - while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) + while( p_desc < desc_end ) { // TODO Do we need to use IAD // tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; @@ -1003,8 +1004,9 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + uint16_t const remaining_len = desc_end-p_desc; - // Check if class is supported + // Check if class is supported TODO drop class_code uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { @@ -1034,9 +1036,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { TU_LOG2("%s open\r\n", driver->name); - uint16_t itf_len = 0; - TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); + uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); + TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); p_desc += itf_len; } } diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 07480fe8e..0736fefa1 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -45,11 +45,11 @@ typedef struct { uint8_t class_code; - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); + void (* const init )(void); + uint16_t (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; // Call by class driver to tell USBH that it has complete the enumeration -- cgit v1.3.1 From c99b70c08cb9c3b252e015fd455c35674282aa91 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 12:35:51 +0700 Subject: force boot protocol for keyboard/mouse --- src/class/hid/hid_host.c | 27 +++++++++++++++------------ src/class/hid/hid_host.h | 6 +++--- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 81ed6e8b6..59fbb097e 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -98,7 +98,7 @@ uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->itf_protocol; } -bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->protocol_mode; @@ -243,7 +243,7 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -286,7 +286,8 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -318,42 +319,44 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); return true; } -static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +// Force device to work in BOOT protocol +static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_PROTOCOL, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_LOG2("HID Get Protocol\r\n"); + TU_LOG2("HID Set Protocol\r\n"); + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; tusb_control_request_t const new_request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .direction = TUSB_DIR_OUT }, - .bRequest = HID_REQ_CONTROL_GET_PROTOCOL, - .wValue = 0, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = HID_PROTOCOL_BOOT, .wIndex = hid_itf->itf_num, .wLength = 1 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); return false; } static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 6ae7c6721..b95f0d9b7 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -66,9 +66,9 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: as HID spec, device will be initialized in Report mode -bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); +// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: device will be initialized in Boot protocol for simplicity. +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -- cgit v1.3.1 From 58d3e8c08b05ac00bd2510c04f7679b5f7503404 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 12:47:48 +0700 Subject: update func comment --- src/class/hid/hid_host.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index b95f0d9b7..ef203123d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -67,7 +67,8 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: device will be initialized in Boot protocol for simplicity. +// Note: Device will be initialized in Boot protocol for simplicity. +// Application can use set_protocol() to switch back to Report protocol. uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -- cgit v1.3.1 From 268dcc8d20da15e64ba7198f0412f758f6b8a911 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 13:05:12 +0700 Subject: fix issue with weird msc device with 3 endpoints --- src/class/msc/msc_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 83cbe7c89..2c027deff 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -366,7 +366,7 @@ uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); TU_ASSERT(drv_len <= max_len, 0); msch_interface_t* p_msc = get_itf(dev_addr); -- cgit v1.3.1 From efc12ae7d4e2c3d6834203aff5dd1178ed601288 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 28 Jun 2021 23:57:57 +0700 Subject: fix SET_PROTOCOl, update hid host behavior for default boot interface --- examples/host/cdc_msc_hid/src/hid_app.c | 166 +++++++++++++++++++------------- src/class/hid/hid_host.c | 12 ++- 2 files changed, 108 insertions(+), 70 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 817646dab..fd00cf653 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -39,11 +39,15 @@ static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // Each HID instance can has multiple reports -static uint8_t _report_count[CFG_TUH_HID]; -static tuh_hid_report_info_t _report_info_arr[CFG_TUH_HID][MAX_REPORT]; +static struct +{ + uint8_t report_count; + tuh_hid_report_info_t report_info[MAX_REPORT]; +}hid_info[CFG_TUH_HID]; static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const * report); +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); void hid_app_task(void) { @@ -61,13 +65,19 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); - // Interface protocol - const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); + // Interface protocol (hid_interface_protocol_enum_t) + const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; + uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); + + printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); - // Parse report descriptor with built-in parser - _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len); - printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); + // By default host stack will use activate boot protocol on supported interface. + // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) + if ( itf_protocol == HID_ITF_PROTOCOL_NONE ) + { + hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len); + printf("HID has %u reports \r\n", hid_info[instance].report_count); + } } // Invoked when device with hid interface is un-mounted @@ -79,66 +89,24 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) // Invoked when received report from device via interrupt endpoint void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { - (void) dev_addr; + uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - uint8_t const rpt_count = _report_count[instance]; - tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance]; - tuh_hid_report_info_t* rpt_info = NULL; - - if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) - { - // Simple report without report ID as 1st byte - rpt_info = &rpt_info_arr[0]; - }else + switch (itf_protocol) { - // Composite report, 1st byte is report ID, data starts from 2nd byte - uint8_t const rpt_id = report[0]; - - // Find report id in the arrray - for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) - { - switch (rpt_info->usage) - { - case HID_USAGE_DESKTOP_KEYBOARD: - TU_LOG1("HID receive keyboard report\r\n"); - // Assume keyboard follow boot report layout - process_kbd_report( (hid_keyboard_report_t const*) report ); - break; - - case HID_USAGE_DESKTOP_MOUSE: - TU_LOG1("HID receive mouse report\r\n"); - // Assume mouse follow boot report layout - process_mouse_report( (hid_mouse_report_t const*) report ); - break; - - default: break; - } + case HID_ITF_PROTOCOL_KEYBOARD: + TU_LOG2("HID receive boot keyboard report\r\n"); + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_ITF_PROTOCOL_MOUSE: + TU_LOG2("HID receive boot mouse report\r\n"); + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: + // Generic report requires matching ReportID and contents with previous parsed report info + process_generic_report(dev_addr, instance, report, len); + break; } } @@ -243,3 +211,69 @@ static void process_mouse_report(hid_mouse_report_t const * report) //------------- cursor movement -------------// cursor_movement(report->x, report->y, report->wheel); } + +//--------------------------------------------------------------------+ +// Generic Report +//--------------------------------------------------------------------+ +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + uint8_t const rpt_count = hid_info[instance].report_count; + tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info; + tuh_hid_report_info_t* rpt_info = NULL; + + if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) + { + // Simple report without report ID as 1st byte + rpt_info = &rpt_info_arr[0]; + }else + { + // Composite report, 1st byte is report ID, data starts from 2nd byte + uint8_t const rpt_id = report[0]; + + // Find report id in the arrray + for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) + { + switch (rpt_info->usage) + { + case HID_USAGE_DESKTOP_KEYBOARD: + TU_LOG1("HID receive keyboard report\r\n"); + // Assume keyboard follow boot report layout + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_USAGE_DESKTOP_MOUSE: + TU_LOG1("HID receive mouse report\r\n"); + // Assume mouse follow boot report layout + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: break; + } + } +} diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 59fbb097e..091c5c1c4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -327,7 +327,7 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) // Force device to work in BOOT protocol static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; @@ -347,7 +347,7 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, .wValue = HID_PROTOCOL_BOOT, .wIndex = hid_itf->itf_num, - .wLength = 1 + .wLength = 0 }; TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); @@ -356,8 +356,12 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE, therefore we could ignore its result - (void) result; + // We can be here after SET_IDLE or SET_PROTOCOL (boot device) + // Trigger assert if result is not successful with set protocol + if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) + { + TU_ASSERT(result == XFER_RESULT_SUCCESS); + } uint8_t const itf_num = (uint8_t) request->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); -- cgit v1.3.1 From c172caa288213535ed5c59cea2c13d0e5b4a0597 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Jun 2021 00:03:34 +0700 Subject: clean up --- src/class/hid/hid_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 091c5c1c4..40b6f5631 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -351,7 +351,7 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * }; TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); - return false; + return true; } static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -- cgit v1.3.1 From 5877f20d4b5d54b2dfe310fedddf1c30fe6dc66c Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 29 Jun 2021 10:57:26 +0200 Subject: Fix IAR compile error on pointer type. Clean up warnings. Signed-off-by: MasterPhi --- src/class/audio/audio_device.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7ad7edf9e..7263958df 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -885,7 +885,7 @@ range [-1, +1) * */ // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) { // Optimize for fast half word copies typedef struct{ @@ -900,15 +900,15 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const switch (nBytesToCopy) { case 1: - while((uint8_t *)src < src_end) + while(src < src_end) { - *dst = *(uint8_t *)src++; + *dst = *src++; dst += n_ff_used; } break; case 2: - while((uint8_t *)src < src_end) + while(src < src_end) { *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; src += 2; @@ -917,23 +917,23 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const break; case 3: - while((uint8_t *)src < src_end) + while(src < src_end) { // memcpy(dst, src, 3); // src = (uint8_t *)src + 3; // dst += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *(uint8_t *)src++; - *dst++ = *(uint8_t *)src++; - *dst++ = *(uint8_t *)src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; dst += 3 * (n_ff_used - 1); } break; case 4: - while((uint8_t *)src < src_end) + while(src < src_end) { *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; src += 4; @@ -993,7 +993,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi if (info.len_lin != 0) { info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = info.ptr_lin + info.len_lin; + src_end = (uint8_t *)info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); // Limit up to desired length @@ -1002,7 +1002,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // Handle wrapped part of FIFO if (info.len_wrap != 0) { - src_end = info.ptr_wrap + info.len_wrap; + src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); } @@ -1956,7 +1956,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: { uint8_t ep = TU_U16_LOW(p_request->wIndex); @@ -2142,10 +2142,10 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (as_itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; + audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; + audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); #endif } #endif -- cgit v1.3.1 From ca98996e1f9ac802c60d9da4c28ab0e16ca640d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jul 2021 22:46:39 +0700 Subject: better support for hid device set/get protocol add caplock detection for hid_composite --- examples/device/hid_composite/src/main.c | 31 ++++++++++++++--- hw/bsp/board.c | 58 +++++++++++++++++++++++++++++--- hw/bsp/board.h | 9 +++-- src/class/hid/hid_device.c | 28 +++++++++++++-- src/device/usbd.c | 2 +- src/device/usbd_control.c | 1 + 6 files changed, 115 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 512f6f9d9..6ddad5aae 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -255,12 +255,30 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { - // TODO set LED based on CAPLOCK, NUMLOCK etc... (void) itf; - (void) report_id; - (void) report_type; - (void) buffer; - (void) bufsize; + + if (report_type == HID_REPORT_TYPE_OUTPUT) + { + // Set keyboard LED e.g Capslock, Numlock etc... + if (report_id == REPORT_ID_KEYBOARD) + { + // bufsize should be (at least) 1 + if ( bufsize < 1 ) return; + + uint8_t const kbd_leds = buffer[0]; + + if (kbd_leds & KEYBOARD_LED_CAPSLOCK) + { + // Capslock On: disable blink, turn led on + blink_interval_ms = 0; + board_led_write(true); + }else + { + // Caplocks Off: back to normal link + blink_interval_ms = BLINK_MOUNTED; + } + } + } } //--------------------------------------------------------------------+ @@ -271,6 +289,9 @@ void led_blinking_task(void) static uint32_t start_ms = 0; static bool led_state = false; + // blink is disabled + if (!blink_interval_ms) return; + // Blink every interval ms if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 383a02ef4..c21c9e976 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -25,6 +25,60 @@ #include "board.h" +#if 0 +#define LED_PHASE_MAX 8 + +static struct +{ + uint32_t phase[LED_PHASE_MAX]; + uint8_t phase_count; + + bool led_state; + uint8_t current_phase; + uint32_t current_ms; +}led_pattern; + +void board_led_pattern(uint32_t const phase_ms[], uint8_t count) +{ + memcpy(led_pattern.phase, phase_ms, 4*count); + led_pattern.phase_count = count; + + // reset with 1st phase is on + led_pattern.current_ms = board_millis(); + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); +} + +void board_led_task(void) +{ + if ( led_pattern.phase_count == 0 ) return; + + uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; + + // return if not enough time + if (board_millis() - led_pattern.current_ms < duration) return; + + led_pattern.led_state = !led_pattern.led_state; + board_led_write(led_pattern.led_state); + + led_pattern.current_ms += duration; + led_pattern.current_phase++; + + if (led_pattern.current_phase == led_pattern.phase_count) + { + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); + } +} + +#endif + +//--------------------------------------------------------------------+ +// newlib read()/write() retarget +//--------------------------------------------------------------------+ + #if defined(__MSP430__) #define sys_write write #define sys_read read @@ -33,10 +87,6 @@ #define sys_read _read #endif -//--------------------------------------------------------------------+ -// newlib read()/write() retarget -//--------------------------------------------------------------------+ - #if defined(LOGGER_RTT) // Logging with RTT diff --git a/hw/bsp/board.h b/hw/bsp/board.h index 7b77def50..782e0939c 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -54,6 +54,10 @@ void board_init(void); // Turn LED on or off void board_led_write(bool state); +// Control led pattern using phase duration in ms. +// For each phase, LED is toggle then repeated, board_led_task() is required to be called +//void board_led_pattern(uint32_t const phase_ms[], uint8_t count); + // Get the current state of button // a '1' means active (pressed), a '0' means inactive. uint32_t board_button_read(void); @@ -81,11 +85,12 @@ int board_uart_write(void const * buf, int len); } #elif CFG_TUSB_OS == OPT_OS_PICO -#include "pico/time.h" -static inline uint32_t board_millis(void) + #include "pico/time.h" + static inline uint32_t board_millis(void) { return to_ms_since_boot(get_absolute_time()); } + #elif CFG_TUSB_OS == OPT_OS_RTTHREAD static inline uint32_t board_millis(void) { diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index e44f282c4..65c7d1a18 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -280,7 +280,21 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + uint8_t* report_buf = p_hid->epin_buf; + uint16_t req_len = request->wLength; + + uint16_t xferlen = 0; + + // If host request a specific Report ID, add ID to as 1 byte of response + if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) + { + *report_buf++ = report_id; + req_len--; + + xferlen++; + } + + xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -298,7 +312,17 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength); + uint8_t const* report_buf = p_hid->epout_buf; + uint16_t report_len = request->wLength; + + // If host request a specific Report ID, extract report ID in buffer before invoking callback + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == p_hid->epout_buf[0]) ) + { + report_buf++; + report_len--; + } + + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); } break; diff --git a/src/device/usbd.c b/src/device/usbd.c index 587d487dc..af4fd58c4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1243,7 +1243,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 724c652e6..7a8244699 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -186,6 +186,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); + TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += xferred_bytes; -- cgit v1.3.1 From 2b3d547b7bccf46c6a274c75cb1769532611c5bf Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jul 2021 23:05:21 +0700 Subject: clean up --- src/class/hid/hid_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 65c7d1a18..a10e3a5e3 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -316,7 +316,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint16_t report_len = request->wLength; // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == p_hid->epout_buf[0]) ) + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) { report_buf++; report_len--; -- cgit v1.3.1 From 6e9da70c18a0dbabaedb1c9aadcc9fe53a0113a7 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 29 Jun 2021 22:40:21 +0200 Subject: Fix audiod_get_AS_interface_index in audio class. Enhance uac2_headset example with multiple sample rates. Add macro to calculate EP size. --- examples/device/uac2_headset/src/main.c | 69 ++++++++++++++++------ examples/device/uac2_headset/src/tusb_config.h | 13 ++-- examples/device/uac2_headset/src/usb_descriptors.c | 2 +- examples/device/uac2_headset/src/usb_descriptors.h | 8 +-- src/class/audio/audio_device.c | 16 ++--- src/device/usbd.h | 5 ++ 6 files changed, 77 insertions(+), 36 deletions(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 1b6a770a3..e76b081c8 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -34,9 +34,11 @@ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif +// List of supported sample rates +const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; +uint32_t current_sample_rate = 44100; + +#define N_SAMPLE_RATES (sizeof(sample_rates) / 4) /* Blink pattern * - 25 ms : streaming data @@ -166,24 +168,30 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - // Example supports only single frequency, same value will be used for current value and range if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG2("Clock get current freq %u\r\n", AUDIO_SAMPLE_RATE); + TU_LOG1("Clock get current freq %u\r\n", current_sample_rate); - audio_control_cur_4_t curf = { tu_htole32(AUDIO_SAMPLE_RATE) }; + audio_control_cur_4_t curf = { tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_4_n_t(1) rangef = + audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = { - .wNumSubRanges = tu_htole16(1), - .subrange[0] = { tu_htole32(AUDIO_SAMPLE_RATE), tu_htole32(AUDIO_SAMPLE_RATE), 0} + .wNumSubRanges = tu_htole16(N_SAMPLE_RATES) }; - TU_LOG2("Clock get freq range (%d, %d, %d)\r\n", (int)rangef.subrange[0].bMin, (int)rangef.subrange[0].bMax, (int)rangef.subrange[0].bRes); + TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); + for(uint8_t i = 0; i < N_SAMPLE_RATES; i++) + { + rangef.subrange[i].bMin = sample_rates[i]; + rangef.subrange[i].bMax = sample_rates[i]; + rangef.subrange[i].bRes = 0; + TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes); + } + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); } } @@ -191,7 +199,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_1_t cur_valid = { .bCur = 1 }; - TU_LOG2("Clock get is valid %u\r\n", cur_valid.bCur); + TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid)); } TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n", @@ -199,6 +207,32 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return false; } +// Helper for clock set requests +static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) +{ + (void)rhport; + + TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); + TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) + { + TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); + + current_sample_rate = ((audio_control_cur_4_t *)buf)->bCur; + + TU_LOG1("Clock set current freq: %d\r\n", current_sample_rate); + + return true; + } + else + { + TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n", + request->bEntityID, request->bControlSelector, request->bRequest); + return false; + } +} + // Helper for feature unit get requests static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { @@ -207,7 +241,7 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; - TU_LOG2("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); + TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1)); } else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request->bControlSelector == AUDIO_FU_CTRL_VOLUME) @@ -218,14 +252,14 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req .wNumSubRanges = tu_htole16(1), .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) } }; - TU_LOG2("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, + TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol)); } else if (request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; - TU_LOG2("Get channel %u volume %u dB\r\n", request->bChannelNumber, cur_vol.bCur); + TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); } } @@ -249,7 +283,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur; - TU_LOG2("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); + TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; } @@ -259,7 +293,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur; - TU_LOG2("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); + TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); return true; } @@ -299,7 +333,8 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) return tud_audio_feature_unit_set_request(rhport, request, buf); - + if (request->bEntityID == UAC2_ENTITY_CLOCK) + return tud_audio_clock_set_request(rhport, request, buf); TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 88f9efcff..9b7ed337c 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -93,13 +93,12 @@ extern "C" { //-------------------------------------------------------------------- // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) //#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN 220 // This equals TUD_AUDIO_HEADSET_STEREO_DESC_LEN, however, including it from usb_descriptors.h is not possible due to some strange include hassle #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN // Audio format type I specifications +#define CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE 96000 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 @@ -108,18 +107,18 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_OUT_SZ // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_OUT*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_SZ_OUT // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 // Size of control request buffer #define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index cd749eb65..f5d8e461b 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -93,7 +93,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_SZ_OUT, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d9c5a63a7..1595d9c5d 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -77,7 +77,7 @@ enum /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 5, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ /* Input Terminal Descriptor(4.7.2.4) */\ TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ @@ -99,21 +99,21 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\ /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + /* Interface 2, Alternate 1 - alternate interface for data streaming */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)\ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7263958df..cb35adb82 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1997,15 +1997,17 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio while (p_desc < p_desc_end) { // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; + if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + // Increase index, bytes read, and pointer + tmp++; } - - // Increase index, bytes read, and pointer - tmp++; p_desc = tu_desc_next(p_desc); } } diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..45aefe53b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -542,6 +542,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ +// Calculate wMaxPacketSize of Endpoints +#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ + ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) + + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u -- cgit v1.3.1 From 204f3152cb486b8de3817bf940efd4593c8bfd07 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Thu, 1 Jul 2021 11:38:06 +0200 Subject: audio_device : clear fifo on intf change. --- src/class/audio/audio_device.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index cb35adb82..230b689cd 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1481,6 +1481,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); + // Clear FIFOs, since data is no longer valid + tu_fifo_clear(&audio->ep_in_ff); + // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); @@ -1502,6 +1505,13 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); + + // Clear FIFOs, since data is no longer valid + tu_fifo_clear(&audio->ep_out_ff); + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + audio->ep_out = 0; // Necessary? // Clear support FIFOs if used -- cgit v1.3.1 From 5f67e5c1e9b10e40ac6e3a649f45f7719b437dc5 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Thu, 1 Jul 2021 11:45:39 +0200 Subject: Clear FIFO only if enabled... Add buffer align --- examples/device/uac2_headset/src/main.c | 14 +++++++------- examples/device/uac2_headset/src/tusb_config.h | 4 ++-- src/class/audio/audio_device.c | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index c9e79a543..f7d20a607 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -78,9 +78,9 @@ int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master chan int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 // Buffer for microphone data -uint8_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4]; // Buffer for speaker data -uint8_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +int32_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 4]; // Speaker data size received in the last frame int spk_data_size; // Resolution per format @@ -430,14 +430,14 @@ void audio_task(void) } else if (current_resolution == 24) { - int32_t *src = (int32_t*)spk_buf; - int32_t *limit = (int32_t*)spk_buf + spk_data_size / 4; - int32_t *dst = (int32_t*)mic_buf; + int32_t *src = spk_buf; + int32_t *limit = spk_buf + spk_data_size / 4; + int32_t *dst = mic_buf; while (src < limit) { // Combine two channels into one - int32_t left = (*src++); - int32_t right = (*src++); + int32_t left = *src++; + int32_t right = *src++; *dst++ = (int32_t)((left + right) / 2) & 0xffffff00; } tud_audio_write((uint8_t *)mic_buf, spk_data_size / 2); diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 642e52551..d955a746d 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -122,7 +122,7 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN)*2 #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) @@ -131,7 +131,7 @@ extern "C" { #define CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) #define CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT)*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT)*2 #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 230b689cd..3e05b3763 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1481,8 +1481,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); +#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid tu_fifo_clear(&audio->ep_in_ff); +#endif // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); @@ -1506,8 +1508,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); +#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid tu_fifo_clear(&audio->ep_out_ff); +#endif // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); -- cgit v1.3.1 From 449936c0f11ea72dd969c8bb353b0f58814f7bc6 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 2 Jul 2021 21:51:54 +0200 Subject: more uac fixes, --- src/class/audio/audio.h | 2 +- src/class/audio/audio_device.c | 50 +++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 936f09104..238295d25 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3e05b3763..31b318c3f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -102,19 +102,19 @@ // EP IN software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO #endif @@ -126,32 +126,32 @@ osal_mutex_def_t ep_in_ff_mutex_wr_3; // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // EP OUT software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO #endif @@ -163,52 +163,52 @@ osal_mutex_def_t ep_out_ff_mutex_rd_3; // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; #if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; #endif #if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO @@ -218,21 +218,21 @@ osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO @@ -294,7 +294,7 @@ typedef struct // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif // Decoding parameters - parameters are set when alternate AS interface is set by host -- cgit v1.3.1 From 090859bf424e910002fff7dc9195d38d6c22ae1f Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 2 Jul 2021 23:44:46 +0200 Subject: Fix speed detection --- src/class/audio/audio_device.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 31b318c3f..cc07d5e19 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2223,22 +2223,19 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value - if (_audiod_fct[func_id].rhport == 0) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - } - else - { - // For HS format is 16.16 as originally demanded - _audiod_fct[func_id].fb_val = feedback; - } +#if !TUD_OPT_HIGH_SPEED + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; +#else + // For HS format is 16.16 as originally demanded + _audiod_fct[func_id].fb_val = feedback; +#endif // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) -- cgit v1.3.1 From 61fd0e2c1cd60921ea3cc6de01534a1e512aff12 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 3 Jul 2021 10:54:20 +0200 Subject: Delay tud_audio_set_itf_cb call with feedback EP. --- src/class/audio/audio_device.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index cc07d5e19..61884f867 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1619,9 +1619,17 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); #endif #endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // In case of asynchronous EP, call Cb after ep_fb is set + if (((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync != 0x01) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } +#else // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - +#endif // Prepare for incoming data #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -- cgit v1.3.1 From 1c8b685457aee291f8352003c7ca7b852c412982 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 4 Jul 2021 00:19:33 +0200 Subject: Move audio_control_request_t to audio.h --- examples/device/uac2_headset/src/main.c | 26 -------------------------- src/class/audio/audio.h | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index b459bc2a8..ba27350b4 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -142,32 +142,6 @@ void tud_resume_cb(void) blink_interval_ms = BLINK_MOUNTED; } -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; - // Helper for clock get requests static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 238295d25..f99061eae 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -823,6 +823,33 @@ typedef struct TU_ATTR_PACKED uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; +// 5.2.2 Control Request Layout +typedef struct TU_ATTR_PACKED +{ + union + { + struct TU_ATTR_PACKED + { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + + uint8_t bmRequestType; + }; + + uint8_t bRequest; ///< Request type audio_cs_req_t + uint8_t bChannelNumber; + uint8_t bControlSelector; + union + { + uint8_t bInterface; + uint8_t bEndpoint; + }; + uint8_t bEntityID; + uint16_t wLength; +} audio_control_request_t; + //// 5.2.3 Control Request Parameter Block Layout // 5.2.3.1 1-byte Control CUR Parameter Block -- cgit v1.3.1 From 98d921c4b3657e473f2231857bb6c82ef567b0e3 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 4 Jul 2021 15:10:45 +0200 Subject: Better handling tud_audio_set_itf_cb with FB. --- src/class/audio/audio_device.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 61884f867..c7b8b8519 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1622,7 +1622,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // In case of asynchronous EP, call Cb after ep_fb is set - if (((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync != 0x01) + if (!(((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync == 0x01 && audio->ep_fb == 0)) { if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } @@ -1643,8 +1643,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_fb = ep_addr; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Invoke callback after ep_out is set + if (audio->ep_out != 0) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } } #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1938,8 +1941,12 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[func_id]); + // Schedule a transmit with the new value if EP is not busy + if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb)) + { + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + return audiod_fb_send(rhport, &_audiod_fct[func_id]); + } } #endif #endif -- cgit v1.3.1 From dfe410ea8beb15b4d85320efeb059f42be647ea6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Jul 2021 12:38:15 +0700 Subject: fix ci build, address review comment --- src/class/dfu/dfu_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index df731ee50..c696d70a2 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -247,9 +247,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); - TU_ASSERT( retval <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -277,7 +276,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); // setup for data phase tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } @@ -285,7 +284,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } -- cgit v1.3.1 From c2d8ed3fd1fdb722d67a30a6768720c9ed578779 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 5 Jul 2021 17:56:21 +0200 Subject: Add alt settings support in DFU class. --- examples/device/dfu/src/main.c | 25 ++++++++--------- examples/device/dfu/src/usb_descriptors.c | 8 ++++-- src/class/dfu/dfu_device.c | 46 ++++++++++++++++++++----------- src/class/dfu/dfu_device.h | 10 ++++--- src/device/usbd.h | 8 +++--- 5 files changed, 56 insertions(+), 41 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1c09066a8..81532ee90 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -115,25 +115,20 @@ void tud_resume_cb(void) blink_interval_ms = BLINK_MOUNTED; } -// Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_runtime_reboot_to_dfu_cb(void) -{ - blink_interval_ms = BLINK_DFU_MODE; -} - //--------------------------------------------------------------------+ // Class callbacks //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(void) +bool tud_dfu_firmware_valid_check_cb(uint8_t alt) { + (void) alt; printf(" Firmware check\r\n"); return true; } -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; - printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; ibInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + uint16_t drv_len = 0; + uint8_t const * p_desc = (uint8_t*)itf_desc; - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + while (max_len) { - tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; - + // Ensure this is DFU Mode + TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), drv_len); + + p_desc = tu_desc_next( p_desc ); drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + max_len -= drv_len; + } return drv_len; } @@ -200,6 +208,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && TUSB_REQ_SET_INTERFACE == request->bRequest ) { + // Save Alt interface + _dfu_state_ctx.alt = request->wValue; tud_control_status(rhport, request); return true; } @@ -248,7 +258,11 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + uint16_t retval = 0; + if (tud_dfu_req_upload_data_cb) + { + tud_dfu_req_upload_data_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -285,7 +299,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt, request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } @@ -426,7 +440,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb() ) + if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -481,7 +495,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb() ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_IDLE; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 9a09a46b1..d5bc88ab2 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -39,13 +39,14 @@ //--------------------------------------------------------------------+ // Invoked during DFU_MANIFEST_SYNC get status request to check if firmware // is valid -bool tud_dfu_firmware_valid_check_cb(void); +bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data // provided by tud_dfu_req_dnload_data_cb @@ -56,7 +57,7 @@ void tud_dfu_dnload_complete(void); // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(void); +bool tud_dfu_device_data_done_check_cb(uint8_t alt); // Invoked when the Host has terminated a download or upload transfer TU_ATTR_WEAK void tud_dfu_abort_cb(void); @@ -64,7 +65,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes // Return the number of bytes to write -uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..41c78de10 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -603,11 +603,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Length of template descriptr: 18 bytes #define TUD_DFU_MODE_DESC_LEN (9 + 9) -// DFU runtime descriptor -// Interface number, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ +// DFU mode descriptor +// Interface number, alt settings, string index, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -- cgit v1.3.1 From c2b9ac9dd415505350c40f6830c1d211de67c342 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 5 Jul 2021 17:57:23 +0200 Subject: Fix ATTR_MANIFESTATION_TOLERANT logic. --- src/class/dfu/dfu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 0570b5958..9eafca359 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -310,7 +310,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -490,7 +490,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); -- cgit v1.3.1 From 05a1b854ffcebe8144481a8af9e447d0eac2ae1f Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Mon, 5 Jul 2021 21:00:04 +0200 Subject: ENCODE -> DECODE --- src/class/audio/audio_device.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c7b8b8519..97a9c495e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1481,9 +1481,14 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); -#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_clear(&audio->ep_in_ff); +#else + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } #endif // Invoke callback - can be used to stop data sampling @@ -1491,14 +1496,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in = 0; // Necessary? - // Clear support FIFOs if used -#if CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - } #endif @@ -1508,9 +1505,14 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); -#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_clear(&audio->ep_out_ff); +#else + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } #endif // Invoke callback - can be used to stop data sampling @@ -1518,14 +1520,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_out = 0; // Necessary? - // Clear support FIFOs if used -#if CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP usbd_edpt_close(rhport, audio->ep_fb); -- cgit v1.3.1 From 82d355aefe5251f6dd15a7406920efaf516df705 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 6 Jul 2021 00:25:00 +0200 Subject: - Remove alt_setting alignment --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 97a9c495e..f6e6e13f4 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -183,12 +183,12 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_ #endif // Active alternate setting of interfaces -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs -- cgit v1.3.1 From 72f916423e85083a090186ecc05a6a5b8962685a Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 6 Jul 2021 10:56:13 +0200 Subject: Fix copy byte count --- src/class/audio/audio_device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f6e6e13f4..404d28817 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -643,7 +643,6 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u // Determine amount of samples uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; @@ -662,14 +661,14 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); + src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); } tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } @@ -994,7 +993,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi { info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); // Limit up to desired length info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); @@ -1003,7 +1002,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi if (info.len_wrap != 0) { src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); + audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); } tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); -- cgit v1.3.1 From cf4220a9fb24279b423656257cea39b3ab68aa67 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 6 Jul 2021 18:03:05 +0200 Subject: Update --- examples/device/dfu/src/tusb_config.h | 1 + src/class/dfu/dfu_device.c | 3 +++ src/class/dfu/dfu_device.h | 11 +++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 90e90b2e4..0df46c14e 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,6 +76,7 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif +// DFU buffer size, must to be set to the largest buffer size used by an any given storage type #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 //------------- CLASS -------------// diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 9eafca359..a186e9140 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -147,6 +147,7 @@ void dfu_moded_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.alt = 0; dfu_debug_print_context(); } @@ -158,6 +159,8 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.alt = 0; + dfu_debug_print_context(); } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d5bc88ab2..c5c1ede28 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -33,6 +33,13 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Default Configure & Validation +//--------------------------------------------------------------------+ + +#if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) + #error " CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it have to be set to the largest buffer size used by an any given storage type" +#endif //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -45,7 +52,7 @@ bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data @@ -65,7 +72,7 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes // Return the number of bytes to write -// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ -- cgit v1.3.1 From bc49ee7f2fc74932c332520b0fd8eccefbae659a Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 11:55:36 +0200 Subject: Better alt settings support --- src/class/dfu/dfu_device.c | 92 +++++++++++++++++++++++++++++++++------------- src/class/dfu/dfu_device.h | 7 +++- 2 files changed, 72 insertions(+), 27 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index a186e9140..f6fcb1339 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -37,6 +37,8 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#define DFU_INTF_UNUSED 0xFF + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -44,9 +46,10 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs; + uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; bool blk_transfer_in_proc; uint8_t alt; + uint8_t intf; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -145,9 +148,13 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = 0; + for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) + { + _dfu_state_ctx.attrs[i] = 0; + } _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; + _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -158,8 +165,13 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; + for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) + { + _dfu_state_ctx.attrs[i] = 0; + } _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; + _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -167,32 +179,55 @@ void dfu_moded_reset(uint8_t rhport) uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; - (void) max_len; - uint16_t drv_len = 0; - uint8_t const * p_desc = (uint8_t*)itf_desc; + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + + uint8_t const *p_desc = (uint8_t const *)itf_desc; - while (max_len) + uint16_t total_len = 0; + + uint8_t last_alt = 0; + + while(max_len >= drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), drv_len); - - p_desc = tu_desc_next( p_desc ); - drv_len += tu_desc_len(p_desc); + (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + uint8_t const alt = ((tusb_desc_interface_t const *)p_desc)->bAlternateSetting; + uint8_t const intf = ((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber; - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + if (_dfu_state_ctx.intf == DFU_INTF_UNUSED) + { + _dfu_state_ctx.intf = intf; } + else + { + // Only one DFU interface is supported + TU_ASSERT(_dfu_state_ctx.intf == intf); + } + + // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings + TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX); + + // Alt should increse by one every time + TU_ASSERT(alt == last_alt++); + + //------------- DFU descriptor -------------// + p_desc = tu_desc_next(p_desc); + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + + p_desc = tu_desc_next(p_desc); max_len -= drv_len; + total_len += drv_len; } - return drv_len; + + return total_len; } // Invoked when a control transfer occurred on an interface of this class @@ -208,11 +243,16 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if(stage == CONTROL_STAGE_SETUP) { // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_INTERFACE) { - // Save Alt interface + // Switch Alt interface _dfu_state_ctx.alt = request->wValue; + + // Re-initalise state machine (Necessary ?) + _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.blk_transfer_in_proc = false; + tud_control_status(rhport, request); return true; } @@ -226,7 +266,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -313,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -331,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -345,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -436,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -493,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c5c1ede28..6f826152f 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,8 +37,13 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ +// Maximum alternate settings (used for different partitons) supported +#if !defined(CFG_TUD_DFU_ATL_MAX) + #define CFG_TUD_DFU_ATL_MAX 2 +#endif + #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error " CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it have to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 88478594bc0c5946853567620beb944940f81a1d Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 12:06:41 +0200 Subject: Update comment --- src/class/dfu/dfu_device.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 6f826152f..67d15c3c6 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -49,15 +49,15 @@ //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware -// is valid +// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware is valid +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // Invoked when a DFU_DNLOAD request is received +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data @@ -66,6 +66,7 @@ void tud_dfu_dnload_complete(void); // Invoked during the last DFU_DNLOAD request, signifying that the host believes // it is done transmitting data. +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure @@ -75,9 +76,9 @@ bool tud_dfu_device_data_done_check_cb(uint8_t alt); TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // This callback must populate data with up to length bytes // Return the number of bytes to write -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 3949fb9e8c1b9a9646223e3edf7a0df4f010b5be Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 12:07:10 +0200 Subject: Add DFU_DETACH support --- src/class/dfu/dfu_device.c | 7 ++++++- src/class/dfu/dfu_device.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f6fcb1339..f4edd713a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -263,6 +263,12 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque switch (request->bRequest) { + case DFU_REQUEST_DETACH: + { + tud_control_status(rhport, request); + if (tud_dfu_reboot_cb) tud_dfu_reboot_cb(); + break; + } case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) @@ -273,7 +279,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } } // fallthrough - case DFU_REQUEST_DETACH: case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 67d15c3c6..53be0005e 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -81,6 +81,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Return the number of bytes to write TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); +// Invoked when a DFU_DETACH request is received +TU_ATTR_WEAK void tud_dfu_reboot_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 71c00432610780f07d0e0776eacdda1186481854 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 12:18:25 +0200 Subject: TU_ASSERT return 0. --- src/class/dfu/dfu_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f4edd713a..8bf2e16be 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -204,14 +204,14 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, else { // Only one DFU interface is supported - TU_ASSERT(_dfu_state_ctx.intf == intf); + TU_ASSERT(_dfu_state_ctx.intf == intf, 0); } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX); + TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); // Alt should increse by one every time - TU_ASSERT(alt == last_alt++); + TU_ASSERT(alt == last_alt++, 0); //------------- DFU descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -220,7 +220,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); p_desc = tu_desc_next(p_desc); max_len -= drv_len; -- cgit v1.3.1 From 941b02c6a98cd34eb84cf499db9810108871d49b Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 18:02:04 +0200 Subject: Reactor to one functional descriptor. --- examples/device/dfu/src/tusb_config.h | 8 +++-- examples/device/dfu/src/usb_descriptors.c | 7 ++--- src/class/dfu/dfu_device.c | 51 ++++++++++++++----------------- src/class/dfu/dfu_device.h | 7 +---- src/device/usbd.h | 47 +++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 0df46c14e..55aa19922 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,14 +76,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -// DFU buffer size, must to be set to the largest buffer size used by an any given storage type -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 - //------------- CLASS -------------// #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 +// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) +#define CFG_TUD_DFU_ALT_COUNT 2 +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 + #ifdef __cplusplus } #endif diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 9565da9b2..200817eb4 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,9 +96,8 @@ uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + // Interface number, detach timeout, transfer size, string index 0, [string index 1 ... string index n] + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8bf2e16be..834648c5a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; + uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; @@ -148,10 +148,7 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -165,10 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -180,15 +174,15 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *)itf_desc; uint16_t total_len = 0; - + uint8_t last_alt = 0; - while(max_len >= drv_len) + while(max_len > drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && @@ -208,25 +202,26 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); + TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); // Alt should increse by one every time TU_ASSERT(alt == last_alt++, 0); - //------------- DFU descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); - - _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; - - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - p_desc = tu_desc_next(p_desc); max_len -= drv_len; total_len += drv_len; } + //------------- DFU descriptor -------------// + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + + _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); + + total_len += sizeof(tusb_desc_dfu_functional_t); + return total_len; } @@ -272,7 +267,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -358,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -376,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -390,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -481,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -538,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 53be0005e..f41b4b651 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,13 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -// Maximum alternate settings (used for different partitons) supported -#if !defined(CFG_TUD_DFU_ATL_MAX) - #define CFG_TUD_DFU_ATL_MAX 2 -#endif - #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 41c78de10..fe1863706 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -600,17 +600,50 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Length of template descriptr: 18 bytes -#define TUD_DFU_MODE_DESC_LEN (9 + 9) +// Maximum alternate settings (used for different partitons) supported +#ifndef CFG_TUD_DFU_ALT_COUNT +#define CFG_TUD_DFU_ALT_COUNT 1 +#endif -// DFU mode descriptor -// Interface number, alt settings, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ +// Length of template descriptor: 18 bytes + number of alternatives * 9 +#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) + +/* Primary Interface */ +#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + +#define _TUD_DFU_FIRST(a, ...) a +#define _TUD_DFU_REST(a, ...) __VA_ARGS__ +#define _TUD_DFU_COMBINE(...) __VA_ARGS__ + +#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) + +#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ + TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) + +// Interface number, detach timeout, transfer size, string index 1, [string index 2, string index n] +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ + TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ + TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) //------------- CDC-ECM -------------// -- cgit v1.3.1 From 7e883e0f41a4fdda699bbaf1d64a28d82527b8f9 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 7 Jul 2021 19:01:00 +0200 Subject: Refactor with one DFU functionnal descriptor --- examples/device/dfu/src/tusb_config.h | 8 +++-- examples/device/dfu/src/usb_descriptors.c | 7 ++--- src/class/dfu/dfu_device.c | 51 ++++++++++++++----------------- src/class/dfu/dfu_device.h | 7 +---- src/device/usbd.h | 47 +++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 48 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 0df46c14e..55aa19922 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,14 +76,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -// DFU buffer size, must to be set to the largest buffer size used by an any given storage type -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 - //------------- CLASS -------------// #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 +// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) +#define CFG_TUD_DFU_ALT_COUNT 2 +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 + #ifdef __cplusplus } #endif diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 9565da9b2..8c5eee455 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,9 +96,8 @@ uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8bf2e16be..834648c5a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; + uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; @@ -148,10 +148,7 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -165,10 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -180,15 +174,15 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *)itf_desc; uint16_t total_len = 0; - + uint8_t last_alt = 0; - while(max_len >= drv_len) + while(max_len > drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && @@ -208,25 +202,26 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); + TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); // Alt should increse by one every time TU_ASSERT(alt == last_alt++, 0); - //------------- DFU descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); - - _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; - - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - p_desc = tu_desc_next(p_desc); max_len -= drv_len; total_len += drv_len; } + //------------- DFU descriptor -------------// + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + + _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); + + total_len += sizeof(tusb_desc_dfu_functional_t); + return total_len; } @@ -272,7 +267,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -358,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -376,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -390,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -481,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -538,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 53be0005e..f41b4b651 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,13 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -// Maximum alternate settings (used for different partitons) supported -#if !defined(CFG_TUD_DFU_ATL_MAX) - #define CFG_TUD_DFU_ATL_MAX 2 -#endif - #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 41c78de10..3d49d4b12 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -600,17 +600,50 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Length of template descriptr: 18 bytes -#define TUD_DFU_MODE_DESC_LEN (9 + 9) +// Maximum alternate settings (used for different partitons) supported +#ifndef CFG_TUD_DFU_ALT_COUNT +#define CFG_TUD_DFU_ALT_COUNT 1 +#endif -// DFU mode descriptor -// Interface number, alt settings, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ +// Length of template descriptor: 18 bytes + number of alternatives * 9 +#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) + +/* Primary Interface */ +#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + +#define _TUD_DFU_FIRST(a, ...) a +#define _TUD_DFU_REST(a, ...) __VA_ARGS__ +#define _TUD_DFU_COMBINE(...) __VA_ARGS__ + +#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) + +#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ + TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) + +// Interface number, attributes, detach timeout, transfer size, string index 1, [string index 2, string index n] +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ + TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ + TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) //------------- CDC-ECM -------------// -- cgit v1.3.1 From 2147a31f25e6e848d9ec690d8324a6fa2d1d3127 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 8 Jul 2021 01:10:02 +0200 Subject: Fix wrong blocknum and length --- src/class/dfu/dfu_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 34472bcdd..6e7ad151b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -50,6 +50,8 @@ typedef struct TU_ATTR_PACKED bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; + uint16_t block; + uint16_t length; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -270,6 +272,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { + _dfu_state_ctx.block = request->wValue; + _dfu_state_ctx.length = request->wLength; return true; } } // fallthrough @@ -349,7 +353,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt, request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); _dfu_state_ctx.blk_transfer_in_proc = false; } -- cgit v1.3.1 From a0691a4fd426f01915a7ce6452b5367aa667fb0b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:48:33 +0700 Subject: update dfu_moded_open --- src/class/dfu/dfu_device.c | 62 ++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 41 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 6e7ad151b..04f086e0e 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -49,7 +49,6 @@ typedef struct TU_ATTR_PACKED uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; - uint8_t intf; uint16_t block; uint16_t length; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; @@ -153,7 +152,6 @@ void dfu_moded_init(void) _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; - _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -167,7 +165,6 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; - _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -176,55 +173,38 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t); + //------------- Interface (with Alt) descriptor -------------// + uint8_t const itf_num = itf_desc->bInterfaceNumber; + uint8_t alt_count = 0; - uint8_t const *p_desc = (uint8_t const *)itf_desc; - - uint16_t total_len = 0; - - uint8_t last_alt = 0; - - while(max_len > drv_len) + uint16_t drv_len = 0; + while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) { - // Ensure this is DFU Mode - TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); - - uint8_t const alt = ((tusb_desc_interface_t const *)p_desc)->bAlternateSetting; - uint8_t const intf = ((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber; - - if (_dfu_state_ctx.intf == DFU_INTF_UNUSED) - { - _dfu_state_ctx.intf = intf; - } - else - { - // Only one DFU interface is supported - TU_ASSERT(_dfu_state_ctx.intf == intf, 0); - } + TU_ASSERT(max_len > drv_len, 0); - // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); + // Alternate must have the same interface number + TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); - // Alt should increse by one every time - TU_ASSERT(alt == last_alt++, 0); + // Alt should increase by one every time + TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); + alt_count++; - p_desc = tu_desc_next(p_desc); - max_len -= drv_len; - total_len += drv_len; + drv_len += tu_desc_len(itf_desc); + itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); } - //------------- DFU descriptor -------------// - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + //------------- DFU Functional descriptor -------------// + tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; + TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); + drv_len += sizeof(tusb_desc_dfu_functional_t); - _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + _dfu_state_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - - total_len += sizeof(tusb_desc_dfu_functional_t); + uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); - return total_len; + return drv_len; } // Invoked when a control transfer occurred on an interface of this class -- cgit v1.3.1 From 134ed995c82635d509621e40568b57309fc26101 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:50:19 +0700 Subject: add alt to tud_dfu_abort_cb() --- src/class/dfu/dfu_device.c | 4 ++-- src/class/dfu/dfu_device.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 04f086e0e..933946b7e 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -503,7 +503,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if ( tud_dfu_abort_cb ) { - tud_dfu_abort_cb(); + tud_dfu_abort_cb(_dfu_state_ctx.alt); } _dfu_state_ctx.state = DFU_IDLE; } @@ -613,7 +613,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(); + tud_dfu_abort_cb(_dfu_state_ctx.alt); } _dfu_state_ctx.state = DFU_IDLE; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c09b9a823..73e5055cd 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -73,7 +73,7 @@ void tud_dfu_dnload_complete(void); bool tud_dfu_device_data_done_check_cb(uint8_t alt); // Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(void); +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); // Invoked when a DFU_UPLOAD request is received // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -- cgit v1.3.1 From 2916cd45753ca579ee1d0b475b2daf3f715243b6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:51:57 +0700 Subject: rename TUD_DFU_MODE_DESCRIPTOR to TUD_DFU_DESCRIPTOR --- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 2 +- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 2 +- src/device/usbd.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 55aa19922..7e10b4321 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -83,7 +83,7 @@ // Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) #define CFG_TUD_DFU_ALT_COUNT 2 -// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 #ifdef __cplusplus diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 8c5eee455..870c18a04 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -97,7 +97,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 933946b7e..ae056b441 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -200,7 +200,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_state_ctx.attrs = func_desc->bAttributes; - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 73e5055cd..8edb2bae3 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -38,7 +38,7 @@ //--------------------------------------------------------------------+ #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index ba415abe8..8c5f0097d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -646,7 +646,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1, string index n] -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ +#define TUD_DFU_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) -- cgit v1.3.1 From 389d34067854fcf39dd1839f2643bd8300aafe1d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 20:17:44 +0700 Subject: clean up --- src/class/dfu/dfu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ae056b441..a7a8f578c 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED +typedef struct { dfu_device_status_t status; dfu_state_t state; -- cgit v1.3.1 From 8c48a4a2886bdac96df274311f84bc6c04c56b95 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 20:23:19 +0700 Subject: clean up --- src/class/dfu/dfu_device.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index a7a8f578c..51e6179bc 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -37,8 +37,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define DFU_INTF_UNUSED 0xFF - //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -- cgit v1.3.1 From 86d511f24452b13c8e5779c7a79bff54a03dafd8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 21:08:13 +0700 Subject: rename tud_dfu_set_timeout_cb() to tud_dfu_get_status_cb() also add state as argument --- examples/device/dfu/src/main.c | 7 +++++-- src/class/dfu/dfu_device.c | 19 +++++++++---------- src/class/dfu/dfu_device.h | 6 +++--- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index ee201c1c5..4ec6d477c 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -125,10 +125,13 @@ bool tud_dfu_firmware_valid_check_cb(uint8_t alt) return true; } -uint16_t tud_dfu_set_timeout_cb(uint8_t alt) +uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) { // For example Alt1 (EEPROM) is slow, add 2000ms timeout - if (alt == 1) return 2000; + if ( state == DFU_DNBUSY ) + { + if (alt == 1) return 2000; + } return 0; } diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 51e6179bc..23669b508 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -293,18 +293,17 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) { - dfu_status_req_payload_t resp; - - uint16_t timeout = 0; - resp.bStatus = _dfu_state_ctx.status; - if(_dfu_state_ctx.state == DFU_DNBUSY && tud_dfu_set_timeout_cb) + uint32_t timeout = 0; + if ( tud_dfu_get_status_cb ) { - timeout = tud_dfu_set_timeout_cb(_dfu_state_ctx.alt); - + timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt, _dfu_state_ctx.state); } - resp.bwPollTimeout[0] = TU_U16_LOW(timeout); - resp.bwPollTimeout[1] = TU_U16_HIGH(timeout); - resp.bwPollTimeout[2] = 0; + + dfu_status_req_payload_t resp; + resp.bStatus = _dfu_state_ctx.status; + resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); + resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); + resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); resp.bState = _dfu_state_ctx.state; resp.iString = 0; diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 8edb2bae3..647fc2c04 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -48,10 +48,10 @@ // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. bool tud_dfu_firmware_valid_check_cb(uint8_t alt); -// Invoked when a DFU_GETSTATUS request is received in DFU_DNBUSY state -// Used to set the bwPollTimeout value, useful for slow Flash in order to make host wait longer +// Invoked when a DFU_GETSTATUS request is received +// Return the bwPollTimeout value for host's response, useful for slow Flash in order to make host wait longer // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -TU_ATTR_WEAK uint16_t tud_dfu_set_timeout_cb(uint8_t alt); +TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); // Invoked when a DFU_DNLOAD request is received // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -- cgit v1.3.1 From 137dff620bc5890afdf59a61cebe355fc6999f12 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Jul 2021 20:24:12 +0700 Subject: add option to silent a driver log --- src/class/msc/msc_device.c | 20 ++++++++++++-------- src/common/tusb_common.h | 18 +++++++++++++----- src/common/tusb_compiler.h | 12 ++++++++---- src/common/tusb_fifo.h | 2 +- 4 files changed, 34 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 7f13b4891..014e8b69e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -37,6 +37,10 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +// Can be selectively disabled to reduce logging when troubleshooting other driver +#define MSC_DEBUG 2 + enum { MSC_STAGE_CMD = 0, @@ -99,7 +103,7 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 -static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = +TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, @@ -114,7 +118,7 @@ static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } }; -static tu_lookup_table_t const _msc_scsi_cmd_table = +TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table = { .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), .items = _msc_scsi_cmd_lookup @@ -232,8 +236,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + // TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; p_csw->tag = p_cbw->tag; @@ -305,8 +309,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: - TU_LOG2(" SCSI Data\r\n"); - //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); + //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); // OUT transfer, invoke callback if needed if ( !tu_bit_test(p_cbw->dir, 7) ) @@ -402,8 +406,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); - // TU_LOG2_MEM(p_csw, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Status: %u\r\n", p_csw->status); + // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); // Invoke complete callback if defined // Note: There is racing issue with samd51 + qspi flash testing with arduino diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 8490daad7..c8a66a879 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -305,11 +305,11 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) } // Log with Level -#define TU_LOG(n, ...) TU_LOG##n(__VA_ARGS__) -#define TU_LOG_MEM(n, ...) TU_LOG##n##_MEM(__VA_ARGS__) -#define TU_LOG_VAR(n, ...) TU_LOG##n##_VAR(__VA_ARGS__) -#define TU_LOG_INT(n, ...) TU_LOG##n##_INT(__VA_ARGS__) -#define TU_LOG_HEX(n, ...) TU_LOG##n##_HEX(__VA_ARGS__) +#define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__) +#define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__) +#define TU_LOG_VAR(n, ...) TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__) +#define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__) +#define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__) #define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) #define TU_LOG_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__) @@ -373,6 +373,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #endif // TODO replace all TU_LOGn with TU_LOG(n) + +#define TU_LOG0(...) +#define TU_LOG0_MEM(...) +#define TU_LOG0_VAR(...) +#define TU_LOG0_INT(...) +#define TU_LOG0_HEX(...) + + #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index f755e13f4..0dd9ba016 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -32,10 +32,14 @@ #ifndef _TUSB_COMPILER_H_ #define _TUSB_COMPILER_H_ -#define TU_STRING(x) #x ///< stringify without expand -#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify -#define TU_STRCAT(a, b) a##b ///< concat without expand -#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat +#define TU_STRING(x) #x ///< stringify without expand +#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify + +#define TU_STRCAT(a, b) a##b ///< concat without expand +#define TU_STRCAT3(a, b, c) a##b##c ///< concat without expand + +#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat +#define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ #define _TU_COUNTER_ __COUNTER__ diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index de2ae163d..18db289a1 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -120,9 +120,9 @@ bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); +uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); bool tu_fifo_full (tu_fifo_t* f); -uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); -- cgit v1.3.1 From ebd98e1a18bf1dfbbf45420310c4dee96a3bfd24 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Jul 2021 21:09:23 +0700 Subject: fix midi stream write return value (off by 1) --- src/class/midi/midi_device.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 4eac0de48..c39e03976 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -240,15 +240,15 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* midid_stream_t* stream = &midi->stream_write; - uint32_t total_written = 0; uint32_t i = 0; - while ( i < bufsize ) + while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) { uint8_t const data = buffer[i]; + i++; if ( stream->index == 0 ) { - // new event packet + //------------- New event packet -------------// uint8_t const msg = data >> 4; @@ -310,9 +310,9 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* } else { - // On-going (buffering) packet + //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, total_written); + TU_ASSERT(stream->index < 4, i); stream->buffer[stream->index] = data; stream->index++; @@ -335,19 +335,14 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* // complete current event packet, reset stream stream->index = stream->total = 0; - // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing - if ( count != 4 ) break; - - // updated written if succeeded - total_written = i; + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, i); } - - i++; } write_flush(midi); - return total_written; + return i; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -- cgit v1.3.1 From ac8d0abecf93af2498f9d5d1438c2af7b133bedc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:04:38 +0700 Subject: rename dfu API - tud_dfu_dnload_complete() -> tud_dfu_download_complete() - tud_dfu_req_dnload_data_cb() -> tud_dfu_download_cb() - tud_dfu_req_upload_data_cb() -> tud_dfu_upload_cb() --- examples/device/dfu/src/main.c | 6 +++--- examples/device/midi_test/src/main.c | 10 +++++++--- src/class/dfu/dfu_device.c | 8 ++++---- src/class/dfu/dfu_device.h | 8 ++++---- 4 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 4ec6d477c..8e7fa9ee0 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -135,7 +135,7 @@ uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) return 0; } -void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); @@ -147,7 +147,7 @@ void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, } #endif - tud_dfu_dnload_complete(); + tud_dfu_download_complete(); } bool tud_dfu_device_data_done_check_cb(uint8_t alt) @@ -167,7 +167,7 @@ void tud_dfu_abort_cb(uint8_t alt) const uint8_t upload_test[2][UPLOAD_SIZE] = {"Hello world from TinyUSB DFU! - Partition 0", "Hello world from TinyUSB DFU! - Partition 1"}; -uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) +uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) { (void) block_num; (void) length; diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 9e0e82a10..66b858323 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -134,10 +134,13 @@ void midi_task(void) uint8_t packet[4]; while ( tud_midi_available() ) tud_midi_packet_read(packet); - // send note every 1000 ms - if (board_millis() - start_ms < 286) return; // not enough time - start_ms += 286; + // send note periodically + if (board_millis() - start_ms < 1000) return; // not enough time + start_ms += 1000; +#if 1 + +#else // Previous positions in the note sequence. int previous = note_pos - 1; @@ -158,6 +161,7 @@ void midi_task(void) // If we are at the end of the sequence, start over. if (note_pos >= sizeof(note_sequence)) note_pos = 0; +#endif } //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 23669b508..c8c0bcfd4 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -283,9 +283,9 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); uint16_t retval = 0; - if (tud_dfu_req_upload_data_cb) + if (tud_dfu_upload_cb) { - tud_dfu_req_upload_data_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_dfu_upload_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; @@ -330,11 +330,11 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); + tud_dfu_download_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); _dfu_state_ctx.blk_transfer_in_proc = false; } -void tud_dfu_dnload_complete(void) +void tud_dfu_download_complete(void) { if (_dfu_state_ctx.state == DFU_DNBUSY) { diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 647fc2c04..2a1f5a8e7 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -58,11 +58,11 @@ TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data -// provided by tud_dfu_req_dnload_data_cb -void tud_dfu_dnload_complete(void); +// provided by tud_dfu_download_cb +void tud_dfu_download_complete(void); // Invoked during the last DFU_DNLOAD request, signifying that the host believes // it is done transmitting data. @@ -79,7 +79,7 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // This callback must populate data with up to length bytes // Return the number of bytes to write -TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); +TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received TU_ATTR_WEAK void tud_dfu_reboot_cb(void); -- cgit v1.3.1 From 57d9f696a2c11cf0004ea2eec1204d80c657cb03 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:24:09 +0700 Subject: clean up --- src/class/dfu/dfu_device.c | 73 ++++++++++------------------------------------ 1 file changed, 16 insertions(+), 57 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index c8c0bcfd4..dcdc34977 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct dfu_state_t state; uint8_t attrs; bool blk_transfer_in_proc; - uint8_t alt; + uint8_t alt_num; uint16_t block; uint16_t length; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; @@ -149,7 +149,7 @@ void dfu_moded_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.alt = 0; + _dfu_state_ctx.alt_num = 0; dfu_debug_print_context(); } @@ -162,7 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.alt = 0; + _dfu_state_ctx.alt_num = 0; dfu_debug_print_context(); } @@ -221,7 +221,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_INTERFACE) { // Switch Alt interface - _dfu_state_ctx.alt = request->wValue; + _dfu_state_ctx.alt_num = (uint8_t) request->wValue; // Re-initalise state machine (Necessary ?) _dfu_state_ctx.state = DFU_IDLE; @@ -244,6 +244,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if (tud_dfu_reboot_cb) tud_dfu_reboot_cb(); break; } + case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) @@ -254,7 +255,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque _dfu_state_ctx.length = request->wLength; return true; } - } // fallthrough + } + // fallthrough case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: @@ -285,7 +287,7 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re uint16_t retval = 0; if (tud_dfu_upload_cb) { - tud_dfu_upload_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_dfu_upload_cb(_dfu_state_ctx.alt_num, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; @@ -296,7 +298,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const uint32_t timeout = 0; if ( tud_dfu_get_status_cb ) { - timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt, _dfu_state_ctx.state); + timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt_num, _dfu_state_ctx.state); } dfu_status_req_payload_t resp; @@ -330,7 +332,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); + tud_dfu_download_cb(_dfu_state_ctx.alt_num,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); _dfu_state_ctx.blk_transfer_in_proc = false; } @@ -384,28 +386,20 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; case DFU_REQUEST_ABORT: - { ; // do nothing, but don't stall so continue on - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -430,16 +424,12 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -450,10 +440,8 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -472,7 +460,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt) ) + if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt_num) ) { _dfu_state_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -485,32 +473,24 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; case DFU_REQUEST_ABORT: - { if ( tud_dfu_abort_cb ) { - tud_dfu_abort_cb(_dfu_state_ctx.alt); + tud_dfu_abort_cb(_dfu_state_ctx.alt_num); } _dfu_state_ctx.state = DFU_IDLE; - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -528,7 +508,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt) ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt_num) ) { _dfu_state_ctx.state = DFU_IDLE; } @@ -538,16 +518,12 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -557,10 +533,9 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { switch (request->bRequest) { + // stall on all other requests default: - { - return false; // stall on all other requests - } + return false; break; } } @@ -573,9 +548,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { default: - { return false; // stall on all other requests - } break; } } @@ -595,31 +568,25 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; case DFU_REQUEST_ABORT: { if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(_dfu_state_ctx.alt); + tud_dfu_abort_cb(_dfu_state_ctx.alt_num); } _dfu_state_ctx.state = DFU_IDLE; } break; default: - { return false; // stall on all other requests - } break; } } @@ -630,27 +597,19 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_CLRSTATUS: - { _dfu_state_ctx.state = DFU_IDLE; - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; default: - { return false; // stall on all other requests - } break; } } -- cgit v1.3.1 From 27676f738d54c1edf87449531b3a1fd24fca59d3 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:31:20 +0700 Subject: rename tud_dfu_reboot_cb() to tud_dfu_detach_cb() --- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index dcdc34977..c807004ec 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -241,7 +241,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DETACH: { tud_control_status(rhport, request); - if (tud_dfu_reboot_cb) tud_dfu_reboot_cb(); + if (tud_dfu_detach_cb) tud_dfu_detach_cb(); break; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 2a1f5a8e7..d5d464f3b 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -82,7 +82,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_reboot_cb(void); +TU_ATTR_WEAK void tud_dfu_detach_cb(void); + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 5b965a38883efb2d7210d48be6f305c0f31ca8fc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:52:38 +0700 Subject: more rename and update --- examples/device/dfu/src/main.c | 14 +-- src/class/dfu/dfu_device.c | 231 +++++++++++++++++++++-------------------- 2 files changed, 128 insertions(+), 117 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 8e7fa9ee0..2c114c5a2 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -28,11 +28,13 @@ * * To transfer firmware from host to device: * - * $ dfu-util -D [filename] + * $ dfu-util -d cafe -a 0 -D [filename] + * $ dfu-util -d cafe -a 1 -D [filename] * * To transfer firmware from device to host: * - * $ dfu-util -U [filename] + * $ dfu-util -d cafe -a 0 -U [filename] + * $ dfu-util -d cafe -a 1 -U [filename] * */ @@ -138,12 +140,12 @@ uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; - printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + printf("Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; ibAttributes; + _dfu_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); @@ -215,67 +215,76 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - if(stage == CONTROL_STAGE_SETUP) + if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_INTERFACE) + // Standard request include GET/SET_INTERFACE + switch (request->bRequest ) { - // Switch Alt interface - _dfu_state_ctx.alt_num = (uint8_t) request->wValue; + case TUSB_REQ_SET_INTERFACE: + // Switch Alt interface and Re-initalize state machine + _dfu_ctx.alt_num = (uint8_t) request->wValue; + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; + + return tud_control_status(rhport, request); + break; - // Re-initalise state machine (Necessary ?) - _dfu_state_ctx.state = DFU_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.blk_transfer_in_proc = false; + case TUSB_REQ_GET_INTERFACE: + return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + break; - tud_control_status(rhport, request); - return true; + // unsupported request + default: return false; } } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) + else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - case DFU_REQUEST_DETACH: + // Class request + switch (request->bRequest) { - tud_control_status(rhport, request); - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); - break; - } + case DFU_REQUEST_DETACH: + { + tud_control_status(rhport, request); + if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + break; + } - case DFU_REQUEST_DNLOAD: - { - if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) + case DFU_REQUEST_DNLOAD: { - _dfu_state_ctx.block = request->wValue; - _dfu_state_ctx.length = request->wLength; - return true; + if ( (stage == CONTROL_STAGE_ACK) + && ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (_dfu_ctx.state == DFU_DNLOAD_SYNC)) + { + _dfu_ctx.block = request->wValue; + _dfu_ctx.length = request->wLength; + return true; + } } - } - // fallthrough - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - if(stage == CONTROL_STAGE_SETUP) + // fallthrough + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: { - return dfu_state_machine(rhport, request); + if(stage == CONTROL_STAGE_SETUP) + { + return dfu_state_machine(rhport, request); + } } - } - break; + break; - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return false; // stall unsupported request + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return false; // stall unsupported request + } + break; } - break; + }else + { + return false; // unsupported request } return true; @@ -287,9 +296,9 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re uint16_t retval = 0; if (tud_dfu_upload_cb) { - tud_dfu_upload_cb(_dfu_state_ctx.alt_num, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_dfu_upload_cb(_dfu_ctx.alt_num, block_num, (uint8_t *)_dfu_ctx.transfer_buf, wLength); } - tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); + tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, retval); return retval; } @@ -298,15 +307,15 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const uint32_t timeout = 0; if ( tud_dfu_get_status_cb ) { - timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt_num, _dfu_state_ctx.state); + timeout = tud_dfu_get_status_cb(_dfu_ctx.alt_num, _dfu_ctx.state); } dfu_status_req_payload_t resp; - resp.bStatus = _dfu_state_ctx.status; + resp.bStatus = _dfu_ctx.status; resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = _dfu_state_ctx.state; + resp.bState = _dfu_ctx.state; resp.iString = 0; tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); @@ -314,7 +323,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) { - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); } static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) @@ -325,25 +334,25 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); // setup for data phase - tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); + tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); } static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_state_ctx.alt_num,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); - _dfu_state_ctx.blk_transfer_in_proc = false; + tud_dfu_download_cb(_dfu_ctx.alt_num,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); + _dfu_ctx.blk_transfer_in_proc = false; } void tud_dfu_download_complete(void) { - if (_dfu_state_ctx.state == DFU_DNBUSY) + if (_dfu_ctx.state == DFU_DNBUSY) { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) + _dfu_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_ctx.state = ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -351,9 +360,9 @@ void tud_dfu_download_complete(void) static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) { TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state)); - switch (_dfu_state_ctx.state) + switch (_dfu_ctx.state) { case DFU_IDLE: { @@ -361,26 +370,26 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; + _dfu_ctx.state = DFU_DNLOAD_SYNC; + _dfu_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; } } break; case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + _dfu_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); } else { - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; } } break; @@ -398,7 +407,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -411,13 +420,13 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ( _dfu_state_ctx.blk_transfer_in_proc ) + if ( _dfu_ctx.blk_transfer_in_proc ) { - _dfu_state_ctx.state = DFU_DNBUSY; + _dfu_ctx.state = DFU_DNBUSY; dfu_req_getstatus_reply(rhport, request); dfu_req_dnload_reply(rhport, request); } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + _dfu_ctx.state = DFU_DNLOAD_IDLE; dfu_req_getstatus_reply(rhport, request); } } @@ -428,7 +437,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -440,7 +449,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -453,19 +462,19 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; + _dfu_ctx.state = DFU_DNLOAD_SYNC; + _dfu_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt_num) ) + if ( tud_dfu_device_data_done_check_cb(_dfu_ctx.alt_num) ) { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + _dfu_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); } else { - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall } } @@ -483,13 +492,13 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_ABORT: if ( tud_dfu_abort_cb ) { - tud_dfu_abort_cb(_dfu_state_ctx.alt_num); + tud_dfu_abort_cb(_dfu_ctx.alt_num); } - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -502,15 +511,15 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { - _dfu_state_ctx.state = DFU_MANIFEST; + _dfu_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt_num) ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_ctx.alt_num) ) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; } dfu_req_getstatus_reply(rhport, request); } @@ -522,7 +531,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -562,7 +571,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; } } break; @@ -579,9 +588,9 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(_dfu_state_ctx.alt_num); + tud_dfu_abort_cb(_dfu_ctx.alt_num); } - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; } break; @@ -601,7 +610,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_CLRSTATUS: - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; break; case DFU_REQUEST_GETSTATE: @@ -616,7 +625,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); return false; // Unexpected state, stall and change to error } -- cgit v1.3.1 From 95ded08e3b96b77bbbb1e11e7f0043fb86b7316f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 16:42:12 +0700 Subject: simplify upload request --- src/class/dfu/dfu.h | 8 ++--- src/class/dfu/dfu_device.c | 88 ++++++++++++++++++++-------------------------- src/common/tusb_types.h | 2 +- 3 files changed, 43 insertions(+), 55 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 18de3bf99..88f2f3529 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -95,10 +95,10 @@ typedef enum { DFU_STATUS_ERRSTALLEDPKT = 0x0F, } dfu_device_status_t; -#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) -#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) -#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) -#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) +#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1u << 0) +#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1u << 1) +#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1u << 2) +#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1u << 3) // DFU Status Request Payload typedef struct TU_ATTR_PACKED diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 7b2f920d2..376feb053 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -58,7 +58,6 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); @@ -218,37 +217,60 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { // Standard request include GET/SET_INTERFACE - switch (request->bRequest ) + switch ( request->bRequest ) { case TUSB_REQ_SET_INTERFACE: - // Switch Alt interface and Re-initalize state machine - _dfu_ctx.alt_num = (uint8_t) request->wValue; - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.blk_transfer_in_proc = false; + if ( stage == CONTROL_STAGE_SETUP ) + { + // Switch Alt interface and Re-initalize state machine + _dfu_ctx.alt_num = (uint8_t) request->wValue; + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; - return tud_control_status(rhport, request); + return tud_control_status(rhport, request); + } break; case TUSB_REQ_GET_INTERFACE: - return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + if(stage == CONTROL_STAGE_SETUP) + { + return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + } break; // unsupported request default: return false; } } - else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) { // Class request - switch (request->bRequest) + switch ( request->bRequest ) { case DFU_REQUEST_DETACH: - { - tud_control_status(rhport, request); - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); - break; - } + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + } + break; + + case DFU_REQUEST_UPLOAD: + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK); + TU_VERIFY(tud_dfu_upload_cb); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + + uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt_num, request->wValue, _dfu_ctx.transfer_buf, request->wLength); + + tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); + } + break; case DFU_REQUEST_DNLOAD: { @@ -262,7 +284,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } } // fallthrough - case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: case DFU_REQUEST_GETSTATE: @@ -290,18 +311,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - uint16_t retval = 0; - if (tud_dfu_upload_cb) - { - tud_dfu_upload_cb(_dfu_ctx.alt_num, block_num, (uint8_t *)_dfu_ctx.transfer_buf, wLength); - } - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, retval); - return retval; -} - static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) { uint32_t timeout = 0; @@ -382,18 +391,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req } break; - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_ctx.state = DFU_ERROR; - } - } - break; - case DFU_REQUEST_GETSTATUS: dfu_req_getstatus_reply(rhport, request); break; @@ -567,15 +564,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { switch (request->bRequest) { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_ctx.state = DFU_IDLE; - } - } - break; - case DFU_REQUEST_GETSTATUS: dfu_req_getstatus_reply(rhport, request); break; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec58a3181..fc1035e2c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -449,7 +449,7 @@ typedef struct TU_ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED{ +typedef struct TU_ATTR_PACKED TU_ATTR_ALIGNED(4) { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. -- cgit v1.3.1 From 6a68fc699724fb216b745dbf48fdae32305f1d35 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 16:51:28 +0700 Subject: update dfu abort --- src/class/dfu/dfu_device.c | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 376feb053..ed36178f1 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -259,6 +259,19 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } break; + case DFU_REQUEST_ABORT: + if ( stage == CONTROL_STAGE_SETUP ) + { + if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); + + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; + + tud_control_status(rhport, request); + } + break; + case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { @@ -287,7 +300,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: { if(stage == CONTROL_STAGE_SETUP) { @@ -297,10 +309,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque break; default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); return false; // stall unsupported request - } break; } }else @@ -399,10 +408,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstate_reply(rhport, request); break; - case DFU_REQUEST_ABORT: - ; // do nothing, but don't stall so continue on - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -486,14 +491,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstate_reply(rhport, request); break; - case DFU_REQUEST_ABORT: - if ( tud_dfu_abort_cb ) - { - tud_dfu_abort_cb(_dfu_ctx.alt_num); - } - _dfu_ctx.state = DFU_IDLE; - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -572,16 +569,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstate_reply(rhport, request); break; - case DFU_REQUEST_ABORT: - { - if (tud_dfu_abort_cb) - { - tud_dfu_abort_cb(_dfu_ctx.alt_num); - } - _dfu_ctx.state = DFU_IDLE; - } - break; - default: return false; // stall on all other requests break; -- cgit v1.3.1 From b4fde90b5518c4e92750af2e27eae598267ad8cf Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 17:03:20 +0700 Subject: update clear status and get state --- src/class/dfu/dfu_device.c | 66 +++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ed36178f1..686d9b023 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -61,6 +61,13 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t c static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); +static void reset_state(void) +{ + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -224,10 +231,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { // Switch Alt interface and Re-initalize state machine _dfu_ctx.alt_num = (uint8_t) request->wValue; - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.blk_transfer_in_proc = false; - + reset_state(); return tud_control_status(rhport, request); } break; @@ -264,14 +268,26 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.blk_transfer_in_proc = false; + reset_state(); + tud_control_status(rhport, request); + } + break; + case DFU_REQUEST_CLRSTATUS: + if ( stage == CONTROL_STAGE_SETUP ) + { + reset_state(); tud_control_status(rhport, request); } break; + case DFU_REQUEST_GETSTATE: + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); + } + break; + case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { @@ -298,8 +314,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } // fallthrough case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: + { if(stage == CONTROL_STAGE_SETUP) { @@ -339,11 +354,6 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); -} - static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { // TODO: add "zero" copy mode so the buffer we read into can be provided by the user @@ -404,10 +414,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -434,10 +440,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req } break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -487,10 +489,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -520,10 +518,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req } break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -565,10 +559,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: return false; // stall on all other requests break; @@ -584,14 +574,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_CLRSTATUS: - _dfu_ctx.state = DFU_IDLE; - break; - - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: return false; // stall on all other requests break; -- cgit v1.3.1 From daca9e520bce0b4eb5882c5692986ec5c513f319 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jul 2021 20:47:50 +0700 Subject: wrap up DFU update --- examples/device/dfu/src/main.c | 95 +++++--- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 4 +- src/class/dfu/dfu.h | 47 ++-- src/class/dfu/dfu_device.c | 393 +++++++++++++++++++----------- src/class/dfu/dfu_device.h | 68 +++--- src/class/dfu/dfu_rt_device.c | 6 +- src/common/tusb_types.h | 2 +- src/device/usbd.c | 2 +- src/tusb_option.h | 4 - 10 files changed, 368 insertions(+), 255 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 2c114c5a2..1621a330b 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -26,7 +26,7 @@ /* * After device is enumerated in dfu mode run the following commands * - * To transfer firmware from host to device: + * To transfer firmware from host to device (best to test with text file) * * $ dfu-util -d cafe -a 0 -D [filename] * $ dfu-util -d cafe -a 1 -D [filename] @@ -45,22 +45,21 @@ #include "bsp/board.h" #include "tusb.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#ifndef DFU_VERBOSE -#define DFU_VERBOSE 0 -#endif +const char* upload_image[2]= +{ + "Hello world from TinyUSB DFU! - Partition 0", + "Hello world from TinyUSB DFU! - Partition 1" +}; /* Blink pattern - * - 1000 ms : device should reboot * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ enum { - BLINK_DFU_MODE = 100, BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -118,65 +117,87 @@ void tud_resume_cb(void) } //--------------------------------------------------------------------+ -// Class callbacks +// DFU callbacks +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(uint8_t alt) -{ - (void) alt; - printf(" Firmware check\r\n"); - return true; -} -uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) { - // For example Alt1 (EEPROM) is slow, add 2000ms timeout if ( state == DFU_DNBUSY ) { - if (alt == 1) return 2000; + // For this example + // - Atl0 Flash is fast : 1 ms + // - Alt1 EEPROM is slow: 100 ms + return (alt == 0) ? 1 : 100; } + else if (state == DFU_MANIFEST) + { + // since we don't buffer entire image and do any flashing in manifest stage + return 0; + } + return 0; } -void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t const* data, uint16_t length) { (void) data; - printf("Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); -#if DFU_VERBOSE for(uint16_t i=0; ibAttributes; - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR + // CFG_TUD_DFU_TRANSFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFSIZE, drv_len); return drv_len; } @@ -216,11 +201,10 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - // nothing to do with DATA stage - if ( stage == CONTROL_STAGE_DATA ) return true; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); + if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { // Standard request include GET/SET_INTERFACE @@ -229,8 +213,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case TUSB_REQ_SET_INTERFACE: if ( stage == CONTROL_STAGE_SETUP ) { - // Switch Alt interface and Re-initalize state machine - _dfu_ctx.alt_num = (uint8_t) request->wValue; + // Switch Alt interface and reset state machine + _dfu_ctx.alt = (uint8_t) request->wValue; reset_state(); return tud_control_status(rhport, request); } @@ -239,7 +223,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case TUSB_REQ_GET_INTERFACE: if(stage == CONTROL_STAGE_SETUP) { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); } break; @@ -249,6 +233,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) { + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + // Class request switch ( request->bRequest ) { @@ -259,73 +245,97 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } else if ( stage == CONTROL_STAGE_ACK ) { - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); } break; - case DFU_REQUEST_ABORT: + case DFU_REQUEST_CLRSTATUS: if ( stage == CONTROL_STAGE_SETUP ) { - if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); - reset_state(); tud_control_status(rhport, request); } break; - case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: if ( stage == CONTROL_STAGE_SETUP ) { - reset_state(); - tud_control_status(rhport, request); + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); } break; - case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: if ( stage == CONTROL_STAGE_SETUP ) { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); + reset_state(); + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); } break; case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { - TU_VERIFY(_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK); + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt_num, request->wValue, _dfu_ctx.transfer_buf, request->wLength); + uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); } break; case DFU_REQUEST_DNLOAD: - { - if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (_dfu_ctx.state == DFU_DNLOAD_SYNC)) + if ( stage == CONTROL_STAGE_SETUP ) { - _dfu_ctx.block = request->wValue; + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); + TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + + // set to true for both download and manifest + _dfu_ctx.flashing_in_progress = true; + + // save block and length for flashing + _dfu_ctx.block = request->wValue; _dfu_ctx.length = request->wLength; - return true; + + if ( request->wLength ) + { + // Download with payload -> transition to DOWNLOAD SYNC + _dfu_ctx.state = DFU_DNLOAD_SYNC; + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); + } + else + { + // Download is complete -> transition to MANIFEST SYNC + _dfu_ctx.state = DFU_MANIFEST_SYNC; + return tud_control_status(rhport, request); + } } - } - // fallthrough - case DFU_REQUEST_GETSTATUS: + break; - { - if(stage == CONTROL_STAGE_SETUP) + case DFU_REQUEST_GETSTATUS: + switch ( _dfu_ctx.state ) { - return dfu_state_machine(rhport, request); + case DFU_DNLOAD_SYNC: + return process_download_get_status(rhport, stage, request); + break; + + case DFU_MANIFEST_SYNC: + return process_manifest_get_status(rhport, stage, request); + break; + + default: + if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); + break; } - } break; - default: - return false; // stall unsupported request - break; + default: return false; // stall unsupported request } }else { @@ -335,32 +345,130 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +void tud_dfu_finish_flashing(uint8_t status) +{ + _dfu_ctx.flashing_in_progress = false; + + if ( status == DFU_STATUS_OK ) + { + if (_dfu_ctx.state == DFU_DNBUSY) + { + _dfu_ctx.state = DFU_DNLOAD_SYNC; + } + else if (_dfu_ctx.state == DFU_MANIFEST) + { + _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) + ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; + } + } + else + { + // failed while flashing, move to dfuError + _dfu_ctx.state = DFU_ERROR; + _dfu_ctx.status = status; + } +} + +static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_DNBUSY; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); + } + else + { + next_state = DFU_DNLOAD_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_DNBUSY; + tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); + }else + { + _dfu_ctx.state = DFU_DNLOAD_IDLE; + } + } + + return true; +} + +static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - uint32_t timeout = 0; - if ( tud_dfu_get_status_cb ) + if ( stage == CONTROL_STAGE_SETUP ) { - timeout = tud_dfu_get_status_cb(_dfu_ctx.alt_num, _dfu_ctx.state); + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_MANIFEST; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); + } + else + { + next_state = DFU_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_MANIFEST; + tud_dfu_manifest_cb(_dfu_ctx.alt); + } + else + { + _dfu_ctx.state = DFU_IDLE; + } } - dfu_status_req_payload_t resp; - resp.bStatus = _dfu_ctx.status; + return true; +} + +static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) +{ + dfu_status_response_t resp; + resp.bStatus = (uint8_t) status; resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = _dfu_ctx.state; - resp.iString = 0; + resp.bState = (uint8_t) state; + resp.iString = 0; - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); + return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } + +#if 0 + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); // setup for data phase tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); } @@ -368,21 +476,9 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_ctx.alt_num,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); - _dfu_ctx.blk_transfer_in_proc = false; -} - -void tud_dfu_download_complete(void) -{ - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); + tud_dfu_download_cb(_dfu_ctx.alt,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); + _dfu_ctx.flashing_in_progress = false; } static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) @@ -398,11 +494,11 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) && (request->wLength > 0) ) { _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.blk_transfer_in_proc = true; + _dfu_ctx.flashing_in_progress = true; dfu_req_dnload_setup(rhport, request); } else { _dfu_ctx.state = DFU_ERROR; @@ -411,7 +507,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -428,14 +524,14 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ( _dfu_ctx.blk_transfer_in_proc ) + if ( _dfu_ctx.flashing_in_progress ) { _dfu_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); dfu_req_dnload_reply(rhport, request); } else { _dfu_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } } break; @@ -466,14 +562,14 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) && (request->wLength > 0) ) { _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.blk_transfer_in_proc = true; + _dfu_ctx.flashing_in_progress = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_ctx.alt_num) ) + if ( tud_dfu_download_complete_cb(_dfu_ctx.alt) ) { _dfu_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -486,7 +582,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -503,17 +599,17 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) == 0) { _dfu_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_ctx.alt_num) ) + if ( tud_dfu_manifest_cb(_dfu_ctx.alt) ) { _dfu_ctx.state = DFU_IDLE; } - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } } break; @@ -556,7 +652,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -571,7 +667,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -590,5 +686,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req return true; } +#endif #endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d5d464f3b..2d398aada 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,53 +37,51 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" +#if !defined(CFG_TUD_DFU_TRANSFER_BUFSIZE) + #error "CFG_TUD_DFU_TRANSFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Must be called when the application is done with flashing started by +// tud_dfu_download_cb() and tud_dfu_manifest_cb(). +// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError +void tud_dfu_finish_flashing(uint8_t status); + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware is valid -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -bool tud_dfu_firmware_valid_check_cb(uint8_t alt); - -// Invoked when a DFU_GETSTATUS request is received -// Return the bwPollTimeout value for host's response, useful for slow Flash in order to make host wait longer -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); - -// Invoked when a DFU_DNLOAD request is received -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Must be called when the application is done using the last block of data -// provided by tud_dfu_download_cb -void tud_dfu_download_complete(void); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(uint8_t alt); -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// Invoked when a DFU_UPLOAD request is received -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// This callback must populate data with up to length bytes -// Return the number of bytes to write +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); + +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); + +// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) +// Application can do checksum, or actual flashing if buffered entire image previously. +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_manifest_cb(uint8_t alt); + +// Invoked when received DFU_UPLOAD request +// Application must populate data with up to length bytes and +// Return the number of written bytes TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received TU_ATTR_WEAK void tud_dfu_detach_cb(void); +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 07e6f30f3..afee2aa1f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -108,10 +108,10 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request case DFU_REQUEST_GETSTATUS: { TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_req_payload_t resp; + dfu_status_response_t resp; // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); + memset(&resp, 0x00, sizeof(dfu_status_response_t)); + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } break; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fc1035e2c..eab67ebd5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -449,7 +449,7 @@ typedef struct TU_ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED TU_ATTR_ALIGNED(4) { +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. diff --git a/src/device/usbd.c b/src/device/usbd.c index af4fd58c4..cf9af783d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,7 +190,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_MODE { - DRIVER_NAME("DFU-MODE") + DRIVER_NAME("DFU") .init = dfu_moded_init, .reset = dfu_moded_reset, .open = dfu_moded_open, diff --git a/src/tusb_option.h b/src/tusb_option.h index bf7591dcf..4351d9486 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -253,10 +253,6 @@ #define CFG_TUD_DFU_MODE 0 #endif -#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE - #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 -#endif - #ifndef CFG_TUD_NET #define CFG_TUD_NET 0 #endif -- cgit v1.3.1 From 3960beece0ea3dccf7ca615bd7841daa6b703d56 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jul 2021 20:52:58 +0700 Subject: rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU --- examples/device/dfu/src/main.c | 2 +- examples/device/dfu/src/tusb_config.h | 4 +--- src/class/dfu/dfu_device.c | 2 +- src/device/usbd.c | 2 +- src/tusb.h | 2 +- src/tusb_option.h | 4 ++-- 6 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src/class') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1621a330b..7133d1624 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -148,7 +148,7 @@ uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t const* data, uint16_t length) { (void) data; - printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + //printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); for(uint16_t i=0; i Date: Thu, 22 Jul 2021 01:00:06 +0700 Subject: rename CFG_TUD_DFU_TRANSFER_BUFSIZE to CFG_TUD_DFU_XFER_BUFSIZE --- examples/device/dfu/.skip.MCU_SAMD11 | 0 examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 2 +- src/class/dfu/dfu_device.c | 243 +----------------------------- src/class/dfu/dfu_device.h | 4 +- 5 files changed, 9 insertions(+), 242 deletions(-) delete mode 100644 examples/device/dfu/.skip.MCU_SAMD11 (limited to 'src/class') diff --git a/examples/device/dfu/.skip.MCU_SAMD11 b/examples/device/dfu/.skip.MCU_SAMD11 deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 2e3b89f49..66e357021 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -80,7 +80,7 @@ #define CFG_TUD_DFU 1 // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR -#define CFG_TUD_DFU_TRANSFER_BUFSIZE 512 +#define CFG_TUD_DFU_XFER_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index a15bb6136..1cfe29c53 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -100,7 +100,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size - TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFSIZE), + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 222795bec..ad87092e0 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -52,7 +52,7 @@ typedef struct uint16_t block; uint16_t length; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; } dfu_state_ctx_t; // Only a single dfu state is allowed @@ -189,9 +189,9 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_ctx.attrs = func_desc->bAttributes; - // CFG_TUD_DFU_TRANSFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR + // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFSIZE, drv_len); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); return drv_len; } @@ -281,7 +281,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); @@ -294,7 +294,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); // set to true for both download and manifest _dfu_ctx.flashing_in_progress = true; @@ -455,237 +455,4 @@ static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * reque return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } - -#if 0 - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); - // setup for data phase - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); -} - -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); - tud_dfu_download_cb(_dfu_ctx.alt,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); - _dfu_ctx.flashing_in_progress = false; -} - -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state)); - - switch (_dfu_ctx.state) - { - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) - && (request->wLength > 0) ) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.flashing_in_progress = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_DNLOAD_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_DNBUSY; - reply_getstatus(rhport, request); - dfu_req_dnload_reply(rhport, request); - } else { - _dfu_ctx.state = DFU_DNLOAD_IDLE; - reply_getstatus(rhport, request); - } - } - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) - && (request->wLength > 0) ) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.flashing_in_progress = true; - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_download_complete_cb(_dfu_ctx.alt) ) - { - _dfu_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) == 0) - { - _dfu_ctx.state = DFU_MANIFEST; - reply_getstatus(rhport, request); - } else - { - if ( tud_dfu_manifest_cb(_dfu_ctx.alt) ) - { - _dfu_ctx.state = DFU_IDLE; - } - reply_getstatus(rhport, request); - } - } - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_MANIFEST: - { - switch (request->bRequest) - { - // stall on all other requests - default: - return false; - break; - } - } - break; - - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - return false; // stall on all other requests - break; - } - } - break; - - case DFU_UPLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - return false; // stall on all other requests - break; - } - } - break; - - case DFU_ERROR: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - return false; // stall on all other requests - break; - } - } - break; - - default: - _dfu_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error - } - - return true; -} - -#endif - #endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 2d398aada..fecf8596f 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,8 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#if !defined(CFG_TUD_DFU_TRANSFER_BUFSIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" +#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) + #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 4e50ceba48c15206543fe662f098a98152ef4235 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:07:39 +0700 Subject: rename packed begin/end --- src/class/cdc/cdc.h | 20 ++++++++++---------- src/common/tusb_compiler.h | 8 ++++---- src/common/tusb_types.h | 4 ++-- src/portable/renesas/usba/dcd_usba.c | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f59690835..7a06711be 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,7 +215,7 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// Header Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -236,10 +236,10 @@ typedef struct TU_ATTR_PACKED uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_union_n_t(no_slave)\ - TU_PACK_STRUCT_BEGIN \ + TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -247,10 +247,10 @@ TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX too uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ } \ -TU_PACK_STRUCT_END +TU_ATTR_PACKED_END -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// Country Selection Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -262,10 +262,10 @@ typedef struct TU_ATTR_PACKED uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_country_selection_n_t(no_country) \ - TU_PACK_STRUCT_BEGIN \ + TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -273,13 +273,13 @@ TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX too uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ } \ -TU_PACK_STRUCT_END +TU_ATTR_PACKED_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. @@ -419,7 +419,7 @@ typedef struct TU_ATTR_PACKED } cdc_line_control_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 6fdd08032..1f3128e0e 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -79,8 +79,8 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used - #define TU_PACK_STRUCT_BEGIN - #define TU_PACK_STRUCT_END + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END #define TU_BIT_FIELD_ORDER_BEGIN #define TU_BIT_FIELD_ORDER_END @@ -150,8 +150,8 @@ #define TU_ATTR_UNUSED #define TU_ATTR_USED - #define TU_PACK_STRUCT_BEGIN _Pragma("pack") - #define TU_PACK_STRUCT_END _Pragma("packoption") + #define TU_ATTR_PACKED_BEGIN _Pragma("pack") + #define TU_ATTR_PACKED_END _Pragma("packoption") #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index f34eb3075..34395365e 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,7 +262,7 @@ enum // USB Descriptors //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// USB Device Descriptor typedef struct TU_ATTR_PACKED @@ -479,7 +479,7 @@ typedef struct TU_ATTR_PACKED{ } tusb_control_request_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 67b92dc89..0c206fdd0 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -120,7 +120,7 @@ typedef union { } hw_fifo_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED @@ -135,7 +135,7 @@ typedef struct TU_ATTR_PACKED } pipe_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) typedef struct { -- cgit v1.3.1 From c4da1abb1eaa7aff432535878ada519d02382419 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:24:59 +0700 Subject: rename bit filed order clean up packed/bit order begin end --- src/class/cdc/cdc.h | 41 +++++++----------------------------- src/common/tusb_compiler.h | 8 +++---- src/common/tusb_types.h | 24 +++++++++------------ src/portable/renesas/usba/dcd_usba.c | 12 +++++------ 4 files changed, 28 insertions(+), 57 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 7a06711be..6042cefe3 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,7 +215,9 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +// Start of all packed definitions for compiler without per-type packed +TU_ATTR_PACKED_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN /// Header Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -236,10 +238,7 @@ typedef struct TU_ATTR_PACKED uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) - #define cdc_desc_func_union_n_t(no_slave)\ - TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -247,10 +246,6 @@ TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX too uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ } \ -TU_ATTR_PACKED_END - - -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// Country Selection Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -262,10 +257,7 @@ typedef struct TU_ATTR_PACKED uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) - #define cdc_desc_func_country_selection_n_t(no_country) \ - TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -273,17 +265,13 @@ TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX too uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ } \ -TU_ATTR_PACKED_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) - /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -298,10 +286,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDataInterface; }cdc_desc_func_call_management_t; -TU_BIT_FIELD_ORDER_END - -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. @@ -310,12 +295,11 @@ typedef struct TU_ATTR_PACKED uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; -TU_BIT_FIELD_ORDER_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); -/// \brief Abstract Control Management Functional Descriptor -/// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +/// Abstract Control Management Functional Descriptor +/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -326,7 +310,6 @@ typedef struct TU_ATTR_PACKED /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -339,7 +322,6 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_direct_line_management_t; -TU_BIT_FIELD_ORDER_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, @@ -356,7 +338,6 @@ typedef struct TU_ATTR_PACKED /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -369,12 +350,10 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_telephone_operational_modes_t; -TU_BIT_FIELD_ORDER_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -390,8 +369,8 @@ typedef struct TU_ATTR_PACKED uint32_t TU_RESERVED : 26; } bmCapabilities; }cdc_desc_func_telephone_call_state_reporting_capabilities_t; -TU_BIT_FIELD_ORDER_END +// TODO remove static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { return p_desc[2]; @@ -410,21 +389,17 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. uint16_t half_duplex_carrier_control : 1; uint16_t : 14; } cdc_line_control_state_t; -TU_BIT_FIELD_ORDER_END - -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) - TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); -/** @} */ +TU_ATTR_PACKED_END // End of all packed definitions +TU_ATTR_BIT_FIELD_ORDER_END #ifdef __cplusplus } diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 1f3128e0e..820782d65 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -82,8 +82,8 @@ #define TU_ATTR_PACKED_BEGIN #define TU_ATTR_PACKED_END - #define TU_BIT_FIELD_ORDER_BEGIN - #define TU_BIT_FIELD_ORDER_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ @@ -153,8 +153,8 @@ #define TU_ATTR_PACKED_BEGIN _Pragma("pack") #define TU_ATTR_PACKED_END _Pragma("packoption") - #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") - #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") + #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") // Endian conversion use well-known host to network (big endian) naming #if defined(__LIT) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 34395365e..d23c6b2dd 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,7 +262,9 @@ enum // USB Descriptors //--------------------------------------------------------------------+ -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +// Start of all packed definitions for compiler without per-type packed +TU_ATTR_PACKED_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN /// USB Device Descriptor typedef struct TU_ATTR_PACKED @@ -297,6 +299,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); + /// USB Configuration Descriptor typedef struct TU_ATTR_PACKED { @@ -328,8 +332,9 @@ typedef struct TU_ATTR_PACKED uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); + /// USB Endpoint Descriptor -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -357,7 +362,6 @@ typedef struct TU_ATTR_PACKED uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; -TU_BIT_FIELD_ORDER_END /// USB Other Speed Configuration Descriptor typedef struct TU_ATTR_PACKED @@ -433,7 +437,6 @@ typedef struct TU_ATTR_PACKED } tusb_desc_webusb_url_t; // DFU Functional Descriptor -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -455,12 +458,10 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -TU_BIT_FIELD_ORDER_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED{ union { struct TU_ATTR_PACKED { @@ -477,17 +478,12 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; -TU_BIT_FIELD_ORDER_END - -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); -// TODO move to somewhere suitable -static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) -{ - return ((uint8_t) (direction << 7)) | ((uint8_t) (type << 5)) | (recipient); -} + +TU_ATTR_PACKED_END // End of all packed definitions +TU_ATTR_BIT_FIELD_ORDER_END //--------------------------------------------------------------------+ // Endpoint helper diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0c206fdd0..f68f97458 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -95,7 +95,7 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) -TU_BIT_FIELD_ORDER_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef struct { union { struct { @@ -108,9 +108,9 @@ typedef struct { }; uint16_t TRN; } reg_pipetre_t; -TU_BIT_FIELD_ORDER_END +TU_ATTR_BIT_FIELD_ORDER_END -TU_BIT_FIELD_ORDER_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef union { struct { volatile uint16_t u8: 8; @@ -118,11 +118,11 @@ typedef union { }; volatile uint16_t u16; } hw_fifo_t; -TU_BIT_FIELD_ORDER_END +TU_ATTR_BIT_FIELD_ORDER_END TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) -TU_BIT_FIELD_ORDER_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ @@ -133,7 +133,7 @@ typedef struct TU_ATTR_PACKED uint32_t : 0; }; } pipe_state_t; -TU_BIT_FIELD_ORDER_END +TU_ATTR_BIT_FIELD_ORDER_END TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) -- cgit v1.3.1 From 15112fdbba8cf4e9ad0d99fafd8b40f07f29fb6d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 22:10:48 +0700 Subject: clean up compiler --- src/class/cdc/cdc.h | 4 ++-- src/common/tusb_compiler.h | 18 +++++++++++++----- src/portable/renesas/usba/dcd_usba.c | 20 ++++---------------- 3 files changed, 19 insertions(+), 23 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 6042cefe3..5df47f70b 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -245,7 +245,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ;\ uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ -} \ +} /// Country Selection Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -264,7 +264,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ;\ uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ -} \ +} //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 820782d65..d3adbbc2d 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -81,7 +81,6 @@ #define TU_ATTR_PACKED_BEGIN #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN #define TU_ATTR_BIT_FIELD_ORDER_END @@ -109,6 +108,11 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) #define TU_BYTE_ORDER TU_LITTLE_ENDIAN @@ -130,6 +134,11 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN @@ -150,11 +159,10 @@ #define TU_ATTR_UNUSED #define TU_ATTR_USED - #define TU_ATTR_PACKED_BEGIN _Pragma("pack") - #define TU_ATTR_PACKED_END _Pragma("packoption") - + #define TU_ATTR_PACKED_BEGIN _Pragma("pack") + #define TU_ATTR_PACKED_END _Pragma("packoption") #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") - #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") + #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") // Endian conversion use well-known host to network (big endian) naming #if defined(__LIT) diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0b78a6e46..c7eb6e15e 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -334,11 +334,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe_state_t *pipe = &_dcd.pipe[0]; /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ -#if TU_BYTE_ORDER == TU_BIG_ENDIAN - USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; -#else - USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; -#endif + USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; } else { /* OUT, a byte */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; @@ -413,11 +409,7 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, USB0.PIPESEL.WORD = num; const unsigned mps = USB0.PIPEMAXP.WORD; if (dir) { /* IN */ -#if TU_BYTE_ORDER == TU_BIG_ENDIAN - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; -#else - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; -#endif + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; @@ -442,11 +434,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; if (tu_edpt_dir(pipe->ep)) { /* IN */ -#if TU_BYTE_ORDER == TU_BIG_ENDIAN - select_pipe(num, USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND); -#else - select_pipe(num, USB_FIFOSEL_MBW_16); -#endif + select_pipe(num, USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0)); const unsigned mps = USB0.PIPEMAXP.WORD; unsigned rem = pipe->remaining; rem -= TU_MIN(rem, mps); @@ -527,7 +515,7 @@ static void process_set_address(uint8_t rhport) #else .bmRequestType = 0, #endif - .bRequest = 5, + .bRequest = TUSB_REQ_SET_ADDRESS, .wValue = addr, .wIndex = 0, .wLength = 0, -- cgit v1.3.1 From 0ba4315ae559f595c0d01ab650ea924d8e9bec69 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 27 Jul 2021 18:08:52 +0200 Subject: Fix IAR warning --- src/class/dfu/dfu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ad87092e0..28abf6e83 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -190,7 +190,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); + uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); return drv_len; @@ -365,7 +365,7 @@ void tud_dfu_finish_flashing(uint8_t status) { // failed while flashing, move to dfuError _dfu_ctx.state = DFU_ERROR; - _dfu_ctx.status = status; + _dfu_ctx.status = (dfu_status_t)status; } } -- cgit v1.3.1 From 6b9f8e454eaf5ac3a9474d0a09f019e700532093 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Fri, 4 Jun 2021 01:22:57 +0900 Subject: add a condition regarding OPT_MCU_RX63N --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 404d28817..86a00ea73 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -86,7 +86,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_RX63X #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From 3c3563288d643fc70ccff80c02a72d330cd65678 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Tue, 29 Jun 2021 20:41:16 +0900 Subject: add RX65N --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 86a00ea73..092e5e125 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -87,7 +87,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_RX63X + CFG_TUSB_MCU == OPT_MCU_RX63X || \ + CFG_TUSB_MCU == OPT_MCU_RX65X #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From ff20e4d6bcffc5d66666050c57719031fa2820e8 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Thu, 29 Jul 2021 20:45:51 +0900 Subject: add the entry for RX72N --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 092e5e125..de0bddcd3 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -88,7 +88,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X + CFG_TUSB_MCU == OPT_MCU_RX65X || \ + CFG_TUSB_MCU == OPT_MCU_RX72N #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From 98e4ba6a12f8ce2b060635dc01f68676b047ce25 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Aug 2021 18:55:12 +0700 Subject: correct midi available with already stream read --- src/class/midi/midi_device.c | 7 ++++++- src/common/tusb_fifo.c | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index c39e03976..9d9619132 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -122,7 +122,12 @@ static void _prep_out_transaction (midid_interface_t* p_midi) uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { (void) cable_num; - return tu_fifo_count(&_midid_itf[itf].rx_ff); + + midid_interface_t const* midi = &_midid_itf[itf]; + midid_stream_t const* stream = &midi->stream_read; + + // when using with packet API stream total & index are both zero + return tu_fifo_count(&midi->rx_ff) + (stream->total - stream->index); } uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 73217cf75..11b8fc5f3 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -323,8 +323,6 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index - - // TODO warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow] if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx)) { p = (p + offset) + f->non_used_index_space; -- cgit v1.3.1 From 794bbd7177dd5f3cab35eadf9a9268eddf61736f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Aug 2021 18:58:27 +0700 Subject: fix warning --- src/class/midi/midi_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 9d9619132..eb85b668c 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -123,7 +123,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { (void) cable_num; - midid_interface_t const* midi = &_midid_itf[itf]; + midid_interface_t* midi = &_midid_itf[itf]; midid_stream_t const* stream = &midi->stream_read; // when using with packet API stream total & index are both zero -- cgit v1.3.1 From 8b78067cc1142c5915ad5fa1275996e92f91a58d Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 7 Aug 2021 12:06:54 +0200 Subject: Use linear buffer for GD32VF103 As the peripheral is the same as on the STM32F1 and STM32F4 lines we do the same. --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index de0bddcd3..ff4e312a7 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -89,7 +89,8 @@ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ - CFG_TUSB_MCU == OPT_MCU_RX72N + CFG_TUSB_MCU == OPT_MCU_RX72N || \ + CFG_TUSB_MCU == OPT_MCU_GD32VF103 #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From 2ea0ef4543ed8a3d127f6354ab3a5ae2a48ec245 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 10 Aug 2021 16:40:43 +0700 Subject: correct newline usage keycode (ENTER 0x28) --- src/class/hid/hid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index ec14c9c7c..9265a2ede 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -871,10 +871,10 @@ enum {0, 0 }, /* 0x07 */ \ {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ {0, HID_KEY_TAB }, /* 0x09 Tab */ \ - {0, HID_KEY_RETURN }, /* 0x0A Line Feed */ \ + {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ {0, 0 }, /* 0x0B */ \ {0, 0 }, /* 0x0C */ \ - {0, HID_KEY_RETURN }, /* 0x0D CR */ \ + {0, HID_KEY_ENTER }, /* 0x0D CR */ \ {0, 0 }, /* 0x0E */ \ {0, 0 }, /* 0x0F */ \ {0, 0 }, /* 0x10 */ \ -- cgit v1.3.1 From a6d18c400ddc6b61f665baae5672ed46af17c99c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Aug 2021 13:29:26 +0700 Subject: fix keyboard report reserved is always 0 --- src/class/hid/hid_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/class') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index a10e3a5e3..2ee80750a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -121,6 +121,7 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi hid_keyboard_report_t report; report.modifier = modifier; + report.reserved = 0; if ( keycode ) { -- cgit v1.3.1 From 62f2efbe8cf1e61f70660abac28f4226bca93daf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 18:26:56 +0700 Subject: hid host skip get report descriptor if too large instead of assert --- examples/host/cdc_msc_hid/src/hid_app.c | 2 ++ src/class/hid/hid_host.c | 58 +++++++++++++++++++++------------ src/class/hid/hid_host.h | 2 ++ src/host/usbh.c | 2 -- 4 files changed, 41 insertions(+), 23 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 420600f9a..5e3ac6a72 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -61,6 +61,8 @@ void hid_app_task(void) // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 40b6f5631..a39ac8bec 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -247,6 +247,8 @@ static bool config_set_protocol (uint8_t dev_addr, tusb_control_requ static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; @@ -367,26 +369,34 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - // Get Report Descriptor + // Get Report Descriptor if possible // using usbh enumeration buffer since report descriptor can be very long - TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE ); + if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) + { + TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); - TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const new_request = + // Driver is mounted without report descriptor + config_driver_mount_complete(dev_addr, instance, NULL, 0); + }else { - .bmRequestType_bit = + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_u16(hid_itf->report_desc_type, 0), - .wIndex = itf_num, - .wLength = hid_itf->report_desc_len - }; + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); + } - TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); return true; } @@ -394,13 +404,21 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); uint8_t const* desc_report = usbh_get_enum_buf(); uint16_t const desc_len = request->wLength; + config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); + + return true; +} + +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + // enumeration is complete tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); @@ -408,9 +426,7 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque hidh_get_report(dev_addr, hid_itf); // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, itf_num); - - return true; + usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index ef203123d..bbef05e25 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -97,6 +97,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted diff --git a/src/host/usbh.c b/src/host/usbh.c index 36c2ea7c8..979fc5065 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -892,8 +892,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura p_desc = tu_desc_next(p_desc); } - TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg); - TU_LOG_INT(2, tu_desc_type(p_desc)); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; -- cgit v1.3.1 From 22a5b1608c0949d46f8e346878bff730712858e4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:31:38 +0700 Subject: change host driver open return type to bool the descriptor len used by driver will be calculated by usbh --- src/class/cdc/cdc_host.c | 12 ++++++------ src/class/cdc/cdc_host.h | 10 +++++----- src/class/hid/hid_host.c | 20 ++++++++++---------- src/class/hid/hid_host.h | 10 +++++----- src/class/msc/msc_host.c | 10 +++++----- src/class/msc/msc_host.h | 10 +++++----- src/host/hub.c | 13 +++++++------ src/host/hub.h | 10 +++++----- src/host/usbh_classdriver.h | 10 +++++----- 9 files changed, 53 insertions(+), 52 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fc7100e81..35b8de3b1 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,7 +149,7 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) max_len; @@ -157,7 +157,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // Protocol 0xFF can be RNDIS device for windows XP TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0xFF != itf_desc->bInterfaceProtocol, 0); + 0xFF != itf_desc->bInterfaceProtocol); cdch_data_t * p_cdc = get_itf(dev_addr); @@ -186,7 +186,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // notification endpoint tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); @@ -205,9 +205,9 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const for(uint32_t i=0; i<2; i++) { tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { @@ -222,7 +222,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const } } - return drv_len; + return true; } bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index edcd258a8..0d435138b 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init (void); -uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); +void cdch_init (void); +bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a39ac8bec..4dd198369 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -249,19 +249,22 @@ static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_requ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len); - uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices @@ -269,13 +272,12 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); //------------- Endpoint Descriptor -------------// - drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); // TODO also open endpoint OUT - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; @@ -292,9 +294,7 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hid_itf->protocol_mode = HID_PROTOCOL_BOOT; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - return drv_len; + return true; } bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index bbef05e25..9a498afec 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -121,11 +121,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init (void); -uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close (uint8_t dev_addr); +void hidh_init (void); +bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 2c027deff..f02f4550a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -360,22 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len, 0); + TU_ASSERT(drv_len <= max_len); msch_interface_t* p_msc = get_itf(dev_addr); tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { @@ -390,7 +390,7 @@ uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_msc->itf_num = desc_itf->bInterfaceNumber; - return drv_len; + return true; } bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 9e4217ba5..7718ad4fe 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -106,11 +106,11 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init (void); -uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void msch_close (uint8_t dev_addr); +void msch_init (void); +bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); +void msch_close (uint8_t dev_addr); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/host/hub.c b/src/host/hub.c index 2ead5bed1..00dce4e65 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -147,16 +147,17 @@ void hub_init(void) tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(hub_interface_t)); } -uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // hub driver does not support multiple TT yet TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass && - 1 <= itf_desc->bInterfaceProtocol, 0); + 0 == itf_desc->bInterfaceSubClass); + + // hub driver does not support multiple TT yet + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len, 0); + TU_ASSERT(drv_len <= max_len); //------------- Interrupt Status endpoint -------------// tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -169,7 +170,7 @@ uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_in = desc_ep->bEndpointAddress; - return drv_len; + return true; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index c9ffe4985..c4d544193 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -181,11 +181,11 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hub_init (void); -uint16_t hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close (uint8_t dev_addr); +void hub_init (void); +bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index fccb30253..8bc2622aa 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -43,11 +43,11 @@ typedef struct { char const* name; #endif - void (* const init )(void); - uint16_t (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; // Call by class driver to tell USBH that it has complete the enumeration -- cgit v1.3.1