Open FFBoard
Open source force feedback firmware
vendor_device.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2019 Ha Thach (tinyusb.org)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#include "tusb_option.h"
28
29#if (CFG_TUD_ENABLED && CFG_TUD_VENDOR)
30
31#include "device/usbd.h"
32#include "device/usbd_pvt.h"
33
34#include "vendor_device.h"
35
36//--------------------------------------------------------------------+
37// MACRO CONSTANT TYPEDEF
38//--------------------------------------------------------------------+
39typedef struct {
40 uint8_t itf_num;
41
42 /*------------- From this point, data is not cleared by bus reset -------------*/
43 // Endpoint Transfer buffer
44 CFG_TUD_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE];
45 CFG_TUD_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE];
46
47 struct {
49 #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
50 uint8_t ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
51 #endif
52 }tx;
53
54 struct {
55 tu_edpt_stream_t stream;
56 #if CFG_TUD_VENDOR_RX_BUFSIZE > 0
57 uint8_t ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE];
58 #endif
59 } rx;
60
62
63CFG_TUD_MEM_SECTION static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
64
65#define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + sizeof(((vendord_interface_t *)0)->itf_num))
66
67//--------------------------------------------------------------------
68// Application API
69//--------------------------------------------------------------------
70
71bool tud_vendor_n_mounted(uint8_t itf) {
72 TU_VERIFY(itf < CFG_TUD_VENDOR);
73 vendord_interface_t* p_itf = &_vendord_itf[itf];
74 return p_itf->rx.stream.ep_addr || p_itf->tx.stream.ep_addr;
75}
76
77//--------------------------------------------------------------------+
78// Read API
79//--------------------------------------------------------------------+
80uint32_t tud_vendor_n_available(uint8_t itf) {
81 TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
82 vendord_interface_t* p_itf = &_vendord_itf[itf];
83
85}
86
87bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) {
88 TU_VERIFY(itf < CFG_TUD_VENDOR);
89 vendord_interface_t* p_itf = &_vendord_itf[itf];
90
91 return tu_edpt_stream_peek(&p_itf->rx.stream, u8);
92}
93
94uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) {
95 TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
96 vendord_interface_t* p_itf = &_vendord_itf[itf];
97 uint8_t const rhport = 0;
98
99 return tu_edpt_stream_read(rhport, &p_itf->rx.stream, buffer, bufsize);
100}
101
102void tud_vendor_n_read_flush (uint8_t itf) {
103 TU_VERIFY(itf < CFG_TUD_VENDOR, );
104 vendord_interface_t* p_itf = &_vendord_itf[itf];
105 uint8_t const rhport = 0;
106
108 tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream);
109}
110
111//--------------------------------------------------------------------+
112// Write API
113//--------------------------------------------------------------------+
114uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) {
115 TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
116 vendord_interface_t* p_itf = &_vendord_itf[itf];
117 uint8_t const rhport = 0;
118
119 return tu_edpt_stream_write(rhport, &p_itf->tx.stream, buffer, (uint16_t) bufsize);
120}
121
122uint32_t tud_vendor_n_write_flush (uint8_t itf) {
123 TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
124 vendord_interface_t* p_itf = &_vendord_itf[itf];
125 uint8_t const rhport = 0;
126
127 return tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream);
128}
129
130uint32_t tud_vendor_n_write_available (uint8_t itf) {
131 TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
132 vendord_interface_t* p_itf = &_vendord_itf[itf];
133 uint8_t const rhport = 0;
134
135 return tu_edpt_stream_write_available(rhport, &p_itf->tx.stream);
136}
137
138//--------------------------------------------------------------------+
139// USBD Driver API
140//--------------------------------------------------------------------+
141void vendord_init(void) {
142 tu_memclr(_vendord_itf, sizeof(_vendord_itf));
143
144 for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
146
147 uint8_t* rx_ff_buf =
148 #if CFG_TUD_VENDOR_RX_BUFSIZE > 0
149 p_itf->rx.ff_buf;
150 #else
151 NULL;
152 #endif
153
154 tu_edpt_stream_init(&p_itf->rx.stream, false, false, false,
155 rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE,
156 p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE);
157
158 uint8_t* tx_ff_buf =
159 #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
160 p_itf->tx.ff_buf;
161 #else
162 NULL;
163 #endif
164
165 tu_edpt_stream_init(&p_itf->tx.stream, false, true, false,
166 tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE,
167 p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE);
168 }
169}
170
171bool vendord_deinit(void) {
172 for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
176 }
177 return true;
178}
179
180void vendord_reset(uint8_t rhport) {
181 (void) rhport;
182
183 for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
185 tu_memclr(p_itf, ITF_MEM_RESET_SIZE);
190 }
191}
192
193uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) {
194 TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0);
195 const uint8_t* p_desc = tu_desc_next(desc_itf);
196 const uint8_t* desc_end = p_desc + max_len;
197
198 // Find available interface
199 vendord_interface_t* p_vendor = NULL;
200 for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
201 if (!tud_vendor_n_mounted(i)) {
202 p_vendor = &_vendord_itf[i];
203 break;
204 }
205 }
206 TU_VERIFY(p_vendor, 0);
207
208 p_vendor->itf_num = desc_itf->bInterfaceNumber;
209 uint8_t found_ep = 0;
210 while (found_ep < desc_itf->bNumEndpoints) {
211 // skip non-endpoint descriptors
212 while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) {
213 p_desc = tu_desc_next(p_desc);
214 }
215 if (p_desc >= desc_end) {
216 break;
217 }
218
219 const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc;
220 TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
221 found_ep++;
222
223 if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
224 tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep);
225 tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf));
226 } else {
227 tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep);
228 TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data
229 }
230
231 p_desc = tu_desc_next(p_desc);
232 }
233
234 return (uint16_t) ((uintptr_t) p_desc - (uintptr_t) desc_itf);
235}
236
237bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
238 (void) result;
239
240 uint8_t itf = 0;
242
243 for ( ; ; itf++, p_itf++) {
244 if (itf >= CFG_TUD_VENDOR) return false;
245 if ((ep_addr == p_itf->rx.stream.ep_addr) || (ep_addr == p_itf->tx.stream.ep_addr)) break;
246 }
247
248 if ( ep_addr == p_itf->rx.stream.ep_addr ) {
249 // Received new data: put into stream's fifo
250 tu_edpt_stream_read_xfer_complete(&p_itf->rx.stream, xferred_bytes);
251
252 // Invoked callback if any
253 if (tud_vendor_rx_cb) {
254 tud_vendor_rx_cb(itf, p_itf->epout_buf, (uint16_t) xferred_bytes);
255 }
256
257 tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream);
258 } else if ( ep_addr == p_itf->tx.stream.ep_addr ) {
259 // Send complete
260 if (tud_vendor_tx_cb) {
261 tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes);
262 }
263
264 #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
265 // try to send more if possible
266 if ( 0 == tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream) ) {
267 // If there is no data left, a ZLP should be sent if xferred_bytes is multiple of EP Packet size and not zero
268 tu_edpt_stream_write_zlp_if_needed(rhport, &p_itf->tx.stream, xferred_bytes);
269 }
270 #endif
271 }
272
273 return true;
274}
275
276#endif
uint8_t u8
uint8_t const * buffer
Definition: midi_device.h:100
uint32_t bufsize
Definition: midi_device.h:95
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint8_t bInterfaceClass
Class code (assigned by the USB-IF).
Definition: tusb_types.h:349
uint8_t bEndpointAddress
Definition: video.h:306
uint8_t bInterfaceNumber
Number of this interface. Zero-based value identifying the index in the array of concurrent interface...
Definition: tusb_types.h:346
struct vendord_interface_t::@53 rx
uint8_t ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]
Definition: vendor_device.c:50
CFG_TUD_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]
Definition: vendor_device.c:45
CFG_TUD_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]
Definition: vendor_device.c:44
tu_edpt_stream_t stream
Definition: vendor_device.c:48
struct vendord_interface_t::@52 tx
bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t *s, uint32_t last_xferred_bytes)
Definition: tusb.c:353
static TU_ATTR_ALWAYS_INLINE bool tu_edpt_stream_clear(tu_edpt_stream_t *s)
Definition: tusb_private.h:110
static TU_ATTR_ALWAYS_INLINE void tu_edpt_stream_close(tu_edpt_stream_t *s)
Definition: tusb_private.h:104
static TU_ATTR_ALWAYS_INLINE bool tu_edpt_stream_peek(tu_edpt_stream_t *s, uint8_t *ch)
Definition: tusb_private.h:164
static TU_ATTR_ALWAYS_INLINE uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t *s)
Definition: tusb_private.h:159
uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t *s)
Definition: tusb.c:426
uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t *s, void *buffer, uint32_t bufsize)
Definition: tusb.c:461
uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t *s)
Definition: tusb.c:405
uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t *s)
Definition: tusb.c:362
uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, void const *buffer, uint32_t bufsize)
Definition: tusb.c:382
static TU_ATTR_ALWAYS_INLINE void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t *s, uint32_t xferred_bytes)
Definition: tusb_private.h:143
static TU_ATTR_ALWAYS_INLINE void tu_edpt_stream_open(tu_edpt_stream_t *s, tusb_desc_endpoint_t const *desc_ep)
Definition: tusb_private.h:97
bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf, uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize)
Definition: tusb.c:282
bool tu_edpt_stream_deinit(tu_edpt_stream_t *s)
Definition: tusb.c:302
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ TUSB_CLASS_VENDOR_SPECIFIC
Definition: tusb_types.h:181
xfer_result_t
Definition: tusb_types.h:236
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
Definition: tusb_types.h:502
static TU_ATTR_ALWAYS_INLINE uint8_t tu_desc_type(void const *desc)
Definition: tusb_types.h:537
static TU_ATTR_ALWAYS_INLINE uint8_t const * tu_desc_next(void const *desc)
Definition: tusb_types.h:531
@ TUSB_DESC_ENDPOINT
Definition: tusb_types.h:97
bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep)
Definition: usbd.c:1277
bool vendord_deinit(void)
uint32_t tud_vendor_n_available(uint8_t itf)
Definition: vendor_device.c:80
void vendord_reset(uint8_t rhport)
uint32_t tud_vendor_n_read(uint8_t itf, void *buffer, uint32_t bufsize)
Definition: vendor_device.c:94
void tud_vendor_n_read_flush(uint8_t itf)
static CFG_TUD_MEM_SECTION vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]
Definition: vendor_device.c:63
uint32_t tud_vendor_n_write(uint8_t itf, void const *buffer, uint32_t bufsize)
uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
bool tud_vendor_n_peek(uint8_t itf, uint8_t *u8)
Definition: vendor_device.c:87
uint32_t tud_vendor_n_write_available(uint8_t itf)
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
bool tud_vendor_n_mounted(uint8_t itf)
Definition: vendor_device.c:71
void vendord_init(void)
uint32_t tud_vendor_n_write_flush(uint8_t itf)
TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes)
TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf, uint8_t const *buffer, uint16_t bufsize)