Skip to content

Commit a46a55b

Browse files
committed
feat(platform/nuttx): update fs & net & cdcacm support
Signed-off-by: sakumisu <1203593632@qq.com>
1 parent c399be3 commit a46a55b

File tree

5 files changed

+734
-50
lines changed

5 files changed

+734
-50
lines changed

platform/nuttx/usbd_cdcacm.c

Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
/*
2+
* Copyright (c) 2025, sakumisu
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <nuttx/kmalloc.h>
7+
#include <nuttx/mutex.h>
8+
#include <nuttx/semaphore.h>
9+
10+
#include "usbd_core.h"
11+
#include "usbd_cdc_acm.h"
12+
13+
#include <nuttx/mm/circbuf.h>
14+
15+
#ifndef CONFIG_USBDEV_CDCACM_RXBUFSIZE
16+
#define CONFIG_USBDEV_CDCACM_RXBUFSIZE 512
17+
#endif
18+
19+
#ifndef CONFIG_USBDEV_CDCACM_TXBUFSIZE
20+
#define CONFIG_USBDEV_CDCACM_TXBUFSIZE 512
21+
#endif
22+
23+
struct usbdev_serial_s {
24+
char name[16];
25+
struct circbuf_s circ;
26+
uint8_t inep;
27+
uint8_t outep;
28+
sem_t txdone_sem;
29+
sem_t rxdone_sem;
30+
struct usbd_interface ctrl_intf;
31+
struct usbd_interface data_intf;
32+
__attribute__((aligned(32))) uint8_t cache_rxbuffer[CONFIG_USBDEV_CDCACM_RXBUFSIZE];
33+
__attribute__((aligned(32))) uint8_t cache_txbuffer[CONFIG_USBDEV_CDCACM_TXBUFSIZE];
34+
};
35+
36+
struct usbdev_serial_s *g_usb_cdcacm_serial[8];
37+
38+
static int nuttx_errorcode(int error)
39+
{
40+
int err = 0;
41+
42+
switch (error) {
43+
case -USB_ERR_NOMEM:
44+
err = -EIO;
45+
break;
46+
case -USB_ERR_INVAL:
47+
err = -EINVAL;
48+
break;
49+
case -USB_ERR_NODEV:
50+
err = -ENODEV;
51+
break;
52+
case -USB_ERR_NOTCONN:
53+
err = -ENOTCONN;
54+
break;
55+
case -USB_ERR_NOTSUPP:
56+
err = -EIO;
57+
break;
58+
case -USB_ERR_BUSY:
59+
err = -EBUSY;
60+
break;
61+
case -USB_ERR_RANGE:
62+
err = -ERANGE;
63+
break;
64+
case -USB_ERR_STALL:
65+
err = -EPERM;
66+
break;
67+
case -USB_ERR_NAK:
68+
err = -EAGAIN;
69+
break;
70+
case -USB_ERR_DT:
71+
err = -EIO;
72+
break;
73+
case -USB_ERR_IO:
74+
err = -EIO;
75+
break;
76+
case -USB_ERR_SHUTDOWN:
77+
err = -ESHUTDOWN;
78+
break;
79+
case -USB_ERR_TIMEOUT:
80+
err = -ETIMEDOUT;
81+
break;
82+
83+
default:
84+
break;
85+
}
86+
return err;
87+
}
88+
89+
void usbd_cdc_acm_bulk_out1(uint8_t busid, uint8_t ep, uint32_t nbytes)
90+
{
91+
nxsem_post(&g_usb_cdcacm_serial[0]->rxdone_sem);
92+
}
93+
94+
void usbd_cdc_acm_bulk_in1(uint8_t busid, uint8_t ep, uint32_t nbytes)
95+
{
96+
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
97+
/* send zlp */
98+
usbd_ep_start_write(busid, ep, NULL, 0);
99+
} else {
100+
nxsem_post(&g_usb_cdcacm_serial[0]->txdone_sem);
101+
}
102+
}
103+
104+
void usbd_cdc_acm_bulk_out2(uint8_t busid, uint8_t ep, uint32_t nbytes)
105+
{
106+
nxsem_post(&g_usb_cdcacm_serial[1]->rxdone_sem);
107+
}
108+
109+
void usbd_cdc_acm_bulk_in2(uint8_t busid, uint8_t ep, uint32_t nbytes)
110+
{
111+
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
112+
/* send zlp */
113+
usbd_ep_start_write(busid, ep, NULL, 0);
114+
} else {
115+
nxsem_post(&g_usb_cdcacm_serial[1]->txdone_sem);
116+
}
117+
}
118+
119+
void usbd_cdc_acm_bulk_out3(uint8_t busid, uint8_t ep, uint32_t nbytes)
120+
{
121+
nxsem_post(&g_usb_cdcacm_serial[2]->rxdone_sem);
122+
}
123+
124+
void usbd_cdc_acm_bulk_in3(uint8_t busid, uint8_t ep, uint32_t nbytes)
125+
{
126+
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
127+
/* send zlp */
128+
usbd_ep_start_write(busid, ep, NULL, 0);
129+
} else {
130+
nxsem_post(&g_usb_cdcacm_serial[2]->txdone_sem);
131+
}
132+
}
133+
134+
/* Character driver methods */
135+
136+
static int usbdev_open(FAR struct file *filep);
137+
static int usbdev_close(FAR struct file *filep);
138+
static ssize_t usbdev_read(FAR struct file *filep, FAR char *buffer,
139+
size_t buflen);
140+
static ssize_t usbdev_write(FAR struct file *filep,
141+
FAR const char *buffer, size_t buflen);
142+
143+
/****************************************************************************
144+
* Private Data
145+
****************************************************************************/
146+
147+
static const struct file_operations g_usbdevops = {
148+
usbdev_open, /* open */
149+
usbdev_close, /* close */
150+
usbdev_read, /* read */
151+
usbdev_write, /* write */
152+
NULL, /* seek */
153+
NULL, /* ioctl */
154+
NULL, /* mmap */
155+
NULL, /* truncate */
156+
NULL /* poll */
157+
};
158+
159+
static int usbdev_open(FAR struct file *filep)
160+
{
161+
FAR struct inode *inode = filep->f_inode;
162+
163+
DEBUGASSERT(inode->i_private);
164+
165+
if (usb_device_is_configured(0)) {
166+
return OK;
167+
} else {
168+
return -ENODEV;
169+
}
170+
}
171+
172+
static int usbdev_close(FAR struct file *filep)
173+
{
174+
FAR struct inode *inode = filep->f_inode;
175+
176+
DEBUGASSERT(inode->i_private);
177+
178+
if (!usb_device_is_configured(0)) {
179+
return -ENODEV;
180+
}
181+
182+
return 0;
183+
}
184+
185+
static ssize_t usbdev_read(FAR struct file *filep, FAR char *buffer,
186+
size_t buflen)
187+
{
188+
FAR struct inode *inode = filep->f_inode;
189+
struct usbdev_serial_s *serial;
190+
__attribute__((aligned(32))) uint8_t cache_tempbuffer[512];
191+
int ret;
192+
193+
DEBUGASSERT(inode->i_private);
194+
serial = (struct usbdev_serial_s *)inode->i_private;
195+
196+
if (!usb_device_is_configured(0)) {
197+
return -ENODEV;
198+
}
199+
200+
while (circbuf_used(&serial->circ) < buflen) {
201+
nxsem_trywait(&serial->rxdone_sem);
202+
usbd_ep_start_read(0, serial->outep, cache_tempbuffer, usbd_get_ep_mps(0, serial->outep));
203+
ret = nxsem_wait(&serial->rxdone_sem);
204+
if (ret < 0) {
205+
return nuttx_errorcode(ret);
206+
}
207+
#if defined(CONFIG_ARCH_DCACHE) && !defined(CONFIG_USB_DCACHE_ENABLE)
208+
up_invalidate_dcache((uintptr_t)cache_tempbuffer, (uintptr_t)(cache_tempbuffer + USB_ALIGN_UP(ret, 64)));
209+
#endif
210+
circbuf_overwrite(&serial->circ, cache_tempbuffer, ret);
211+
}
212+
circbuf_read(&serial->circ, buffer, buflen);
213+
return buflen;
214+
}
215+
216+
static ssize_t usbdev_write(FAR struct file *filep, FAR const char *buffer,
217+
size_t buflen)
218+
{
219+
FAR struct inode *inode = filep->f_inode;
220+
struct usbdev_serial_s *serial;
221+
int ret;
222+
223+
DEBUGASSERT(inode->i_private);
224+
serial = (struct usbdev_serial_s *)inode->i_private;
225+
226+
if (!usb_device_is_configured(0)) {
227+
return -ENODEV;
228+
}
229+
230+
#ifdef CONFIG_ARCH_DCACHE
231+
uint32_t write_len = 0;
232+
233+
while (write_len < buflen) {
234+
uint32_t len = buflen - write_len;
235+
if (len > CONFIG_USBDEV_CDCACM_TXBUFSIZE) {
236+
len = CONFIG_USBDEV_CDCACM_TXBUFSIZE;
237+
}
238+
memcpy(serial->cache_txbuffer, buffer + write_len, len);
239+
#ifndef CONFIG_USB_DCACHE_ENABLE
240+
up_clean_dcache((uintptr_t)serial->cache_txbuffer, (uintptr_t)(serial->cache_txbuffer + USB_ALIGN_UP(len, 64)));
241+
#endif
242+
nxsem_trywait(&serial->txdone_sem);
243+
usbd_ep_start_write(0, serial->inep, serial->cache_txbuffer, usbd_get_ep_mps(0, serial->inep));
244+
ret = nxsem_wait(&serial->txdone_sem);
245+
if (ret < 0) {
246+
return nuttx_errorcode(ret);
247+
} else {
248+
write_len += len;
249+
}
250+
}
251+
return buflen;
252+
#else
253+
nxsem_trywait(&serial->txdone_sem);
254+
usbd_ep_start_write(0, serial->inep, buffer, buflen);
255+
ret = nxsem_wait(&serial->txdone_sem);
256+
if (ret < 0) {
257+
return nuttx_errorcode(ret);
258+
} else {
259+
return buflen;
260+
}
261+
#endif
262+
}
263+
264+
static struct usbd_endpoint cdc_out_ep[8] = {
265+
{ .ep_addr = 0,
266+
.ep_cb = usbd_cdc_acm_bulk_out1 },
267+
{ .ep_addr = 0,
268+
.ep_cb = usbd_cdc_acm_bulk_out2 },
269+
{ .ep_addr = 0,
270+
.ep_cb = usbd_cdc_acm_bulk_out3 }
271+
};
272+
273+
static struct usbd_endpoint cdc_in_ep[8] = {
274+
{ .ep_addr = 0,
275+
.ep_cb = usbd_cdc_acm_bulk_in1 },
276+
{ .ep_addr = 0,
277+
.ep_cb = usbd_cdc_acm_bulk_in2 },
278+
{ .ep_addr = 0,
279+
.ep_cb = usbd_cdc_acm_bulk_in3 }
280+
};
281+
282+
static void cdcacm_notify_handler1(uint8_t busid, uint8_t event, void *arg)
283+
{
284+
switch (event) {
285+
case USBD_EVENT_RESET:
286+
break;
287+
288+
case USBD_EVENT_CONFIGURED:
289+
nxsem_post(&g_usb_cdcacm_serial[0]->txdone_sem);
290+
nxsem_post(&g_usb_cdcacm_serial[0]->rxdone_sem);
291+
break;
292+
default:
293+
break;
294+
}
295+
}
296+
297+
static void cdcacm_notify_handler2(uint8_t busid, uint8_t event, void *arg)
298+
{
299+
switch (event) {
300+
case USBD_EVENT_RESET:
301+
302+
break;
303+
304+
case USBD_EVENT_CONFIGURED:
305+
nxsem_post(&g_usb_cdcacm_serial[1]->txdone_sem);
306+
nxsem_post(&g_usb_cdcacm_serial[1]->rxdone_sem);
307+
break;
308+
default:
309+
break;
310+
}
311+
}
312+
313+
static void cdcacm_notify_handler3(uint8_t busid, uint8_t event, void *arg)
314+
{
315+
switch (event) {
316+
case USBD_EVENT_RESET:
317+
318+
break;
319+
320+
case USBD_EVENT_CONFIGURED:
321+
nxsem_post(&g_usb_cdcacm_serial[2]->txdone_sem);
322+
nxsem_post(&g_usb_cdcacm_serial[2]->rxdone_sem);
323+
break;
324+
default:
325+
break;
326+
}
327+
}
328+
329+
usbd_notify_handler cdcacm_notify_handler[8] = {
330+
cdcacm_notify_handler1,
331+
cdcacm_notify_handler2,
332+
cdcacm_notify_handler3
333+
};
334+
335+
void usbd_cdcacm_init(uint8_t busid, uint8_t id, const char *name, uint8_t inep, uint8_t outep)
336+
{
337+
g_usb_cdcacm_serial[id] = kmm_malloc(sizeof(struct usbdev_serial_s));
338+
DEBUGASSERT(g_usb_cdcacm_serial[id]);
339+
340+
memset(g_usb_cdcacm_serial[id], 0, sizeof(struct usbdev_serial_s));
341+
memcpy(g_usb_cdcacm_serial[id]->name, name, strlen(name));
342+
343+
circbuf_init(&g_usb_cdcacm_serial[id]->circ, g_usb_cdcacm_serial[id]->cache_rxbuffer, CONFIG_USBDEV_CDCACM_RXBUFSIZE);
344+
345+
nxsem_init(&g_usb_cdcacm_serial[id]->rxdone_sem, 0, 0);
346+
nxsem_init(&g_usb_cdcacm_serial[id]->txdone_sem, 0, 0);
347+
348+
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &g_usb_cdcacm_serial[id]->ctrl_intf));
349+
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &g_usb_cdcacm_serial[id]->data_intf));
350+
g_usb_cdcacm_serial[id]->ctrl_intf.notify_handler = cdcacm_notify_handler[id];
351+
352+
cdc_out_ep[id].ep_addr = outep;
353+
cdc_in_ep[id].ep_addr = inep;
354+
usbd_add_endpoint(busid, &cdc_out_ep[id]);
355+
usbd_add_endpoint(busid, &cdc_in_ep[id]);
356+
357+
register_driver(name, &g_usbdevops, 0666, g_usb_cdcacm_serial[id]);
358+
}
359+
360+
void usbd_cdcacm_deinit(uint8_t busid, uint8_t id)
361+
{
362+
unregister_driver(g_usb_cdcacm_serial[id]->name);
363+
364+
kmm_free(g_usb_cdcacm_serial[id]);
365+
}

0 commit comments

Comments
 (0)