Open FFBoard
Open source force feedback firmware
dcd_cxd56.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright 2019 Sony Semiconductor Solutions Corporation
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_TUSB_MCU == OPT_MCU_CXD56
30
31#include <errno.h>
32#include <nuttx/usb/usbdev.h>
33#include <nuttx/arch.h>
34
35#include "device/dcd.h"
36#include "device/usbd_pvt.h"
37
38#define CXD56_EPNUM (7)
39#define CXD56_SETUP_QUEUE_DEPTH (4)
40#define CXD56_MAX_DATA_OUT_SIZE (64)
41
42OSAL_QUEUE_DEF(usbd_int_set, _setup_queue_def, CXD56_SETUP_QUEUE_DEPTH, struct usb_ctrlreq_s);
43
45{
46 struct usbdevclass_driver_s usbdevclass_driver;
47 FAR struct usbdev_ep_s *ep[CXD56_EPNUM];
48 FAR struct usbdev_req_s *req[CXD56_EPNUM];
51 FAR uint8_t dataout[CXD56_MAX_DATA_OUT_SIZE];
52 size_t outlen;
53};
54
56static struct usbdev_s *usbdev;
57
58static int _dcd_bind (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
59static void _dcd_unbind (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
60static int _dcd_setup (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev,
61 FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen);
62static void _dcd_disconnect (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
63static void _dcd_suspend (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
64static void _dcd_resume (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
65
66static const struct usbdevclass_driverops_s g_driverops =
67{
68 _dcd_bind, /* bind */
69 _dcd_unbind, /* unbind */
70 _dcd_setup, /* setup */
71 _dcd_disconnect, /* disconnect */
72 _dcd_suspend, /* suspend */
73 _dcd_resume, /* resume */
74};
75
76static void usbdcd_ep0incomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
77{
78 (void) ep;
79
80 uint8_t ep_addr = (uint32_t)req->priv;
81
82 if (req->result || req->xfrd != req->len)
83 {
84 if (req->len)
85 {
86 dcd_event_xfer_complete(0, ep_addr, req->xfrd, XFER_RESULT_SUCCESS, true);
87 }
88 }
89 else
90 {
91 if (req->xfrd)
92 {
93 dcd_event_xfer_complete(0, ep_addr, req->xfrd, XFER_RESULT_SUCCESS, true);
94 }
95 }
96}
97
98static int _dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
99{
100 (void) driver;
101
102 usbdev = dev;
103 usbdcd_driver.ep[0] = dev->ep0;
104
105 #ifdef EP_ALLOCREQ
106 // SDK v2
107 usbdcd_driver.req[0] = EP_ALLOCREQ(usbdcd_driver.ep[0]);
108 if (usbdcd_driver.req[0] != NULL) {
109 usbdcd_driver.req[0]->len = 64;
110 usbdcd_driver.req[0]->buf = EP_ALLOCBUFFER(usbdcd_driver.ep[0], 64);
111 if (!usbdcd_driver.req[0]->buf) {
112 EP_FREEREQ(usbdcd_driver.ep[0], usbdcd_driver.req[0]);
113 usbdcd_driver.req[0] = NULL;
114 return ENOMEM;
115 }
116 }
117 #else
118 // SDK v3
119 usbdcd_driver.req[0] = usbdev_allocreq(usbdcd_driver.ep[0], 64);
120 if (usbdcd_driver.req[0] == NULL) {
121 return ENOMEM;
122 }
123 #endif
124
126
127 DEV_CONNECT(dev);
128 return 0;
129}
130
131static void _dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
132{
133 (void) driver;
134 (void) dev;
135}
136
137static int _dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev,
138 FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen)
139{
140 (void) driver;
141 (void) dev;
142
144 {
146 dcd_event_setup_received(0, (uint8_t const *) ctrl, true);
147 }
148 else
149 {
151 }
152
153 if (outlen > 0 && outlen <= CXD56_MAX_DATA_OUT_SIZE)
154 {
155 memcpy(usbdcd_driver.dataout, dataout, outlen);
156 usbdcd_driver.outlen = outlen;
157 }
158
159 return 0;
160}
161
162static void _dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
163{
164 (void) driver;
165
166 tusb_speed_t speed;
167
168 switch (dev->speed)
169 {
170 case USB_SPEED_LOW:
171 speed = TUSB_SPEED_LOW;
172 break;
173 case USB_SPEED_FULL:
174 speed = TUSB_SPEED_FULL;
175 break;
176 case USB_SPEED_HIGH:
177 speed = TUSB_SPEED_HIGH;
178 break;
179 default:
180 speed = TUSB_SPEED_HIGH;
181 break;
182 }
183
184 dcd_event_bus_reset(0, speed, true);
185 DEV_CONNECT(dev);
186}
187
188static void _dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
189{
190 (void) driver;
191 (void) dev;
192
193 dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
194}
195
196static void _dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
197{
198 (void) driver;
199 (void) dev;
200
201 dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
202}
203
204bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
205 (void) rhport;
206 (void) rh_init;
207
208 usbdcd_driver.usbdevclass_driver.speed = USB_SPEED_HIGH;
211 usbdcd_driver.setup_queue = osal_queue_create(&_setup_queue_def);
212
213 usbdev_register(&usbdcd_driver.usbdevclass_driver);
214
215 return true;
216}
217
218// Enable device interrupt
219void dcd_int_enable(uint8_t rhport)
220{
221 (void) rhport;
222
223 up_enable_irq(CXD56_IRQ_USB_INT);
224}
225
226// Disable device interrupt
227void dcd_int_disable(uint8_t rhport)
228{
229 (void) rhport;
230
231 up_disable_irq(CXD56_IRQ_USB_INT);
232}
233
234// Receive Set Address request, mcu port must also include status IN response
235void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
236{
237 (void) rhport;
238 (void) dev_addr;
239}
240
241void dcd_remote_wakeup(uint8_t rhport)
242{
243 (void) rhport;
244
245 DEV_WAKEUP(usbdev);
246}
247
248void dcd_connect(uint8_t rhport)
249{
250 (void) rhport;
251 DEV_CONNECT(usbdev);
252}
253
254void dcd_disconnect(uint8_t rhport)
255{
256 (void) rhport;
257 DEV_DISCONNECT(usbdev);
258}
259
260void dcd_sof_enable(uint8_t rhport, bool en)
261{
262 (void) rhport;
263 (void) en;
264
265 // TODO implement later
266}
267
268//--------------------------------------------------------------------+
269// Endpoint API
270//--------------------------------------------------------------------+
271
272bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
273{
274 (void) rhport;
275
276 uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
277 uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
278 uint8_t xfrtype = 0;
279 uint16_t const ep_mps = tu_edpt_packet_size(p_endpoint_desc);
280
281 struct usb_epdesc_s epdesc;
282
283 if (epnum >= CXD56_EPNUM)
284 {
285 return false;
286 }
287
288 switch (p_endpoint_desc->bmAttributes.xfer)
289 {
290 case 1:
291 xfrtype = USB_EP_ATTR_XFER_ISOC;
292 break;
293 case 2:
294 xfrtype = USB_EP_ATTR_XFER_BULK;
295 break;
296 case 3:
297 xfrtype = USB_EP_ATTR_XFER_INT;
298 break;
299 }
300
301 usbdcd_driver.ep[epnum] = DEV_ALLOCEP(usbdev, epnum, dir == TUSB_DIR_IN, xfrtype);
302 if (usbdcd_driver.ep[epnum] == NULL)
303 {
304 return false;
305 }
306
307 usbdcd_driver.req[epnum] = NULL;
308
309 #ifdef EP_ALLOCREQ
310 // sdk v2
311 usbdcd_driver.req[epnum] = EP_ALLOCREQ(usbdcd_driver.ep[epnum]);
312 if (usbdcd_driver.req[epnum] != NULL) {
313 usbdcd_driver.req[epnum]->len = ep_mps;
314 }
315 #else
316 // sdk v3
317 usbdcd_driver.req[epnum] = usbdev_allocreq(usbdcd_driver.ep[epnum], ep_mps);
318 #endif
319
320 if(usbdcd_driver.req[epnum] == NULL) {
321 return false;
322 }
323
324 usbdcd_driver.req[epnum]->callback = usbdcd_ep0incomplete;
325
326 epdesc.len = p_endpoint_desc->bLength;
327 epdesc.type = p_endpoint_desc->bDescriptorType;
328 epdesc.addr = p_endpoint_desc->bEndpointAddress;
329 epdesc.attr = xfrtype;
330 epdesc.mxpacketsize[0] = LSBYTE(ep_mps);
331 epdesc.mxpacketsize[1] = MSBYTE(ep_mps);
332 epdesc.interval = p_endpoint_desc->bInterval;
333
334 if (EP_CONFIGURE(usbdcd_driver.ep[epnum], &epdesc, false) < 0)
335 {
336 return false;
337 }
338
339 return true;
340}
341
342void dcd_edpt_close_all (uint8_t rhport)
343{
344 (void) rhport;
345 // TODO implement dcd_edpt_close_all()
346}
347
348bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
349{
350 (void) rhport;
351
352 bool ret = true;
353 uint8_t epnum = tu_edpt_number(ep_addr);
354
355 if (epnum >= CXD56_EPNUM)
356 {
357 return false;
358 }
359
360 if (epnum == 0)
361 {
362 if (total_bytes == 0)
363 {
365 dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false);
366 }
367 else if (ep_addr == 0x00 && total_bytes == usbdcd_driver.outlen)
368 {
372 }
373 else
374 {
375 usbdcd_driver.req[epnum]->len = total_bytes;
376 usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr);
377 usbdcd_driver.req[epnum]->flags = total_bytes < usbdcd_driver.ep[epnum]->maxpacket ? USBDEV_REQFLAGS_NULLPKT : 0;
378 usbdcd_driver.req[epnum]->buf = buffer;
379
380 if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0)
381 {
382 ret = false;
383 }
384 }
385
386 struct usb_ctrlreq_s ctrl;
387
389 {
391 {
393 dcd_event_setup_received(0, (uint8_t *)&ctrl, false);
394 }
395 }
396 }
397 else
398 {
399 usbdcd_driver.req[epnum]->len = total_bytes;
400 usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr);
401 usbdcd_driver.req[epnum]->flags = total_bytes < usbdcd_driver.ep[epnum]->maxpacket ? USBDEV_REQFLAGS_NULLPKT : 0;
402 usbdcd_driver.req[epnum]->buf = buffer;
403
404 if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0)
405 {
406 ret = false;
407 }
408 }
409
410 return ret;
411}
412
413void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
414{
415 (void) rhport;
416
417 uint8_t epnum = tu_edpt_number(ep_addr);
418
419 if (epnum >= CXD56_EPNUM)
420 {
421 return;
422 }
423
424 EP_STALL(usbdcd_driver.ep[epnum]);
425}
426
427void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
428{
429 (void) rhport;
430
431 uint8_t epnum = tu_edpt_number(ep_addr);
432
433 if (epnum >= CXD56_EPNUM)
434 {
435 return;
436 }
437
438 EP_RESUME(usbdcd_driver.ep[epnum]);
439}
440
441#endif
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
Definition: dcd.h:196
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
Definition: dcd.h:222
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
Definition: dcd.h:213
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
Definition: dcd.h:204
static void _dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
Definition: dcd_cxd56.c:196
static void _dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
Definition: dcd_cxd56.c:131
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_cxd56.c:413
void dcd_disconnect(uint8_t rhport)
Definition: dcd_cxd56.c:254
void dcd_edpt_close_all(uint8_t rhport)
Definition: dcd_cxd56.c:342
void dcd_int_disable(uint8_t rhport)
Definition: dcd_cxd56.c:227
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
Definition: dcd_cxd56.c:272
static void usbdcd_ep0incomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
Definition: dcd_cxd56.c:76
static void _dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
Definition: dcd_cxd56.c:188
OSAL_QUEUE_DEF(usbd_int_set, _setup_queue_def, CXD56_SETUP_QUEUE_DEPTH, struct usb_ctrlreq_s)
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_cxd56.c:427
static struct usbdcd_driver_s usbdcd_driver
Definition: dcd_cxd56.c:55
void dcd_connect(uint8_t rhport)
Definition: dcd_cxd56.c:248
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_cxd56.c:348
static void _dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
Definition: dcd_cxd56.c:162
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
Definition: dcd_cxd56.c:235
static int _dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen)
Definition: dcd_cxd56.c:137
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: dcd_cxd56.c:204
static int _dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev)
Definition: dcd_cxd56.c:98
void dcd_int_enable(uint8_t rhport)
Definition: dcd_cxd56.c:219
void dcd_remote_wakeup(uint8_t rhport)
Definition: dcd_cxd56.c:241
static const struct usbdevclass_driverops_s g_driverops
Definition: dcd_cxd56.c:66
static struct usbdev_s * usbdev
Definition: dcd_cxd56.c:56
void dcd_sof_enable(uint8_t rhport, bool en)
Definition: dcd_cxd56.c:260
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
uint8_t const * buffer
Definition: midi_device.h:100
static TU_ATTR_ALWAYS_INLINE osal_queue_t osal_queue_create(osal_queue_def_t *qdef)
QueueHandle_t osal_queue_t
Definition: osal_freertos.h:55
static TU_ATTR_ALWAYS_INLINE bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr)
static TU_ATTR_ALWAYS_INLINE bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec)
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint8_t bInterval
Definition: tusb_types.h:372
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint8_t bDescriptorType
Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
Definition: audio.h:657
uint8_t bLength
Size of this descriptor in bytes: 9.
Definition: audio.h:656
uint8_t bEndpointAddress
Definition: video.h:306
osal_queue_t setup_queue
Definition: dcd_cxd56.c:49
FAR struct usbdev_ep_s * ep[CXD56_EPNUM]
Definition: dcd_cxd56.c:47
FAR struct usbdev_req_s * req[CXD56_EPNUM]
Definition: dcd_cxd56.c:48
bool setup_processed
Definition: dcd_cxd56.c:50
size_t outlen
Definition: dcd_cxd56.c:52
FAR uint8_t dataout[CXD56_MAX_DATA_OUT_SIZE]
Definition: dcd_cxd56.c:51
struct usbdevclass_driver_s usbdevclass_driver
Definition: dcd_cxd56.c:46
@ TUSB_DIR_IN
Definition: tusb_types.h:67
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
Definition: tusb_types.h:49
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
@ TUSB_SPEED_LOW
Definition: tusb_types.h:51
@ TUSB_SPEED_HIGH
Definition: tusb_types.h:52
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
Definition: tusb_types.h:507
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
Definition: tusb_types.h:515
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
void usbd_int_set(bool enabled)
Definition: usbd.c:1226