Skip to content

Commit 2d63459

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

File tree

6 files changed

+718
-50
lines changed

6 files changed

+718
-50
lines changed

osal/usb_osal_nuttx.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
131131

132132
void usb_osal_sem_reset(usb_osal_sem_t sem)
133133
{
134+
nxsem_reset((sem_t *)sem, 0);
134135
}
135136

136137
usb_osal_mutex_t usb_osal_mutex_create(void)

platform/nuttx/usbd_cdcacm.c

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

0 commit comments

Comments
 (0)