229 Commits

Author SHA1 Message Date
sakumisu
1be34f4d36 fix(core/usbd_core): fix ep config for more eps when call usbd_set_interface 2024-12-28 16:43:19 +08:00
sakumisu
515b83e0f8 docs: release v1.4.2 2024-12-23 20:04:02 +08:00
sakumisu
be6537637c chore: fix missing license 2024-12-23 20:01:05 +08:00
yangpeng
e6801fcbb8 修复VID/PID匹配逻辑 2024-12-20 16:37:59 +08:00
sakumisu
75e6dc6300 update(port/dwc2/usb_glue_gd): add check for ep 2024-12-19 21:20:33 +08:00
sakumisu
effee4d4c2 update(port/dwc2/usb_glue_at): import system_core_clock 2024-12-16 21:30:26 +08:00
sakumisu
05b46c8bad update(port/dwc2/usb_glue_st): support stm32h7rs 2024-12-16 20:55:02 +08:00
sakumisu
ddc19a9d65 update(port/dwc2/usb_dc_dwc2): support up to 16 endpoints 2024-12-16 20:53:52 +08:00
sakumisu
886f1ec6b4 fix warning 2024-12-09 20:53:02 +08:00
sakumisu
7980cb056c docs: update rst 2024-12-09 20:18:07 +08:00
sakumisu
f86443a70b update(port/ohci): update ohci common code 2024-12-09 20:17:50 +08:00
sakumisu
bfc1139d80 docs: add vendor rst 2024-12-04 23:04:12 +08:00
sakumisu
8d2afc1540 update(port/ehci/usb_glue_aic): add check for CONFIG_USB_OHCI_HCOR_OFFSET 2024-12-04 22:47:08 +08:00
sakumisu
87b8a4ad7f docs: update rst 2024-12-01 20:59:32 +08:00
sakumisu
9ff35e9020 update(port/dwc2/usb_hc_dwc2): do not support hs hub with ls/fs device 2024-11-29 22:42:54 +08:00
sakumisu
a03a9cd481 chore: add canaan logo 2024-11-29 22:41:56 +08:00
sakumisu
88d57eb99b update(cherrymp): use own osal 2024-11-28 18:25:47 +08:00
sakumisu
5850e27743 update(port/fsdev): add check for iso, we do not support 2024-11-27 22:14:05 +08:00
sakumisu
015aa77487 docs: update rst 2024-11-27 20:17:05 +08:00
sakumisu
4416dfa5cf fix(class/cdc/usbd_cdc_ecm): fix missing return 2024-11-27 19:37:42 +08:00
sakumisu
d874bed6aa chore: add missing license 2024-11-26 21:27:22 +08:00
sakumisu
7f75da270f update(cherrymp): change mq to sem for fast run 2024-11-26 21:04:14 +08:00
sakumisu
1a39169f6e update(port/dwc2/usb_dc_dwc2): clear crst bit because some mcu cannot be self-clearing, refs:#276 2024-11-25 21:03:51 +08:00
Zhihong Chen
82a0d243f8 usbd_video: use pingpang buffer to improve tx performance
- use pingpang buffer to improve tx performance

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-11-25 16:55:28 +08:00
sakumisu
ac3be8cb3a update(class/audio): change volume unit with dB, fix uac2.0 volume range 2024-11-25 16:21:25 +08:00
sakumisu
a72ecd2202 update: change memcpy to fast memcpy 2024-11-24 23:04:27 +08:00
sakumisu
c6bdacee6d docs: add share rst 2024-11-21 21:42:03 +08:00
sakumisu
ea03856337 fix warning 2024-11-21 21:00:10 +08:00
sakumisu
1c1217f8fa fix(port/dwc2/usb_dc_dwc2): do not clear other intr bits 2024-11-21 20:57:24 +08:00
Zhihong Chen
093a1836f0 demo: video_static_h264_template.c: fix end brace
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-11-18 17:31:02 +08:00
Zhihong Chen
70ef616676 HPMicro: update hpmicro port files
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-11-18 17:31:02 +08:00
sakumisu
6517919bd2 refactor(class/video/usbd_video): refactor video stream transfer, support n frames in one transfer 2024-11-16 22:35:58 +08:00
sakumisu
2b72d8c6d8 chore(scons): add kendryte config 2024-11-13 22:44:44 +08:00
sakumisu
261502f3b2 fix(cherrymp): fix bool to uint32_t 2024-11-13 22:44:38 +08:00
sakumisu
e3ff8ffe6a update(demo): set hid busy before write 2024-11-13 21:49:58 +08:00
sakumisu
24fc172ad8 update(demo/usbd_rndis): update send & recv done api, add check for this demo 2024-11-11 21:50:13 +08:00
sakumisu
58d552d03d update(class/cdc/usbd_cdc_ecm): support transfer api for enet & wireless without lwip 2024-11-11 21:48:13 +08:00
sakumisu
d0edc30c11 update(demo/usb_host): move test macro before run api 2024-11-11 21:44:33 +08:00
sakumisu
6ea1e2f94f update(osal/freertos): update usb_osal_mq_recv and usb_osal_mq_send for isr api 2024-11-06 20:14:35 +08:00
sakumisu
037c2a8323 update(platform/rtthread): remove unused idle task check 2024-11-04 20:07:43 +08:00
sakumisu
608ee773de chore(cmake): update idf config for lwip & freertos 2024-11-04 20:07:19 +08:00
sakumisu
c51a6f35a6 feat(class/aoa): add usb aoa host 2024-10-31 21:45:19 +08:00
sakumisu
a13bee0663 feat(core/usbh_core): add usbh_find_hubport api 2024-10-31 21:45:19 +08:00
sakumisu
fd1baa62df update(osal/usb_osal_thread): implement usb_osal_sem_reset 2024-10-31 21:45:19 +08:00
sakumisu
6e6fdda62a update(port/ehci/usb_glue_aic): remove lsusb shell, add check for ehci configflag 2024-10-31 21:45:19 +08:00
Dozingfiretruck
f02ff21cfb add:cherryusb_config_template.h add CONFIG_USB_HS configuration description 2024-10-31 12:28:32 +08:00
sakumisu
d6aae26371 update(class/audio/usbh_auido): update audio volume and mute api, caculate volume with volume min & max 2024-10-30 22:19:37 +08:00
sakumisu
77136aa743 update(core/usbd_core): implement USB_REQUEST_GET_INTERFACE request, refs:#268 2024-10-30 22:19:14 +08:00
sakumisu
4784017f56 chore: update comment 2024-10-30 21:04:06 +08:00
electretmike
149fb046bc fix: rename class to class_code, for c++ compatibility (#269)
Co-authored-by: Michiel van Leeuwen <michiel@embeddedacoustics.com>
2024-10-30 15:11:46 +08:00
sakumisu
f437b3e51c docs: release v1.4.1 2024-10-20 20:49:36 +08:00
sakumisu
65151b9534 feat(class/video/usbd_video): add usbd_video_stream_start_write api for video split tranfer, every transfer with one ep_mps 2024-10-18 17:18:51 +08:00
sakumisu
05315b7ea5 fix(port/dwc2/usb_hc_dwc2): fix check typo 2024-10-17 09:21:31 +08:00
sakumisu
f1a1434047 chore(platform/usbh_lwip): remove Double quotation marks 2024-10-11 21:53:24 +08:00
sakumisu
a20e312b55 update(port/kinetis): update mcx glue for mcxa153/mcxc444 2024-10-11 20:02:39 +08:00
sakumisu
83b5d842c7 docs: fix some translations 2024-10-10 21:39:40 +08:00
sakumisu
e425b992be feat(port/kinetis): add kinetis usbip 2024-10-10 21:30:42 +08:00
HalfSweet
0b81f3b2a2 Update start.rst 2024-10-10 21:23:58 +08:00
HalfSweet
287eb130ac Update deploy-docs.yml 2024-10-10 21:23:58 +08:00
sakumisu
525884a00f feat(class/audio/usb_audio): add audio altsetting desc init macros 2024-09-30 16:46:58 +08:00
sakumisu
2c52445639 update(platform/none/usbh_lwip): remove freertos, use osal api 2024-09-28 14:37:36 +08:00
sakumisu
df888eb9bc update(class/wireless/usbh_rndis): reduce rndis control buffer 2024-09-28 14:32:13 +08:00
Derek Konigsberg
5a15f714f5 Reduce size of HID class request buffer
With the change from cherry-embedded#260, this buffer no longer needs to be so large.  It can be reduced to the save a lot of memory.
2024-09-28 00:27:38 +08:00
sakumisu
bb79408275 Create cppcheck.yml 2024-09-27 22:16:32 +08:00
sakumisu
2b6eebcbb2 fix(class/msc/usbh_msc): when device stalls by usbh_msc_get_maxlun, ingore error and set lun=0, refs:#259 2024-09-27 19:03:33 +08:00
sakumisu
ab59beebd4 update(class/hid/usbh_hid): export usbh_hid_get_report_descriptor api, refs:#260 2024-09-27 19:03:33 +08:00
sakumisu
c377747e67 docs: update rst 2024-09-27 19:03:33 +08:00
sakumisu
2f14ee7a7b update(port/dwc2/usb_dc_dwc2): enlarge CONFIG_USB_DWC2_TX1_FIFO_SIZE for video demo and export CONFIG_USB_DWC2_DMA_ENABLE 2024-09-27 19:03:33 +08:00
sakumisu
0d65bbc6ba fix(core/usbd_core): reset endpoint only for altsetting 0, refs:#258 2024-09-27 19:02:28 +08:00
sakumisu
76bbd09fed fix(port/dwc2/usb_dc_dwc2): set multi packet for iso in tx empty process, every transfer will reset this bits, so we need restore it. remove ununsed iso imcomplete isr 2024-09-26 21:22:36 +08:00
HalfSweet
a8ef0c4cac fix: action running permissions 2024-09-24 21:59:05 +08:00
HalfSweet
b461f4e2d1 Add issue template (#257) 2024-09-24 21:52:15 +08:00
HalfSweet
5fb7d4d0e9 Add Github Action for Documentation Builds (#256) 2024-09-24 20:14:31 +08:00
sakumisu
8cb95b04cf chore(cmake): fix cdc acm config name 2024-09-19 20:57:23 +08:00
sakumisu
df7ecdf019 docs: update memory usage 2024-09-19 20:57:05 +08:00
sakumisu
68bf529608 fix(class/msc/usbd_msc): fix warning and add check for CONFIG_USBDEV_MSC_MAX_BUFSIZE 2024-09-19 20:25:11 +08:00
sakumisu
02340e0f44 chore: static code analysis 2024-09-19 09:50:18 +08:00
CCHhui
171b36e766 fix(core/usbh_core): Fix raw_config_desc heap out of bounds 2024-09-16 22:48:35 +08:00
sakumisu
0371bb921c docs: update rst 2024-09-11 22:26:29 +08:00
sakumisu
7ec7891fe4 update(demo): set bNumConfigurations with zero in Device Qualifier Descriptor, we do not request other speed desc as default 2024-09-09 22:48:18 +08:00
sakumisu
da391c6cf9 docs: update rst framework 2024-09-08 22:12:35 +08:00
sakumisu
b56b67182a refactor(class/audio/usbh_audio): refactor getting audio control info 2024-09-08 22:12:29 +08:00
sakumisu
e6fde5efab fix(port/dwc2): fix dwc2 rx fifo size, remove divided by 4 2024-09-08 22:11:38 +08:00
sakumisu
0487af6900 fix(port/dwc2): reset dma burst then modify, clear HCINT intstatus first 2024-09-08 22:11:38 +08:00
wangyz1997
be2880a7e8 fix(port/dwc2): fix typo 2024-09-08 22:11:38 +08:00
sakumisu
97e2a38b4a chore(cmake): do not use env variable 2024-09-08 22:11:38 +08:00
sakumisu
a139a70782 update(usbh_core): add terminate char for raw_config_desc 2024-09-07 22:43:43 +08:00
sakumisu
cb6a0c2ad6 chore(cherrymp): add license 2024-09-07 22:42:27 +08:00
sakumisu
bacacdb32c update: remove uvc queue 2024-09-06 22:24:16 +08:00
sakumisu
0323ffb424 update(class/cdc): set cdc acm bFunctionProtocol to 0x00 2024-09-04 22:06:14 +08:00
sakumisu
89e93f6c93 chore(scons): fix missing libpath 2024-09-02 18:57:15 +08:00
sakumisu
1deab668ef fix(port/ehci/usb_glue_ma35d0): fix typo 2024-09-02 18:54:53 +08:00
sakumisu
fbe2e3f8a3 fix(class/msc/usbd_msc): fix missing return value 2024-09-02 18:54:11 +08:00
sakumisu
d03dfe43ca update(port/dwc2/usb_hc_dwc2): power enable at last for common with other host ip 2024-09-01 11:59:11 +08:00
sakumisu
e42e99e975 update(platform/usbh_lwip): check lwip min stack size 2024-08-31 21:01:36 +08:00
sakumisu
8a7979378d update(osal): add error log and assert when alloc fail, and stop working 2024-08-31 18:23:00 +08:00
sakumisu
a8a5d95f8f fix(platform/rtthread/usbh_dfs): fix mem free 2024-08-31 16:08:10 +08:00
sakumisu
02ac1db3ff docs: update logo 2024-08-30 20:35:35 +08:00
tyustli
0d561ea313 Update usb_dc_dwc2.c
According to DS, the status register is W1C, |= will read the register first, write 1 to the corresponding bit, then write the register, if there is more than one status, it will be cleared by mistake. I'm not sure if other IP dcd's have the same problem?
2024-08-29 09:43:11 +08:00
sakumisu
e603389638 docs: release v1.4.0 2024-08-26 19:53:58 +08:00
sakumisu
b932cc5803 chore(cmake): update chipidea and threadx 2024-08-26 19:53:58 +08:00
sakumisu
5f43dc8662 feat(osal): add threadx port 2024-08-26 19:53:58 +08:00
Zhihong Chen
f5ce56990c usbd_core: add usb_device_is_suspend() API
- add usb_device_is_suspend() API

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-08-26 11:10:28 +08:00
sakumisu
f517adcf6d fix(port/bl): overflow check 2024-08-25 20:19:33 +08:00
sakumisu
2a563dc41f feat(port/chipidea): add chipidea port, add nxp mxc glue for chipidea and ehci 2024-08-25 20:19:25 +08:00
sakumisu
b045a1d490 fix(core/usbh_core.c): fix error name 2024-08-24 15:53:19 +08:00
sakumisu
563fbf58e1 update(port/hpm): check resume in port change 2024-08-23 22:36:14 +08:00
sakumisu
8435f1af32 chore(cmake): use config to enable lwip port 2024-08-23 22:36:03 +08:00
Zhihong Chen
2726e2e7b6 port: hpmicro: add USBH_USE_CUSTOM_ISR add USBD_USE_CUSTOM_ISR to control isr
- add USBH_USE_CUSTOM_ISR add USBD_USE_CUSTOM_ISR to control isr

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-08-23 13:57:45 +08:00
sakumisu
e8b22163bb update(port/dwc2/usb_dc_dwc2): add busid for functions to support multi ip 2024-08-22 20:36:28 +08:00
sakumisu
35da8d6747 fix: fix -Wunused-parameter warning with -Wextra cflag 2024-08-21 20:08:47 +08:00
sakumisu
43dc854b4d docs: update doc 2024-08-21 20:04:18 +08:00
sakumisu
f0fc75179e update(class/hid/usbh_hid): read report size from hid desc 2024-08-18 20:54:39 +08:00
sakumisu
f1e7043384 chore(kconfig): change description 2024-08-18 15:22:27 +08:00
sakumisu
e4954d4194 feat: add usb adb device with cherrysh 2024-08-17 21:06:06 +08:00
Zhihong Chen
07c6c296ed HPMicro: update usb_dc_hpm.c
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-08-16 21:32:09 +08:00
Zhihong Chen
500367dd82 port: ehci: should not be clear CSC/PEC/OCC flag when usb_hc_init()
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-08-16 21:32:09 +08:00
sakumisu
1efc29be5f feat(common): add usb_hexdump for test 2024-08-16 14:23:14 +08:00
sakumisu
143a5ce3fd refactor: move CHERRYUSB_VERSION and CHERRYUSB_VERSION_STR into usb_version.h 2024-08-16 14:16:45 +08:00
sakumisu
b171b28a75 refactor(class/cdc): rename usbd_cdc to usbd_cdc_acm 2024-08-16 14:16:08 +08:00
udoudou
668e414917 Fix IDF compilation error 2024-08-16 00:18:30 +08:00
sakumisu
03f8711b20 update(cherrymp): rename to cherrymp 2024-08-15 17:51:54 +08:00
sakumisu
393756f111 fix(class): use different buffer for cdc_acm,hid,msc,serial 2024-08-15 17:34:02 +08:00
sakumisu
4a252c3f73 update: idf config update 2024-08-14 21:56:40 +08:00
Yang Xijing
4b2000b405 Correct spelling errors. 2024-08-14 17:29:18 +08:00
sakumisu
9720eb2f76 docs: update png 2024-08-13 21:57:43 +08:00
sakumisu
68badf6f4c fix(port/dwc2): check idle when flush fifo, add delay for dwc2_set_mode 2024-08-13 18:10:36 +08:00
sakumisu
907d23871e fix(class/hid): fix typo 2024-08-13 18:10:07 +08:00
sakumisu
70944027c5 chore: update cmake and kconfig 2024-08-12 22:28:45 +08:00
sakumisu
a41da8928e feat(osal): import idf osal from udoudou/esp_cherryusb 2024-08-12 22:27:29 +08:00
sakumisu
bbcc767465 update(demo): change uint32_t to uintptr_t for 64bit cpu register 2024-08-09 22:49:46 +08:00
sakumisu
72e8eb7d84 feat(demo/msc_ram_template): add api for msc polling 2024-08-09 22:47:25 +08:00
zhugengyu
18d9c21553 Add PUSB2 and XHCI driver and RTOS glue (#236) 2024-08-09 22:43:22 +08:00
sakumisu
cbd6955bde fix(class/msc/usbd_msc): fix spelling 2024-08-08 18:11:23 +08:00
sakumisu
b4bbe69d12 feat(class/msc/usbd_msc): add msc polling mode to move read & write from isr to while1 2024-08-08 18:03:30 +08:00
Kevincoooool
e1cbccc58a Modifying the USB Int Source to support esp32p4 2024-08-07 12:08:10 +08:00
LiPeng
dfc90da28a Fix the bug that USBD_EVENT_DEINIT was not notified correctly 2024-08-06 14:10:07 +08:00
wangzongqiang
8451bc64bb change hid_mouse_report 2024-08-05 16:05:40 +08:00
sakumisu
3fc30cd058 update(demo/bootuf2): use flash cache 2024-07-30 20:27:25 +08:00
sakumisu
e95387c558 update(port/hpm/usb_dc_hpm): remove phcd clear 2024-07-30 19:53:21 +08:00
sakumisu
35a76f58bb update(port/hpm/usb_dc_hpm): enable resume handler 2024-07-30 18:12:46 +08:00
sakumisu
564d568732 fix(core/usbd_core): fix self powered check 2024-07-30 17:46:02 +08:00
sakumisu
9394f1f8d6 feat(port/dwc2): import kendryte glue from k230_sdk 2024-07-27 19:28:07 +08:00
sakumisu
bef45dc360 feat(port): add remote wakeup api 2024-07-26 22:02:01 +08:00
sakumisu
50b62c946d feat(core/usbd_core): support webusb 2024-07-25 21:39:36 +08:00
sakumisu
b399ff63ce feat(demo): add uf2 demo 2024-07-23 23:08:37 +08:00
sakumisu
4c4ee7f003 chore(docs): update rst 2024-07-23 20:13:28 +08:00
sakumisu
1c2fd3407a refactor(osal): use osal malloc and free, remove usb_malloc & usb_free macro 2024-07-23 19:37:54 +08:00
sakumisu
1927566dfc chore(docs): update rst 2024-07-21 17:44:57 +08:00
sakumisu
b7556b2ddc feat(class/vendor/wifi/usbh_bl616): add bl616 usbwifi driver 2024-07-19 23:23:32 +08:00
charschu
f1058c5e1a fix(port/dwc2/usb_dc_dwc2): fix lost ep0 setup intstatus by clear, for dwc2 version 4.3 2024-07-18 13:26:33 +08:00
sakumisu
643578e5be update(port/musb/usb_hc_musb): add portpower bit for commit e4b56cee 2024-07-15 18:09:55 +08:00
sakumisu
390e24fbe5 fix typo 2024-07-15 18:09:55 +08:00
sakumisu
ba02a48873 fix(demo/winusb1.0_template): fix WINUSB_IFx_WCIDProperties array 2024-07-15 18:09:55 +08:00
Till Harbaum
c766cbe91e Add host driver for XBOX controllers 2024-07-15 17:54:12 +08:00
Till Harbaum
9dd52fddf0 Workaround for BL616 power control 2024-07-15 17:01:57 +08:00
sakumisu
9c14ea19a9 fix(port/bl): fix test mode api 2024-07-13 10:13:37 +08:00
sakumisu
218fa8e85d update(demo/hid_mouse_template): draw circle to test report rate 2024-07-13 10:13:37 +08:00
sakumisu
eb147d7276 fix: fix typo 2024-07-13 10:13:37 +08:00
HaoboGu
c0bfbf7952 doc(readme): fix typo 2024-07-11 21:53:16 +08:00
sakumisu
1a9c1481f4 feat(core/usbd_core): support get hid desc request(0x21), support get status for remote wakeup & self powered 2024-07-11 13:58:16 +08:00
sakumisu
3d3c6bb5a2 fix(kconfig): fix spelling 2024-07-10 20:28:45 +08:00
Zhihong Chen
a942ec85a8 port: ehci: update init and deinit
- update init and deinit

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-07-09 21:11:36 +08:00
liuhy
a4a06573ea fix(port/musb/usb_dc_musb.c): usbd_ep_is_stalled api err. 2024-07-09 16:10:04 +08:00
sakumisu
7fab3c29f0 feat(port): implement usbd_ep_is_stalled api 2024-07-08 21:54:39 +08:00
sakumisu
4f3a3f496e feat(wifi/bl616): add bl616 usbwifi 2024-07-07 12:10:17 +08:00
sakumisu
e4b56cee89 update(hub): update hub macros and hub params for usb3.0 2024-07-07 12:07:12 +08:00
sakumisu
53114c0f16 refactor(e(o)hci): rename usb_hc_e(o)hci to usb_e(o)hci_reg, usb_hc_e(o)hci_priv to usb_hc_e(o)hci 2024-07-04 21:35:59 +08:00
sakumisu
29aaf56396 chore: release v1.3.1 2024-06-28 16:34:28 +08:00
sakumisu
c24eea6077 fix(port): enter section before alloc pipe 2024-06-28 16:33:45 +08:00
sakumisu
8fa517016e feat: add dhcp-server and dns-server module 2024-06-28 16:33:45 +08:00
sakumisu
35807fb9d9 fix(demo/cdc_ecm_template): device tcp/ip stack mac can't same as host 2024-06-28 16:33:45 +08:00
aozima
6e7502ec07 fix(demo/cdc_rndis_template): device tcp/ip stack mac can't same as host. 2024-06-28 16:33:45 +08:00
sakumisu
ab7ef4b116 chore(sconscript): update musb config 2024-06-25 18:08:42 +08:00
sakumisu
adee4b6727 update(class/vendor/net/usbh_asix): ignore the remain data that len is less than 4 2024-06-25 17:48:35 +08:00
sakumisu
6c92681e48 refactor(platform): add usbh_xxx_get_eth_txbuf api, especially for lwip pbuf list 2024-06-25 17:18:19 +08:00
sakumisu
31cd834ded chore(sconscript): fix spelling 2024-06-24 21:23:50 +08:00
sakumisu
a1274bad0a update(platform/rtthread/usbh_dfs): add hpm6e00 chip 2024-06-24 21:23:32 +08:00
sakumisu
c377ebfc61 update(class/video/usbd_video): make payload fill api common 2024-06-23 22:46:51 +08:00
sakumisu
1decfd0365 update(class/hub/usbh_hub): enumerate in order 2024-06-23 14:48:07 +08:00
sakumisu
dc0070b054 update(class/msc/usbh_msc): add MSC_INQUIRY_TIMEOUT to break quickly in inquiry stage 2024-06-23 14:46:50 +08:00
sakumisu
755d067650 update: check class->hport validity 2024-06-23 14:16:57 +08:00
sakumisu
69fe1598ed update(core/usbd_core): increase intf array from 8 to 16 2024-06-23 13:50:23 +08:00
sakumisu
0f8ec31981 update rst for malloc free 2024-06-22 19:33:43 +08:00
sakumisu
3bf74d2101 fix(common/usb_memcpy): fix warning in 64bit 2024-06-22 17:19:20 +08:00
sakumisu
10437a7d13 update(core/usbh_core): do not use slist, we use recursion 2024-06-22 15:44:09 +08:00
sakumisu
a1ab76dd3e chore(sconscript): add hc32 config 2024-06-22 00:23:48 +08:00
sakumisu
27394f5759 fix(demo/video_audiov1_hid_template): fix typo 2024-06-22 00:14:23 +08:00
yjun
740627cf3c update(demo/video): using endpoint desc init macro in video demo 2024-06-17 22:24:13 +08:00
yjun
7a26ad5082 update(class/video): add xu descriptor definition 2024-06-17 22:24:13 +08:00
yjun
ff2070d14b fix(class/video): vc header descriptor definition 2024-06-17 22:24:13 +08:00
sakumisu
0cb245e6d3 fix(common/usb_memcpy): fix missing USB_MEMCPY_H 2024-06-17 21:09:06 +08:00
sakumisu
556bf91879 fix(class/video/usb_video): fix missing bDescriptorSubType in vc header descriptor 2024-06-17 18:37:31 +08:00
sakumisu
5d87a750ac fix(core/usbh_core): fix missing free devaddr caused by 935325 2024-06-17 18:37:22 +08:00
sakumisu
8a4f210ee7 fix memcpy to strncpy 2024-06-16 23:40:15 +08:00
sakumisu
82f11fa647 fix(demo): fix missing usbh_int_urb_fill, musb will modify urb->transfer_buffer_length, this is a patch for musb 2024-06-16 22:24:08 +08:00
sakumisu
47e6ed1c75 fix(class/audio/usbh_audio): fix sample frequence 2024-06-16 20:59:46 +08:00
sakumisu
b4d54d2aa6 fix(core/usbh_core): fix get mult 2024-06-16 18:11:04 +08:00
sakumisu
96db9b96da update h264 macro 2024-06-16 16:08:01 +08:00
sakumisu
62da380c25 feat(demo): add uvc_uac_hid template 2024-06-16 10:03:22 +08:00
sakumisu
66e3ffb90d update readme 2024-06-15 21:31:36 +08:00
sakumisu
afa77ec20b update(video): add more video desc macros, like h264, yuv, add vc endpoint to choose, add yuv template 2024-06-15 17:54:56 +08:00
sakumisu
0f8c145d93 update(port/musb): config fifo from fifo table, add beken and es32 glue 2024-06-15 13:33:28 +08:00
sakumisu
3cf2d6da31 fix warning 2024-06-14 22:17:16 +08:00
sakumisu
bf9a236c9a fix(demo/hid_custom_inout_template): add missing macros 2024-06-14 20:45:47 +08:00
sakumisu
bf8e092627 remove print log for device, because we do not allow printf in isr 2024-06-14 10:02:12 +08:00
sakumisu
e9a7eb9eeb fix warning 2024-06-14 00:25:07 +08:00
sakumisu
277f3940f6 remove ununsed code 2024-06-14 00:25:02 +08:00
sakumisu
bf54bc2ff1 update(port/ehci): use static iso pool for iso urb to reduce alloc time 2024-06-11 21:59:37 +08:00
sakumisu
77af563898 add comments for dwc2 fifo macro 2024-06-11 21:58:17 +08:00
sakumisu
f57234e668 update port readme 2024-06-09 15:44:52 +08:00
sakumisu
3429f833f3 update(port/musb/usb_dc_musb): remove ununsed code 2024-06-09 15:27:21 +08:00
jinsc
9d265f2398 已在hc32f4a0上测试usbd的usb_glue_hc.c 2024-06-08 19:12:25 +08:00
sakumisu
935325175f remove old xhci patch 2024-06-07 21:51:33 +08:00
sakumisu
6fd87902b5 remove old version 2024-06-07 10:29:44 +08:00
sakumisu
b1660f743f update rst 2024-06-06 22:53:51 +08:00
sakumisu
f197716f52 update(port/dwc2/usb_hc_dwc2): add check for fifo with ep mps 2024-06-06 21:48:56 +08:00
sakumisu
62ed025ddc fix(port/musb/usbh_hc_musb): fix missing leave critical when return with error 2024-06-06 20:28:49 +08:00
yukelab
883c0a5dc5 review cdc-ecm enum success but comunication error
1. review usbd_cdc_ecm_eth_tx send data fail
2. review CDC_ECM_DESCRIPTOR_INIT macro wMaxSegmentSize parameter error
2024-06-05 14:39:00 +08:00
sakumisu
cf0137686d fix(class/cdc/usbd_cdc_ecm): fix build error 2024-06-05 10:19:20 +08:00
sakumisu
48a125b28d fix spelling 2024-06-01 23:13:26 +08:00
sakumisu
e2877d3fe0 update(demo/usb_host): remove ununsed net class 2024-06-01 23:10:04 +08:00
sakumisu
3429f73a65 update: add comments for net process, support len > 16K for ncm/rndis/asix/rtl8152 2024-06-01 18:54:51 +08:00
sakumisu
3c102bd265 update readme 2024-05-31 23:01:12 +08:00
sakumisu
ba098529af update(class/wireless/usbd_rndis): print max pkts and size in init msg resp 2024-05-31 22:44:19 +08:00
sakumisu
2d63b52d0b feat: use fast memcpy for net 2024-05-31 22:31:43 +08:00
sakumisu
5f28438eec fix(class/wireless/usbd_rndis): change total size to 1558 2024-05-30 16:29:45 +08:00
Chen Leeren
edf4e5c7fc Unify the number of endpoint names and fix a data receiving bug 2024-05-27 22:03:07 +08:00
sakumisu
865d2f5d96 refactor(platform): update platform support 2024-05-24 22:49:18 +08:00
324 changed files with 28509 additions and 12037 deletions

85
.github/ISSUE_TEMPLATE/1-bug-report.yml vendored Normal file
View File

@@ -0,0 +1,85 @@
name: "🐞 上报bug / Bug report"
description: "提交bug以让改进软件功能 / Create a report to help us improve"
labels: ["peding"]
body:
- type: markdown
attributes:
value: |
感谢上报新的问题请填写以下信息以帮助我们更好地理解问题。请注意如果您不按模板填写issue那您的issue可能会被关闭或者删除
我们的工作语言是中文或者英文请使用这两种语言之一填写issue。
Thank you for reporting a new issue! Please fill in the following information to help us better understand the problem. Please note that if you do not fill in the issue according to the template, your issue may be closed or deleted!
Our working languages are Chinese or English, please use one of these two languages to fill in the issue.
- type: textarea
id: bug-description
attributes:
label: 描述一下这个bug / Describe the bug
description: 请使用简介并详细的语句来描述这个bug。 / A clear and concise description of what the bug is.
placeholder: 我准备……我想要……但是实际上它……了 / I am doing ... What I expect is ... What actually happening is ...
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: 复现步骤 / To Reproduce
description: 按照下面的步骤可以复现bug / Steps to reproduce the behavior
placeholder: 首先……然后……接着…… / Go to '...', Click on '....', Scroll down to '....'
validations:
required: true
- type: textarea
id: target
attributes:
label: 设备信息 / Target Device
description: 您使用的板子/芯片型号、使用的引脚、以及USB IP类型 / Your target board/chip model, the pins you used, and the type of USB IP you used
placeholder: |-
板子型号HPM5301EVKLite
引脚PA24 PA25
USB IP/
validations:
required: true
- type: textarea
id: log
attributes:
label: 日志 / Log
description: 请提供输出 log
placeholder: |-
[D/USB] EP0 send 18 bytes, 0 remained
[D/USB] EP0 recv out status
[D/USB] EP0 send 0 bytes, 0 remained
[D/USB] EP0 send 18 bytes, 0 remained
[D/USB] EP0 recv out status
validations:
required: true
- type: markdown
attributes:
value: |
以下的部分仅在移植的时候需要填写,如果不是移植问题,请忽略这部分。
The following section is only required when porting, if it is not a porting issue, please ignore this section.
- type: textarea
id: configure
attributes:
label: 配置 / Configuration
description: 请确认 USB 中断,时钟,引脚,寄存器地址是否正确,并截图 / Please confirm that the USB interrupt, clock, pin, and register address are correct, and provide a screenshot
- type: textarea
id: USBIrq
attributes:
label: USB中断 / USB Interrupt
description: 请确认是否能进入USB中断
- type: textarea
id: cache
attributes:
label: 缓存 / Cache
description: 芯片是否带有 cache功能是否做了 no cache 处理,并截图 / Whether the chip has a cache function, whether no cache processing is done, and provide a screenshot
- type: checkboxes
id: bussiness
attributes:
label: 商业 / Business
description: 是否流片并销售 / Whether it is mass-produced and sold
options:
- label: 是 / Yes

17
.github/workflows/cppcheck.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Cppcheck action
on:
push:
pull_request:
jobs:
build:
name: cppcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: cppcheck
shell: bash
run: |
sudo apt install cppcheck
cppcheck --enable=warning,portability,performance --language=c --platform=unix32 --std=c99 --force . -i third_party/ -i class/template -i port/template/

28
.github/workflows/deploy-docs.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Deploy docs
on:
push:
branches:
- master
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: ammaraskar/sphinx-action@8.0.2
with:
docs-folder: "docs/"
- uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: docs/build/html

155
CMakeLists.txt Normal file
View File

@@ -0,0 +1,155 @@
cmake_minimum_required(VERSION 3.15)
if(BL_SDK_BASE)
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC_ACM 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)
set(CONFIG_CHERRYUSB_DEVICE_DCD "bl")
set(CONFIG_CHERRYUSB_HOST 1)
set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
set(CONFIG_CHERRYUSB_HOST_HID 1)
set(CONFIG_CHERRYUSB_HOST_MSC 1)
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
set(CONFIG_CHERRYUSB_HOST_CP210X 1)
set(CONFIG_CHERRYUSB_HOST_FTDI 1)
set(CONFIG_CHERRYUSB_HOST_PL2303 1)
set(CONFIG_CHERRYUSB_OSAL "freertos")
set(CONFIG_CHERRYUSB_HOST_HCD "ehci_bouffalo")
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
sdk_generate_library(cherryusb)
sdk_add_include_directories(${cherryusb_incs})
sdk_library_add_sources(${cherryusb_srcs})
sdk_library_add_sources(platform/none/usbh_lwip.c)
elseif(HPM_SDK_BASE)
set(CONFIG_CHERRYUSB_HOST 1)
set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
set(CONFIG_CHERRYUSB_HOST_HID 1)
set(CONFIG_CHERRYUSB_HOST_MSC 1)
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
# set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
set(CONFIG_CHERRYUSB_HOST_CP210X 1)
set(CONFIG_CHERRYUSB_HOST_FTDI 1)
set(CONFIG_CHERRYUSB_HOST_PL2303 1)
set(CONFIG_CHERRYUSB_HOST_BL616 1)
set(CONFIG_CHERRYUSB_OSAL "freertos")
set(CONFIG_CHERRYUSB_HOST_HCD "ehci_hpm")
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
sdk_inc(${cherryusb_incs})
sdk_src(${cherryusb_srcs})
sdk_src(platform/none/usbh_lwip.c)
elseif(ESP_PLATFORM)
set(CONFIG_CHERRYUSB_DEVICE_DCD "dwc2_esp")
set(CONFIG_CHERRYUSB_HOST_HCD "dwc2_esp")
set(CONFIG_CHERRYUSB_OSAL "idf")
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
set(ldfragments "osal/idf/linker.lf")
if(CONFIG_CHERRYUSB_HOST_CDC_ECM OR CONFIG_CHERRYUSB_HOST_CDC_RNDIS OR CONFIG_CHERRYUSB_HOST_CDC_NCM
OR CONFIG_CHERRYUSB_HOST_ASIX OR CONFIG_CHERRYUSB_HOST_RTL8152 OR CONFIG_CHERRYUSB_HOST_BL616)
list(APPEND cherryusb_srcs platform/none/usbh_lwip.c)
idf_component_get_property(lwip lwip COMPONENT_LIB)
target_compile_definitions(${lwip} PRIVATE "-DPBUF_POOL_BUFSIZE=1600")
endif()
idf_component_get_property(freertos_include freertos ORIG_INCLUDE_PATH)
idf_component_register(SRCS ${cherryusb_srcs}
INCLUDE_DIRS ${cherryusb_incs} ${freertos_include}
PRIV_REQUIRES usb
LDFRAGMENTS ${ldfragments}
)
if(CONFIG_CHERRYUSB_HOST)
target_linker_script(${COMPONENT_LIB} INTERFACE "osal/idf/usbh_class_info.ld")
# 强制链接器不删除符号
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_acm_class_info")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_data_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_HID)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u hid_custom_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_MSC)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u msc_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_ecm_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u rndis_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_ncm_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_VIDEO)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u video_ctrl_class_info")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u video_streaming_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_AUDIO)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u audio_ctrl_intf_class_info")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u audio_streaming_intf_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
if(CONFIG_USBHOST_BLUETOOTH_HCI_H4)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bluetooth_h4_nrf_class_info")
else()
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bluetooth_class_info")
endif()
endif()
if(CONFIG_CHERRYUSB_HOST_ASIX)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u asix_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_RTL8152)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u rtl8152_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_FTDI)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ftdi_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_CH34X)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ch34x_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_CP210X)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cp210x_class_info")
endif()
if(CONFIG_CHERRYUSB_HOST_PL2303)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u pl2303_class_info")
endif()
endif()
if(CONFIG_CHERRYUSB)
set_source_files_properties("class/audio/usbd_audio.c"
PROPERTIES COMPILE_FLAGS
-Wno-maybe-uninitialized)
endif()
endif()

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -1,6 +1,6 @@
# Kconfig file for CherryUSB
menuconfig CHERRYUSB
bool "Using CherryUSB"
bool "CherryUSB Configuration"
default n
if CHERRYUSB
@@ -36,14 +36,30 @@ if CHERRYUSB
bool "dwc2_at"
config CHERRYUSB_DEVICE_DWC2_GD
bool "dwc2_gd"
config CHERRYUSB_DEVICE_DWC2_HC
bool "dwc2_hc"
config CHERRYUSB_DEVICE_DWC2_KENDRYTE
bool "dwc2_kendryte"
config CHERRYUSB_DEVICE_DWC2_CUSTOM
bool "dwc2_custom"
config CHERRYUSB_DEVICE_MUSB_STANDARD
bool "musb_standard"
config CHERRYUSB_DEVICE_MUSB_ES
bool "musb_es"
config CHERRYUSB_DEVICE_MUSB_SUNXI
bool "musb_sunxi"
config CHERRYUSB_DEVICE_MUSB_BK
bool "musb_bk"
config CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
config CHERRYUSB_DEVICE_KINETIS_MCX
bool "kinetis_mcx"
config CHERRYUSB_DEVICE_KINETIS_MM32
bool "kinetis_mm32"
config CHERRYUSB_DEVICE_KINETIS_CUSTOM
bool "kinetis_custom"
config CHERRYUSB_DEVICE_CHIPIDEA_MCX
bool "chipidea_mcx"
config CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
bool "chipidea_custom"
config CHERRYUSB_DEVICE_BL
bool "bouffalo"
config CHERRYUSB_DEVICE_HPM
@@ -101,9 +117,14 @@ if CHERRYUSB
prompt "Enable usb dfu device"
default n
config CHERRYUSB_DEVICE_ADB
bool
prompt "Enable usb adb device"
default n
choice
prompt "Select usb device template"
default CHERRYUSB_DEVICE_TEMPLATE
default CHERRYUSB_DEVICE_TEMPLATE_NONE
config CHERRYUSB_DEVICE_TEMPLATE_NONE
bool "none (Implement it yourself)"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
@@ -158,28 +179,44 @@ if CHERRYUSB
bool "ehci_hpm"
config CHERRYUSB_HOST_EHCI_AIC
bool "ehci_aic"
config CHERRYUSB_HOST_EHCI_NUVOTON_NUC980
bool "ehci_nuvoton_nuc980"
config CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0
bool "ehci_nuvoton_ma35d0"
config CHERRYUSB_HOST_EHCI_MCX
bool "ehci_mcx"
config CHERRYUSB_HOST_EHCI_NUC980
bool "ehci_nuc980"
config CHERRYUSB_HOST_EHCI_MA35D0
bool "ehci_ma35d0"
config CHERRYUSB_HOST_EHCI_CUSTOM
bool "ehci_custom"
config CHERRYUSB_HOST_DWC2_ST
bool "dwc2_st"
config CHERRYUSB_HOST_DWC2_ESP
bool "dwc2_esp"
config CHERRYUSB_HOST_DWC2_HC
bool "dwc2_hc"
config CHERRYUSB_HOST_DWC2_KENDRYTE
bool "dwc2_kendryte"
config CHERRYUSB_HOST_DWC2_CUSTOM
bool "dwc2_custom"
config CHERRYUSB_HOST_MUSB_STANDARD
bool "musb_standard"
config CHERRYUSB_HOST_MUSB_ES
bool "musb_es"
config CHERRYUSB_HOST_MUSB_SUNXI
bool "musb_sunxi"
config CHERRYUSB_HOST_MUSB_BK
bool "musb_bk"
config CHERRYUSB_HOST_MUSB_CUSTOM
bool "musb_custom"
config CHERRYUSB_HOST_PUSB2
bool "pusb2"
config CHERRYUSB_HOST_XHCI
config CHERRYUSB_HOST_XHCI_PHYTIUM
bool "xhci_phytium"
config CHERRYUSB_HOST_XHCI_CUSTOM
bool "xhci"
config CHERRYUSB_HOST_KINETIS_MCX
bool "kinetis_mcx"
config CHERRYUSB_HOST_KINETIS_MM32
bool "kinetis_mm32"
config CHERRYUSB_HOST_KINETIS_CUSTOM
bool "kinetis_custom"
endchoice
config CHERRYUSB_HOST_CDC_ACM
@@ -197,19 +234,22 @@ if CHERRYUSB
prompt "Enable usb msc driver"
default n
config CHERRYUSB_HOST_CDC_RNDIS
bool
prompt "Enable usb rndis driver"
default n
config CHERRYUSB_HOST_CDC_ECM
bool
prompt "Enable usb cdc ecm driver"
select USBHOST_PLATFORM_CDC_ECM
default n
config CHERRYUSB_HOST_CDC_RNDIS
bool
prompt "Enable usb rndis driver"
select USBHOST_PLATFORM_CDC_RNDIS
default n
config CHERRYUSB_HOST_CDC_NCM
bool
prompt "Enable usb cdc ncm driver"
select USBHOST_PLATFORM_CDC_NCM
default n
config CHERRYUSB_HOST_VIDEO
@@ -230,11 +270,13 @@ if CHERRYUSB
config CHERRYUSB_HOST_ASIX
bool
prompt "Enable usb asix driver"
select USBHOST_PLATFORM_ASIX
default n
config CHERRYUSB_HOST_RTL8152
bool
prompt "Enable usb rtl8152 driver"
select USBHOST_PLATFORM_RTL8152
default n
config CHERRYUSB_HOST_FTDI
@@ -252,6 +294,31 @@ if CHERRYUSB
prompt "Enable usb cp210x driver"
default n
config CHERRYUSB_HOST_PL2303
bool
prompt "Enable usb pl2303 driver"
default n
config CHERRYUSB_HOST_AOA
bool
prompt "Enable usb aoa driver"
default n
config USBHOST_PLATFORM_CDC_ECM
bool
config USBHOST_PLATFORM_CDC_RNDIS
bool
config USBHOST_PLATFORM_CDC_NCM
bool
config USBHOST_PLATFORM_ASIX
bool
config USBHOST_PLATFORM_RTL8152
bool
config CHERRYUSB_HOST_TEMPLATE
bool
prompt "Use usb host template"
@@ -270,34 +337,9 @@ if CHERRYUSB
depends on CHERRYUSB_HOST_HID
config TEST_USBH_MSC
int
prompt "demo for test msc, do not enable because it has used dfs instead"
prompt "demo for test msc"
default 0
depends on CHERRYUSB_HOST_MSC
config TEST_USBH_CDC_ECM
int
prompt "demo for test cdc ecm"
default 0
depends on CHERRYUSB_HOST_CDC_ECM
config TEST_USBH_CDC_NCM
int
prompt "demo for test cdc ncm"
default 0
depends on CHERRYUSB_HOST_CDC_NCM
config TEST_USBH_RNDIS
int
prompt "demo for test cdc rndis"
default 0
depends on CHERRYUSB_HOST_CDC_RNDIS
config TEST_USBH_ASIX
int
prompt "demo for test asix"
default 0
depends on CHERRYUSB_HOST_ASIX
config TEST_USBH_RTL8152
int
prompt "demo for test rtl8152"
default 0
depends on CHERRYUSB_HOST_RTL8152
endif
endif

130
README.md
View File

@@ -1,6 +1,16 @@
# CherryUSB
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
<p align="center">
<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"><a>
<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
<a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
<a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
</p>
[中文版](./README_zh.md)
<p align="center">
<a href="./README_zh.md">中文</a>
|
<a href="./README.md">English</a>
</p>
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
@@ -17,12 +27,12 @@ In order to make it easier for users to learn USB basics, enumeration, driver lo
- Class-drivers and porting-drivers are templating and simplification
- Clear API classification (slave: initialisation, registration api, command callback api, data sending and receiving api; host: initialisation, lookup api, data sending and receiving api)
### Easy to use USB
### Easy to use USB
In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
- Equivalent to using uart tx dma/uart rx dma
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does the packetization process)
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does it)
### Easy to bring out USB performance
@@ -32,31 +42,18 @@ Taking into account USB performance issues and trying to achieve the theoretical
- Memory zero copy
- If IP has DMA then uses DMA mode (DMA with hardware packetization)
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
- Subcontracting function is handled in interrupt
- Packetization is handled in interrupt
## Directoy Structure
```
.
├── class
├── common
├── core
├── demo
├── docs
├── osal
├── packet capture
└── port
└── tools
```
## Directory Structure
| Directory | Description |
|:-------------:|:---------------------------:|
|class | usb class driver |
|common | usb spec macros and utils |
|core | usb core implementation |
|demo | different chips demo |
|demo | usb device and host demo |
|osal | os wrapper |
|platform | class support for other os |
|docs | doc for guiding |
|port | usb dcd and hcd porting |
|tools | tool url |
@@ -78,21 +75,23 @@ CherryUSB Device Stack has the following functions
- Support Device Firmware Upgrade CLASS (DFU)
- Support USB MIDI CLASS (MIDI)
- Support Remote NDIS (RNDIS)
- Support WINUSB1.0、WINUSB2.0(with BOS)
- Support WINUSB1.0、WINUSB2.0、WEBUSB、BOS
- Support Vendor class
- Support UF2
- Support Android Debug Bridge (Only support shell)
- Support multi device with the same USB IP
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
|usbd_core.c | ~4400 | 512(default) + 320 | 0 | 0 |
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|usbd_msc.c | ~3800 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|usbd_video.c | ~2600 | 0 | 84 | 0 |
|usbd_rndis.c | ~2100 | 2 * 1580(default)+156+8 | 76 | 0 |
## Host Stack Overview
@@ -100,6 +99,7 @@ The CherryUSB Host Stack has a standard enumeration implementation for devices m
CherryUSB Host Stack has the following functions
- Support low speed, full speed, high speed and super speed devices
- Automatic loading of supported Class drivers
- Support blocking transfers and asynchronous transfers
- Support Composite Device
@@ -107,12 +107,13 @@ CherryUSB Host Stack has the following functions
- Support Communication Device Class (CDC_ACM, CDC_ECM)
- Support Human Interface Device (HID)
- Support Mass Storage Class (MSC)
- Support USB Video CLASS (commercial charge)
- Support USB Audio CLASS (commercial charge)
- Support USB Video CLASS (UVC1.0、UVC1.5)
- Support USB Audio CLASS (UAC1.0)
- Support Remote NDIS (RNDIS)
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
- Support Vendor class
- Support Vendor class (serial, net, wifi)
- Support USB modeswitch
- Support Android Open Accessory
- Support multi host with the same USB IP
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
@@ -121,16 +122,17 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_core.c | ~9000 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|usbh_hub.c | ~6000 | 32 + 4 * (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~900 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2700 | 64 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1400 | 256 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3800 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~4100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~4200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~3300 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros
@@ -158,13 +160,14 @@ Only standard and commercial USB IP are listed.
| IP | device | host | Support status |
|:----------------:|:----------:|:--------:|:--------------:|
| OHCI(intel) | none | OHCI | × |
| OHCI(intel) | none | OHCI | |
| EHCI(intel) | none | EHCI | √ |
| XHCI(intel) | none | XHCI | √ |
| UHCI(intel) | none | UHCI | × |
| UHCI(intel) | none | UHCI | × |
| DWC2(synopsys) | DWC2 | DWC2 | √ |
| MUSB(mentor) | MUSB | MUSB | √ |
| FOTG210(faraday)| FOTG210 | EHCI | √ |
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
| CDNS3(cadence) | CDNS3 | XHCI | × |
| DWC3(synopsys) | DWC3 | XHCI | × |
@@ -186,17 +189,32 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Package Support
CherryUSB package is available as follows:
- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
## Commercial Support
Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
## Contact
@@ -206,4 +224,4 @@ CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
Thanks to the following companies for their support (in no particular order).
<img src="docs/assets/bouffalolab.jpg" width="100" height="100"/> <img src="docs/assets/hpmicro.jpg" width="100" height="100" /> <img src="docs/assets/eastsoft.jpg" width="100" height="100" /> <img src="docs/assets/rtthread.jpg" width="100" height="100" /> <img src="docs/assets/sophgo.jpg" width="100" height="100" /> <img src="docs/assets/phytium.jpg" width="100" height="100" /> <img src="docs/assets/thead.jpg" width="100" height="100" /> <img src="docs/assets/nuvoton.jpg" width="100" height="100" /> <img src="docs/assets/artinchip.jpg" width="100" height="100" />
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" /> <img src="docs/assets/canaan.jpg" width="100" height="80" />

View File

@@ -1,6 +1,16 @@
# CherryUSB
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
<p align="center">
<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"><a>
<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
<a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
<a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
</p>
[English](./README.md)
<p align="center">
<a href="./README_zh.md">中文</a>
|
<a href="./README.md">English</a>
</p>
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
@@ -22,7 +32,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma因此设计的数据收发类接口具备以下优点
- 等价于使用 uart tx dma/uart rx dma
- 收发长度没有限制,用户不需要关心 USB 分包过程porting 驱动做分包过程
- 收发长度没有限制,用户不需要关心 USB 分包过程(分包过程在 porting 中处理
### 易于发挥 USB 性能
@@ -32,30 +42,19 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
- Memory zero copy
- IP 如果带 DMA 则使用 DMA 模式DMA 带硬件分包功能)
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
- 分包功能在中断中处理
- 分包过程在中断中执行
## 目录结构
```
.
├── class
├── common
├── core
├── demo
├── docs
├── osal
└── port
└── tools
```
| 目录名 | 描述 |
|:-------------:|:-------------------------------:|
|class | usb class 类主从驱动 |
|common | usb spec 定义、常用宏、标准接口定义 |
|core | usb 主从协议栈核心实现 |
|demo | 示例 |
|demo | 主从 class demo |
|docs | 文档 |
|osal | os 封装层 |
|platform | 其他 os 全家桶适配 |
|port | usb 主从需要实现的 porting 接口 |
|tools | 工具链接 |
@@ -76,21 +75,23 @@ CherryUSB Device 协议栈当前实现以下功能:
- 支持 Device Firmware Upgrade CLASS (DFU)
- 支持 USB MIDI CLASS (MIDI)
- 支持 Remote NDIS (RNDIS)
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
- 支持 Vendor 类 class
- 支持 UF2
- 支持 Android Debug Bridge (Only support shell)
- 支持相同 USB IP 的多从机
CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
|usbd_core.c | ~4400 | 512(default) + 320 | 0 | 0 |
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|usbd_msc.c | ~3800 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|usbd_video.c | ~2600 | 0 | 84 | 0 |
|usbd_rndis.c | ~2100 | 2 * 1580(default)+156+8 | 76 | 0 |
## Host 协议栈简介
@@ -98,6 +99,7 @@ CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了
CherryUSB Host 协议栈当前实现以下功能:
- 支持 low speed, full speed, high speed 和 super speed 设备
- 自动加载支持的Class 驱动
- 支持阻塞式传输和异步传输
- 支持复合设备
@@ -105,12 +107,13 @@ CherryUSB Host 协议栈当前实现以下功能:
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
- 支持 Human Interface Device (HID)
- 支持 Mass Storage Class (MSC)
- Support USB Video CLASS(商业收费)
- Support USB Audio CLASS(商业收费)
- Support USB Video CLASS (UVC1.0、UVC1.5)
- Support USB Audio CLASS (UAC1.0)
- 支持 Remote NDIS (RNDIS)
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
- 支持 Vendor 类 class
- 支持 Vendor 类 class (serial, net, wifi)
- 支持 USB modeswitch
- 支持 Android Open Accessory
- 支持相同 USB IP 的多主机
同时CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
@@ -119,16 +122,17 @@ CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_core.c | ~9000 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|usbh_hub.c | ~6000 | 32 + 4 * (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~900 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2700 | 64 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1400 | 256 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3800 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~4100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~4200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~3300 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
其中,`sizeof(struct usbh_hub)``sizeof(struct usbh_hubport)` 受以下宏影响:
@@ -156,13 +160,14 @@ x 受以下宏影响:
| IP | device | host | Support status |
|:----------------:|:----------:|:--------:|:--------------:|
| OHCI(intel) | none | OHCI | × |
| OHCI(intel) | none | OHCI | |
| EHCI(intel) | none | EHCI | √ |
| XHCI(intel) | none | XHCI | √ |
| UHCI(intel) | none | UHCI | × |
| UHCI(intel) | none | UHCI | × |
| DWC2(synopsys) | DWC2 | DWC2 | √ |
| MUSB(mentor) | MUSB | MUSB | √ |
| FOTG210(faraday)| FOTG210 | EHCI | √ |
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
| CDNS3(cadence) | CDNS3 | XHCI | × |
| DWC3(synopsys) | DWC3 | XHCI | × |
@@ -185,19 +190,34 @@ CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Contact
## 软件包支持
CherryUSB 软件包可以通过以下方式获取:
- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
## 商业支持
参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html 。
## 联系
CherryUSB QQ 群:642693751
CherryUSB 微信群:与我联系后邀请加入
@@ -206,4 +226,4 @@ CherryUSB 微信群:与我联系后邀请加入
感谢以下企业支持(顺序不分先后)。
<img src="docs/assets/bouffalolab.jpg" width="100" height="100"/> <img src="docs/assets/hpmicro.jpg" width="100" height="100" /> <img src="docs/assets/eastsoft.jpg" width="100" height="100" /> <img src="docs/assets/rtthread.jpg" width="100" height="100" /> <img src="docs/assets/sophgo.jpg" width="100" height="100" /> <img src="docs/assets/phytium.jpg" width="100" height="100" /> <img src="docs/assets/thead.jpg" width="100" height="100" /> <img src="docs/assets/nuvoton.jpg" width="100" height="100" /> <img src="docs/assets/artinchip.jpg" width="100" height="100" />
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" /> <img src="docs/assets/canaan.jpg" width="100" height="80" />

View File

@@ -15,6 +15,8 @@ path += [cwd + '/class/vendor/net']
path += [cwd + '/class/vendor/serial']
src = []
LIBS = []
LIBPATH = []
CPPDEFINES = []
# USB DEVICE
@@ -40,15 +42,33 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_GD']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_gd.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_HC']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_hc.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_KENDRYTE']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_kendryte.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_CUSTOM']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_STANDARD']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_ES']):
src += Glob('port/musb/usb_dc_musb.c')
src += Glob('port/musb/usb_glue_es.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
src += Glob('port/musb/usb_dc_musb.c')
src += Glob('port/musb/usb_glue_sunxi.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_BK']):
src += Glob('port/musb/usb_dc_musb.c')
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
src += Glob('port/musb/usb_dc_musb.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_KINETIS_MCX']):
src += Glob('port/kinetis/usb_dc_kinetis.c')
src += Glob('port/kinetis/usb_glue_mcx.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_KINETIS_CUSTOM']):
src += Glob('port/kinetis/usb_dc_kinetis.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
src += Glob('port/chipidea/usb_dc_chipidea.c')
src += Glob('port/chipidea/usb_glue_mcx.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_BL']):
src += Glob('port/bouffalolab/usb_dc_bl.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
@@ -61,9 +81,18 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('port/ch32/usb_dc_usbhs.c')
else:
src += Glob('port/ch32/usb_dc_usbfs.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
path += [cwd + '/port/xhci/rt-thread']
src += Glob('port/pusb2/rt-thread/usb_dc_glue_phytium.c')
if GetDepend(['ARCH_ARMV8']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_dc_a64.a']
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_dc_a32_softfp_neon.a']
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ACM']):
src += Glob('class/cdc/usbd_cdc.c')
src += Glob('class/cdc/usbd_cdc_acm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
src += Glob('class/hid/usbd_hid.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC']):
@@ -133,10 +162,14 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_aic.c')
src += Glob('port/ohci/usb_hc_ohci.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_NUC980']):
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_MCX']):
path += [cwd + '/port/chipidea']
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_mcx.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUC980']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_nuc980.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0']):
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_MA35D0']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_ma35d0.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_CUSTOM']):
@@ -147,15 +180,49 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ESP']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
src += Glob('port/dwc2/usb_glue_esp.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_KENDRYTE']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
src += Glob('port/dwc2/usb_glue_kendryte.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_CUSTOM']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_STANDARD']):
src += Glob('port/musb/usb_hc_musb.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_ES']):
src += Glob('port/musb/usb_hc_musb.c')
src += Glob('port/musb/usb_glue_es.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
src += Glob('port/musb/usb_hc_musb.c')
src += Glob('port/musb/usb_glue_sunxi.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_BK']):
src += Glob('port/musb/usb_hc_musb.c')
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
src += Glob('port/musb/usb_hc_musb.c')
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_MCX']):
src += Glob('port/kinetis/usb_hc_kinetis.c')
src += Glob('port/kinetis/usb_glue_mcx.c')
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_CUSTOM']):
src += Glob('port/kinetis/usb_hc_kinetis.c')
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
path += [cwd + '/port/pusb2/rt-thread']
src += Glob('port/pusb2/rt-thread/usb_hc_glue_phytium.c')
if GetDepend(['ARCH_ARMV8']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_hc_a64.a']
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_hc_a32_softfp_neon.a']
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
path += [cwd + '/port/xhci/phytium/rt-thread']
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium_plat.c')
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium.c')
if GetDepend(['ARCH_ARMV8']):
LIBPATH = [cwd + '/port/xhci/phytium']
LIBS = ['libxhci_a64.a']
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/xhci/phytium']
LIBS = ['libxhci_a32_softfp_neon.a']
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ACM']):
src += Glob('class/cdc/usbh_cdc_acm.c')
@@ -191,13 +258,20 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
src += Glob('demo/usb_host.c')
if GetDepend('RT_USING_DFS'):
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
if GetDepend('RT_USING_DFS') and GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
src += Glob('platform/rtthread/usbh_dfs.c')
src += Glob('third_party/rt-thread-5.0/usb_msh.c')
src += Glob('third_party/rt-thread-5.0/usb_check.c')
if GetDepend('PKG_CHERRYUSB_HOST_CDC_ECM') \
or GetDepend('PKG_CHERRYUSB_HOST_CDC_RNDIS') \
or GetDepend('PKG_CHERRYUSB_HOST_CDC_NCM') \
or GetDepend('PKG_CHERRYUSB_HOST_ASIX') \
or GetDepend('PKG_CHERRYUSB_HOST_RTL8152'):
src += Glob('platform/rtthread/usbh_lwip.c')
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
src += Glob('platform/rtthread/usb_msh.c')
src += Glob('platform/rtthread/usb_check.c')
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], LIBS = LIBS, LIBPATH=LIBPATH, CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')

View File

@@ -1,5 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 3
PATCHLEVEL = 0
VERSION_MINOR = 4
PATCHLEVEL = 2
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

@@ -36,14 +36,17 @@ ${CMAKE_CURRENT_LIST_DIR}/class/audio
${CMAKE_CURRENT_LIST_DIR}/class/video
${CMAKE_CURRENT_LIST_DIR}/class/wireless
${CMAKE_CURRENT_LIST_DIR}/class/midi
${CMAKE_CURRENT_LIST_DIR}/class/adb
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
${CMAKE_CURRENT_LIST_DIR}/class/aoa
)
if(CONFIG_CHERRYUSB_DEVICE)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
if(CONFIG_CHERRYUSB_DEVICE_CDC)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc.c)
if(CONFIG_CHERRYUSB_DEVICE_CDC_ACM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_acm.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_HID)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbd_hid.c)
@@ -69,28 +72,50 @@ if(CONFIG_CHERRYUSB_DEVICE)
if(CONFIG_CHERRYUSB_DEVICE_DFU)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_ADB)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/adb/usbd_adb.c)
endif()
if(DEFINED CONFIG_CHERRYUSB_DEVICE_DCD)
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_st")
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_st")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_st.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_esp")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_aic")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_aic.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_at")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_at.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_gd")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_gd.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_hc")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_hc.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb_es")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_es.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb_sunxi")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_sunxi.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb_bk")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "chipidea_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_dc_chipidea.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_glue_mcx.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "kinetis_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_dc_kinetis.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/bouffalolab/usb_dc_bl.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "aic")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic_ll.c)
endif()
endif()
@@ -108,6 +133,9 @@ if(CONFIG_CHERRYUSB_HOST)
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
endif()
@@ -129,18 +157,10 @@ if(CONFIG_CHERRYUSB_HOST)
endif()
if(CONFIG_CHERRYUSB_HOST_VIDEO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbh_video.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/chry_pool.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/usbh_uvc_queue.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool)
endif()
if(CONFIG_CHERRYUSB_HOST_AUDIO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
endif()
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
@@ -196,6 +216,12 @@ if(CONFIG_CHERRYUSB_HOST)
if(CONFIG_CHERRYUSB_HOST_PL2303)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_pl2303.c)
endif()
if(CONFIG_CHERRYUSB_HOST_BL616)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c)
endif()
if(CONFIG_CHERRYUSB_HOST_AOA)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c)
endif()
if(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
@@ -213,6 +239,12 @@ if(CONFIG_CHERRYUSB_HOST)
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_aic.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_mcx.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_nuvoton")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
#list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
@@ -223,8 +255,21 @@ if(CONFIG_CHERRYUSB_HOST)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "dwc2_esp")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "musb")
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "dwc2_hc")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_hc.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "musb_es")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_es.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "musb_sunxi")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_sunxi.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "musb_bk")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "kinetis_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
endif()
endif()
@@ -237,5 +282,25 @@ if(DEFINED CONFIG_CHERRYUSB_OSAL)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_yoc.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "idf")
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/osal/idf)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/idf/usb_osal_idf.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "threadx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_threadx.c)
endif()
endif()
if(CONFIG_CHERRYRB)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
endif()
if(CONFIG_CHERRYMP)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_freertos.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_rtthread.c)
endif()
endif()

View File

@@ -6,16 +6,10 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x010300
#define CHERRYUSB_VERSION_STR "v1.3.0"
/* ================ USB common Configuration ================ */
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
#define usb_malloc(size) malloc(size)
#define usb_free(ptr) free(ptr)
#ifndef CONFIG_USB_DBG_LEVEL
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
#endif
@@ -72,6 +66,10 @@
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
// #define CONFIG_USBDEV_MSC_POLLING
/* move msc read & write from isr to thread */
// #define CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_PRIO
@@ -168,6 +166,17 @@
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048)
#endif
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
*/
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE
#define CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE (2048)
#endif
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE
#define CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE (2048)
#endif
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
*/
@@ -199,13 +208,20 @@
#define CONFIG_USBDEV_EP_NUM 8
#endif
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */
// #define CONFIG_USB_HS
/* ---------------- FSDEV Configuration ---------------- */
//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
/* ---------------- DWC2 Configuration ---------------- */
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
*/
// #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
/* IN Endpoints Max packet Size / 4 */
// #define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (512 / 4)
// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024 / 4)
// #define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (0 / 4)
@@ -214,6 +230,8 @@
// #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_DMA_ENABLE
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI
@@ -253,7 +271,7 @@
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE) / 4)
// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI

310
class/adb/usbd_adb.c Normal file
View File

@@ -0,0 +1,310 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_adb.h"
#define ADB_OUT_EP_IDX 0
#define ADB_IN_EP_IDX 1
#define ADB_STATE_READ_MSG 0
#define ADB_STATE_READ_DATA 1
#define ADB_STATE_WRITE_MSG 2
#define ADB_STATE_WRITE_DATA 3
#define ADB_STATE_AWRITE_MSG 4
#define ADB_STATE_AWRITE_DATA 5
#define MAX_PAYLOAD_V1 (4 * 1024)
#define MAX_PAYLOAD_V2 (256 * 1024)
#define MAX_PAYLOAD MAX_PAYLOAD_V1
#define A_VERSION 0x01000000
#define A_SYNC 0x434e5953
#define A_CNXN 0x4e584e43
#define A_OPEN 0x4e45504f
#define A_OKAY 0x59414b4f
#define A_CLSE 0x45534c43
#define A_WRTE 0x45545257
#define A_AUTH 0x48545541
struct adb_msg {
uint32_t command; /* command identifier constant (A_CNXN, ...) */
uint32_t arg0; /* first argument */
uint32_t arg1; /* second argument */
uint32_t data_length; /* length of payload (0 is allowed) */
uint32_t data_crc32; /* crc32 of data payload */
uint32_t magic; /* command ^ 0xffffffff */
};
struct adb_packet {
struct adb_msg msg;
uint8_t payload[MAX_PAYLOAD];
};
struct usbd_adb {
uint8_t state;
uint8_t common_state;
uint8_t write_state;
bool writable;
uint32_t localid;
uint32_t shell_remoteid;
uint32_t file_remoteid;
} adb_client;
static struct usbd_endpoint adb_ep_data[2];
USB_NOCACHE_RAM_SECTION struct adb_packet tx_packet;
USB_NOCACHE_RAM_SECTION struct adb_packet rx_packet;
static inline uint32_t adb_packet_checksum(struct adb_packet *packet)
{
uint32_t sum = 0;
uint32_t i;
for (i = 0; i < packet->msg.data_length; ++i) {
sum += (uint32_t)(packet->payload[i]);
}
return sum;
}
static uint32_t usbd_adb_get_remoteid(uint32_t localid)
{
if (localid == ADB_SHELL_LOALID) {
return adb_client.shell_remoteid;
} else {
return adb_client.file_remoteid;
}
}
static void adb_send_msg(struct adb_packet *packet)
{
adb_client.common_state = ADB_STATE_WRITE_MSG;
packet->msg.data_crc32 = adb_packet_checksum(packet);
packet->msg.magic = packet->msg.command ^ 0xffffffff;
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
}
static void adb_send_okay(struct adb_packet *packet, uint32_t localid)
{
packet->msg.command = A_OKAY;
packet->msg.arg0 = localid;
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
packet->msg.data_length = 0;
adb_send_msg(&tx_packet);
}
static void adb_send_close(struct adb_packet *packet, uint32_t localid, uint32_t remoteid)
{
packet->msg.command = A_CLSE;
packet->msg.arg0 = localid;
packet->msg.arg1 = remoteid;
packet->msg.data_length = 0;
adb_send_msg(&tx_packet);
}
void usbd_adb_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
if (adb_client.common_state == ADB_STATE_READ_MSG) {
if (nbytes != sizeof(struct adb_msg)) {
USB_LOG_ERR("invalid adb msg size:%d\r\n", nbytes);
return;
}
USB_LOG_DBG("command:%x arg0:%x arg1:%x len:%d\r\n",
rx_packet.msg.command,
rx_packet.msg.arg0,
rx_packet.msg.arg1,
rx_packet.msg.data_length);
if (rx_packet.msg.data_length) {
/* setup next out ep read transfer */
adb_client.common_state = ADB_STATE_READ_DATA;
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, rx_packet.payload, rx_packet.msg.data_length);
} else {
if (rx_packet.msg.command == A_CLSE) {
adb_client.writable = false;
usbd_adb_notify_write_done();
USB_LOG_INFO("Close remoteid:%x\r\n", rx_packet.msg.arg0);
}
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
}
} else if (adb_client.common_state == ADB_STATE_READ_DATA) {
switch (rx_packet.msg.command) {
case A_SYNC:
break;
case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
char *support_feature = "device::"
"ro.product.name=cherryadb;"
"ro.product.model=cherrysh;"
"ro.product.device=cherryadb;"
"features=cmd,shell_v1";
tx_packet.msg.command = A_CNXN;
tx_packet.msg.arg0 = A_VERSION;
tx_packet.msg.arg1 = MAX_PAYLOAD;
tx_packet.msg.data_length = strlen(support_feature);
memcpy(tx_packet.payload, support_feature, strlen(support_feature));
adb_send_msg(&tx_packet);
adb_client.writable = false;
break;
case A_OPEN: /* OPEN(local-id, 0, "destination") */
rx_packet.payload[rx_packet.msg.data_length] = '\0';
if (strncmp((const char *)rx_packet.payload, "shell:", 6) == 0) {
adb_client.localid = ADB_SHELL_LOALID;
adb_client.shell_remoteid = rx_packet.msg.arg0;
adb_send_okay(&tx_packet, ADB_SHELL_LOALID);
USB_LOG_INFO("Open shell service, remoteid:%x\r\n", rx_packet.msg.arg0);
} else if (strncmp((const char *)rx_packet.payload, "sync:", 5) == 0) {
adb_client.localid = ADB_FILE_LOALID;
adb_client.file_remoteid = rx_packet.msg.arg0;
adb_send_okay(&tx_packet, ADB_FILE_LOALID);
USB_LOG_INFO("Open file service, remoteid:%x\r\n", rx_packet.msg.arg0);
}
break;
case A_OKAY:
break;
case A_CLSE:
break;
case A_WRTE: /* WRITE(local-id, remote-id, "data") */
if ((rx_packet.msg.arg0 == adb_client.shell_remoteid) && (rx_packet.msg.arg1 == ADB_SHELL_LOALID)) {
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
} else if ((rx_packet.msg.arg0 == adb_client.file_remoteid) && (rx_packet.msg.arg1 == ADB_FILE_LOALID)) {
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
} else {
adb_send_close(&tx_packet, 0, rx_packet.msg.arg0);
}
break;
case A_AUTH:
break;
default:
break;
}
}
}
void usbd_adb_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
(void)nbytes;
if (adb_client.common_state == ADB_STATE_WRITE_MSG) {
if (tx_packet.msg.data_length) {
adb_client.common_state = ADB_STATE_WRITE_DATA;
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
} else {
if (rx_packet.msg.command == A_WRTE) {
adb_client.writable = true;
if (adb_client.localid == ADB_SHELL_LOALID) {
usbd_adb_notify_shell_read(rx_packet.payload, rx_packet.msg.data_length);
} else {
}
}
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
}
} else if (adb_client.common_state == ADB_STATE_WRITE_DATA) {
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
} else if (adb_client.write_state == ADB_STATE_AWRITE_MSG) {
if (tx_packet.msg.data_length) {
adb_client.write_state = ADB_STATE_AWRITE_DATA;
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
} else {
}
} else if (adb_client.write_state == ADB_STATE_AWRITE_DATA) {
usbd_adb_notify_write_done();
}
}
void adb_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)arg;
switch (event) {
case USBD_EVENT_INIT:
break;
case USBD_EVENT_DEINIT:
break;
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONFIGURED:
adb_client.common_state = ADB_STATE_READ_MSG;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
break;
default:
break;
}
}
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep)
{
(void)busid;
intf->class_interface_handler = NULL;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = adb_notify_handler;
adb_ep_data[ADB_OUT_EP_IDX].ep_addr = out_ep;
adb_ep_data[ADB_OUT_EP_IDX].ep_cb = usbd_adb_bulk_out;
adb_ep_data[ADB_IN_EP_IDX].ep_addr = in_ep;
adb_ep_data[ADB_IN_EP_IDX].ep_cb = usbd_adb_bulk_in;
usbd_add_endpoint(busid, &adb_ep_data[ADB_OUT_EP_IDX]);
usbd_add_endpoint(busid, &adb_ep_data[ADB_IN_EP_IDX]);
return intf;
}
bool usbd_adb_can_write(void)
{
return adb_client.writable;
}
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len)
{
struct adb_packet *packet;
packet = &tx_packet;
packet->msg.command = A_WRTE;
packet->msg.arg0 = localid;
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
packet->msg.data_length = len;
memcpy(packet->payload, data, len);
packet->msg.data_crc32 = adb_packet_checksum(packet);
packet->msg.magic = packet->msg.command ^ 0xffffffff;
adb_client.write_state = ADB_STATE_AWRITE_MSG;
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
return 0;
}
void usbd_adb_close(uint32_t localid)
{
adb_send_close(&tx_packet, 0, usbd_adb_get_remoteid(localid));
}

38
class/adb/usbd_adb.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_ADB_H
#define USBD_ADB_H
#include <stdint.h>
#define ADB_SHELL_LOALID 0x01
#define ADB_FILE_LOALID 0x02
// clang-format off
#define ADB_DESCRIPTOR_INIT(bFirstInterface, in_ep, out_ep, wMaxPacketSize) \
USB_INTERFACE_DESCRIPTOR_INIT(bFirstInterface, 0x00, 0x02, 0xff, 0x42, 0x01, 0x02), \
USB_ENDPOINT_DESCRIPTOR_INIT(in_ep, 0x02, wMaxPacketSize, 0x00), \
USB_ENDPOINT_DESCRIPTOR_INIT(out_ep, 0x02, wMaxPacketSize, 0x00)
// clang-format on
#ifdef __cplusplus
extern "C" {
#endif
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep);
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len);
void usbd_adb_notify_file_read(uint8_t *data, uint32_t len);
void usbd_adb_notify_write_done(void);
bool usbd_adb_can_write(void);
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len);
void usbd_adb_close(uint32_t localid);
#ifdef __cplusplus
}
#endif
#endif /* USBD_ADB_H */

48
class/aoa/usb_aoa.h Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_AOA_H
#define USB_AOA_H
//AOA 1.0
#define AOA_ACCESSORY_VENDOR_ID 0x18D1
#define AOA_ACCESSORY_PRODUCT_ID 0x2D00
#define AOA_ACCESSORY_ADB_PRODUCT_ID 0x2D01
//AOA 2.0
#define AOA_AUDIO_PRODUCT_ID 0x2D02
#define AOA_AUDIO_ADB_PRODUCT_ID 0x2D03
#define AOA_ACCESSORY_AUDIO_PRODUCT_ID 0x2D04
#define AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID 0x2D05
//AOA 1.0
#define AOA_ACCESSORY_GET_PROTOCOL 51
#define AOA_ACCESSORY_SEND_STRING 52
#define AOA_ACCESSORY_START 53
//AOA 2.0
#define AOA_ACCESSORY_REGISTER_HID 54
#define AOA_ACCESSORY_UNREGISTER_HID 55
#define AOA_ACCESSORY_SET_HID_REPORT_DESC 56
#define AOA_ACCESSORY_SEND_HID_EVENT 57
#define AOA_ACCESSORY_SET_AUDIO_MODE 58
#define AOA_ACCESSORY_STRING_MANUFACTURER 0
#define AOA_ACCESSORY_STRING_MODEL 1
#define AOA_ACCESSORY_STRING_DESCRIPTION 2
#define AOA_ACCESSORY_STRING_VERSION 3
#define AOA_ACCESSORY_STRING_URI 4
#define AOA_ACCESSORY_STRING_SERIAL 5
struct aoa_string_info {
char acc_manufacturer[64];
char acc_model[64];
char acc_description[64];
char acc_version[64];
char acc_uri[64];
char acc_serial[64];
};
#endif /* USB_AOA_H */

289
class/aoa/usbh_aoa.c Normal file
View File

@@ -0,0 +1,289 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_aoa.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_aoa"
#include "usb_log.h"
#define DEV_FORMAT "/dev/aoa"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_aoa_buffer[128];
static struct usbh_aoa g_aoa_class;
int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info)
{
struct usb_setup_packet *setup;
int ret;
setup = hport->setup;
if (setup == NULL) {
return -USB_ERR_INVAL;
}
USB_LOG_INFO("Try switch into aoa mode\r\n");
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_GET_PROTOCOL;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 2;
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("AOA version: v%d.%d\r\n", g_aoa_buffer[0], g_aoa_buffer[1]);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
setup->wValue = 0;
setup->wIndex = AOA_ACCESSORY_STRING_MANUFACTURER;
setup->wLength = strlen(info->acc_manufacturer) + 1;
memcpy(g_aoa_buffer, info->acc_manufacturer, strlen(info->acc_manufacturer));
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
setup->wValue = 0;
setup->wIndex = AOA_ACCESSORY_STRING_MODEL;
setup->wLength = strlen(info->acc_model) + 1;
memcpy(g_aoa_buffer, info->acc_model, strlen(info->acc_model));
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
setup->wValue = 0;
setup->wIndex = AOA_ACCESSORY_STRING_DESCRIPTION;
setup->wLength = strlen(info->acc_description) + 1;
memcpy(g_aoa_buffer, info->acc_description, strlen(info->acc_description));
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
setup->wValue = 0;
setup->wIndex = AOA_ACCESSORY_STRING_VERSION;
setup->wLength = strlen(info->acc_version) + 1;
memcpy(g_aoa_buffer, info->acc_version, strlen(info->acc_version));
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
setup->wValue = 0;
setup->wIndex = AOA_ACCESSORY_STRING_URI;
setup->wLength = strlen(info->acc_uri) + 1;
memcpy(g_aoa_buffer, info->acc_uri, strlen(info->acc_uri));
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
setup->wValue = 0;
setup->wIndex = AOA_ACCESSORY_STRING_SERIAL;
setup->wLength = strlen(info->acc_serial) + 1;
memcpy(g_aoa_buffer, info->acc_serial, strlen(info->acc_serial));
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_START;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Switch into aoa mode success, wait usb device restart...\r\n");
return 0;
}
int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len)
{
struct usb_setup_packet *setup;
int ret;
uint8_t len;
uint32_t offset;
if (!aoa_class || !aoa_class->hport) {
return -USB_ERR_INVAL;
}
setup = aoa_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_REGISTER_HID;
setup->wValue = id;
setup->wIndex = report_len;
setup->wLength = 0;
ret = usbh_control_transfer(aoa_class->hport, setup, NULL);
if (ret < 0) {
return ret;
}
offset = 0;
while (report_len > 0) {
len = report_len > 64 ? 64 : report_len;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SET_HID_REPORT_DESC;
setup->wValue = id;
setup->wIndex = offset;
setup->wLength = len;
memcpy(g_aoa_buffer, report + offset, len);
ret = usbh_control_transfer(aoa_class->hport, setup, g_aoa_buffer);
if (ret < 0) {
return ret;
}
offset += len;
report_len -= len;
}
return ret;
}
int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len)
{
struct usb_setup_packet *setup;
int ret;
uint8_t len;
uint32_t offset;
if (!aoa_class || !aoa_class->hport) {
return -USB_ERR_INVAL;
}
setup = aoa_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = AOA_ACCESSORY_SEND_HID_EVENT;
setup->wValue = id;
setup->wIndex = 0;
setup->wLength = event_len;
memcpy(g_aoa_buffer, event, event_len);
return usbh_control_transfer(aoa_class->hport, setup, event);
}
static int usbh_aoa_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_aoa *aoa_class = &g_aoa_class;
memset(aoa_class, 0, sizeof(struct usbh_aoa));
aoa_class->hport = hport;
aoa_class->intf = intf;
hport->config.intf[intf].priv = aoa_class;
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(aoa_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(aoa_class->bulkout, ep_desc);
}
}
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register AOA Class:%s\r\n", hport->config.intf[intf].devname);
usbh_aoa_run(aoa_class);
return 0;
}
static int usbh_aoa_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_aoa *aoa_class = (struct usbh_aoa *)hport->config.intf[intf].priv;
if (aoa_class) {
if (aoa_class->bulkin) {
usbh_kill_urb(&aoa_class->bulkin_urb);
}
if (aoa_class->bulkout) {
usbh_kill_urb(&aoa_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister AOA Class:%s\r\n", hport->config.intf[intf].devname);
usbh_aoa_stop(aoa_class);
}
memset(aoa_class, 0, sizeof(struct usbh_aoa));
}
return ret;
}
__WEAK void usbh_aoa_run(struct usbh_aoa *aoa_class)
{
(void)aoa_class;
}
__WEAK void usbh_aoa_stop(struct usbh_aoa *aoa_class)
{
(void)aoa_class;
}
static const uint16_t aoa_id_table[][2] = {
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_PRODUCT_ID },
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_ADB_PRODUCT_ID },
{ AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_PRODUCT_ID },
{ AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_ADB_PRODUCT_ID },
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_PRODUCT_ID },
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID },
{ 0, 0 },
};
const struct usbh_class_driver aoa_class_driver = {
.driver_name = "aoa",
.connect = usbh_aoa_connect,
.disconnect = usbh_aoa_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info aoa_intf_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0xff,
.bInterfaceProtocol = 0x00,
.id_table = aoa_id_table,
.class_driver = &aoa_class_driver
};

40
class/aoa/usbh_aoa.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_AOA_H
#define USBH_AOA_H
#include "usb_aoa.h"
struct usbh_aoa {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info);
int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len);
int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len);
void usbh_aoa_run(struct usbh_aoa *aoa_class);
void usbh_aoa_stop(struct usbh_aoa *aoa_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_AOA_H */

View File

@@ -132,11 +132,11 @@
#define AUDIO_FORMAT_ALAW 0x0004
#define AUDIO_FORMAT_MULAW 0x0005
#define AUDIO_V2_FORMAT_PCM 0x00000001
#define AUDIO_V2_FORMAT_PCM8 0x00000002
#define AUDIO_V2_FORMAT_IEEE_FLOAT 0x00000004
#define AUDIO_V2_FORMAT_ALAW 0x00000008
#define AUDIO_V2_FORMAT_MULAW 0x00000010
#define AUDIO_V2_FORMAT_PCM 0x00000001
#define AUDIO_V2_FORMAT_PCM8 0x00000002
#define AUDIO_V2_FORMAT_IEEE_FLOAT 0x00000004
#define AUDIO_V2_FORMAT_ALAW 0x00000008
#define AUDIO_V2_FORMAT_MULAW 0x00000010
/* bmChannelConfig: a bitmap field that indicates which spatial locations
* are occupied by the channels present in the cluster. The bit allocations
@@ -648,6 +648,18 @@ struct audio_cs_if_ac_feature_unit_descriptor {
#define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + (ch + 1) * n)
struct audio_cs_if_ac_selector_unit_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bUnitID;
uint8_t bNrInPins;
uint8_t baSourceID[1];
uint8_t iSelector;
} __PACKED;
#define AUDIO_SIZEOF_AC_SELECTOR_UNIT_DESC(n) (6 + n)
struct audio_cs_if_as_general_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -812,6 +824,60 @@ struct audio_cs_ep_ep_general_descriptor {
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval, ...) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
bAlternateSetting, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
0x01, /* bDelay */ \
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag : AUDIO_FORMAT_PCM */ \
0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
bNrChannels, /* bNrChannels */ \
bSubFrameSize, /* bSubFrameSize : Bytes per audio subframe */ \
bBitResolution, /* bBitResolution : bits per sample */ \
(PP_NARG(__VA_ARGS__)/3), /* bSamFreqType : only one frequency supported */ \
__VA_ARGS__, /* tSamFreq : Audio sampling frequency coded on 3 bytes */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
bmAttributes, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
bInterval, /* bInterval : one packet per frame */ \
0x00, /* bRefresh */ \
0x00, /* bSynchAddress */ \
0x07, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
AUDIO_EP_CONTROL_SAMPLING_FEQ, /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */ \
0x00, /* bLockDelayUnits */ \
0x00, /* wLockDelay */ \
0x00
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
#define AUDIO_AS_ALTSETTING0_DESCRIPTOR_INIT(bInterfaceNumber) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00 /* iInterface */
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT(bInterfaceNumber, bNumEndpoints) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -1096,6 +1162,58 @@ struct audio_v2_control_range3_param_block {
0x00, /* wLockDelay */ \
0x00
#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
bAlternateSetting, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x10, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
bTerminalLink, /* bTerminalLink : Unit ID of the Output or Input Terminal*/ \
0x00, /* bmControls */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType : AUDIO_FORMAT_TYPE_I */ \
DBVAL(AUDIO_V2_FORMAT_PCM), /* bmFormats PCM */ \
bNrChannels, /* bNrChannels */ \
DBVAL(bmChannelConfig), /* bmChannelConfig */ \
0x00, /* iChannelNames */ \
0x06, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
bSubslotSize, /* bSubslotSize */ \
bBitResolution, /* bBitResolution */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
bmAttributes, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
bInterval, /* bInterval */ \
0x08, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
0x00, /* bmAttributes */ \
0x00, /* bmControls */ \
0x00, /* bLockDelayUnits */ \
0x00, /* wLockDelay */ \
0x00
#define AUDIO_V2_AS_ALTSETTING0_DESCRIPTOR_INIT(bInterfaceNumber) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
0x00 /* iInterface */
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, bFeedbackEndpointAddress) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -1150,12 +1268,13 @@ struct audio_v2_control_range3_param_block {
bFeedbackEndpointAddress, /* bFeedbackEndpointAddress Revise Dir to bEndpointAddress */ \
0x11, /* bmAttributes: TransferType=Isochronous SyncType=None EndpointType=Feedback */ \
WBVAL(4), /* XXXX wMaxPacketSize in Bytes */ \
bInterval /* bInterval */ \
bInterval /* bInterval */
// clang-format on
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_INIT_LEN (0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
#define AUDIO_SAMPLE_FREQ_NUM(num) (uint8_t)(num), (uint8_t)((num >> 8))
#define AUDIO_SAMPLE_FREQ_3B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))

View File

@@ -62,7 +62,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
setup->bRequest);
uint8_t entity_id;
uint8_t ep;
uint8_t ep = 0;
uint8_t subtype = 0x01;
uint8_t control_selector;
uint8_t ch;
@@ -136,27 +136,26 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
memcpy(&volume, *data, *len);
if (volume < 0x8000) {
volume_db = volume / 256;
} else if (volume > 0x8000) {
volume_db = (0xffff - volume + 1) / -256;
} else {
volume_db = (volume - 0x10000) / 256;
}
volume_db += 128; /* 0 ~ 255 */
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db);
break;
case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume_db -= 128;
if (volume_db >= 0) {
volume = volume_db * 256;
} else {
volume = volume_db * 256 + 0xffff + 1;
volume = volume_db * 256 + 0x10000;
}
USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
memcpy(*data, &volume, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
(*data)[0] = 0x00; /* -2560/256 dB */
(*data)[1] = 0xdb;
(*data)[0] = 0x00; /* -100 dB */
(*data)[1] = 0x9c;
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
@@ -165,7 +164,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
(*data)[0] = 0x00; /* -256/256 dB */
(*data)[0] = 0x00; /* 1 dB */
(*data)[1] = 0x01;
*len = 2;
break;
@@ -178,22 +177,31 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume = volume_db;
if (volume_db >= 0) {
volume = volume_db * 256;
} else {
volume = volume_db * 256 + 0x10000;
}
USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
memcpy(*data, &volume, 2);
*len = 2;
} else {
memcpy(&volume, *data, *len);
volume_db = volume;
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
if (volume < 0x8000) {
volume_db = volume / 256;
} else {
volume_db = (volume - 0x10000) / 256;
}
USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = 1;
*((uint16_t *)(*data + 2)) = 0;
*((uint16_t *)(*data + 4)) = 100;
*((uint16_t *)(*data + 6)) = 1;
*((uint16_t *)(*data + 2)) = 0x9c00; /* MIN -100 dB */
*((uint16_t *)(*data + 4)) = 0x0000; /* MAX 0 dB */
*((uint16_t *)(*data + 6)) = 0x100; /* RES 1 dB */
*len = 8;
} else {
}
@@ -287,7 +295,7 @@ static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
}
}
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
@@ -312,33 +320,58 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
return intf;
}
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db)
{
(void)busid;
(void)ep;
(void)ch;
(void)volume_db;
}
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
{
(void)busid;
(void)ep;
(void)ch;
return 0;
}
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
{
(void)busid;
(void)ep;
(void)ch;
(void)mute;
}
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
{
(void)busid;
(void)ep;
(void)ch;
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
(void)busid;
(void)ep;
(void)sampling_freq;
}
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
(void)ep;
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
(void)busid;
(void)ep;
(void)sampling_freq_table;
}

View File

@@ -27,7 +27,7 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface
void usbd_audio_open(uint8_t busid, uint8_t intf);
void usbd_audio_close(uint8_t busid, uint8_t intf);
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db);
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);

View File

@@ -21,10 +21,6 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
@@ -32,11 +28,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_audio *usbh_audio_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
g_audio_class[devno].minor = devno;
return &g_audio_class[devno];
@@ -47,17 +43,17 @@ static struct usbh_audio *usbh_audio_class_alloc(void)
static void usbh_audio_class_free(struct usbh_audio *audio_class)
{
int devno = audio_class->minor;
uint8_t devno = audio_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(audio_class, 0, sizeof(struct usbh_audio));
}
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution)
{
struct usb_setup_packet *setup = audio_class->hport->setup;
struct usb_setup_packet *setup;
struct usb_endpoint_descriptor *ep_desc;
uint8_t mult;
uint16_t mps;
@@ -65,24 +61,33 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
uint8_t intf = 0xff;
uint8_t altsetting = 1;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
if (audio_class->is_opened) {
return 0;
}
for (uint8_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
if (audio_class->module[i].altsetting[j].sampfreq[k] == samp_freq) {
intf = audio_class->module[i].data_intf;
altsetting = j;
goto freq_found;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
intf = audio_class->as_msg_table[i].stream_intf;
for (uint8_t j = 1; j < audio_class->as_msg_table[i].num_of_altsetting; j++) {
if (audio_class->as_msg_table[i].as_format[j].bBitResolution == bitresolution) {
for (uint8_t k = 0; k < audio_class->as_msg_table[i].as_format[j].bSamFreqType; k++) {
uint32_t freq = 0;
memcpy(&freq, &audio_class->as_msg_table[i].as_format[j].tSamFreq[3 * k], 3);
if (freq == samp_freq) {
altsetting = j;
goto freq_found;
}
}
}
}
}
}
return -USB_ERR_NODEV;
freq_found:
@@ -100,16 +105,18 @@ freq_found:
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
setup->wIndex = ep_desc->bEndpointAddress;
setup->wLength = 3;
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].ep_attr & AUDIO_EP_CONTROL_SAMPLING_FEQ) {
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
setup->wIndex = ep_desc->bEndpointAddress;
setup->wLength = 3;
memcpy(g_audio_buf, &samp_freq, 3);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
memcpy(g_audio_buf, &samp_freq, 3);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
}
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
@@ -122,22 +129,27 @@ freq_found:
USBH_EP_INIT(audio_class->isoout, ep_desc);
}
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
USB_LOG_INFO("Open audio stream :%s, altsetting: %u\r\n", name, altsetting);
audio_class->is_opened = true;
return ret;
}
int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
{
struct usb_setup_packet *setup = audio_class->hport->setup;
struct usb_setup_packet *setup;
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t intf = 0xff;
uint8_t altsetting = 1;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->module[i].data_intf;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
intf = audio_class->as_msg_table[i].stream_intf;
}
}
@@ -145,7 +157,17 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
return -USB_ERR_NODEV;
}
USB_LOG_INFO("Close audio module :%s\r\n", name);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = 0;
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Close audio stream :%s\r\n", name);
audio_class->is_opened = false;
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
@@ -159,77 +181,166 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
}
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = 0;
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume)
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db)
{
struct usb_setup_packet *setup = audio_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
uint8_t intf;
uint16_t volume_hex;
int volume_min_db;
int volume_max_db;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
if ((volume_db > 127) || (volume_db < -127)) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
feature_id = audio_class->as_msg_table[i].feature_terminal_id;
intf = audio_class->as_msg_table[i].stream_intf;
}
}
if (intf == 0xff) {
if (feature_id == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_MIN;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_MAX;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_GET_RES;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_res, g_audio_buf, 2);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | intf;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2;
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) {
volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256;
} else {
volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256;
}
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) {
volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256;
} else {
volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256;
}
USB_LOG_INFO("Get ch:%d dB range: %d dB ~ %d dB\r\n", volume_min_db, volume_max_db);
if (volume_db >= 0) {
volume_hex = volume_db * 256;
if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) {
return -USB_ERR_RANGE;
}
} else {
volume_hex = volume_db * 256 + 0x10000;
if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) {
return -USB_ERR_RANGE;
}
}
memcpy(g_audio_buf, &volume_hex, 2);
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur = volume_hex;
return ret;
}
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute)
{
struct usb_setup_packet *setup = audio_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
uint8_t intf = 0xff;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
feature_id = audio_class->as_msg_table[i].feature_terminal_id;
intf = audio_class->as_msg_table[i].stream_intf;
}
}
if (intf == 0xff) {
if (feature_id == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch;
setup->wIndex = (feature_id << 8) | intf;
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 1;
memcpy(g_audio_buf, &mute, 1);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].mute = mute;
return ret;
}
@@ -237,26 +348,28 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
{
USB_LOG_INFO("============= Audio module information ===================\r\n");
USB_LOG_RAW("bcdADC :%04x\r\n", audio_class->bcdADC);
USB_LOG_RAW("Num of modules :%u\r\n", audio_class->module_num);
USB_LOG_RAW("Num of altsettings:%u\r\n", audio_class->num_of_intf_altsettings);
USB_LOG_RAW("Num of audio stream :%u\r\n", audio_class->stream_intf_num);
for (uint8_t i = 0; i < audio_class->module_num; i++) {
USB_LOG_RAW(" module name :%s\r\n", audio_class->module[i].name);
USB_LOG_RAW(" module feature unit id :%d\r\n", audio_class->module[i].feature_unit_id);
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
USB_LOG_RAW("\tstream name :%s\r\n", audio_class->as_msg_table[i].stream_name);
USB_LOG_RAW("\tstream intf :%u\r\n", audio_class->as_msg_table[i].stream_intf);
USB_LOG_RAW("\tNum of altsetting :%u\r\n", audio_class->as_msg_table[i].num_of_altsetting);
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
for (uint8_t j = 0; j < audio_class->as_msg_table[i].num_of_altsetting; j++) {
if (j == 0) {
USB_LOG_RAW(" Ingore altsetting 0\r\n");
USB_LOG_RAW("\t\tIngore altsetting 0\r\n");
continue;
}
USB_LOG_RAW(" Altsetting %u\r\n", j);
USB_LOG_RAW(" module channels :%u\r\n", audio_class->module[i].altsetting[j].channels);
//USB_LOG_RAW(" module format_type :%u\r\n",audio_class->module[i].altsetting[j].format_type);
USB_LOG_RAW(" module bitresolution :%u\r\n", audio_class->module[i].altsetting[j].bitresolution);
USB_LOG_RAW(" module sampfreq num :%u\r\n", audio_class->module[i].altsetting[j].sampfreq_num);
USB_LOG_RAW("\t\tAltsetting :%u\r\n", j);
USB_LOG_RAW("\t\t\tbNrChannels :%u\r\n", audio_class->as_msg_table[i].as_format[j].bNrChannels);
USB_LOG_RAW("\t\t\tbBitResolution :%u\r\n", audio_class->as_msg_table[i].as_format[j].bBitResolution);
USB_LOG_RAW("\t\t\tbSamFreqType :%u\r\n", audio_class->as_msg_table[i].as_format[j].bSamFreqType);
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
USB_LOG_RAW(" module sampfreq :%d hz\r\n", audio_class->module[i].altsetting[j].sampfreq[k]);
for (uint8_t k = 0; k < audio_class->as_msg_table[i].as_format[j].bSamFreqType; k++) {
uint32_t freq = 0;
memcpy(&freq, &audio_class->as_msg_table[i].as_format[j].tSamFreq[3 * k], 3);
USB_LOG_RAW("\t\t\t\tSampleFreq :%u\r\n", freq);
}
}
}
@@ -267,14 +380,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
{
int ret;
uint8_t cur_iface = 0xff;
uint8_t cur_iface_count = 0xff;
uint8_t cur_alt_setting = 0xff;
uint8_t cur_iface = 0;
uint8_t cur_iface_count = 0;
uint8_t cur_alt_setting = 0;
uint8_t input_offset = 0;
uint8_t output_offset = 0;
uint8_t feature_unit_offset = 0;
uint8_t format_offset = 0;
uint8_t *p;
struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
struct usbh_audio *audio_class = usbh_audio_class_alloc();
if (audio_class == NULL) {
@@ -284,8 +397,6 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
audio_class->hport = hport;
audio_class->ctrl_intf = intf;
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
hport->config.intf[intf].priv = audio_class;
p = hport->raw_config_desc;
@@ -311,72 +422,49 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
case AUDIO_CONTROL_INPUT_TERMINAL: {
struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p;
audio_class->module[input_offset].input_terminal_id = desc->bTerminalID;
audio_class->module[input_offset].input_terminal_type = desc->wTerminalType;
audio_class->module[input_offset].input_channel_config = desc->wChannelConfig;
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
audio_class->module[input_offset].terminal_link_id = desc->bTerminalID;
}
if (desc->wTerminalType == AUDIO_INTERM_MIC) {
audio_class->module[input_offset].name = "mic";
}
memcpy(&ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor));
input_offset++;
} break;
break;
case AUDIO_CONTROL_OUTPUT_TERMINAL: {
struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p;
audio_class->module[output_offset].output_terminal_id = desc->bTerminalID;
audio_class->module[output_offset].output_terminal_type = desc->wTerminalType;
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
audio_class->module[output_offset].terminal_link_id = desc->bTerminalID;
}
if (desc->wTerminalType == AUDIO_OUTTERM_SPEAKER) {
audio_class->module[output_offset].name = "speaker";
}
memcpy(&ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor));
output_offset++;
} break;
case AUDIO_CONTROL_FEATURE_UNIT: {
struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p;
audio_class->module[feature_unit_offset].feature_unit_id = desc->bUnitID;
audio_class->module[feature_unit_offset].feature_unit_controlsize = desc->bControlSize;
for (uint8_t j = 0; j < desc->bControlSize; j++) {
audio_class->module[feature_unit_offset].feature_unit_controls[j] = p[6 + j];
}
memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength);
feature_unit_offset++;
} break;
case AUDIO_CONTROL_PROCESSING_UNIT:
default:
USB_LOG_ERR("Do not support %02x subtype\r\n", p[DESC_bDescriptorSubType]);
return -USB_ERR_NOTSUPP;
}
} else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_STREAMING_GENERAL: {
struct audio_cs_if_as_general_descriptor *desc = (struct audio_cs_if_as_general_descriptor *)p;
break;
/* all altsetting have the same general */
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].stream_intf = cur_iface;
memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_general, desc, sizeof(struct audio_cs_if_as_general_descriptor));
} break;
case AUDIO_STREAMING_FORMAT_TYPE: {
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].num_of_altsetting = (cur_alt_setting + 1);
memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_format[cur_alt_setting], desc, desc->bLength);
} break;
default:
break;
}
} else if ((cur_iface < (audio_class->ctrl_intf + cur_iface_count)) && (cur_iface > audio_class->ctrl_intf)) {
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_STREAMING_GENERAL:
break;
case AUDIO_STREAMING_FORMAT_TYPE: {
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
audio_class->module[format_offset].data_intf = cur_iface;
audio_class->module[format_offset].altsetting[cur_alt_setting].channels = desc->bNrChannels;
audio_class->module[format_offset].altsetting[cur_alt_setting].format_type = desc->bFormatType;
audio_class->module[format_offset].altsetting[cur_alt_setting].bitresolution = desc->bBitResolution;
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq_num = desc->bSamFreqType;
for (uint8_t j = 0; j < desc->bSamFreqType; j++) {
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq[j] = (uint32_t)(p[10 + j] << 16) |
(uint32_t)(p[9 + j] << 8) |
(uint32_t)(p[8 + j] << 0);
}
if (cur_alt_setting == (hport->config.intf[intf + 1].altsetting_num - 1)) {
format_offset++;
}
} break;
default:
break;
}
break;
case AUDIO_ENDPOINT_DESCRIPTOR_TYPE:
if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
if (p[DESC_bDescriptorSubType] == AUDIO_ENDPOINT_GENERAL) {
struct audio_cs_ep_ep_general_descriptor *desc = (struct audio_cs_ep_ep_general_descriptor *)p;
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].ep_attr = desc->bmAttributes;
}
}
break;
@@ -387,16 +475,98 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
p += p[DESC_bLength];
}
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
if ((input_offset != output_offset) && (input_offset != feature_unit_offset)) {
USB_LOG_ERR("Audio control descriptor is invalid\r\n");
return -USB_ERR_INVAL;
}
audio_class->module_num = input_offset;
if (cur_iface_count == 0xff) {
USB_LOG_ERR("Audio descriptor must have iad descriptor\r\n");
return -USB_ERR_INVAL;
}
for (size_t i = 0; i < audio_class->module_num; i++) {
ret = usbh_audio_close(audio_class, audio_class->module[i].name);
audio_class->stream_intf_num = input_offset;
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
/* Search 0x0101 in input or output desc */
for (uint8_t streamidx = 0; streamidx < audio_class->stream_intf_num; streamidx++) {
if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_input.bTerminalID) {
/* INPUT --> FEATURE UNIT --> OUTPUT */
audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[streamidx].ac_input.bTerminalID;
/* Search input terminal id in feature desc */
for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
if (ac_msg_table[streamidx].ac_input.bTerminalID == ac_msg_table[featureidx].ac_feature_unit.bSourceID) {
audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
/* Search feature unit id in output desc */
for (uint8_t outputid = 0; outputid < audio_class->stream_intf_num; outputid++) {
if (ac_msg_table[featureidx].ac_feature_unit.bUnitID == ac_msg_table[outputid].ac_output.bSourceID) {
audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[outputid].ac_output.bTerminalID;
switch (ac_msg_table[outputid].ac_output.wTerminalType) {
case AUDIO_OUTTERM_SPEAKER:
audio_class->as_msg_table[i].stream_name = "speaker";
break;
case AUDIO_OUTTERM_HEADPHONES:
audio_class->as_msg_table[i].stream_name = "headphoens";
break;
case AUDIO_OUTTERM_HEADDISPLAY:
audio_class->as_msg_table[i].stream_name = "headdisplay";
break;
default:
audio_class->as_msg_table[i].stream_name = "unknown";
break;
}
break;
}
}
break;
}
}
} else if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_output.bTerminalID) {
/* OUTPUT --> FEATURE UNIT --> INPUT */
audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[streamidx].ac_output.bTerminalID;
/* Search output terminal id in feature desc */
for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
if (ac_msg_table[streamidx].ac_output.bSourceID == ac_msg_table[featureidx].ac_feature_unit.bUnitID) {
audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
/* Search feature unit id in input desc */
for (uint8_t inputid = 0; inputid < audio_class->stream_intf_num; inputid++) {
if (ac_msg_table[featureidx].ac_feature_unit.bSourceID == ac_msg_table[inputid].ac_input.bTerminalID) {
audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[inputid].ac_input.bTerminalID;
switch (ac_msg_table[inputid].ac_input.wTerminalType) {
case AUDIO_INTERM_MIC:
audio_class->as_msg_table[i].stream_name = "mic";
break;
default:
audio_class->as_msg_table[i].stream_name = "unknown";
break;
}
break;
}
}
break;
}
}
}
}
}
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
if (audio_class->as_msg_table[i].stream_name == NULL) {
USB_LOG_ERR("Audio stream search fail\r\n");
return -USB_ERR_NODEV;
}
}
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
ret = usbh_audio_close(audio_class, audio_class->as_msg_table[i].stream_name);
if (ret < 0) {
USB_LOG_ERR("Fail to close audio module :%s\r\n", audio_class->module[i].name);
USB_LOG_ERR("Fail to close audio stream :%s\r\n", audio_class->as_msg_table[i].stream_name);
return ret;
}
}
@@ -436,20 +606,26 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
static int usbh_audio_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
{
(void)audio_class;
}
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
{
(void)audio_class;
}
const struct usbh_class_driver audio_ctrl_class_driver = {
@@ -466,18 +642,18 @@ const struct usbh_class_driver audio_streaming_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOCONTROL,
.protocol = 0x00,
.bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
.bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOCONTROL,
.bInterfaceProtocol = 0x00,
.id_table = NULL,
.class_driver = &audio_ctrl_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOSTREAMING,
.protocol = 0x00,
.bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
.bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING,
.bInterfaceProtocol = 0x00,
.id_table = NULL,
.class_driver = &audio_streaming_class_driver
};

View File

@@ -8,34 +8,31 @@
#include "usb_audio.h"
struct usbh_audio_format_type {
uint8_t channels;
uint8_t format_type;
uint8_t bitresolution;
uint8_t sampfreq_num;
uint32_t sampfreq[3];
#ifndef CONFIG_USBHOST_AUDIO_MAX_STREAMS
#define CONFIG_USBHOST_AUDIO_MAX_STREAMS 3
#endif
struct usbh_audio_ac_msg {
struct audio_cs_if_ac_input_terminal_descriptor ac_input;
struct audio_cs_if_ac_feature_unit_descriptor ac_feature_unit;
struct audio_cs_if_ac_output_terminal_descriptor ac_output;
};
/**
* bSourceID in feature_unit = input_terminal_id
* bSourceID in output_terminal = feature_unit_id
* terminal_link_id = input_terminal_id or output_terminal_id (if input_terminal_type or output_terminal_type is 0x0101)
*
*
*/
struct usbh_audio_module {
const char *name;
uint8_t data_intf;
struct usbh_audio_as_msg {
const char *stream_name;
uint8_t stream_intf;
uint8_t input_terminal_id;
uint16_t input_terminal_type;
uint16_t input_channel_config;
uint8_t feature_terminal_id;
uint8_t output_terminal_id;
uint16_t output_terminal_type;
uint8_t feature_unit_id;
uint8_t feature_unit_controlsize;
uint8_t feature_unit_controls[8];
uint8_t terminal_link_id;
struct usbh_audio_format_type altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
uint8_t ep_attr;
uint8_t num_of_altsetting;
uint16_t volume_min;
uint16_t volume_max;
uint16_t volume_res;
uint16_t volume_cur;
bool mute;
struct audio_cs_if_as_general_descriptor as_general;
struct audio_cs_if_as_format_type_descriptor as_format[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
};
struct usbh_audio {
@@ -50,9 +47,8 @@ struct usbh_audio {
bool is_opened;
uint16_t bcdADC;
uint8_t bInCollection;
uint8_t num_of_intf_altsettings;
struct usbh_audio_module module[2];
uint8_t module_num;
uint8_t stream_intf_num;
struct usbh_audio_as_msg as_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
void *user_data;
};
@@ -61,9 +57,9 @@ struct usbh_audio {
extern "C" {
#endif
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq);
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution);
int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db);
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
void usbh_audio_run(struct usbh_audio *audio_class);

View File

@@ -421,7 +421,7 @@ struct cdc_ncm_ndp16 {
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -430,7 +430,7 @@ struct cdc_ncm_ndp16 {
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
@@ -489,8 +489,8 @@ struct cdc_ncm_ndp16 {
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
0x01, /* bFunctionSubClass */ \
0x03, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -498,8 +498,8 @@ struct cdc_ncm_ndp16 {
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
0x01, /* bInterfaceSubClass */ \
0x03, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
@@ -524,7 +524,7 @@ struct cdc_ncm_ndp16 {
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x08, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x05, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
@@ -588,7 +588,7 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx)
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
str_idx, /* Device's MAC string index */\
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
WBVAL(wMaxSegmentSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
0x07, /* bLength */ \
@@ -596,7 +596,7 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx)
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x05, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \

View File

@@ -1,29 +1,13 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_H
#define USBD_CDC_H
#include "usb_cdc.h"
// legacy for old version
#ifdef __cplusplus
extern "C" {
#endif
#include "usbd_cdc_acm.h"
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_H */
#endif

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
const char *stop_name[] = { "1", "1.5", "2" };
const char *parity_name[] = { "N", "O", "E", "M", "S" };
@@ -85,6 +85,8 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
{
(void)busid;
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
@@ -95,10 +97,16 @@ struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interfa
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
(void)busid;
(void)intf;
(void)line_coding;
}
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
(void)busid;
(void)intf;
line_coding->dwDTERate = 2000000;
line_coding->bDataBits = 8;
line_coding->bParityType = 0;
@@ -107,12 +115,20 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
(void)busid;
(void)intf;
(void)dtr;
}
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
{
(void)busid;
(void)intf;
(void)rts;
}
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
{
(void)busid;
(void)intf;
}

29
class/cdc/usbd_cdc_acm.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_ACM_H
#define USBD_CDC_ACM_H
#include "usb_cdc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_ACM_H */

View File

@@ -7,17 +7,21 @@
#include "usbd_cdc_ecm.h"
#define CDC_ECM_OUT_EP_IDX 0
#define CDC_ECM_IN_EP_IDX 1
#define CDC_ECM_INT_EP_IDX 2
#define CDC_ECM_IN_EP_IDX 1
#define CDC_ECM_INT_EP_IDX 2
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1536U
/* Describe EndPoints configuration */
static struct usbd_endpoint cdc_ecm_ep_data[3];
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
#endif
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
volatile uint32_t g_cdc_ecm_rx_data_length = 0;
volatile uint32_t g_cdc_ecm_tx_data_length = 0;
@@ -68,8 +72,10 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed
break;
}
if (bytes2send) {
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
if (usb_device_is_configured(0)) {
if (bytes2send) {
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
}
}
}
@@ -79,6 +85,10 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
"bRequest 0x%02x\r\n",
setup->bRequest);
(void)busid;
(void)data;
(void)len;
g_cmd_intf = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
@@ -89,11 +99,11 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
* bit3 Broadcast
* bit4 Multicast
*/
if (g_current_net_status == 0) {
g_current_net_status = 1;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
g_connect_speed_table[0] = 100000000; /* 100 Mbps */
g_connect_speed_table[1] = 100000000; /* 100 Mbps */
usbd_cdc_ecm_set_connect(true, g_connect_speed_table);
#endif
break;
default:
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
@@ -105,15 +115,19 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)busid;
(void)arg;
switch (event) {
case USBD_EVENT_RESET:
g_current_net_status = 0;
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_tx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
break;
case USBD_EVENT_CONFIGURED:
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
#endif
break;
default:
@@ -123,36 +137,45 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
g_cdc_ecm_rx_data_length += nbytes;
(void)busid;
if (nbytes < usbd_get_ep_mps(busid, ep)) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
} else {
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, ep));
}
g_cdc_ecm_rx_data_length = nbytes;
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_data_length);
}
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
(void)busid;
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(0, ep, NULL, 0);
} else {
usbd_cdc_ecm_data_send_done(g_cdc_ecm_tx_data_length);
g_cdc_ecm_tx_data_length = 0;
}
}
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if (g_current_net_status == 1) {
g_current_net_status = 2;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
(void)busid;
(void)ep;
(void)nbytes;
if (g_current_net_status == 2) {
g_current_net_status = 3;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE, 0, g_connect_speed_table);
} else {
g_current_net_status = 0;
}
}
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
{
if (!usb_device_is_configured(0)) {
return -USB_ERR_NODEV;
}
if (g_cdc_ecm_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
@@ -160,14 +183,17 @@ int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
g_cdc_ecm_tx_data_length = len;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, len);
}
void usbd_cdc_ecm_start_read_next(void)
int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len)
{
if (!usb_device_is_configured(0)) {
return -USB_ERR_NODEV;
}
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
return usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, buf, len);
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
@@ -175,19 +201,19 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void)
{
struct pbuf *p;
if (g_cdc_ecm_rx_data_buffer == NULL) {
if (g_cdc_ecm_rx_data_length == 0) {
return NULL;
}
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
if (p == NULL) {
usbd_cdc_ecm_start_read_next();
usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
return NULL;
}
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
usb_memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
p->len = g_cdc_ecm_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
usbd_cdc_ecm_start_read_next();
usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
return p;
}
@@ -206,13 +232,11 @@ int usbd_cdc_ecm_eth_tx(struct pbuf *p)
buffer = g_cdc_ecm_tx_buffer;
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
usb_memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
g_cdc_ecm_tx_data_length = p->tot_len;
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, p->tot_len);
}
#endif
@@ -237,11 +261,24 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const
return intf;
}
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2])
{
memcpy(g_connect_speed_table, speed, 8);
if (connect) {
g_current_net_status = 2;
memcpy(g_connect_speed_table, speed, 8);
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
} else {
g_current_net_status = 1;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_DISCONNECTED, NULL);
}
}
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
__WEAK void usbd_cdc_ecm_data_recv_done(uint32_t len)
{
}
(void)len;
}
__WEAK void usbd_cdc_ecm_data_send_done(uint32_t len)
{
(void)len;
}

View File

@@ -12,21 +12,15 @@
extern "C" {
#endif
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
/* Init cdc ecm interface driver */
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
/* Setup request command callback api */
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]);
/* Api for eth only without any net stack */
uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
void usbd_cdc_ecm_send_done(void);
void usbd_cdc_ecm_data_recv_done(uint32_t len);
void usbd_cdc_ecm_data_send_done(uint32_t len);
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_start_read_next(void);
int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len);
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#include "lwip/netif.h"

View File

@@ -12,18 +12,18 @@
#define DEV_FORMAT "/dev/ttyACM%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_cdc_acm_class[devno], 0, sizeof(struct usbh_cdc_acm));
g_cdc_acm_class[devno].minor = devno;
return &g_cdc_acm_class[devno];
@@ -34,17 +34,22 @@ static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
{
int devno = cdc_acm_class->minor;
uint8_t devno = cdc_acm_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
}
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup = cdc_acm_class->hport->setup;
struct usb_setup_packet *setup;
if (!cdc_acm_class || !cdc_acm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_acm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
@@ -52,33 +57,43 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
memcpy(g_cdc_acm_buf[cdc_acm_class->minor], line_coding, sizeof(struct cdc_line_coding));
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
}
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup = cdc_acm_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!cdc_acm_class || !cdc_acm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_acm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
setup->wValue = 0;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
memcpy(line_coding, g_cdc_acm_buf[cdc_acm_class->minor], sizeof(struct cdc_line_coding));
return ret;
}
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts)
{
struct usb_setup_packet *setup = cdc_acm_class->hport->setup;
struct usb_setup_packet *setup;
if (!cdc_acm_class || !cdc_acm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_acm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
@@ -216,20 +231,26 @@ int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
(void)cdc_acm_class;
}
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
{
(void)cdc_acm_class;
}
const struct usbh_class_driver cdc_acm_class_driver = {
@@ -245,19 +266,19 @@ const struct usbh_class_driver cdc_data_class_driver = {
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
.bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
.bInterfaceProtocol = 0x00,
.id_table = NULL,
.class_driver = &cdc_acm_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.class = USB_DEVICE_CLASS_CDC_DATA,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = NULL,
.class_driver = &cdc_data_class_driver
};

View File

@@ -32,7 +32,12 @@ static struct usbh_cdc_ecm g_cdc_ecm_class;
static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class, uint16_t filter_value)
{
struct usb_setup_packet *setup = cdc_ecm_class->hport->setup;
struct usb_setup_packet *setup;
if (!cdc_ecm_class || !cdc_ecm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_ecm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_ETHERNET_PACKET_FILTER;
@@ -188,7 +193,7 @@ get_mac:
}
USB_LOG_INFO("Set CDC ECM packet filter:%04x\r\n", CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
@@ -230,15 +235,8 @@ void usbh_cdc_ecm_rx_thread(void *argument)
{
uint32_t g_cdc_ecm_rx_length;
int ret;
err_t err;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#else
pbuf_type type = PBUF_POOL;
#endif
struct netif *netif = (struct netif *)argument;
(void)argument;
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
// clang-format off
find_class:
@@ -254,44 +252,33 @@ find_class:
usb_osal_msleep(100);
goto find_class;
}
usb_osal_msleep(128);
}
g_cdc_ecm_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, g_cdc_ecm_rx_buffer, CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
g_cdc_ecm_rx_length = g_cdc_ecm_class.bulkin_urb.actual_length;
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize).
* Short packet is zero, check if g_cdc_ecm_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 512 < 1514.
* This case is always true
*/
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize) ||
(g_cdc_ecm_class.bulkin_urb.actual_length < CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE)) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = g_cdc_ecm_rx_buffer;
#else
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
#endif
g_cdc_ecm_rx_length = 0;
usbh_cdc_ecm_eth_input(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
g_cdc_ecm_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
}
g_cdc_ecm_rx_length = 0;
} else {
/* read continue util read short packet */
if (g_cdc_ecm_rx_length > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_cdc_ecm_rx_length = 0;
}
/* There's no way to run here. */
}
}
// clang-format off
@@ -301,38 +288,31 @@ delete:
// clang-format on
}
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void)
{
int ret;
struct pbuf *q;
uint8_t *buffer = g_cdc_ecm_tx_buffer;
return g_cdc_ecm_tx_buffer;
}
int usbh_cdc_ecm_eth_output(uint32_t buflen)
{
if (g_cdc_ecm_class.connect_status == false) {
return ERR_BUF;
return -USB_ERR_NOTCONN;
}
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
USB_LOG_DBG("txlen:%d\r\n", buflen);
USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
return usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
}
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
{
(void)cdc_ecm_class;
}
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
{
(void)cdc_ecm_class;
}
const struct usbh_class_driver cdc_ecm_class_driver = {
@@ -343,9 +323,9 @@ const struct usbh_class_driver cdc_ecm_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
.bInterfaceSubClass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
.id_table = NULL,
.class_driver = &cdc_ecm_class_driver
};

View File

@@ -8,9 +8,6 @@
#include "usb_cdc.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_cdc_ecm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
@@ -29,10 +26,6 @@ struct usbh_cdc_ecm {
uint16_t max_segment_size;
uint32_t speed[2];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
@@ -45,7 +38,9 @@ int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p);
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void);
int usbh_cdc_ecm_eth_output(uint32_t buflen);
void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_cdc_ecm_rx_thread(void *argument);
#ifdef __cplusplus

View File

@@ -33,9 +33,14 @@ static struct usbh_cdc_ncm g_cdc_ncm_class;
static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, struct cdc_ncm_ntb_parameters *param)
{
struct usb_setup_packet *setup = cdc_ncm_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!cdc_ncm_class || !cdc_ncm_class->hport) {
return -USB_ERR_INVAL;
}
setup = cdc_ncm_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_GET_NTB_PARAMETERS;
setup->wValue = 0;
@@ -43,7 +48,7 @@ static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, s
setup->wLength = 28;
ret = usbh_control_transfer(cdc_ncm_class->hport, setup, g_cdc_ncm_buf);
if (ret < 0) {
if (ret < 8) {
return ret;
}
@@ -206,7 +211,7 @@ get_mac:
}
}
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
@@ -248,15 +253,13 @@ void usbh_cdc_ncm_rx_thread(void *argument)
{
uint32_t g_cdc_ncm_rx_length;
int ret;
err_t err;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE;
#else
pbuf_type type = PBUF_POOL;
uint32_t transfer_size = (16 * 1024);
#endif
struct netif *netif = (struct netif *)argument;
(void)argument;
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
// clang-format off
find_class:
@@ -276,7 +279,7 @@ find_class:
g_cdc_ncm_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkin_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkin, &g_cdc_ncm_rx_buffer[g_cdc_ncm_rx_length], (CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE > (16 * 1024)) ? (16 * 1024) : CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkin_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkin, &g_cdc_ncm_rx_buffer[g_cdc_ncm_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkin_urb);
if (ret < 0) {
goto find_class;
@@ -284,7 +287,12 @@ find_class:
g_cdc_ncm_rx_length += g_cdc_ncm_class.bulkin_urb.actual_length;
if (g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize)) {
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize).
* Short packet is zero, check if g_cdc_ncm_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 1024 < 2048.
*/
if ((g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize)) ||
(g_cdc_ncm_class.bulkin_urb.actual_length < transfer_size)) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ncm_rx_length);
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_rx_buffer[0];
@@ -311,29 +319,21 @@ find_class:
if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
p = pbuf_alloc(PBUF_RAW, ndp16_datagram->wDatagramLength, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
#else
memcpy(p->payload, (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex], ndp16_datagram->wDatagramLength);
#endif
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
USB_LOG_ERR("No memory to alloc pbuf for cdc ncm rx\r\n");
}
uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength);
}
}
g_cdc_ncm_rx_length = 0;
} else {
if (g_cdc_ncm_rx_length > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_cdc_ncm_rx_length = 0;
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
if (g_cdc_ncm_rx_length == CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
#else
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
}
}
@@ -344,15 +344,17 @@ delete:
// clang-format on
}
err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void)
{
return &g_cdc_ncm_tx_buffer[16];
}
int usbh_cdc_ncm_eth_output(uint32_t buflen)
{
int ret;
struct pbuf *q;
uint8_t *buffer;
struct cdc_ncm_ndp16_datagram *ndp16_datagram;
if (g_cdc_ncm_class.connect_status == false) {
return ERR_BUF;
return -USB_ERR_NOTCONN;
}
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_tx_buffer[0];
@@ -360,8 +362,8 @@ err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
nth16->dwSignature = CDC_NCM_NTH16_SIGNATURE;
nth16->wHeaderLength = 12;
nth16->wSequence = g_cdc_ncm_class.bulkout_sequence++;
nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(p->tot_len, 4);
nth16->wNdpIndex = 16 + USB_ALIGN_UP(p->tot_len, 4);
nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(buflen, 4);
nth16->wNdpIndex = 16 + USB_ALIGN_UP(buflen, 4);
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex];
@@ -371,36 +373,26 @@ err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 0];
ndp16_datagram->wDatagramIndex = 16;
ndp16_datagram->wDatagramLength = p->tot_len;
ndp16_datagram->wDatagramLength = buflen;
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 1];
ndp16_datagram->wDatagramIndex = 0;
ndp16_datagram->wDatagramLength = 0;
buffer = &g_cdc_ncm_tx_buffer[16];
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
USB_LOG_DBG("txlen:%d\r\n", nth16->wBlockLength);
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkout_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkout, g_cdc_ncm_tx_buffer, nth16->wBlockLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
return usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
}
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
{
(void)cdc_ncm_class;
}
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
{
(void)cdc_ncm_class;
}
const struct usbh_class_driver cdc_ncm_class_driver = {
@@ -411,9 +403,9 @@ const struct usbh_class_driver cdc_ncm_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_NETWORK_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
.bInterfaceSubClass = CDC_NETWORK_CONTROL_MODEL,
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
.id_table = NULL,
.class_driver = &cdc_ncm_class_driver
};

View File

@@ -8,9 +8,6 @@
#include "usb_cdc.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_cdc_ncm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
@@ -33,10 +30,6 @@ struct usbh_cdc_ncm {
uint16_t max_segment_size;
uint32_t speed[2];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
@@ -49,7 +42,9 @@ int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class);
void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class);
void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p);
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void);
int usbh_cdc_ncm_eth_output(uint32_t buflen);
void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_cdc_ncm_rx_thread(void *argument);
#ifdef __cplusplus

View File

@@ -558,26 +558,24 @@ struct usb_hid_kbd_report
};
/* Keyboard output report (1 byte) (HID B.1),
* see USBHID_KBDOUT_* definitions
* see HID_KBD_OUTPUT_* definitions
*/
/* Mouse input report (HID B.2) */
struct usb_hid_mouse_report
{
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
uint8_t xdisp; /* X displacement */
uint8_t ydisp; /* y displacement */
int8_t xdisp; /* X displacement */
int8_t ydisp; /* y displacement */
/* Device specific additional bytes may follow */
#ifdef CONFIG_INPUT_MOUSE_WHEEL
uint8_t wdisp; /* Wheel displacement */
#endif
};
/* Joystick input report (1 bytes) (HID D.1) */
struct usb_hid_js_report
{
uint8_t xpos; /* X position */
uint8_t ypos; /* X position */
int8_t xpos; /* X position */
int8_t ypos; /* X position */
uint8_t buttons; /* See USBHID_JSIN_* definitions */
uint8_t throttle; /* Throttle */
};

View File

@@ -50,6 +50,8 @@ static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_p
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
{
(void)busid;
intf->class_interface_handler = hid_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
@@ -60,30 +62,65 @@ struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *
return intf;
}
/*
* Appendix G: HID Request Support Requirements
*
* The following table enumerates the requests that need to be supported by various types of HID class devices.
* Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
* ------------------------------------------------------------------------------------------
* Boot Mouse Required Optional Optional Optional Required Required
* Non-Boot Mouse Required Optional Optional Optional Optional Optional
* Boot Keyboard Required Optional Required Required Required Required
* Non-Boot Keybrd Required Optional Required Required Optional Optional
* Other Device Required Optional Optional Optional Optional Optional
*/
__WEAK void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
{
(void)busid;
(void)intf;
(void)report_id;
(void)report_type;
(*data[0]) = 0;
*len = 1;
}
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
{
(void)busid;
(void)intf;
(void)report_id;
return 0;
}
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
{
(void)busid;
(void)intf;
return 0;
}
__WEAK void usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
{
(void)busid;
(void)intf;
(void)report_id;
(void)report_type;
(void)report;
(void)report_len;
}
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
{
(void)busid;
(void)intf;
(void)report_id;
(void)duration;
}
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
{
(void)busid;
(void)intf;
(void)protocol;
}

View File

@@ -12,18 +12,26 @@
#define DEV_FORMAT "/dev/input%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[CONFIG_USBHOST_MAX_HID_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_hid *usbh_hid_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
g_hid_class[devno].minor = devno;
return &g_hid_class[devno];
@@ -34,36 +42,40 @@ static struct usbh_hid *usbh_hid_class_alloc(void)
static void usbh_hid_class_free(struct usbh_hid *hid_class)
{
int devno = hid_class->minor;
uint8_t devno = hid_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(hid_class, 0, sizeof(struct usbh_hid));
}
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer, uint32_t buflen)
{
struct usb_setup_packet *setup = hid_class->hport->setup;
int ret;
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
setup->wIndex = hid_class->intf;
setup->wLength = 128;
setup->wLength = buflen;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf, ret - 8);
return ret;
return usbh_control_transfer(hid_class->hport, setup, buffer);
}
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration)
{
struct usb_setup_packet *setup = hid_class->hport->setup;
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_SET_IDLE;
@@ -76,26 +88,36 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
{
struct usb_setup_packet *setup = hid_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_GET_IDLE;
setup->wValue = 0;
setup->wIndex = hid_class->intf;
setup->wLength = 1;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
if (ret < 0) {
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 8) {
return ret;
}
memcpy(buffer, g_hid_buf, 1);
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
{
struct usb_setup_packet *setup = hid_class->hport->setup;
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_SET_PROTOCOL;
@@ -108,7 +130,12 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
{
struct usb_setup_packet *setup = hid_class->hport->setup;
struct usb_setup_packet *setup;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_SET_REPORT;
@@ -121,7 +148,13 @@ int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
{
struct usb_setup_packet *setup = hid_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!hid_class || !hid_class->hport) {
return -USB_ERR_INVAL;
}
setup = hid_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = HID_REQUEST_GET_REPORT;
@@ -129,13 +162,21 @@ int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
setup->wIndex = 0;
setup->wLength = buflen;
return usbh_control_transfer(hid_class->hport, setup, buffer);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 8) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t cur_iface = 0xff;
uint8_t *p;
bool found = false;
struct usbh_hid *hid_class = usbh_hid_class_alloc();
if (hid_class == NULL) {
@@ -148,6 +189,42 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
hport->config.intf[intf].priv = hid_class;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
if (cur_iface == intf) {
hid_class->protocol = p[7];
struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)(p + 9);
if (desc->bDescriptorType != HID_DESCRIPTOR_TYPE_HID) {
USB_LOG_ERR("HID descriptor not found\r\n");
return -USB_ERR_INVAL;
}
if (desc->subdesc[0].bDescriptorType != HID_DESCRIPTOR_TYPE_HID_REPORT) {
USB_LOG_ERR("HID report descriptor not found\r\n");
return -USB_ERR_INVAL;
}
hid_class->report_size = desc->subdesc[0].wDescriptorLength;
found = true;
goto found;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
if (found == false) {
USB_LOG_ERR("HID interface not found\r\n");
return -USB_ERR_INVAL;
}
found:
// /* 0x0 = boot protocol, 0x1 = report protocol */
// ret = usbh_hid_set_protocol(hid_class, 0x1);
// if (ret < 0) {
@@ -159,7 +236,8 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
USB_LOG_WRN("Do not support set idle\r\n");
}
ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc);
/* We read report desc but do nothing (because of too much memory usage for parsing report desc, parsed by users) */
ret = usbh_hid_get_report_descriptor(hid_class, g_hid_buf[hid_class->minor], MIN(sizeof(g_hid_buf[hid_class->minor]), hid_class->report_size));
if (ret < 0) {
return ret;
}
@@ -209,10 +287,12 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
{
(void)hid_class;
}
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
{
(void)hid_class;
}
const struct usbh_class_driver hid_class_driver = {
@@ -223,9 +303,9 @@ const struct usbh_class_driver hid_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.class = USB_DEVICE_CLASS_HID,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = USB_DEVICE_CLASS_HID,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = NULL,
.class_driver = &hid_class_driver
};

View File

@@ -15,7 +15,9 @@ struct usbh_hid {
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t report_desc[256];
uint16_t report_size;
uint8_t protocol;
uint8_t intf; /* interface number */
uint8_t minor;
@@ -26,6 +28,7 @@ struct usbh_hid {
extern "C" {
#endif
int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer, uint32_t buflen);
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration);
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer);
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);

View File

@@ -10,6 +10,12 @@
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
#define HUB_MAX_DEPTH 5
#define HUB_SUBCLASS 0x00
#define HUB_PROTOCOL_STT 0x01
#define HUB_PROTOCOL_MTT 0x02
/* Hub class requests */
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
@@ -27,23 +33,31 @@
#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
/* Port features */
#define HUB_PORT_FEATURE_CONNECTION (0x00)
#define HUB_PORT_FEATURE_ENABLE (0x01)
#define HUB_PORT_FEATURE_SUSPEND (0x02)
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
#define HUB_PORT_FEATURE_RESET (0x04)
#define HUB_PORT_FEATURE_L1 (0x05)
#define HUB_PORT_FEATURE_POWER (0x08)
#define HUB_PORT_FEATURE_LOWSPEED (0x09)
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
#define HUB_PORT_FEATURE_CONNECTION (0x00)
#define HUB_PORT_FEATURE_ENABLE (0x01)
#define HUB_PORT_FEATURE_SUSPEND (0x02)
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
#define HUB_PORT_FEATURE_RESET (0x04)
#define HUB_PORT_FEATURE_L1 (0x05) /* USB 2.0 only */
#define HUB_PORT_FEATURE_POWER (0x08) /* USB 2.0 only */
#define HUB_PORT_FEATURE_POWER_SS (0x09) /* USB 3.0 only */
/* This is a bit tricky because HUB_PORT_FEATURE_POWER_SS and
HUB_PORT_FEATURE_LOWSPEED share the same bit. */
#define HUB_PORT_FEATURE_LOWSPEED (0x09) /* USB 2.0 only */
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) /* USB 2.0 only */
#define HUB_PORT_FEATURE_TEST (0x0b) /* USB 2.0 only */
#define HUB_PORT_FEATURE_INDICATOR (0x0c) /* USB 2.0 only */
/* Port status change (wPortChange) */
#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
#define HUB_PORT_FEATURE_C_ENABLE (0x11)
#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
#define HUB_PORT_FEATURE_C_ENABLE (0x11) /* USB 2.0 only */
#define HUB_PORT_FEATURE_C_SUSPEND (0x12) /* USB 2.0 only */
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
#define HUB_PORT_FEATURE_C_RESET (0x14)
#define HUB_PORT_FEATURE_TEST (0x15)
#define HUB_PORT_FEATURE_INDICATOR (0x16)
#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
#define HUB_PORT_FEATURE_C_BH_RESET (0x15) /* USB 3.0 only */
#define HUB_PORT_FEATURE_C_LINK_STATE (0x16) /* USB 3.0 only */
#define HUB_PORT_FEATURE_C_CONFIG_ERR (0x17) /* USB 3.0 only */
/* Hub status */
#define HUB_STATUS_LOCALPOWER (1 << 0)
@@ -56,23 +70,42 @@
/* Hub port status */
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
#define HUB_PORT_STATUS_ENABLE (1 << 1)
#define HUB_PORT_STATUS_SUSPEND (1 << 2)
#define HUB_PORT_STATUS_SUSPEND (1 << 2) /* USB 2.0 only */
#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
#define HUB_PORT_STATUS_RESET (1 << 4)
#define HUB_PORT_STATUS_L1 (1 << 5)
#define HUB_PORT_STATUS_POWER (1 << 8)
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
#define HUB_PORT_STATUS_TEST (1 << 11)
#define HUB_PORT_STATUS_INDICATOR (1 << 12)
#define HUB_PORT_STATUS_L1 (1 << 5) /* USB 2.0 only */
/* Port Link State (PORT_LINK_STATE), USB 3.0 only */
#define HUB_PORT_STATUS_LS_U0 (0x00 << 5)
#define HUB_PORT_STATUS_LS_U1 (0x01 << 5)
#define HUB_PORT_STATUS_LS_U2 (0x02 << 5)
#define HUB_PORT_STATUS_LS_U3 (0x03 << 5)
#define HUB_PORT_STATUS_LS_SS_DISABLED (0x04 << 5)
#define HUB_PORT_STATUS_LS_RX_DETECT (0x05 << 5)
#define HUB_PORT_STATUS_LS_SS_INACTIVE (0x06 << 5)
#define HUB_PORT_STATUS_LS_POLLING (0x07 << 5)
#define HUB_PORT_STATUS_LS_RECOVERY (0x08 << 5)
#define HUB_PORT_STATUS_LS_HOT_RESET (0x09 << 5)
#define HUB_PORT_STATUS_LS_COMP_MOD (0x0a << 5)
#define HUB_PORT_STATUS_LS_LOOPBACK (0x0b << 5)
#define HUB_PORT_STATUS_POWER (1 << 8)
#define HUB_PORT_STATUS_POWER_SS (1 << 9) /* USB 3.0 only */
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) /* USB 2.0 only */
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) /* USB 2.0 only */
#define HUB_PORT_STATUS_TEST (1 << 11) /* USB 2.0 only */
#define HUB_PORT_STATUS_INDICATOR (1 << 12) /* USB 2.0 only */
/* Hub port status change */
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
#define HUB_PORT_STATUS_C_ENABLE (1 << 1) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
#define HUB_PORT_STATUS_C_RESET (1 << 4)
#define HUB_PORT_STATUS_C_L1 (1 << 5)
#define HUB_PORT_STATUS_C_L1 (1 << 5) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_BH_RESET (1 << 5) /* USB 3.0 only */
#define HUB_PORT_STATUS_C_PORTLINK (1 << 6) /* USB 3.0 only */
#define HUB_PORT_STATUS_C_CONFIGERR (1 << 7) /* USB 3.0 only */
/* Hub characteristics */
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
@@ -106,6 +139,21 @@ struct usb_hub_descriptor {
#define USB_SIZEOF_HUB_DESC 9
/* Super speed Hub descriptor */
struct usb_hub_ss_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bNbrPorts;
uint16_t wHubCharacteristics;
uint8_t bPwrOn2PwrGood;
uint8_t bHubContrCurrent;
uint8_t bHubHdrDecLat;
uint16_t wHubDelay;
uint8_t DeviceRemovable;
} __PACKED;
#define USB_SIZEOF_HUB_SS_DESC 11
/* Hub status */
struct hub_status {
uint16_t wPortStatus;

View File

@@ -27,24 +27,17 @@ extern void usbh_hubport_release(struct usbh_hubport *hport);
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
#ifdef CONFIG_USBHOST_XHCI
struct usbh_hubport *usbh_get_roothub_port(unsigned int port)
{
return &roothub.child[port - 1];
}
#endif
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
static uint32_t g_devinuse = 0;
static struct usbh_hub *usbh_hub_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
return &g_hub_class[devno];
@@ -55,16 +48,14 @@ static struct usbh_hub *usbh_hub_class_alloc(void)
static void usbh_hub_class_free(struct usbh_hub *hub_class)
{
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
uint8_t devno = hub_class->index - EXTHUB_FIRST_INDEX;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(hub_class, 0, sizeof(struct usbh_hub));
}
#endif
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
@@ -74,15 +65,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
/* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
and we havn't handle the difference here */
if ((hub->parent->speed == USB_SPEED_SUPER) ||
(hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
} else {
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
}
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_HUB_DESC;
@@ -94,8 +77,8 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
return ret;
}
#if 0
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
static int _usbh_hub_get_hub_ss_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
int ret;
@@ -103,20 +86,20 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
setup = hub->parent->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = HUB_REQUEST_GET_STATUS;
setup->wValue = 0;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
setup->wIndex = 0;
setup->wLength = 2;
setup->wLength = USB_SIZEOF_HUB_SS_DESC;
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hub_buf[hub->bus->busid], 2);
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_SS_DESC);
return ret;
}
#endif
#endif
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -187,6 +170,8 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
{
(void)length;
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -1;
@@ -206,6 +191,29 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
}
return 0;
}
static int parse_hub_ss_descriptor(struct usb_hub_ss_descriptor *desc, uint16_t length)
{
(void)length;
if (desc->bLength < USB_SIZEOF_HUB_SS_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -1;
} else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB3) {
USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
return -2;
} else {
USB_LOG_RAW("SuperSpeed Hub Descriptor:\r\n");
USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
}
return 0;
}
#endif
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
@@ -318,22 +326,65 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->bus = hport->bus;
hub->speed = hport->speed;
hport->self = hub;
hport->config.intf[intf].priv = hub;
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
if (ret < 0) {
return ret;
if (hport->depth > HUB_MAX_DEPTH) {
USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
return -USB_ERR_INVAL;
}
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
/*
* Super-Speed hubs need to know their depth to be able to
* parse the bits of the route-string that correspond to
* their downstream port number.
*
*/
if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
ret = usbh_hub_set_depth(hub, hport->depth - 1);
if (ret < 0) {
USB_LOG_ERR("Unable to set hub depth \r\n");
return ret;
}
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
/* Get hub descriptor. */
if (hport->speed == USB_SPEED_SUPER) {
ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
if (ret < 0) {
return ret;
}
parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
hub->nports = hub->hub_ss_desc.bNbrPorts;
hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
hub->tt_think = 0U;
} else {
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
if (ret < 0) {
return ret;
}
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
hub->nports = hub->hub_desc.bNbrPorts;
hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
}
for (uint8_t port = 0; port < hub->nports; port++) {
hub->child[port].port = port + 1;
hub->child[port].parent = hub;
hub->child[port].bus = hport->bus;
}
if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
hub->ismtt = 1;
} else {
hub->ismtt = 0;
}
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(hub->intin, ep_desc);
@@ -341,28 +392,16 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
return -1;
}
if (hport->speed == USB_SPEED_SUPER) {
uint16_t depth = 0;
struct usbh_hubport *parent = hport->parent->parent;
while (parent) {
depth++;
parent = parent->parent->parent;
}
ret = usbh_hub_set_depth(hub, depth);
if (ret < 0) {
return ret;
}
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
if (ret < 0) {
return ret;
}
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
usb_osal_msleep(hub->powerdelay);
for (uint8_t port = 0; port < hub->nports; port++) {
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
if (ret < 0) {
@@ -373,8 +412,6 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->connected = true;
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
usb_slist_add_tail(&hub->bus->hub_list, &hub->list);
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
@@ -404,7 +441,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
usb_osal_timer_delete(hub->int_timer);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
child = &hub->child[port];
usbh_hubport_release(child);
child->parent = NULL;
@@ -412,7 +449,6 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
usb_slist_remove(&hub->bus->hub_list, &hub->list);
}
usbh_hub_class_free(hub);
@@ -421,38 +457,28 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
#endif
static void usbh_hubport_enumerate_thread(void *argument)
{
struct usbh_hubport *child = (struct usbh_hubport *)argument;
if (usbh_enumerate(child) < 0) {
/** release child sources */
usbh_hubport_release(child);
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
}
usb_osal_thread_delete(NULL);
}
static void usbh_hub_events(struct usbh_hub *hub)
{
struct usbh_hubport *child;
struct hub_port_status port_status;
uint8_t portchange_index;
uint16_t portchange_index;
uint16_t portstatus;
uint16_t portchange;
uint16_t mask;
uint16_t feat;
uint8_t speed;
int ret;
size_t flags;
if (!hub->connected) {
return;
}
portchange_index = hub->int_buffer[0];
hub->int_buffer[0] &= ~portchange_index;
flags = usb_osal_enter_critical_section();
memcpy(&portchange_index, hub->int_buffer, 2);
usb_osal_leave_critical_section(flags);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
for (uint8_t port = 0; port < hub->nports; port++) {
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
if (!(portchange_index & (1 << (port + 1)))) {
@@ -558,29 +584,24 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
}
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
speed = USB_SPEED_HIGH;
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
speed = USB_SPEED_LOW;
}
#ifdef CONFIG_USBHOST_XHCI
else {
extern uint8_t usbh_get_port_speed(struct usbh_hub * hub, const uint8_t port);
/* USB3.0 speed cannot get from portstatus, checkout port speed instead */
uint8_t super_speed = usbh_get_port_speed(hub, port + 1);
if (super_speed > USB_SPEED_HIGH) {
/* assert that when using USB 3.0 ports, attached device must also be USB 3.0 speed */
speed = super_speed;
/*
* Figure out device speed. This is a bit tricky because
* HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
*/
if (portstatus & HUB_PORT_STATUS_POWER) {
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
speed = USB_SPEED_HIGH;
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
speed = USB_SPEED_LOW;
} else {
speed = USB_SPEED_FULL;
}
} else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
speed = USB_SPEED_SUPER;
} else {
USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
continue;
}
#else
else {
speed = USB_SPEED_FULL;
}
#endif
child = &hub->child[port];
/** release child sources first */
@@ -588,6 +609,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
memset(child, 0, sizeof(struct usbh_hubport));
child->parent = hub;
child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
child->connected = true;
child->port = port + 1;
child->speed = speed;
@@ -596,8 +618,11 @@ static void usbh_hub_events(struct usbh_hub *hub)
USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
/* create disposable thread to enumerate device on current hport, do not block hub thread */
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
if (usbh_enumerate(child) < 0) {
/** release child sources */
usbh_hubport_release(child);
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
}
} else {
child = &hub->child[port];
/** release child sources */
@@ -648,6 +673,17 @@ void usbh_hub_thread_wakeup(struct usbh_hub *hub)
int usbh_hub_initialize(struct usbh_bus *bus)
{
char thread_name[32] = { 0 };
struct usbh_hub *hub;
hub = &bus->hcd.roothub;
hub->connected = true;
hub->index = 1;
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
bus->hub_mq = usb_osal_mq_create(7);
if (bus->hub_mq == NULL) {
@@ -666,21 +702,17 @@ int usbh_hub_initialize(struct usbh_bus *bus)
int usbh_hub_deinitialize(struct usbh_bus *bus)
{
usb_slist_t *hub_list;
struct usbh_hubport *hport;
struct usbh_hub *hub;
size_t flags;
flags = usb_osal_enter_critical_section();
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
hub = &bus->hcd.roothub;
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
usbh_hubport_release(hport);
}
usbh_hubport_release(hport);
}
usb_hc_deinit(bus);
@@ -702,9 +734,9 @@ const struct usbh_class_driver hub_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
.class = USB_DEVICE_CLASS_HUB,
.subclass = 0,
.protocol = 0,
.bInterfaceClass = USB_DEVICE_CLASS_HUB,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.id_table = NULL,
.class_driver = &hub_class_driver
};

View File

@@ -10,10 +10,6 @@
struct usbh_hub;
#define USBH_HUB_MAX_PORTS 4
/* Maximum size of an interrupt IN transfer */
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -9,6 +9,8 @@
#include "usb_scsi.h"
#if defined(CONFIG_USBDEV_MSC_THREAD)
#include "usb_osal.h"
#elif defined(CONFIG_USBDEV_MSC_POLLING)
#include "chry_ringbuffer.h"
#endif
#define MSD_OUT_EP_IDX 0
@@ -50,6 +52,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
usb_osal_mq_t usbd_msc_mq;
usb_osal_thread_t usbd_msc_thread;
uint32_t nbytes;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_t msc_rb;
uint8_t msc_rb_pool[2];
uint32_t nbytes;
#endif
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
@@ -94,21 +100,25 @@ static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb
void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)arg;
switch (event) {
case USBD_EVENT_INIT:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_mq\r\n");
}
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)busid);
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)(uint32_t)busid);
if (g_usbd_msc[busid].usbd_msc_thread == NULL) {
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_thread\r\n");
}
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_init(&g_usbd_msc[busid].msc_rb, g_usbd_msc[busid].msc_rb_pool, sizeof(g_usbd_msc[busid].msc_rb_pool));
#endif
break;
case USBD_EVENT_DEINIT:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
if (g_usbd_msc[busid].usbd_msc_mq) {
usb_osal_mq_delete(g_usbd_msc[busid].usbd_msc_mq);
}
@@ -500,6 +510,9 @@ static bool SCSI_readCapacity10(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -522,9 +535,12 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
return true;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
return true;
#else
return SCSI_processRead(busid);
#endif
@@ -532,6 +548,9 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -554,9 +573,12 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
return false;
}
g_usbd_msc[busid].stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
return true;
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
return true;
#else
return SCSI_processRead(busid);
#endif
@@ -565,6 +587,10 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -594,6 +620,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
(void)data;
(void)len;
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
@@ -803,6 +833,8 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
switch (g_usbd_msc[busid].stage) {
case MSC_READ_CBW:
if (SCSI_CBWDecode(busid, nbytes) == false) {
@@ -815,9 +847,12 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_WRITE10:
case SCSI_CMD_WRITE12:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
g_usbd_msc[busid].nbytes = nbytes;
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
g_usbd_msc[busid].nbytes = nbytes;
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_OUT);
#else
if (SCSI_processWrite(busid, nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -835,13 +870,18 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)ep;
(void)nbytes;
switch (g_usbd_msc[busid].stage) {
case MSC_DATA_IN:
switch (g_usbd_msc[busid].cbw.CB[0]) {
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
#elif defined(CONFIG_USBDEV_MSC_POLLING)
chry_ringbuffer_write_byte(&g_usbd_msc[busid].msc_rb, MSC_DATA_IN);
#else
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -870,19 +910,38 @@ void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
}
}
#ifdef CONFIG_USBDEV_MSC_THREAD
#if defined(CONFIG_USBDEV_MSC_THREAD)
static void usbdev_msc_thread(void *argument)
{
uintptr_t event;
int ret;
uint8_t busid = (uint8_t)argument;
uint8_t busid = (uint8_t)(uint32_t)argument;
while (1) {
ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
USB_LOG_DBG("%d\r\n", event);
USB_LOG_DBG("event:%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else if (event == MSC_DATA_IN) {
if (SCSI_processRead(busid) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else {
}
}
}
#elif defined(CONFIG_USBDEV_MSC_POLLING)
void usbd_msc_polling(uint8_t busid)
{
uint8_t event;
if (chry_ringbuffer_read_byte(&g_usbd_msc[busid].msc_rb, &event)) {
USB_LOG_DBG("event:%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -918,9 +977,9 @@ struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *
for (uint8_t i = 0u; i <= g_usbd_msc[busid].max_lun; i++) {
usbd_msc_get_cap(busid, i, &g_usbd_msc[busid].scsi_blk_nbr[i], &g_usbd_msc[busid].scsi_blk_size[i]);
if (g_usbd_msc[busid].scsi_blk_size[i] > CONFIG_USBDEV_MSC_MAX_BUFSIZE) {
USB_LOG_ERR("msc block buffer overflow\r\n");
return NULL;
if (CONFIG_USBDEV_MSC_MAX_BUFSIZE % g_usbd_msc[busid].scsi_blk_size[i]) {
USB_LOG_ERR("CONFIG_USBDEV_MSC_MAX_BUFSIZE must be a multiple of block size\r\n");
while(1){}
}
}
@@ -932,7 +991,7 @@ void usbd_msc_set_readonly(uint8_t busid, bool readonly)
g_usbd_msc[busid].readonly = readonly;
}
bool usbd_msc_set_popup(uint8_t busid)
bool usbd_msc_get_popup(uint8_t busid)
{
return g_usbd_msc[busid].popup;
}

View File

@@ -23,7 +23,9 @@ int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *b
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
bool usbd_msc_set_popup(uint8_t busid);
bool usbd_msc_get_popup(uint8_t busid);
void usbd_msc_polling(uint8_t busid);
#ifdef __cplusplus
}

View File

@@ -13,7 +13,9 @@
#define DEV_FORMAT "/dev/sd%c"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[64];
#define MSC_INQUIRY_TIMEOUT 500
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
static uint32_t g_devinuse = 0;
@@ -21,11 +23,11 @@ static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
static struct usbh_msc *usbh_msc_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_msc_class[devno], 0, sizeof(struct usbh_msc));
g_msc_class[devno].sdchar = 'a' + devno;
return &g_msc_class[devno];
@@ -36,17 +38,22 @@ static struct usbh_msc *usbh_msc_class_alloc(void)
static void usbh_msc_class_free(struct usbh_msc *msc_class)
{
int devno = msc_class->sdchar - 'a';
uint8_t devno = msc_class->sdchar - 'a';
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(msc_class, 0, sizeof(struct usbh_msc));
}
static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
{
struct usb_setup_packet *setup = msc_class->hport->setup;
struct usb_setup_packet *setup;
if (!msc_class || !msc_class->hport) {
return -USB_ERR_INVAL;
}
setup = msc_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = MSC_REQUEST_GET_MAX_LUN;
@@ -80,6 +87,8 @@ static void usbh_msc_cbw_dump(struct CBW *cbw)
static void usbh_msc_csw_dump(struct CSW *csw)
{
(void)csw;
USB_LOG_DBG("CSW:\r\n");
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
@@ -113,14 +122,14 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
return ret;
}
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer, uint32_t timeout)
{
int nbytes;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, timeout);
if (nbytes < 0) {
USB_LOG_ERR("cbw transfer error\r\n");
goto __err_exit;
@@ -128,16 +137,16 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
if (cbw->dDataLength != 0) {
if (cbw->CB[0] == SCSI_CMD_WRITE10) {
nbytes = usbh_msc_bulk_out_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
nbytes = usbh_msc_bulk_out_transfer(msc_class, buffer, cbw->dDataLength, timeout);
} else if (cbw->CB[0] == SCSI_CMD_READCAPACITY10) {
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, timeout);
if (nbytes >= 0) {
/* Save the capacity information */
msc_class->blocknum = GET_BE32(&buffer[0]) + 1;
msc_class->blocksize = GET_BE32(&buffer[4]);
}
} else {
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, timeout);
}
if (nbytes < 0) {
@@ -148,7 +157,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
/* Receive the CSW */
memset(csw, 0, USB_SIZEOF_MSC_CSW);
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, timeout);
if (nbytes < 0) {
USB_LOG_ERR("csw transfer error\r\n");
goto __err_exit;
@@ -175,14 +184,14 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
@@ -190,7 +199,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -200,7 +209,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
@@ -208,7 +217,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -218,7 +227,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_INQUIRY;
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
@@ -226,7 +235,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -235,7 +244,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], MSC_INQUIRY_TIMEOUT);
}
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
@@ -243,11 +252,11 @@ static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memcpy(g_msc_buf, message, 31);
memcpy(g_msc_buf[msc_class->sdchar - 'a'], message, 31);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], NULL, MSC_INQUIRY_TIMEOUT);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
@@ -267,12 +276,17 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
hport->config.intf[intf].priv = msc_class;
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf[msc_class->sdchar - 'a']);
if (ret < 0) {
return ret;
if (ret == -USB_ERR_STALL) {
USB_LOG_WRN("Device does not support multiple LUNs\r\n");
g_msc_buf[msc_class->sdchar - 'a'][0] = 0;
} else {
return ret;
}
}
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[msc_class->sdchar - 'a'][0] + 1);
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
@@ -363,13 +377,12 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -380,7 +393,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
@@ -388,7 +401,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
cbw = (struct CBW *)g_msc_buf[msc_class->sdchar - 'a'];
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
@@ -400,7 +413,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
}
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
@@ -414,10 +427,12 @@ void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
{
(void)msc_class;
}
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
{
(void)msc_class;
}
const struct usbh_class_driver msc_class_driver = {
@@ -428,9 +443,9 @@ const struct usbh_class_driver msc_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_MASS_STORAGE,
.subclass = MSC_SUBCLASS_SCSI,
.protocol = MSC_PROTOCOL_BULK_ONLY,
.bInterfaceClass = USB_DEVICE_CLASS_MASS_STORAGE,
.bInterfaceSubClass = MSC_SUBCLASS_SCSI,
.bInterfaceProtocol = MSC_PROTOCOL_BULK_ONLY,
.id_table = NULL,
.class_driver = &msc_class_driver
};

View File

@@ -9,11 +9,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_xxx *usbh_xxx_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_xxx_class[devno], 0, sizeof(struct usbh_xxx));
g_xxx_class[devno].minor = devno;
return &g_xxx_class[devno];
@@ -24,10 +24,10 @@ static struct usbh_xxx *usbh_xxx_class_alloc(void)
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
{
int devno = xxx_class->minor;
uint8_t devno = xxx_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(xxx_class, 0, sizeof(struct usbh_xxx));
}
@@ -89,9 +89,9 @@ static const struct usbh_class_driver xxx_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = 0,
.subclass = 0,
.protocol = 0,
.bInterfaceClass = 0,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.id_table = NULL,
.class_driver = &xxx_class_driver
};

View File

@@ -14,10 +14,9 @@
#define DEV_FORMAT "/dev/asix"
static struct usbh_asix g_asix_class;
#define CONFIG_USBHOST_ASIX_ETH_MAX_SIZE (1514U + 8)
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[16];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[32];
@@ -56,9 +55,14 @@ static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
void *data,
uint16_t size)
{
struct usb_setup_packet *setup = asix_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!asix_class || !asix_class->hport) {
return -USB_ERR_INVAL;
}
setup = asix_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = cmd;
setup->wValue = value;
@@ -66,7 +70,7 @@ static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
setup->wLength = size;
ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
if (ret < 0) {
if (ret < 8) {
return ret;
}
memcpy(data, g_asix_buf, ret - 8);
@@ -81,7 +85,12 @@ static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
void *data,
uint16_t size)
{
struct usb_setup_packet *setup = asix_class->hport->setup;
struct usb_setup_packet *setup;
if (!asix_class || !asix_class->hport) {
return -USB_ERR_INVAL;
}
setup = asix_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = cmd;
@@ -89,9 +98,12 @@ static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
setup->wIndex = index;
setup->wLength = size;
memcpy(g_asix_buf, data, size);
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
if (data && size) {
memcpy(g_asix_buf, data, size);
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
} else {
return usbh_control_transfer(asix_class->hport, setup, NULL);
}
}
static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val)
@@ -263,6 +275,15 @@ static int usbh_asix_write_gpio(struct usbh_asix *asix_class, uint16_t value, in
static void usbh_asix_set_multicast(struct usbh_asix *asix_class)
{
uint16_t rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_AM;
#if CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE == 4096
rx_ctl |= AX_RX_CTL_MFB_4096;
#elif CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE == 8192
rx_ctl |= AX_RX_CTL_MFB_8192;
#elif CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE == 16384
rx_ctl |= AX_RX_CTL_MFB_16384;
#else
rx_ctl |= AX_RX_CTL_MFB_2048;
#endif
const uint8_t multi_filter[] = { 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40 };
usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MULTI_FILTER, 0, 0, (uint8_t *)multi_filter, AX_MCAST_FILTER_SIZE);
@@ -589,7 +610,7 @@ static int usbh_asix_connect(struct usbh_hubport *hport, uint8_t intf)
USB_LOG_INFO("Init %s done\r\n", asix_class->name);
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register ASIX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_asix_run(asix_class);
@@ -653,17 +674,16 @@ void usbh_asix_rx_thread(void *argument)
{
uint32_t g_asix_rx_length;
int ret;
err_t err;
uint16_t len;
uint16_t len_crc;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
uint32_t data_offset;
#if CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE;
#else
pbuf_type type = PBUF_POOL;
uint32_t transfer_size = (16 * 1024);
#endif
struct netif *netif = (struct netif *)argument;
(void)argument;
USB_LOG_INFO("Create asix rx thread\r\n");
// clang-format off
find_class:
@@ -679,11 +699,12 @@ find_class:
usb_osal_msleep(100);
goto find_class;
}
usb_osal_msleep(128);
}
g_asix_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], CONFIG_USBHOST_ASIX_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_asix_class.bulkin_urb);
if (ret < 0) {
goto find_class;
@@ -691,38 +712,43 @@ find_class:
g_asix_rx_length += g_asix_class.bulkin_urb.actual_length;
if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize)) {
len = ((uint16_t)g_asix_rx_buffer[0] | ((uint16_t)(g_asix_rx_buffer[1]) << 8)) & 0x7ff;
len_crc = g_asix_rx_buffer[2] | ((uint16_t)(g_asix_rx_buffer[3]) << 8);
if (len != (~len_crc & 0x7ff)) {
USB_LOG_ERR("asix rx header error\r\n");
continue;
}
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize).
* Short packet is zero, check if g_asix_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 1024 < 2048.
*/
if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize) ||
(g_asix_class.bulkin_urb.actual_length < transfer_size)) {
USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length);
p = pbuf_alloc(PBUF_RAW, len, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = (uint8_t *)&g_asix_rx_buffer[4];
#else
memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len);
#endif
g_asix_rx_length = 0;
data_offset = 0;
while (g_asix_rx_length > 0) {
len = ((uint16_t)g_asix_rx_buffer[data_offset + 0] | ((uint16_t)(g_asix_rx_buffer[data_offset + 1]) << 8)) & 0x7ff;
len_crc = g_asix_rx_buffer[data_offset + 2] | ((uint16_t)(g_asix_rx_buffer[data_offset + 3]) << 8);
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
if (len != (~len_crc & 0x7ff)) {
USB_LOG_ERR("rx header error\r\n");
g_asix_rx_length = 0;
continue;
}
uint8_t *buf = (uint8_t *)&g_asix_rx_buffer[data_offset + 4];
usbh_asix_eth_input(buf, len);
g_asix_rx_length -= (len + 4);
data_offset += (len + 4);
if (g_asix_rx_length < 4) {
g_asix_rx_length = 0;
}
} else {
g_asix_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n");
}
} else {
if (g_asix_rx_length > CONFIG_USBHOST_ASIX_ETH_MAX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_asix_rx_length = 0;
#if CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE <= (16 * 1024)
if (g_asix_rx_length == CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
#else
if ((g_asix_rx_length + (16 * 1024)) > CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
}
}
@@ -733,54 +759,48 @@ delete:
// clang-format on
}
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p)
uint8_t *usbh_asix_get_eth_txbuf(void)
{
return &g_asix_tx_buffer[4];
}
int usbh_asix_eth_output(uint32_t buflen)
{
int ret;
struct pbuf *q;
uint16_t actual_len;
uint8_t *buffer = &g_asix_tx_buffer[4];
if (g_asix_class.connect_status == false) {
return ERR_BUF;
return -USB_ERR_NOTCONN;
}
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
g_asix_tx_buffer[0] = p->tot_len & 0xff;
g_asix_tx_buffer[1] = (p->tot_len >> 8) & 0xff;
g_asix_tx_buffer[0] = buflen & 0xff;
g_asix_tx_buffer[1] = (buflen >> 8) & 0xff;
g_asix_tx_buffer[2] = ~g_asix_tx_buffer[0];
g_asix_tx_buffer[3] = ~g_asix_tx_buffer[1];
if (!(p->tot_len + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 8);
g_asix_tx_buffer[p->tot_len + 4 + 0] = 0x00;
g_asix_tx_buffer[p->tot_len + 4 + 1] = 0x00;
g_asix_tx_buffer[p->tot_len + 4 + 2] = 0xff;
g_asix_tx_buffer[p->tot_len + 4 + 3] = 0xff;
actual_len = p->tot_len + 8;
if (!(buflen + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
USB_LOG_DBG("txlen:%d\r\n", buflen + 8);
g_asix_tx_buffer[buflen + 4 + 0] = 0x00;
g_asix_tx_buffer[buflen + 4 + 1] = 0x00;
g_asix_tx_buffer[buflen + 4 + 2] = 0xff;
g_asix_tx_buffer[buflen + 4 + 3] = 0xff;
actual_len = buflen + 8;
} else {
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4);
actual_len = p->tot_len + 4;
USB_LOG_DBG("txlen:%d\r\n", buflen + 4);
actual_len = buflen + 4;
}
usbh_bulk_urb_fill(&g_asix_class.bulkout_urb, g_asix_class.hport, g_asix_class.bulkout, g_asix_tx_buffer, actual_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_asix_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
return usbh_submit_urb(&g_asix_class.bulkout_urb);
}
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
{
(void)asix_class;
}
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
{
(void)asix_class;
}
static const uint16_t asix_id_table[][2] = {
@@ -797,9 +817,9 @@ static const struct usbh_class_driver asix_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info asix_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = asix_id_table,
.class_driver = &asix_class_driver
};

View File

@@ -6,9 +6,6 @@
#ifndef USBH_ASIX_H
#define USBH_ASIX_H
#include "lwip/netif.h"
#include "lwip/pbuf.h"
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define AX_CMD_SET_SW_MII 0x06
@@ -156,10 +153,6 @@ struct usbh_asix {
bool connect_status;
uint8_t mac[6];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
@@ -172,8 +165,10 @@ int usbh_asix_get_connect_status(struct usbh_asix *asix_class);
void usbh_asix_run(struct usbh_asix *asix_class);
void usbh_asix_stop(struct usbh_asix *asix_class);
uint8_t *usbh_asix_get_eth_txbuf(void);
int usbh_asix_eth_output(uint32_t buflen);
void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_asix_rx_thread(void *argument);
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p);
#ifdef __cplusplus
}

View File

@@ -946,9 +946,14 @@ static int usbh_rtl8152_read_regs(struct usbh_rtl8152 *rtl8152_class,
uint16_t size,
void *data)
{
struct usb_setup_packet *setup = rtl8152_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!rtl8152_class || !rtl8152_class->hport) {
return -USB_ERR_INVAL;
}
setup = rtl8152_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = RTL8152_REQ_GET_REGS;
setup->wValue = value;
@@ -956,7 +961,7 @@ static int usbh_rtl8152_read_regs(struct usbh_rtl8152 *rtl8152_class,
setup->wLength = size;
ret = usbh_control_transfer(rtl8152_class->hport, setup, g_rtl8152_buf);
if (ret < 0) {
if (ret < 8) {
return ret;
}
memcpy(data, g_rtl8152_buf, ret - 8);
@@ -970,7 +975,12 @@ static int usbh_rtl8152_write_regs(struct usbh_rtl8152 *rtl8152_class,
uint16_t size,
void *data)
{
struct usb_setup_packet *setup = rtl8152_class->hport->setup;
struct usb_setup_packet *setup;
if (!rtl8152_class || !rtl8152_class->hport) {
return -USB_ERR_INVAL;
}
setup = rtl8152_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = RTL8152_REQ_SET_REGS;
@@ -987,9 +997,10 @@ static int generic_ocp_read(struct usbh_rtl8152 *tp, uint16_t index, uint16_t si
{
uint16_t limit = 64;
int ret = 0;
uint8_t *buf = data;
/* both size and indix must be 4 bytes align */
if ((size & 3) || !size || (index & 3) || !data)
if ((size & 3) || !size || (index & 3) || !buf)
return -USB_ERR_INVAL;
if ((uint32_t)index + (uint32_t)size > 0xffff)
@@ -997,20 +1008,20 @@ static int generic_ocp_read(struct usbh_rtl8152 *tp, uint16_t index, uint16_t si
while (size) {
if (size > limit) {
ret = usbh_rtl8152_read_regs(tp, index, type, limit, data);
ret = usbh_rtl8152_read_regs(tp, index, type, limit, buf);
if (ret < 0)
break;
index += limit;
data += limit;
buf += limit;
size -= limit;
} else {
ret = usbh_rtl8152_read_regs(tp, index, type, size, data);
ret = usbh_rtl8152_read_regs(tp, index, type, size, buf);
if (ret < 0)
break;
index += size;
data += size;
buf += size;
size = 0;
break;
}
@@ -1025,9 +1036,10 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
int ret;
uint16_t byteen_start, byteen_end, byen;
uint16_t limit = 512;
uint8_t *buf = data;
/* both size and indix must be 4 bytes align */
if ((size & 3) || !size || (index & 3) || !data)
if ((size & 3) || !size || (index & 3) || !buf)
return -USB_ERR_INVAL;
if ((uint32_t)index + (uint32_t)size > 0xffff)
@@ -1040,12 +1052,12 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
/* Split the first DWORD if the byte_en is not 0xff */
if (byen != BYTE_EN_DWORD) {
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, data);
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, buf);
if (ret < 0)
goto error1;
index += 4;
data += 4;
buf += 4;
size -= 4;
}
@@ -1060,22 +1072,22 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
if (size > limit) {
ret = usbh_rtl8152_write_regs(tp, index,
type | BYTE_EN_DWORD,
limit, data);
limit, buf);
if (ret < 0)
goto error1;
index += limit;
data += limit;
buf += limit;
size -= limit;
} else {
ret = usbh_rtl8152_write_regs(tp, index,
type | BYTE_EN_DWORD,
size, data);
size, buf);
if (ret < 0)
goto error1;
index += size;
data += size;
buf += size;
size = 0;
break;
}
@@ -1083,7 +1095,7 @@ static int generic_ocp_write(struct usbh_rtl8152 *tp, uint16_t index, uint16_t b
/* Set the last DWORD */
if (byen != BYTE_EN_DWORD)
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, data);
ret = usbh_rtl8152_write_regs(tp, index, type | byen, 4, buf);
}
error1:
@@ -2080,7 +2092,7 @@ static int usbh_rtl8152_connect(struct usbh_hubport *hport, uint8_t intf)
}
}
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register RTL8152 Class:%s\r\n", hport->config.intf[intf].devname);
@@ -2122,17 +2134,15 @@ void usbh_rtl8152_rx_thread(void *argument)
{
uint32_t g_rtl8152_rx_length;
int ret;
err_t err;
uint16_t len;
uint16_t data_offset;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#if CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE;
#else
pbuf_type type = PBUF_POOL;
uint32_t transfer_size = (16 * 1024);
#endif
struct netif *netif = (struct netif *)argument;
(void)argument;
USB_LOG_INFO("Create rtl8152 rx thread\r\n");
// clang-format off
find_class:
@@ -2162,7 +2172,7 @@ find_class:
g_rtl8152_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_rtl8152_class.bulkin_urb, g_rtl8152_class.hport, g_rtl8152_class.bulkin, &g_rtl8152_rx_buffer[g_rtl8152_rx_length], (CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE > (16 * 1024)) ? (16 * 1024) : CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
usbh_bulk_urb_fill(&g_rtl8152_class.bulkin_urb, g_rtl8152_class.hport, g_rtl8152_class.bulkin, &g_rtl8152_rx_buffer[g_rtl8152_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rtl8152_class.bulkin_urb);
if (ret < 0) {
goto find_class;
@@ -2170,7 +2180,12 @@ find_class:
g_rtl8152_rx_length += g_rtl8152_class.bulkin_urb.actual_length;
if (g_rtl8152_rx_length % USB_GET_MAXPACKETSIZE(g_rtl8152_class.bulkin->wMaxPacketSize)) {
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_rtl8152_rx_length % USB_GET_MAXPACKETSIZE(g_rtl8152_class.bulkin->wMaxPacketSize).
* Short packet is zero, check if g_rtl8152_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 1024 < 2048.
*/
if (g_rtl8152_rx_length % USB_GET_MAXPACKETSIZE(g_rtl8152_class.bulkin->wMaxPacketSize) ||
(g_rtl8152_class.bulkin_urb.actual_length < transfer_size)) {
data_offset = 0;
USB_LOG_DBG("rxlen:%d\r\n", g_rtl8152_rx_length);
@@ -2181,20 +2196,9 @@ find_class:
USB_LOG_DBG("data_offset:%d, eth len:%d\r\n", data_offset, len);
p = pbuf_alloc(PBUF_RAW, len, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = (uint8_t *)&g_rtl8152_rx_buffer[data_offset + sizeof(struct rx_desc)];
#else
memcpy(p->payload, (uint8_t *)&g_rtl8152_rx_buffer[data_offset + sizeof(struct rx_desc)], len);
#endif
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
USB_LOG_ERR("No memory to alloc pbuf for rtl8152 rx\r\n");
}
uint8_t *buf = (uint8_t *)&g_rtl8152_rx_buffer[data_offset + sizeof(struct rx_desc)];
usbh_rtl8152_eth_input(buf, len);
data_offset += (len + sizeof(struct rx_desc));
g_rtl8152_rx_length -= (len + sizeof(struct rx_desc));
@@ -2204,9 +2208,14 @@ find_class:
}
}
} else {
if (g_rtl8152_rx_length > CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_rtl8152_rx_length = 0;
#if CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE <= (16 * 1024)
if (g_rtl8152_rx_length == CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
#else
if ((g_rtl8152_rx_length + (16 * 1024)) > CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
}
}
@@ -2217,44 +2226,37 @@ delete:
// clang-format on
}
err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p)
uint8_t *usbh_rtl8152_get_eth_txbuf(void)
{
int ret;
struct pbuf *q;
uint8_t *buffer;
struct tx_desc *tx_desc = (struct tx_desc *)g_rtl8152_tx_buffer;
return (g_rtl8152_tx_buffer + sizeof(struct tx_desc));
}
int usbh_rtl8152_eth_output(uint32_t buflen)
{
struct tx_desc *tx_desc;
if (g_rtl8152_class.connect_status == false) {
return ERR_BUF;
return -USB_ERR_NOTCONN;
}
tx_desc->opts1 = p->tot_len | TX_FS | TX_LS;
tx_desc = (struct tx_desc *)g_rtl8152_tx_buffer;
tx_desc->opts1 = buflen | TX_FS | TX_LS;
tx_desc->opts2 = 0;
buffer = g_rtl8152_tx_buffer + sizeof(struct tx_desc);
USB_LOG_DBG("txlen:%d\r\n", buflen + sizeof(struct tx_desc));
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + sizeof(struct tx_desc));
usbh_bulk_urb_fill(&g_rtl8152_class.bulkout_urb, g_rtl8152_class.hport, g_rtl8152_class.bulkout, g_rtl8152_tx_buffer, p->tot_len + sizeof(struct tx_desc), USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rtl8152_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
usbh_bulk_urb_fill(&g_rtl8152_class.bulkout_urb, g_rtl8152_class.hport, g_rtl8152_class.bulkout, g_rtl8152_tx_buffer, buflen + sizeof(struct tx_desc), USB_OSAL_WAITING_FOREVER, NULL, NULL);
return usbh_submit_urb(&g_rtl8152_class.bulkout_urb);
}
__WEAK void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
{
(void)rtl8152_class;
}
__WEAK void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
{
(void)rtl8152_class;
}
static const uint16_t rtl_id_table[][2] = {
@@ -2270,9 +2272,9 @@ static const struct usbh_class_driver rtl8152_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info rtl8152_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = rtl_id_table,
.class_driver = &rtl8152_class_driver
};

View File

@@ -6,9 +6,6 @@
#ifndef USBH_RTL8152_H
#define USBH_RTL8152_H
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_rtl8152 {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
@@ -24,10 +21,6 @@ struct usbh_rtl8152 {
bool connect_status;
uint32_t speed[2];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
uint8_t version;
uint8_t eee_adv;
uint8_t eee_en;
@@ -63,8 +56,10 @@ int usbh_rtl8152_get_connect_status(struct usbh_rtl8152 *rtl8152_class);
void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class);
void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class);
uint8_t *usbh_rtl8152_get_eth_txbuf(void);
int usbh_rtl8152_eth_output(uint32_t buflen);
void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_rtl8152_rx_thread(void *argument);
err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p);
#ifdef __cplusplus
}

View File

@@ -17,11 +17,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x));
g_ch34x_class[devno].minor = devno;
return &g_ch34x_class[devno];
@@ -32,10 +32,10 @@ static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class)
{
int devno = ch34x_class->minor;
uint8_t devno = ch34x_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(ch34x_class, 0, sizeof(struct usbh_ch34x));
}
@@ -90,9 +90,14 @@ static int usbh_ch34x_get_baudrate_div(uint32_t baudrate, uint8_t *factor, uint8
static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!ch34x_class || !ch34x_class->hport) {
return -USB_ERR_INVAL;
}
setup = ch34x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_READ_VERSION;
setup->wValue = 0;
@@ -110,7 +115,12 @@ static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class)
static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
struct usb_setup_packet *setup;
if (!ch34x_class || !ch34x_class->hport) {
return -USB_ERR_INVAL;
}
setup = ch34x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_WRITE_REG;
@@ -123,12 +133,17 @@ static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class)
int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
struct usb_setup_packet *setup;
uint16_t reg_value = 0;
uint16_t value = 0;
uint8_t factor = 0;
uint8_t divisor = 0;
if (!ch34x_class || !ch34x_class->hport) {
return -USB_ERR_INVAL;
}
setup = ch34x_class->hport->setup;
memcpy((uint8_t *)&ch34x_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
/* refer to https://github.com/WCHSoftGroup/ch341ser_linux/blob/main/driver/ch341.c */
@@ -197,7 +212,12 @@ int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_c
int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
struct usb_setup_packet *setup;
if (!ch34x_class || !ch34x_class->hport) {
return -USB_ERR_INVAL;
}
setup = ch34x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_MODEM_CTRL;
@@ -329,10 +349,12 @@ int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
{
(void)ch34x_class;
}
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
{
(void)ch34x_class;
}
static const uint16_t ch34x_id_table[][2] = {
@@ -348,9 +370,9 @@ const struct usbh_class_driver ch34x_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = ch34x_id_table,
.class_driver = &ch34x_class_driver
};

View File

@@ -10,18 +10,18 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
#define CONFIG_USBHOST_MAX_CP210X_CLASS 4
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x));
g_cp210x_class[devno].minor = devno;
return &g_cp210x_class[devno];
@@ -32,17 +32,22 @@ static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class)
{
int devno = cp210x_class->minor;
uint8_t devno = cp210x_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(cp210x_class, 0, sizeof(struct usbh_cp210x));
}
static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
struct usb_setup_packet *setup;
if (!cp210x_class || !cp210x_class->hport) {
return -USB_ERR_INVAL;
}
setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_IFC_ENABLE;
@@ -55,7 +60,12 @@ static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class)
static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
struct usb_setup_packet *setup;
if (!cp210x_class || !cp210x_class->hport) {
return -USB_ERR_INVAL;
}
setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_FLOW;
@@ -70,7 +80,12 @@ static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class)
static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
struct usb_setup_packet *setup;
if (!cp210x_class || !cp210x_class->hport) {
return -USB_ERR_INVAL;
}
setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_CHARS;
@@ -87,7 +102,12 @@ static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class)
static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t baudrate)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
struct usb_setup_packet *setup;
if (!cp210x_class || !cp210x_class->hport) {
return -USB_ERR_INVAL;
}
setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_BAUDRATE;
@@ -101,9 +121,14 @@ static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t b
static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t databits, uint8_t parity, uint8_t stopbits)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
struct usb_setup_packet *setup;
uint16_t value;
if (!cp210x_class || !cp210x_class->hport) {
return -USB_ERR_INVAL;
}
setup = cp210x_class->hport->setup;
value = ((databits & 0x0F) << 8) | ((parity & 0x0f) << 4) | ((stopbits & 0x03) << 0);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
@@ -117,9 +142,14 @@ static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t
static int usbh_cp210x_set_mhs(struct usbh_cp210x *cp210x_class, uint8_t dtr, uint8_t rts, uint8_t dtr_mask, uint8_t rts_mask)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
struct usb_setup_packet *setup;
uint16_t value;
if (!cp210x_class || !cp210x_class->hport) {
return -USB_ERR_INVAL;
}
setup = cp210x_class->hport->setup;
value = ((dtr & 0x01) << 0) | ((rts & 0x01) << 1) | ((dtr_mask & 0x01) << 8) | ((rts_mask & 0x01) << 9);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
@@ -268,10 +298,12 @@ int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buf
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
{
(void)cp210x_class;
}
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
{
(void)cp210x_class;
}
static const uint16_t cp210x_id_table[][2] = {
@@ -287,9 +319,9 @@ const struct usbh_class_driver cp210x_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = cp210x_id_table,
.class_driver = &cp210x_class_driver
};

View File

@@ -10,18 +10,18 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
#define CONFIG_USBHOST_MAX_FTDI_CLASS 4
#define CONFIG_USBHOST_MAX_FTDI_CLASS 1
static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi));
g_ftdi_class[devno].minor = devno;
return &g_ftdi_class[devno];
@@ -32,10 +32,10 @@ static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class)
{
int devno = ftdi_class->minor;
uint8_t devno = ftdi_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(ftdi_class, 0, sizeof(struct usbh_ftdi));
}
@@ -57,7 +57,7 @@ static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_
}
int divisor = FTDI_USB_CLK / baudrate;
int frac_bits = 0;
for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
for (uint8_t i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
if ((divisor & 0xF) == frac[i]) {
frac_bits = i;
break;
@@ -71,7 +71,12 @@ static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_
int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup;
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_RESET_REQUEST;
@@ -84,7 +89,12 @@ int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class)
static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup;
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_SET_MODEM_CTRL_REQUEST;
@@ -97,11 +107,16 @@ static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value)
static int usbh_ftdi_set_baudrate(struct usbh_ftdi *ftdi_class, uint32_t baudrate)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup;
uint32_t itdf_divisor;
uint16_t value;
uint8_t baudrate_high;
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
usbh_ftdi_caculate_baudrate(&itdf_divisor, baudrate);
value = itdf_divisor & 0xFFFF;
baudrate_high = (itdf_divisor >> 16) & 0xff;
@@ -123,10 +138,15 @@ static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t datab
* D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2
* D14 BREAK_OFF=0, BREAK_ON=1
**/
struct usb_setup_packet *setup;
uint16_t value;
uint16_t value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f);
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup = ftdi_class->hport->setup;
value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_SET_DATA_REQUEST;
@@ -139,7 +159,12 @@ static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t datab
static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t value)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup;
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_SET_LATENCY_TIMER_REQUEST;
@@ -152,7 +177,12 @@ static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t va
static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup;
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_SET_FLOW_CTRL_REQUEST;
@@ -165,9 +195,14 @@ static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value)
static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!ftdi_class || !ftdi_class->hport) {
return -USB_ERR_INVAL;
}
setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_POLL_MODEM_STATUS_REQUEST;
setup->wValue = 0x0000;
@@ -335,10 +370,12 @@ int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, u
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
{
(void)ftdi_class;
}
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
{
(void)ftdi_class;
}
static const uint16_t ftdi_id_table[][2] = {
@@ -355,9 +392,9 @@ const struct usbh_class_driver ftdi_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = ftdi_id_table,
.class_driver = &ftdi_class_driver
};

View File

@@ -15,7 +15,7 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_pl2303_buf[64];
#define CONFIG_USBHOST_MAX_PL2303_CLASS 4
#define CONFIG_USBHOST_MAX_PL2303_CLASS 1
#define UT_WRITE_VENDOR_DEVICE (USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
#define UT_READ_VENDOR_DEVICE (USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
@@ -25,11 +25,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_pl2303 *usbh_pl2303_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_PL2303_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_pl2303_class[devno], 0, sizeof(struct usbh_pl2303));
g_pl2303_class[devno].minor = devno;
return &g_pl2303_class[devno];
@@ -40,10 +40,10 @@ static struct usbh_pl2303 *usbh_pl2303_class_alloc(void)
static void usbh_pl2303_class_free(struct usbh_pl2303 *pl2303_class)
{
int devno = pl2303_class->minor;
uint8_t devno = pl2303_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(pl2303_class, 0, sizeof(struct usbh_pl2303));
}
@@ -131,7 +131,12 @@ static int usbh_pl2303_do(struct usbh_pl2303 *pl2303_class,
uint8_t req_type, uint8_t request, uint16_t value, uint16_t index,
uint16_t length)
{
struct usb_setup_packet *setup = pl2303_class->hport->setup;
struct usb_setup_packet *setup;
if (!pl2303_class || !pl2303_class->hport) {
return -USB_ERR_INVAL;
}
setup = pl2303_class->hport->setup;
setup->bmRequestType = req_type;
setup->bRequest = request;
@@ -144,7 +149,12 @@ static int usbh_pl2303_do(struct usbh_pl2303 *pl2303_class,
int usbh_pl2303_set_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup = pl2303_class->hport->setup;
struct usb_setup_packet *setup;
if (!pl2303_class || !pl2303_class->hport) {
return -USB_ERR_INVAL;
}
setup = pl2303_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
@@ -159,9 +169,14 @@ int usbh_pl2303_set_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_lin
int usbh_pl2303_get_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding)
{
struct usb_setup_packet *setup = pl2303_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!pl2303_class || !pl2303_class->hport) {
return -USB_ERR_INVAL;
}
setup = pl2303_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
setup->wValue = 0;
@@ -178,7 +193,12 @@ int usbh_pl2303_get_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_lin
int usbh_pl2303_set_line_state(struct usbh_pl2303 *pl2303_class, bool dtr, bool rts)
{
struct usb_setup_packet *setup = pl2303_class->hport->setup;
struct usb_setup_packet *setup;
if (!pl2303_class || !pl2303_class->hport) {
return -USB_ERR_INVAL;
}
setup = pl2303_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
@@ -393,10 +413,12 @@ int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buf
__WEAK void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class)
{
(void)pl2303_class;
}
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
{
(void)pl2303_class;
}
static const uint16_t pl2303_id_table[][2] = {
@@ -418,9 +440,9 @@ const struct usbh_class_driver pl2303_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info pl2303_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = pl2303_id_table,
.class_driver = &pl2303_class_driver
};

6
class/vendor/wifi/README.md vendored Normal file
View File

@@ -0,0 +1,6 @@
# BL616 USB WIFI
Usbwifi firmware please contact bouffalolab. You can purchase a module in the following ways:
- https://iot.mi.com/moduleBrowser.html
- https://docs.ai-thinker.com/ai_m61

512
class/vendor/wifi/usbh_bl616.c vendored Normal file
View File

@@ -0,0 +1,512 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_bl616.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_bl616"
#include "usb_log.h"
#define DEV_FORMAT "/dev/wifi/bl616"
#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
#define ARR_ELE_6(e) (e)[0], (e)[1], (e)[2], (e)[3], (e)[4], (e)[5]
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bl616_tx_buffer[2048 + 512];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bl616_rx_buffer[2048 + 512];
static struct usbh_bl616 g_bl616_class;
static const char *auth_to_str(uint8_t auth)
{
const char *table[RNM_WIFI_AUTH_MAX] = {
[RNM_WIFI_AUTH_UNKNOWN] = "UNKNOWN",
[RNM_WIFI_AUTH_OPEN] = "OPEN",
[RNM_WIFI_AUTH_WEP] = "WEP",
[RNM_WIFI_AUTH_WPA_PSK] = "WPA-PSK",
[RNM_WIFI_AUTH_WPA2_PSK] = "WPA2-PSK",
[RNM_WIFI_AUTH_WPA_WPA2_PSK] = "WPA2-PSK/WPA-PSK",
[RNM_WIFI_AUTH_WPA_ENTERPRISE] = "WPA-ENT",
[RNM_WIFI_AUTH_WPA3_SAE] = "WPA3-SAE",
[RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE] = "WPA2-PSK/WPA3-SAE",
};
if (auth < RNM_WIFI_AUTH_MAX)
return table[auth];
else
return table[RNM_WIFI_AUTH_UNKNOWN];
}
static const char *cipher_to_str(uint8_t cipher)
{
const char *table[RNM_WIFI_CIPHER_MAX] = {
[RNM_WIFI_CIPHER_UNKNOWN] = "UNKNOWN",
[RNM_WIFI_CIPHER_NONE] = "NONE",
[RNM_WIFI_CIPHER_WEP] = "WEP",
[RNM_WIFI_CIPHER_AES] = "AES",
[RNM_WIFI_CIPHER_TKIP] = "TKIP",
[RNM_WIFI_CIPHER_TKIP_AES] = "TKIP/AES",
};
if (cipher < RNM_WIFI_CIPHER_MAX)
return table[cipher];
else
return table[RNM_WIFI_CIPHER_UNKNOWN];
}
static int parse_get_mac_rsp_msg(struct usbh_bl616 *bl616_class, void *buf, int buf_len)
{
usb_data_t *usb_hdr = buf;
rnm_mac_addr_ind_msg_t *rsp = buf + sizeof(usb_data_t);
if (buf_len != sizeof(usb_data_t) + sizeof(rnm_mac_addr_ind_msg_t)) {
return -1;
}
if (usb_hdr->type != USBWIFI_DATA_TYPE_CMD || usb_hdr->length != sizeof(rnm_mac_addr_ind_msg_t)) {
return -1;
}
if (rsp->hdr.cmd != BFLB_CMD_GET_MAC_ADDR || !(rsp->hdr.flags & RNM_MSG_FLAG_ACK)) {
return -1;
}
memcpy(bl616_class->sta_mac, rsp->sta_mac, 6);
memcpy(bl616_class->ap_mac, rsp->ap_mac, 6);
return 0;
}
static int usbh_bl616_bulk_in_transfer(struct usbh_bl616 *bl616_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &bl616_class->bulkin_urb;
usbh_bulk_urb_fill(urb, bl616_class->hport, bl616_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
static int usbh_bl616_bulk_out_transfer(struct usbh_bl616 *bl616_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &bl616_class->bulkout_urb;
usbh_bulk_urb_fill(urb, bl616_class->hport, bl616_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
static int usbh_bl616_get_wifi_mac(struct usbh_bl616 *bl616_class)
{
int ret;
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_base_msg_t *rnm_msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(rnm_msg, 0, sizeof(rnm_base_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_base_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
rnm_msg->cmd = BFLB_CMD_GET_MAC_ADDR;
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
ret = usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
if (ret < 0) {
return ret;
}
ret = usbh_bl616_bulk_in_transfer(bl616_class, g_bl616_rx_buffer, sizeof(g_bl616_rx_buffer), 500);
if (ret < 0) {
return ret;
}
ret = parse_get_mac_rsp_msg(bl616_class, g_bl616_rx_buffer, ret);
return ret;
}
static int usbh_bl616_wifi_open(struct usbh_bl616 *bl616_class)
{
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(msg, 0, sizeof(rnm_base_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_base_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
msg->cmd = BFLB_CMD_HELLO;
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
return usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
}
static int usbh_bl616_wifi_close(struct usbh_bl616 *bl616_class)
{
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(msg, 0, sizeof(rnm_base_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_base_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
msg->cmd = BFLB_CMD_UNLOAD_DRV;
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
return usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
}
int usbh_bl616_wifi_sta_connect(const char *ssid,
const int ssid_len,
const char *password,
const int pwd_len)
{
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_sta_connect_msg_t *msg = (rnm_sta_connect_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(msg, 0, sizeof(rnm_sta_connect_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_sta_connect_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
msg->hdr.cmd = BFLB_CMD_STA_CONNECT;
msg->hdr.msg_id = 0x0001;
msg->hdr.session_id = 0x0002;
msg->ssid_len = ssid_len;
memcpy(msg->ssid, ssid, ssid_len);
if (password) {
memcpy(msg->password, password, pwd_len);
}
msg_len = sizeof(usb_data_t) + sizeof(rnm_sta_connect_msg_t);
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
}
int usbh_bl616_wifi_sta_disconnect(void)
{
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(msg, 0, sizeof(rnm_base_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_base_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
msg->cmd = BFLB_CMD_STA_DISCONNECT;
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
}
int usbh_bl616_get_wifi_scan_result(void)
{
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(msg, 0, sizeof(rnm_base_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_base_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
msg->cmd = BFLB_CMD_SCAN_RESULTS;
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
}
int usbh_bl616_wifi_scan(void)
{
int ret;
uint32_t msg_len;
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
memset(usb_hdr, 0, sizeof(usb_data_t));
memset(msg, 0, sizeof(rnm_base_msg_t));
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
usb_hdr->length = sizeof(rnm_base_msg_t);
usb_hdr->payload_offset = sizeof(usb_data_t);
msg->cmd = BFLB_CMD_SCAN;
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
ret = usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
if (ret < 0) {
return ret;
}
usb_osal_msleep(500);
return usbh_bl616_get_wifi_scan_result();
}
static int usbh_bl616_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_bl616 *bl616_class = &g_bl616_class;
memset(bl616_class, 0, sizeof(struct usbh_bl616));
bl616_class->hport = hport;
bl616_class->intf = intf;
hport->config.intf[intf].priv = bl616_class;
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(bl616_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(bl616_class->bulkout, ep_desc);
}
}
usbh_bl616_get_wifi_mac(bl616_class);
usbh_bl616_wifi_close(bl616_class);
usbh_bl616_wifi_open(bl616_class);
USB_LOG_INFO("BL616 WIFI STA MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
bl616_class->sta_mac[0],
bl616_class->sta_mac[1],
bl616_class->sta_mac[2],
bl616_class->sta_mac[3],
bl616_class->sta_mac[4],
bl616_class->sta_mac[5]);
USB_LOG_INFO("BL616 WIFI AP MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
bl616_class->ap_mac[0],
bl616_class->ap_mac[1],
bl616_class->ap_mac[2],
bl616_class->ap_mac[3],
bl616_class->ap_mac[4],
bl616_class->ap_mac[5]);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bl616_run(bl616_class);
return ret;
}
static int usbh_bl616_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_bl616 *bl616_class = (struct usbh_bl616 *)hport->config.intf[intf].priv;
if (bl616_class) {
if (bl616_class->bulkin) {
usbh_kill_urb(&bl616_class->bulkin_urb);
}
if (bl616_class->bulkout) {
usbh_kill_urb(&bl616_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bl616_stop(bl616_class);
}
memset(bl616_class, 0, sizeof(struct usbh_bl616));
}
return ret;
}
void usbh_bl616_rx_thread(void *argument)
{
int ret;
usb_data_t *usb_hdr;
rnm_base_msg_t *msg;
rnm_sta_ip_update_ind_msg_t *ipmsg;
rnm_scan_ind_msg_t *scanmsg;
uint8_t *data;
(void)argument;
USB_LOG_INFO("Create bl616 wifi rx thread\r\n");
while (1) {
ret = usbh_bl616_bulk_in_transfer(&g_bl616_class, g_bl616_rx_buffer, sizeof(g_bl616_rx_buffer), USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
break;
}
usb_hdr = (usb_data_t *)g_bl616_rx_buffer;
if (usb_hdr->type == USBWIFI_DATA_TYPE_CMD) {
msg = (rnm_base_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
switch (msg->cmd) {
case BFLB_CMD_STA_CONNECTED_IND:
USB_LOG_INFO("AP connected\n");
g_bl616_class.connect_status = true;
usbh_bl616_sta_connect_callback();
break;
case BFLB_CMD_STA_DISCONNECTED_IND:
if (g_bl616_class.connect_status == true) {
g_bl616_class.connect_status = false;
USB_LOG_INFO("AP disconnected\n");
usbh_bl616_sta_disconnect_callback();
}
break;
case BFLB_CMD_STA_IP_UPDATE_IND:
ipmsg = (rnm_sta_ip_update_ind_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
USB_LOG_INFO("WIFI IP update\r\n");
USB_LOG_INFO("WIFI IPv4 Address : %d:%d:%d:%d\r\n",
ipmsg->ip4_addr[0],
ipmsg->ip4_addr[1],
ipmsg->ip4_addr[2],
ipmsg->ip4_addr[3]);
USB_LOG_INFO("WIFI IPv4 Mask : %d:%d:%d:%d\r\n",
ipmsg->ip4_mask[0],
ipmsg->ip4_mask[1],
ipmsg->ip4_mask[2],
ipmsg->ip4_mask[3]);
USB_LOG_INFO("WIFI IPv4 Gateway : %d:%d:%d:%d\r\n\r\n",
ipmsg->ip4_gw[0],
ipmsg->ip4_gw[1],
ipmsg->ip4_gw[2],
ipmsg->ip4_gw[3]);
g_bl616_class.mode = BL_MODE_STA;
usbh_bl616_sta_update_ip(ipmsg->ip4_addr, ipmsg->ip4_mask, ipmsg->ip4_gw);
break;
case BFLB_CMD_SCAN_RESULTS:
scanmsg = (rnm_scan_ind_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
USB_LOG_INFO("WIFI scan result:\r\n");
for (uint32_t i = 0; i < scanmsg->num; ++i) {
struct bf1b_wifi_scan_record *r = &scanmsg->records[i];
USB_LOG_INFO("BSSID " MAC_FMT ", channel %u, rssi %d, auth %s, cipher %s, SSID %s\r\n",
ARR_ELE_6(r->bssid), r->channel, r->rssi,
auth_to_str(r->auth_mode), cipher_to_str(r->cipher), r->ssid);
}
break;
default:
break;
}
} else if (usb_hdr->type == USBWIFI_DATA_TYPE_PKT) {
data = (uint8_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
usbh_bl616_eth_input(data, usb_hdr->length);
} else {
}
}
USB_LOG_INFO("Delete bl616 wifi rx thread\r\n");
usb_osal_thread_delete(NULL);
}
uint8_t *usbh_bl616_get_eth_txbuf(void)
{
return (g_bl616_tx_buffer + sizeof(usb_data_t));
}
int usbh_bl616_eth_output(uint32_t buflen)
{
usb_data_t *usb_hdr;
uint32_t txlen;
if (g_bl616_class.connect_status == false) {
return -USB_ERR_NOTCONN;
}
usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
memset(usb_hdr, 0, sizeof(usb_data_t));
usb_hdr->type = USBWIFI_DATA_TYPE_PKT;
usb_hdr->length = buflen;
usb_hdr->payload_offset = sizeof(usb_data_t);
txlen = buflen + sizeof(usb_data_t);
if (!(txlen % USB_GET_MAXPACKETSIZE(g_bl616_class.bulkout->wMaxPacketSize))) {
txlen += 1;
}
USB_LOG_DBG("txlen:%d\r\n", txlen);
usbh_bulk_urb_fill(&g_bl616_class.bulkout_urb, g_bl616_class.hport, g_bl616_class.bulkout, g_bl616_tx_buffer, txlen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
return usbh_submit_urb(&g_bl616_class.bulkout_urb);
}
int wifi_sta_connect(int argc, char **argv)
{
if (argc < 3) {
USB_LOG_ERR("Usage: %s <ssid> <password>\r\n", argv[0]);
return -1;
}
usbh_bl616_wifi_sta_connect(argv[1], strlen(argv[1]), argv[2], strlen(argv[2]));
return 0;
}
int wifi_scan(int argc, char **argv)
{
(void)argc;
(void)argv;
usbh_bl616_wifi_scan();
return 0;
}
__WEAK void usbh_bl616_run(struct usbh_bl616 *bl616_class)
{
(void)bl616_class;
}
__WEAK void usbh_bl616_stop(struct usbh_bl616 *bl616_class)
{
(void)bl616_class;
}
static const uint16_t bl616_id_table[][2] = {
{ 0x349b, 0x616f },
{ 0, 0 },
};
static const struct usbh_class_driver bl616_class_driver = {
.driver_name = "bl616_wifi",
.connect = usbh_bl616_connect,
.disconnect = usbh_bl616_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info bl616_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = bl616_id_table,
.class_driver = &bl616_class_driver
};

220
class/vendor/wifi/usbh_bl616.h vendored Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_BL616_H
#define USBH_BL616_H
#define USBWIFI_DATA_TYPE_CMD 0xA55A
#define USBWIFI_DATA_TYPE_PKT 0x6996
#define USB_DATA_FLAG_AP_PKT (1u << 0)
typedef enum {
BFLB_CMD_REBOOT = 0,
BFLB_CMD_RESET,
BFLB_CMD_HELLO,
BFLB_CMD_PING,
BFLB_CMD_GET_MAC_ADDR,
// Scan
BFLB_CMD_SCAN,
BFLB_CMD_SCAN_RESULTS,
// STA
BFLB_CMD_STA_CONNECT,
BFLB_CMD_STA_DISCONNECT,
BFLB_CMD_STA_CONNECTED_IND,
BFLB_CMD_STA_DISCONNECTED_IND,
BFLB_CMD_STA_IP_UPDATE_IND,
BFLB_CMD_STA_SET_AUTO_RECONNECT,
BFLB_CMD_STA_GET_LINK_STATUS,
// AP
BFLB_CMD_AP_START,
BFLB_CMD_AP_STOP,
BFLB_CMD_AP_STARTED_IND,
BFLB_CMD_AP_STOPPED_IND,
BFLB_CMD_AP_GET_STA_LIST,
// Monitor
BFLB_CMD_MONITOR_START,
BFLB_CMD_MONITOR_STOP,
BFLB_CMD_MONITOR_SET_CHANNEL,
BFLB_CMD_MONITOR_GET_CHANNEL,
BFLB_CMD_SET_LPM_MODE,
// OTA
BFLB_CMD_GET_DEV_VERSION,
BFLB_CMD_OTA,
BFLB_CMD_EXT,
BFLB_CMD_USER_EXT,
BFLB_CMD_UNLOAD_DRV,
BFLB_CMD_MAX,
} bflb_cmd_t;
typedef enum {
STATUS_OK,
STATUS_NOMEM = 128,
STATUS_INVALID_INPUT,
STATUS_INVALID_MODE,
STATUS_ERR_UNSPECIFIED,
STATUS_NOT_IMPLEMENTED,
} cmd_status_t;
typedef enum {
RNM_WIFI_AUTH_UNKNOWN = 0,
RNM_WIFI_AUTH_OPEN,
RNM_WIFI_AUTH_WEP,
RNM_WIFI_AUTH_WPA_PSK,
RNM_WIFI_AUTH_WPA2_PSK,
RNM_WIFI_AUTH_WPA_WPA2_PSK,
RNM_WIFI_AUTH_WPA_ENTERPRISE,
RNM_WIFI_AUTH_WPA3_SAE,
RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE,
RNM_WIFI_AUTH_MAX,
} rnm_wifi_auth_mode_t;
typedef enum {
RNM_WIFI_CIPHER_UNKNOWN = 0,
RNM_WIFI_CIPHER_NONE,
RNM_WIFI_CIPHER_WEP,
RNM_WIFI_CIPHER_AES,
RNM_WIFI_CIPHER_TKIP,
RNM_WIFI_CIPHER_TKIP_AES,
RNM_WIFI_CIPHER_MAX,
} rnm_wifi_cipher_t;
/* common header */
typedef struct {
uint16_t cmd;
// flag ACK is used by server to indicate a response to client
#define RNM_MSG_FLAG_ACK (1 << 0)
// flag TRANSPARENT is never transfered to peer but used locally
#define RNM_MSG_FLAG_TRANSPARENT (1 << 1)
// flag ASYNC is used by server to notify client events such as STA_CONNECTED
#define RNM_MSG_FLAG_ASYNC (1 << 2)
uint16_t flags;
uint16_t status;
uint16_t msg_id;
uint16_t session_id;
uint16_t msg_id_replying;
} rnm_base_msg_t;
typedef struct {
rnm_base_msg_t hdr;
} rnm_ack_msg_t;
typedef struct {
rnm_base_msg_t hdr;
uint8_t sta_mac[6];
uint8_t ap_mac[6];
} rnm_mac_addr_ind_msg_t;
typedef struct {
rnm_base_msg_t hdr;
uint16_t ssid_len;
uint8_t ssid[32];
uint8_t password[64];
} rnm_sta_connect_msg_t;
typedef struct {
rnm_base_msg_t hdr;
uint8_t ip4_addr[4];
uint8_t ip4_mask[4];
uint8_t ip4_gw[4];
uint8_t ip4_dns1[4];
uint8_t ip4_dns2[4];
uint8_t gw_mac[6];
} rnm_sta_ip_update_ind_msg_t;
struct bf1b_wifi_scan_record {
uint8_t bssid[6];
// TODO use compressed SSID encoding to save room
uint8_t ssid[32 + 1];
uint16_t channel;
int8_t rssi;
uint8_t auth_mode;
uint8_t cipher;
} __PACKED;
typedef struct {
rnm_base_msg_t hdr;
uint16_t num;
struct bf1b_wifi_scan_record records[];
} rnm_scan_ind_msg_t;
typedef enum {
BL_MODE_NONE,
BL_MODE_STA, // card is STA
BL_MODE_AP, // card is AP
BL_MODE_STA_AP, // card is STA&AP
BL_MODE_SNIFFER, // card is sniffer
BL_MODE_MAX,
} bl_wifi_mode_t;
typedef struct {
uint16_t type;
uint16_t length;
uint16_t flags;
uint16_t payload_offset;
uint32_t rsvd[8];
uint8_t payload[];
} __attribute__((aligned(4))) usb_data_t;
struct usbh_bl616 {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
uint8_t intf;
uint8_t sta_mac[6];
uint8_t ap_mac[6];
uint8_t mode;
bool connect_status;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_bl616_wifi_sta_connect(const char *ssid,
const int ssid_len,
const char *password,
const int pwd_len);
int usbh_bl616_wifi_sta_disconnect(void);
int usbh_bl616_wifi_scan(void);
void usbh_bl616_sta_connect_callback(void);
void usbh_bl616_sta_disconnect_callback(void);
void usbh_bl616_sta_update_ip(uint8_t ip4_addr[4], uint8_t ip4_mask[4], uint8_t ip4_gw[4]);
uint8_t *usbh_bl616_get_eth_txbuf(void);
int usbh_bl616_eth_output(uint32_t buflen);
void usbh_bl616_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_bl616_rx_thread(void *argument);
void usbh_bl616_run(struct usbh_bl616 *bl616_class);
void usbh_bl616_stop(struct usbh_bl616 *bl616_class);
int wifi_sta_connect(int argc, char **argv);
int wifi_scan(int argc, char **argv);
#ifdef __cplusplus
}
#endif
#endif /* USBH_BL616_H */

228
class/vendor/xbox/usbh_xbox.c vendored Normal file
View File

@@ -0,0 +1,228 @@
/*
* Copyright (c) 2024 Till Harbaum
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_xbox.h"
#define DEV_FORMAT "/dev/xbox%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_xbox_buf[128];
static struct usbh_xbox g_xbox_class[CONFIG_USBHOST_MAX_XBOX_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_xbox *usbh_xbox_class_alloc(void)
{
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_XBOX_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_xbox_class[devno], 0, sizeof(struct usbh_xbox));
g_xbox_class[devno].minor = devno;
return &g_xbox_class[devno];
}
}
return NULL;
}
static void usbh_xbox_class_free(struct usbh_xbox *xbox_class)
{
uint8_t devno = xbox_class->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(xbox_class, 0, sizeof(struct usbh_xbox));
}
int usbh_xbox_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
struct usbh_xbox *xbox_class = usbh_xbox_class_alloc();
if (xbox_class == NULL) {
USB_LOG_ERR("Fail to alloc xbox_class\r\n");
return -USB_ERR_NOMEM;
}
xbox_class->hport = hport;
xbox_class->intf = intf;
hport->config.intf[intf].priv = xbox_class;
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(xbox_class->intin, ep_desc);
} else {
USBH_EP_INIT(xbox_class->intout, ep_desc);
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, xbox_class->minor);
USB_LOG_INFO("Register XBOX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xbox_run(xbox_class);
return 0;
}
int usbh_xbox_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_xbox *xbox_class = (struct usbh_xbox *)hport->config.intf[intf].priv;
if (xbox_class) {
if (xbox_class->intin) {
usbh_kill_urb(&xbox_class->intin_urb);
}
if (xbox_class->intout) {
usbh_kill_urb(&xbox_class->intout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister XBOX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xbox_stop(xbox_class);
}
usbh_xbox_class_free(xbox_class);
}
return ret;
}
__WEAK void usbh_xbox_run(struct usbh_xbox *xbox_class)
{
}
__WEAK void usbh_xbox_stop(struct usbh_xbox *xbox_class)
{
}
const struct usbh_class_driver xbox_class_driver = {
.driver_name = "xbox",
.connect = usbh_xbox_connect,
.disconnect = usbh_xbox_disconnect
};
static const uint16_t xbox_id_table[][2] = {
{ 0x0079, 0x18d4 }, // GPD Win 2 X-Box Controller
{ 0x03eb, 0xff01 }, // Wooting One (Legacy)
{ 0x03eb, 0xff02 }, // Wooting Two (Legacy)
{ 0x044f, 0xb326 }, // Thrustmaster Gamepad GP XID
{ 0x045e, 0x028e }, // Microsoft X-Box 360 pad
{ 0x045e, 0x028f }, // Microsoft X-Box 360 pad v2
{ 0x046d, 0xc21d }, // Logitech Gamepad F310
{ 0x046d, 0xc21e }, // Logitech Gamepad F510
{ 0x046d, 0xc21f }, // Logitech Gamepad F710
{ 0x046d, 0xc242 }, // Logitech Chillstream Controller
{ 0x046d, 0xcaa3 }, // Logitech DriveFx Racing Wheel
{ 0x056e, 0x2004 }, // Elecom JC-U3613M
{ 0x06a3, 0xf51a }, // Saitek P3600
{ 0x0738, 0x4716 }, // Mad Catz Wired Xbox 360 Controller
{ 0x0738, 0x4718 }, // Mad Catz Street Fighter IV FightStick SE
{ 0x0738, 0x4726 }, // Mad Catz Xbox 360 Controller
{ 0x0738, 0x4736 }, // Mad Catz MicroCon Gamepad
{ 0x0738, 0x4740 }, // Mad Catz Beat Pad
{ 0x0738, 0x9871 }, // Mad Catz Portable Drum
{ 0x0738, 0xb726 }, // Mad Catz Xbox controller - MW2
{ 0x0738, 0xbeef }, // Mad Catz JOYTECH NEO SE Advanced GamePad
{ 0x0738, 0xcb02 }, // Saitek Cyborg Rumble Pad - PC/Xbox 360
{ 0x0738, 0xcb03 }, // Saitek P3200 Rumble Pad - PC/Xbox 360
{ 0x0738, 0xcb29 }, // Saitek Aviator Stick AV8R02
{ 0x0738, 0xf738 }, // Super SFIV FightStick TE S
{ 0x07ff, 0xffff }, // Mad Catz GamePad
{ 0x0e6f, 0x0113 }, // Afterglow AX.1 Gamepad for Xbox 360
{ 0x0e6f, 0x011f }, // Rock Candy Gamepad Wired Controller
{ 0x0e6f, 0x0131 }, // PDP EA Sports Controller
{ 0x0e6f, 0x0133 }, // Xbox 360 Wired Controller
{ 0x0e6f, 0x0201 }, // Pelican PL-3601 'TSZ' Wired Xbox 360 Controller
{ 0x0e6f, 0x0213 }, // Afterglow Gamepad for Xbox 360
{ 0x0e6f, 0x021f }, // Rock Candy Gamepad for Xbox 360
{ 0x0e6f, 0x0301 }, // Logic3 Controller
{ 0x0e6f, 0x0401 }, // Logic3 Controller
{ 0x0e6f, 0x0413 }, // Afterglow AX.1 Gamepad for Xbox 360
{ 0x0e6f, 0x0501 }, // PDP Xbox 360 Controller
{ 0x0e6f, 0xf900 }, // PDP Afterglow AX.1
{ 0x0f0d, 0x000a }, // Hori Co. DOA4 FightStick
{ 0x0f0d, 0x000c }, // Hori PadEX Turbo
{ 0x1038, 0x1430 }, // SteelSeries Stratus Duo
{ 0x1038, 0x1431 }, // SteelSeries Stratus Duo
{ 0x11c9, 0x55f0 }, // Nacon GC-100XF
{ 0x1209, 0x2882 }, // Ardwiino Controller
{ 0x12ab, 0x0301 }, // PDP AFTERGLOW AX.1
{ 0x1430, 0x4748 }, // RedOctane Guitar Hero X-plorer
{ 0x1430, 0xf801 }, // RedOctane Controller
{ 0x146b, 0x0601 }, // BigBen Interactive XBOX 360 Controller
{ 0x1532, 0x0037 }, // Razer Sabertooth
{ 0x15e4, 0x3f00 }, // Power A Mini Pro Elite
{ 0x15e4, 0x3f0a }, // Xbox Airflo wired controller
{ 0x15e4, 0x3f10 }, // Batarang Xbox 360 controller
{ 0x162e, 0xbeef }, // Joytech Neo-Se Take2
{ 0x1689, 0xfd00 }, // Razer Onza Tournament Edition
{ 0x1689, 0xfd01 }, // Razer Onza Classic Edition
{ 0x1689, 0xfe00 }, // Razer Sabertooth
{ 0x1949, 0x041a }, // Amazon Game Controller
{ 0x1bad, 0x0002 }, // Harmonix Rock Band Guitar
{ 0x1bad, 0xf016 }, // Mad Catz Xbox 360 Controller
{ 0x1bad, 0xf021 }, // Mad Cats Ghost Recon FS GamePad
{ 0x1bad, 0xf023 }, // MLG Pro Circuit Controller (Xbox)
{ 0x1bad, 0xf025 }, // Mad Catz Call Of Duty
{ 0x1bad, 0xf027 }, // Mad Catz FPS Pro
{ 0x1bad, 0xf028 }, // Street Fighter IV FightPad
{ 0x1bad, 0xf030 }, // Mad Catz Xbox 360 MC2 MicroCon Racing Wheel
{ 0x1bad, 0xf036 }, // Mad Catz MicroCon GamePad Pro
{ 0x1bad, 0xf038 }, // Street Fighter IV FightStick TE
{ 0x1bad, 0xf501 }, // HoriPad EX2 Turbo
{ 0x1bad, 0xf506 }, // Hori Real Arcade Pro.EX Premium VLX
{ 0x1bad, 0xf900 }, // Harmonix Xbox 360 Controller
{ 0x1bad, 0xf901 }, // Gamestop Xbox 360 Controller
{ 0x1bad, 0xf903 }, // Tron Xbox 360 controller
{ 0x1bad, 0xf904 }, // PDP Versus Fighting Pad
{ 0x1bad, 0xfa01 }, // MadCatz GamePad
{ 0x1bad, 0xfd00 }, // Razer Onza TE
{ 0x1bad, 0xfd01 }, // Razer Onza
{ 0x20d6, 0x2001 }, // BDA Xbox Series X Wired Controller
{ 0x20d6, 0x281f }, // PowerA Wired Controller For Xbox 360
{ 0x24c6, 0x5300 }, // PowerA MINI PROEX Controller
{ 0x24c6, 0x5303 }, // Xbox Airflo wired controller
{ 0x24c6, 0x530a }, // Xbox 360 Pro EX Controller
{ 0x24c6, 0x531a }, // PowerA Pro Ex
{ 0x24c6, 0x5397 }, // FUS1ON Tournament Controller
{ 0x24c6, 0x5500 }, // Hori XBOX 360 EX 2 with Turbo
{ 0x24c6, 0x5501 }, // Hori Real Arcade Pro VX-SA
{ 0x24c6, 0x5506 }, // Hori SOULCALIBUR V Stick
{ 0x24c6, 0x550d }, // Hori GEM Xbox controller
{ 0x24c6, 0x5b00 }, // ThrustMaster Ferrari 458 Racing Wheel
{ 0x24c6, 0x5b02 }, // Thrustmaster, Inc. GPX Controller
{ 0x24c6, 0x5b03 }, // Thrustmaster Ferrari 458 Racing Wheel
{ 0x24c6, 0x5d04 }, // Razer Sabertooth
{ 0x24c6, 0xfafe }, // Rock Candy Gamepad for Xbox 360
{ 0x2563, 0x058d }, // OneXPlayer Gamepad
{ 0x2dc8, 0x3106 }, // 8BitDo Ultimate Wireless / Pro 2 Wired Controller
{ 0x2dc8, 0x3109 }, // 8BitDo Ultimate Wireless Bluetooth
{ 0x31e3, 0x1100 }, // Wooting One
{ 0x31e3, 0x1200 }, // Wooting Two
{ 0x31e3, 0x1210 }, // Wooting Lekker
{ 0x31e3, 0x1220 }, // Wooting Two HE
{ 0x31e3, 0x1230 }, // Wooting Two HE (ARM)
{ 0x31e3, 0x1300 }, // Wooting 60HE (AVR)
{ 0x31e3, 0x1310 }, // Wooting 60HE (ARM)
{ 0x3285, 0x0607 }, // Nacon GC-100
{ 0x413d, 0x2104 }, // Black Shark Green Ghost Gamepad
{ 0x0000, 0x0000 } // end of list
};
CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = USB_DEVICE_CLASS_VEND_SPECIFIC,
.bInterfaceSubClass = 0x5d,
.bInterfaceProtocol = 0x01,
.id_table = xbox_id_table,
.class_driver = &xbox_class_driver
};

31
class/vendor/xbox/usbh_xbox.h vendored Normal file
View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2024, Till Harbaum
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_XBOX_H
#define USBH_XBOX_H
struct usbh_xbox {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t intf; /* interface number */
uint8_t minor;
};
#ifdef __cplusplus
extern "C" {
#endif
void usbh_xbox_run(struct usbh_xbox *xbox_class);
void usbh_xbox_stop(struct usbh_xbox *xbox_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_XBOX_H */

View File

@@ -806,14 +806,15 @@ struct video_still_probe_and_commit_controls {
struct video_cs_if_vc_header_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdVDC;
uint8_t bDescriptorSubType;
uint16_t bcdUVC;
uint16_t wTotalLength;
uint32_t dwClockFrequency;
uint8_t bInCollection;
uint8_t baInterfaceNr[];
} __PACKED;
#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (11 + n)
#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (12 + n)
struct video_cs_if_vc_input_terminal_descriptor {
uint8_t bLength;
@@ -860,6 +861,22 @@ struct video_cs_if_vc_output_terminal_descriptor {
#define VIDEO_SIZEOF_VC_OUTPUT_TERMINAL_DESC 9
struct video_cs_if_vc_extension_unit_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bUnitID;
uint8_t guidExtensionCode[16];
uint8_t bNumControls;
uint8_t bNrInPins;
// uint8_t baSourceID[];
uint8_t bControlSize;
// uint8_t bmControls[]
uint8_t iExtension;
} __PACKED;
#define VIDEO_SIZEOF_VC_EXTENSION_UNIT_DESC(p, n) (24 + p + n)
struct video_cs_ep_vc_ep_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -922,7 +939,7 @@ struct video_cs_if_vs_frame_uncompressed_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
@@ -931,10 +948,10 @@ struct video_cs_if_vs_frame_uncompressed_descriptor {
uint32_t dwMaxVideoFrameBufferSize;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwFrameInterval;
uint32_t dwFrameInterval[];
} __PACKED;
#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC 30
#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC(n) (26 + 4 * (n))
struct video_cs_if_vs_format_mjpeg_descriptor {
uint8_t bLength;
@@ -956,7 +973,7 @@ struct video_cs_if_vs_frame_mjpeg_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
@@ -965,11 +982,48 @@ struct video_cs_if_vs_frame_mjpeg_descriptor {
uint32_t dwMaxVideoFrameBufferSize;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwFrameInterval1;
uint32_t dwFrameInterval2;
uint32_t dwFrameInterval[];
} __PACKED;
#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + n)
#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + 4 * (n))
/* H264 Payload - 3.1.1. H264 Video Format Descriptor */
struct video_cs_if_vs_format_h26x_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bNumFrameDescriptors;
uint8_t guidFormat[16];
uint8_t bBitsPerPixel;
uint8_t bDefaultFrameIndex;
uint8_t bAspectRatioX;
uint8_t bAspectRatioY;
uint8_t bmInterfaceFlags;
uint8_t bCopyProtect;
uint8_t bVariableSize;
} __PACKED;
#define VIDEO_SIZEOF_VS_FORMAT_H264_DESC 28
/* H264 Payload - 3.1.2. H264 Video Frame Descriptor */
struct video_cs_if_vs_frame_h26x_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
uint32_t dwMinBitRate;
uint32_t dwMaxBitRate;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwBytesPerLine;
uint32_t dwFrameInterval[];
} __PACKED;
#define VIDEO_SIZEOF_VS_FRAME_H264_DESC(n) (26 + 4 * (n))
struct video_cs_if_vs_colorformat_descriptor {
uint8_t bLength;
@@ -1041,74 +1095,145 @@ struct video_autoexposure_mode {
#define VIDEO_GUID_YUY2 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_NV12 0x4E, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_NV21 0x4E, 0x56, 0x32, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_M420 0x4D, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_I420 0x49, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_H264 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_VC_TERMINAL_LEN (13 + 18 + 12 + 9)
/*Length of template descriptor: 81 bytes*/
#define VIDEO_VC_DESCRIPTOR_LEN (8 + 9 + VIDEO_VC_TERMINAL_LEN + 7 + 5)
#define VIDEO_VC_NOEP_DESCRIPTOR_LEN (8 + 9 + VIDEO_VC_TERMINAL_LEN)
// clang-format off
#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bNumEndpoints, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
/* Interface Association Descriptor */ \
0x08, \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
bFirstInterface, \
0x02, \
USB_DEVICE_CLASS_VIDEO, \
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
0x00, \
0x00, \
/* VideoControl Interface Descriptor */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
bNumEndpoints, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ \
/*Class-specific VideoControl Interface Descriptor */ \
0x0d, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
WBVAL(wTotalLength), /* wTotalLength */ \
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
0x01, /* bInCollection : Number of streaming interfaces. */ \
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ \
/* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
0x12, \
0x24, \
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x01, /* bTerminalID */ \
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
0x00, /* bAssocTerminal */ \
0x00, /* iTerminal */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
WBVAL(0x0000), /* wOcularFocalLength */ \
0x03, /* bControlSize */ \
0x00, 0x00, 0x00, /* bmControls */ \
0x0c, \
0x24, \
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
0x02, /* bUnitID */ \
0x01, /* bSourceID */ \
0x00, 0x00, /* wMaxMultiplier */ \
0x02, /* bControlSize */ \
0x00, 0x00, /* bmControls */ \
0x00, /* iProcessing */ \
0x00, /* bmVideoStandards */ \
0x09, \
0x24, \
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x03, /* bTerminalID */ \
WBVAL(VIDEO_TT_STREAMING), \
0x00, /* bAssocTerminal */ \
0x02, /* bSourceID */ \
0x00 /* iTerminal */
#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bEndpointAddress, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
/* Interface Association Descriptor */ \
0x08, \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
bFirstInterface, \
0x02, \
USB_DEVICE_CLASS_VIDEO, \
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
0x00, \
0x00, /* VideoControl Interface Descriptor */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ /*Class-specific VideoControl Interface Descriptor */ \
0x0d, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
WBVAL(wTotalLength), /* wTotalLength */ \
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
0x01, /* bInCollection : Number of streaming interfaces. */ \
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
0x12, \
0x24, \
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x01, /* bTerminalID */ \
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
0x00, /* bAssocTerminal */ \
0x00, /* iTerminal */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
WBVAL(0x0000), /* wOcularFocalLength */ \
0x03, /* bControlSize */ \
0x00, 0x00, 0x00, /* bmControls */ \
0x0c, \
0x24, \
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
0x02, /* bUnitID */ \
0x01, /* bSourceID */ \
0x00, 0x00, /* wMaxMultiplier */ \
0x02, /* bControlSize */ \
0x00, 0x00, /* bmControls */ \
0x00, /* iProcessing */ \
0x00, /* bmVideoStandards */ \
0x09, \
0x24, \
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x03, /* bTerminalID */ \
WBVAL(VIDEO_TT_STREAMING), \
0x00, /* bAssocTerminal */ \
0x02, /* bSourceID */ \
0x00, /* iTerminal */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x08, /* bInterval */ \
/* Class-specific VC Interrupt Endpoint Descriptor */ \
0x05, 0x25, 0x03, 0x10, 0x00
#define VIDEO_VC_NOEP_DESCRIPTOR_INIT(bFirstInterface, bEndpointAddress, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
/* Interface Association Descriptor */ \
0x08, \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
bFirstInterface, \
0x02, \
USB_DEVICE_CLASS_VIDEO, \
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
0x00, \
0x00, /* VideoControl Interface Descriptor */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ /*Class-specific VideoControl Interface Descriptor */ \
0x0d, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
WBVAL(wTotalLength), /* wTotalLength */ \
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
0x01, /* bInCollection : Number of streaming interfaces. */ \
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
0x12, \
0x24, \
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x01, /* bTerminalID */ \
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
0x00, /* bAssocTerminal */ \
0x00, /* iTerminal */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
WBVAL(0x0000), /* wOcularFocalLength */ \
0x03, /* bControlSize */ \
0x00, 0x00, 0x00, /* bmControls */ \
0x0c, \
0x24, \
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
0x02, /* bUnitID */ \
0x01, /* bSourceID */ \
0x00, 0x00, /* wMaxMultiplier */ \
0x02, /* bControlSize */ \
0x00, 0x00, /* bmControls */ \
0x00, /* iProcessing */ \
0x00, /* bmVideoStandards */ \
0x09, \
0x24, \
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x03, /* bTerminalID */ \
WBVAL(VIDEO_TT_STREAMING), \
0x00, /* bAssocTerminal */ \
0x02, /* bSourceID */ \
0x00 /* iTerminal */ \
#define VIDEO_VS_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints) \
/* Video Streaming (VS) Interface Descriptor */ \
0x09, /* bLength */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType : INTERFACE */ \
bInterfaceNumber, /* bInterfaceNumber: Index of this interface */ \
bAlternateSetting, /* bAlternateSetting: Index of this alternate setting */ \
@@ -1118,21 +1243,37 @@ struct video_autoexposure_mode {
0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
0x00 /* iInterface : unused */
#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
/*Class-specific VideoStream Header Descriptor (Input) */ \
0x0d + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
WBVAL(wTotalLength), \
bEndpointAddress, \
0x00, /* bmInfo : No dynamic format change supported. */ \
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
#define VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
/*Class-specific VideoStream Header Descriptor (Input) */ \
0x0d + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
WBVAL(wTotalLength), \
bEndpointAddress, \
0x00, /* bmInfo : No dynamic format change supported. */ \
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
0x01, /* bControlSize : Size of the bmaControls field */ \
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
#define VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
/*Class-specific VideoStream Header Descriptor (Input) */ \
0x0d + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_SUBTYPE, \
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
WBVAL(wTotalLength), \
bEndpointAddress, \
0x00, /* bmInfo : No dynamic format change supported. */ \
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat) \
/*Payload Format(UNCOMPRESSED) Descriptor */ \
@@ -1142,7 +1283,7 @@ struct video_autoexposure_mode {
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
GUIDFormat, /* GUID Format YUY2 {32595559-0000-0010-8000-00AA00389B71} */ \
0x0c, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
0x10, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
@@ -1150,8 +1291,8 @@ struct video_autoexposure_mode {
0x00 /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */
#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwFrameInterval) \
0x1e, \
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
0x1a + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, \
bFrameIndex, \
@@ -1161,13 +1302,13 @@ struct video_autoexposure_mode {
DBVAL(dwMinBitRate), \
DBVAL(dwMaxBitRate), \
DBVAL(dwMaxVideoFrameBufferSize), \
DBVAL(dwDefaultFrameInterval), \
0x01, \
DBVAL(dwFrameInterval)
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
__VA_ARGS__
#define VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
/*Payload Format(MJPEG) Descriptor */ \
0x0b, /* bLength */ \
0x0b, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
0x06, /* bDescriptorSubType : VS_FORMAT_MJPEG subtype */ \
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
@@ -1181,7 +1322,7 @@ struct video_autoexposure_mode {
#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_MJPEG */ \
bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
@@ -1194,5 +1335,46 @@ struct video_autoexposure_mode {
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
__VA_ARGS__
#define VIDEO_VS_FORMAT_H264_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
/*Payload Format(H.264) Descriptor */ \
0x1c, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_FORMAT_FRAME_BASED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FORMAT_FRAME_BASED subtype */\
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
VIDEO_GUID_H264, \
0x00, /* bmFlags : Uses fixed size samples.. */ \
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
0x00, /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */ \
0x00 /* Variable size: False */
#define VIDEO_VS_FRAME_H264_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
dwDefaultFrameInterval, bFrameIntervalType, ...) \
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_FRAME_FRAME_BASED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_BASED */ \
bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
0x00, /* bmCapabilities : Still images using capture method 0 are supported at this frame setting.D1: Fixed frame-rate. */ \
WBVAL(wWidth), /* wWidth (2bytes): Width of frame is 128 pixels. */ \
WBVAL(wHeight), /* wHeight (2bytes): Height of frame is 64 pixels. */ \
DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \
DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
DBVAL(0x00), /* dwBytesPerLine (4bytes) */ \
__VA_ARGS__
#define VIDEO_VS_COLOR_MATCHING_DESCRIPTOR_INIT() \
0x06, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_COLORFORMAT_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_COLORFORMAT */ \
0x01, /* bColorPrimaries */ \
0x01, /* bTransferCharacteristics */ \
0x04 /* bMatrixCoefficients */
// clang-format on
#endif /*USB_VIDEO_H */

View File

@@ -18,12 +18,28 @@ struct usbd_video_priv {
uint8_t power_mode;
uint8_t error_code;
struct video_entity_info info[3];
uint8_t *ep_buf0;
uint8_t *ep_buf1;
bool ep_buf0_ready;
bool ep_buf1_ready;
uint32_t ep_buf0_len;
uint32_t ep_buf1_len;
uint8_t ep_buf_idx;
bool stream_finish;
uint32_t max_packets;
uint8_t *stream_buf;
uint32_t stream_len;
uint32_t stream_offset;
uint8_t stream_frameid;
uint32_t stream_headerlen;
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
(void)busid;
switch (control_selector) {
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
switch (setup->bRequest) {
@@ -295,8 +311,7 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
case VIDEO_PU_BRIGHTNESS_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR: {
uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
USB_LOG_INFO("Video set brightness:%d\r\n", wBrightness);
//uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
} break;
case VIDEO_REQUEST_GET_CUR: {
uint16_t wBrightness = 0x0080;
@@ -670,7 +685,7 @@ static int video_class_interface_request_handler(uint8_t busid, struct usb_setup
} else {
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
}
} else if (intf_num == 1) { /* Video Stream Inteface */
} else if (intf_num == 1) { /* Video Stream Inteface */
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
}
return -1;
@@ -699,7 +714,7 @@ static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
}
}
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
{
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
@@ -736,9 +751,47 @@ void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameIn
g_usbd_video[busid].commit.bPreferedVersion = 0;
g_usbd_video[busid].commit.bMinVersion = 0;
g_usbd_video[busid].commit.bMaxVersion = 0;
g_usbd_video[busid].stream_frameid = 0;
g_usbd_video[busid].stream_headerlen = 2;
}
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
{
struct video_payload_header *header;
uint32_t len;
uint32_t offset;
len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
offset = 0;
while (len > 0) {
header = (struct video_payload_header *)&ep_buf[offset];
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
header->headerInfoUnion.bmheaderInfo = 0;
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
&g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
len2);
g_usbd_video[busid].stream_offset += len2;
len -= len2;
offset += (len2 + g_usbd_video[busid].stream_headerlen);
if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
}
}
return offset;
}
struct usbd_interface *usbd_video_init_intf(uint8_t busid,
struct usbd_interface *intf,
uint32_t dwFrameInterval,
uint32_t dwMaxVideoFrameSize,
uint32_t dwMaxPayloadTransferSize)
@@ -762,28 +815,70 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
return intf;
}
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
{
uint32_t packets;
uint32_t last_packet_size;
uint32_t picture_pos = 0;
static uint8_t uvc_header[2] = { 0x02, 0x80 };
uint32_t remain;
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
for (size_t i = 0; i < packets; i++) {
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
if (i == (packets - 1)) {
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
} else {
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */
g_usbd_video[busid].ep_buf0_ready = false;
g_usbd_video[busid].ep_buf_idx = 1;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
} else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */
g_usbd_video[busid].ep_buf1_ready = false;
g_usbd_video[busid].ep_buf_idx = 0;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
} else {
if (g_usbd_video[busid].stream_finish) {
return true;
}
}
uvc_header[1] ^= 1;
*out_len = (input_len + 2 * packets);
return packets;
}
if (!g_usbd_video[busid].ep_buf0_ready) {
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
if (remain == 0) {
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
} else {
g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
g_usbd_video[busid].ep_buf0_ready = true;
if (!g_usbd_video[busid].ep_buf1_ready) {
g_usbd_video[busid].ep_buf_idx = 0;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
}
}
}
if (!g_usbd_video[busid].ep_buf1_ready) {
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
if (remain == 0) {
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
} else {
g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
g_usbd_video[busid].ep_buf1_ready = true;
}
}
return false;
}
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
{
if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
return -1;
}
g_usbd_video[busid].ep_buf0 = ep_buf0;
g_usbd_video[busid].ep_buf1 = ep_buf1;
g_usbd_video[busid].ep_buf0_ready = false;
g_usbd_video[busid].ep_buf1_ready = false;
g_usbd_video[busid].ep_buf_idx = 0;
g_usbd_video[busid].stream_finish = false;
g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
g_usbd_video[busid].stream_buf = stream_buf;
g_usbd_video[busid].stream_len = stream_len;
g_usbd_video[busid].stream_offset = 0;
usbd_video_stream_split_transfer(busid, ep);
return 0;
}

View File

@@ -20,7 +20,9 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
void usbd_video_open(uint8_t busid, uint8_t intf);
void usbd_video_close(uint8_t busid, uint8_t intf);
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep);
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len);
#ifdef __cplusplus
}

View File

@@ -34,11 +34,11 @@ static uint32_t g_devinuse = 0;
static struct usbh_video *usbh_video_class_alloc(void)
{
int devno;
uint8_t devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
g_video_class[devno].minor = devno;
return &g_video_class[devno];
@@ -49,20 +49,25 @@ static struct usbh_video *usbh_video_class_alloc(void)
static void usbh_video_class_free(struct usbh_video *video_class)
{
int devno = video_class->minor;
uint8_t devno = video_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(video_class, 0, sizeof(struct usbh_video));
}
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
{
struct usb_setup_packet *setup = video_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
uint8_t retry;
if (!video_class || !video_class->hport) {
return -USB_ERR_INVAL;
}
setup = video_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = request;
setup->wValue = cs << 8;
@@ -91,9 +96,14 @@ int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
{
struct usb_setup_packet *setup = video_class->hport->setup;
struct usb_setup_packet *setup;
int ret;
if (!video_class || !video_class->hport) {
return -USB_ERR_INVAL;
}
setup = video_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = request;
setup->wValue = cs << 8;
@@ -136,7 +146,7 @@ int usbh_video_open(struct usbh_video *video_class,
uint16_t wHeight,
uint8_t altsetting)
{
struct usb_setup_packet *setup = video_class->hport->setup;
struct usb_setup_packet *setup;
struct usb_endpoint_descriptor *ep_desc;
uint8_t mult;
uint16_t mps;
@@ -146,6 +156,11 @@ int usbh_video_open(struct usbh_video *video_class,
uint8_t frameidx = 0;
uint8_t step;
if (!video_class || !video_class->hport) {
return -USB_ERR_INVAL;
}
setup = video_class->hport->setup;
if (video_class->is_opened) {
return 0;
}
@@ -265,9 +280,14 @@ errout:
int usbh_video_close(struct usbh_video *video_class)
{
struct usb_setup_packet *setup = video_class->hport->setup;
struct usb_setup_packet *setup;
int ret = 0;
if (!video_class || !video_class->hport) {
return -USB_ERR_INVAL;
}
setup = video_class->hport->setup;
USB_LOG_INFO("Close video device\r\n");
video_class->is_opened = false;
@@ -475,20 +495,26 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
(void)hport;
(void)intf;
return 0;
}
__WEAK void usbh_video_run(struct usbh_video *video_class)
{
(void)video_class;
}
__WEAK void usbh_video_stop(struct usbh_video *video_class)
{
(void)video_class;
}
const struct usbh_class_driver video_ctrl_class_driver = {
@@ -505,18 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_VIDEO,
.subclass = VIDEO_SC_VIDEOCONTROL,
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
.bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL,
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.id_table = NULL,
.class_driver = &video_ctrl_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_VIDEO,
.subclass = VIDEO_SC_VIDEOSTREAMING,
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
.bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING,
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.id_table = NULL,
.class_driver = &video_streaming_class_driver
};

View File

@@ -102,6 +102,8 @@ static void rndis_notify_rsp(void)
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
(void)busid;
switch (setup->bRequest) {
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
rndis_encapsulated_cmd_handler(*data, setup->wLength);
@@ -152,6 +154,8 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
rndis_initialize_cmplt_t *resp;
(void)len;
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->RequestId = cmd->RequestId;
resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
@@ -177,6 +181,9 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
{
rndis_halt_msg_t *resp;
(void)data;
(void)len;
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
resp->MessageLength = 0;
@@ -192,6 +199,8 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
uint8_t *infomation_buffer;
uint32_t infomation_len = 0;
(void)len;
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
resp->RequestId = cmd->RequestId;
@@ -217,7 +226,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
case OID_GEN_MAXIMUM_FRAME_SIZE:
case OID_GEN_TRANSMIT_BLOCK_SIZE:
case OID_GEN_RECEIVE_BLOCK_SIZE:
RNDIS_INQUIRY_PUT_LE32(0x05DC);
RNDIS_INQUIRY_PUT_LE32(0x05DC); /* mtu 1500 */
infomation_len = 4;
break;
case OID_GEN_VENDOR_ID:
@@ -255,7 +264,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE);
RNDIS_INQUIRY_PUT_LE32(0x0616); /* 1514 + 44 */
infomation_len = 4;
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
@@ -338,6 +347,8 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
rndis_set_cmplt_t *resp;
rndis_config_parameter_t *param;
(void)len;
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->RequestId = cmd->RequestId;
resp->MessageType = REMOTE_NDIS_SET_CMPLT;
@@ -394,6 +405,9 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
rndis_reset_cmplt_t *resp;
(void)data;
(void)len;
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
resp->MessageLength = sizeof(rndis_reset_cmplt_t);
@@ -412,6 +426,8 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
rndis_keepalive_cmplt_t *resp;
(void)len;
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
resp->RequestId = cmd->RequestId;
resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
@@ -425,6 +441,9 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
(void)busid;
(void)arg;
switch (event) {
case USBD_EVENT_RESET:
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
@@ -445,6 +464,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
rndis_data_packet_t *hdr;
(void)busid;
(void)ep;
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
@@ -456,21 +478,28 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
g_rndis_rx_data_length = hdr->DataLength;
usbd_rndis_data_recv_done();
usbd_rndis_data_recv_done(g_rndis_rx_data_length);
}
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
(void)busid;
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(0, ep, NULL, 0);
} else {
usbd_rndis_data_send_done(g_rndis_tx_data_length);
g_rndis_tx_data_length = 0;
}
}
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
(void)ep;
(void)nbytes;
//USB_LOG_DBG("len:%d\r\n", nbytes);
}
@@ -488,7 +517,7 @@ struct pbuf *usbd_rndis_eth_rx(void)
if (p == NULL) {
return NULL;
}
memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
p->len = g_rndis_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
@@ -518,7 +547,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
usb_memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
@@ -564,3 +593,13 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
return intf;
}
__WEAK void usbd_rndis_data_recv_done(uint32_t len)
{
(void)len;
}
__WEAK void usbd_rndis_data_send_done(uint32_t len)
{
(void)len;
}

View File

@@ -18,7 +18,8 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
const uint8_t in_ep,
const uint8_t int_ep, uint8_t mac[6]);
void usbd_rndis_data_recv_done(void);
void usbd_rndis_data_recv_done(uint32_t len);
void usbd_rndis_data_send_done(uint32_t len);
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
struct pbuf *usbd_rndis_eth_rx(void);

View File

@@ -96,7 +96,7 @@ static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
}
USB_LOG_INFO("Bluetooth select altsetting 0\r\n");
#endif
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bluetooth_run(bluetooth_class);
return ret;
@@ -234,7 +234,12 @@ delete :
static int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen)
{
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
struct usb_setup_packet *setup = bluetooth_class->hport->setup;
struct usb_setup_packet *setup;
if (!bluetooth_class || !bluetooth_class->hport) {
return -USB_ERR_INVAL;
}
setup = bluetooth_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = 0x00;
@@ -360,14 +365,18 @@ delete :
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
{
(void)data;
(void)len;
}
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
{
(void)bluetooth_class;
}
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
{
(void)bluetooth_class;
}
static const struct usbh_class_driver bluetooth_class_driver = {
@@ -384,18 +393,18 @@ static const uint16_t bluetooth_id_table[][2] = {
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.id_table = bluetooth_id_table,
.class_driver = &bluetooth_class_driver
};
#else
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x01,
.bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01,
.id_table = NULL,
.class_driver = &bluetooth_class_driver
};

View File

@@ -13,7 +13,7 @@
#define DEV_FORMAT "/dev/rndis"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[512];
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
@@ -26,6 +26,7 @@ static struct usbh_rndis g_rndis_class;
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
{
(void)rndis_class;
// int ret;
// struct usbh_urb *urb = &rndis_class->intin_urb;
@@ -40,11 +41,16 @@ static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
{
struct usb_setup_packet *setup = rndis_class->hport->setup;
struct usb_setup_packet *setup;
int ret = 0;
rndis_initialize_msg_t *cmd;
rndis_initialize_cmplt_t *resp;
if (!rndis_class || !rndis_class->hport) {
return -USB_ERR_INVAL;
}
setup = rndis_class->hport->setup;
cmd = (rndis_initialize_msg_t *)g_rndis_buf;
cmd->MessageType = REMOTE_NDIS_INITIALIZE_MSG;
@@ -74,7 +80,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 4096;
setup->wLength = sizeof(g_rndis_buf);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -82,16 +88,26 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
return ret;
}
rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer;
rndis_class->max_transfer_size = resp->MaxTransferSize;
USB_LOG_INFO("MaxPacketsPerTransfer:%d\r\n", resp->MaxPacketsPerTransfer);
USB_LOG_INFO("MaxTransferSize:%d\r\n", resp->MaxTransferSize);
return ret;
}
int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len)
{
struct usb_setup_packet *setup = rndis_class->hport->setup;
struct usb_setup_packet *setup;
int ret = 0;
rndis_query_msg_t *cmd;
rndis_query_cmplt_t *resp;
if (!rndis_class || !rndis_class->hport) {
return -USB_ERR_INVAL;
}
setup = rndis_class->hport->setup;
cmd = (rndis_query_msg_t *)g_rndis_buf;
cmd->MessageType = REMOTE_NDIS_QUERY_MSG;
@@ -122,7 +138,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 4096;
setup->wLength = sizeof(g_rndis_buf);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -138,11 +154,16 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len)
{
struct usb_setup_packet *setup = rndis_class->hport->setup;
struct usb_setup_packet *setup;
int ret = 0;
rndis_set_msg_t *cmd;
rndis_set_cmplt_t *resp;
if (!rndis_class || !rndis_class->hport) {
return -USB_ERR_INVAL;
}
setup = rndis_class->hport->setup;
cmd = (rndis_set_msg_t *)g_rndis_buf;
cmd->MessageType = REMOTE_NDIS_SET_MSG;
@@ -174,7 +195,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 4096;
setup->wLength = sizeof(g_rndis_buf);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -205,11 +226,16 @@ int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
{
struct usb_setup_packet *setup = rndis_class->hport->setup;
struct usb_setup_packet *setup;
int ret = 0;
rndis_keepalive_msg_t *cmd;
rndis_keepalive_cmplt_t *resp;
if (!rndis_class || !rndis_class->hport) {
return -USB_ERR_INVAL;
}
setup = rndis_class->hport->setup;
cmd = (rndis_keepalive_msg_t *)g_rndis_buf;
cmd->MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
@@ -236,7 +262,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 4096;
setup->wLength = sizeof(g_rndis_buf);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
@@ -361,14 +387,14 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
}
uint32_t packet_filter = 0x0f;
usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
ret = usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("rndis set OID_GEN_CURRENT_PACKET_FILTER success\r\n");
uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
ret = usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
if (ret < 0) {
return ret;
}
@@ -382,7 +408,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
rndis_class->mac[4],
rndis_class->mac[5]);
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
usbh_rndis_run(rndis_class);
@@ -425,18 +451,17 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
void usbh_rndis_rx_thread(void *argument)
{
uint32_t g_rndis_rx_length;
uint32_t pmg_offset;
int ret;
err_t err;
struct pbuf *p;
uint32_t pmg_offset;
rndis_data_packet_t *pmsg;
rndis_data_packet_t temp;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE;
#else
pbuf_type type = PBUF_POOL;
uint32_t transfer_size = (16 * 1024);
#endif
struct netif *netif = (struct netif *)argument;
(void)argument;
USB_LOG_INFO("Create rndis rx thread\r\n");
// clang-format off
@@ -453,17 +478,23 @@ find_class:
usb_osal_msleep(100);
goto find_class;
}
usb_osal_msleep(128);
}
g_rndis_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, (CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE > (16 * 1024)) ? (16 * 1024) : CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, &g_rndis_rx_buffer[g_rndis_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_rndis_rx_length += g_rndis_class.bulkin_urb.actual_length;
/* A transfer is complete because last packet is a short packet.
* Short packet is not zero, match g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize).
* Short packet cannot be zero.
*/
if (g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize)) {
pmg_offset = 0;
@@ -476,33 +507,20 @@ find_class:
/* Not word-aligned case */
if (pmg_offset & 0x3) {
memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
usb_memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
pmsg = &temp;
}
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, type);
if (p != NULL) {
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = src;
#else
memcpy(p->payload, src, pmsg->DataLength);
#endif
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
pmg_offset += pmsg->MessageLength;
g_rndis_rx_length -= pmsg->MessageLength;
uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
/* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
if (g_rndis_rx_length < 4) {
g_rndis_rx_length = 0;
}
} else {
usbh_rndis_eth_input(buf, pmsg->DataLength);
pmg_offset += pmsg->MessageLength;
g_rndis_rx_length -= pmsg->MessageLength;
/* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
if (g_rndis_rx_length < 4) {
g_rndis_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
}
} else {
USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
@@ -511,9 +529,14 @@ find_class:
}
}
} else {
if (g_rndis_rx_length > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_rndis_rx_length = 0;
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
if (g_rndis_rx_length == CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
#else
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
#endif
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
while (1) {
}
}
}
}
@@ -525,55 +548,48 @@ delete:
// clang-format on
}
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
uint8_t *usbh_rndis_get_eth_txbuf(void)
{
return (g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
}
int usbh_rndis_eth_output(uint32_t buflen)
{
int ret;
struct pbuf *q;
uint8_t *buffer;
rndis_data_packet_t *hdr;
uint32_t len;
if (g_rndis_class.connect_status == false) {
return ERR_BUF;
return -USB_ERR_NOTCONN;
}
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
memset(hdr, 0, sizeof(rndis_data_packet_t));
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
hdr->MessageLength = sizeof(rndis_data_packet_t) + buflen;
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
hdr->DataLength = p->tot_len;
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
hdr->DataLength = buflen;
len = hdr->MessageLength;
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
if (!(hdr->MessageLength % g_rndis_class.bulkout->wMaxPacketSize)) {
if (!(len % g_rndis_class.bulkout->wMaxPacketSize)) {
len += 1;
}
USB_LOG_DBG("txlen:%d\r\n", len);
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
return usbh_submit_urb(&g_rndis_class.bulkout_urb);
}
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
{
(void)rndis_class;
}
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
{
(void)rndis_class;
}
static const struct usbh_class_driver rndis_class_driver = {
@@ -584,9 +600,9 @@ static const struct usbh_class_driver rndis_class_driver = {
CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x03,
.bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x03,
.id_table = NULL,
.class_driver = &rndis_class_driver
};

View File

@@ -8,9 +8,6 @@
#include "usb_cdc.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_rndis {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
@@ -25,15 +22,14 @@ struct usbh_rndis {
uint8_t minor;
uint32_t request_id;
uint32_t tx_offset;
uint32_t max_transfer_pkts; /* max packets in one transfer */
uint32_t max_transfer_size; /* max size in one transfer */
uint32_t link_speed;
bool connect_status;
uint8_t mac[6];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
@@ -47,7 +43,9 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
void usbh_rndis_run(struct usbh_rndis *rndis_class);
void usbh_rndis_stop(struct usbh_rndis *rndis_class);
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p);
uint8_t *usbh_rndis_get_eth_txbuf(void);
int usbh_rndis_eth_output(uint32_t buflen);
void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen);
void usbh_rndis_rx_thread(void *argument);
#ifdef __cplusplus

View File

@@ -33,6 +33,13 @@ int usb_dc_deinit(uint8_t busid);
*/
int usbd_set_address(uint8_t busid, const uint8_t addr);
/**
* @brief Set remote wakeup feature
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_set_remote_wakeup(uint8_t busid);
/**
* @brief Get USB device speed
*

View File

@@ -614,7 +614,7 @@ struct usb_webusb_url_descriptor {
char URL[];
} __PACKED;
struct usb_webusb_url_ex_descriptor {
struct usb_webusb_descriptor {
uint8_t vendor_code;
const uint8_t *string;
uint32_t string_len;

View File

@@ -34,6 +34,7 @@ struct usbh_iso_frame_packet {
* Structure containing the USB Urb configuration.
*/
struct usbh_urb {
usb_slist_t list;
void *hcpriv;
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *ep;

View File

@@ -82,4 +82,33 @@ void usb_assert(const char *filename, int linenum);
usb_assert(__FILE__, __LINE__); \
} while (0)
#define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
static inline void usb_hexdump(const void *ptr, uint32_t buflen)
{
unsigned char *buf = (unsigned char *)ptr;
uint32_t i, j;
(void)buf;
for (i = 0; i < buflen; i += 16) {
CONFIG_USB_PRINTF("%08X:", i);
for (j = 0; j < 16; j++)
if (i + j < buflen) {
if ((j % 8) == 0) {
CONFIG_USB_PRINTF(" ");
}
CONFIG_USB_PRINTF("%02X ", buf[i + j]);
} else
CONFIG_USB_PRINTF(" ");
CONFIG_USB_PRINTF(" ");
for (j = 0; j < 16; j++)
if (i + j < buflen)
CONFIG_USB_PRINTF("%c", ___is_print(buf[i + j]) ? buf[i + j] : '.');
CONFIG_USB_PRINTF("\n");
}
}
#endif /* USB_LOG_H */

91
common/usb_memcpy.h Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_MEMCPY_H
#define USB_MEMCPY_H
#include <stdint.h>
#include <stddef.h>
#define ALIGN_UP_DWORD(x) ((uint32_t)(uintptr_t)(x) & (sizeof(uint32_t) - 1))
static inline void dword2array(char *addr, uint32_t w)
{
addr[0] = w;
addr[1] = w >> 8;
addr[2] = w >> 16;
addr[3] = w >> 24;
}
static inline void *usb_memcpy(void *s1, const void *s2, size_t n)
{
char *b1 = (char *)s1;
const char *b2 = (const char *)s2;
uint32_t *w1;
const uint32_t *w2;
if (ALIGN_UP_DWORD(b1) == ALIGN_UP_DWORD(b2)) {
while (ALIGN_UP_DWORD(b1) != 0 && n > 0) {
*b1++ = *b2++;
--n;
}
w1 = (uint32_t *)b1;
w2 = (const uint32_t *)b2;
while (n >= 4 * sizeof(uint32_t)) {
*w1++ = *w2++;
*w1++ = *w2++;
*w1++ = *w2++;
*w1++ = *w2++;
n -= 4 * sizeof(uint32_t);
}
while (n >= sizeof(uint32_t)) {
*w1++ = *w2++;
n -= sizeof(uint32_t);
}
b1 = (char *)w1;
b2 = (const char *)w2;
while (n--) {
*b1++ = *b2++;
}
} else {
while (n > 0 && ALIGN_UP_DWORD(b2) != 0) {
*b1++ = *b2++;
--n;
}
w2 = (const uint32_t *)b2;
while (n >= 4 * sizeof(uint32_t)) {
dword2array(b1, *w2++);
b1 += sizeof(uint32_t);
dword2array(b1, *w2++);
b1 += sizeof(uint32_t);
dword2array(b1, *w2++);
b1 += sizeof(uint32_t);
dword2array(b1, *w2++);
b1 += sizeof(uint32_t);
n -= 4 * sizeof(uint32_t);
}
while (n >= sizeof(uint32_t)) {
dword2array(b1, *w2++);
b1 += sizeof(uint32_t);
n -= sizeof(uint32_t);
}
b2 = (const char *)w2;
while (n--) {
*b1++ = *b2++;
}
}
return s1;
}
#endif

View File

@@ -58,4 +58,7 @@ void usb_osal_leave_critical_section(size_t flag);
void usb_osal_msleep(uint32_t delay);
void *usb_osal_malloc(size_t size);
void usb_osal_free(void *ptr);
#endif /* USB_OSAL_H */

21
common/usb_version.h Normal file
View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_VERSION_H
#define USB_VERSION_H
#ifdef CHERRYUSB_VERSION
#warning "Please do not define CHERRYUSB_VERSION in usb_config.h"
#undef CHERRYUSB_VERSION
#endif
#ifdef CHERRYUSB_VERSION_STR
#warning "Please do not define CHERRYUSB_VERSION_STR in usb_config.h"
#undef CHERRYUSB_VERSION_STR
#endif
#define CHERRYUSB_VERSION 0x010402
#define CHERRYUSB_VERSION_STR "v1.4.2"
#endif

View File

@@ -45,19 +45,26 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
struct usb_msosv1_descriptor *msosv1_desc;
struct usb_msosv2_descriptor *msosv2_desc;
struct usb_bos_descriptor *bos_desc;
struct usb_webusb_descriptor *webusb_url_desc;
#endif
/* Buffer used for storing standard, class and vendor request data */
USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
/** Currently selected configuration */
uint8_t configuration;
uint8_t device_address;
bool self_powered;
bool remote_wakeup_support;
bool remote_wakeup_enabled;
bool is_suspend;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
uint8_t speed;
#endif
#ifdef CONFIG_USBDEV_TEST_MODE
bool test_req;
#endif
struct usbd_interface *intf[8];
struct usbd_interface *intf[16];
uint8_t intf_altsetting[16];
uint8_t intf_offset;
struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_EP_NUM];
@@ -92,16 +99,17 @@ static bool is_device_configured(uint8_t busid)
* This function sets endpoint configuration according to one specified in USB
* endpoint descriptor and then enables it for data transfers.
*
* @param [in] busid busid
* @param [in] ep Endpoint descriptor byte array
*
* @return true if successfully configured and enabled
*/
static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
USB_LOG_INFO("Open ep:0x%02x type:%u mps:%u\r\n",
ep->bEndpointAddress,
USB_GET_ENDPOINT_TYPE(ep->bmAttributes),
USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
USB_LOG_DBG("Open ep:0x%02x type:%u mps:%u\r\n",
ep->bEndpointAddress,
USB_GET_ENDPOINT_TYPE(ep->bmAttributes),
USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
if (ep->bEndpointAddress & 0x80) {
g_usbd_core[busid].tx_msg[ep->bEndpointAddress & 0x7f].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
@@ -119,15 +127,16 @@ static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descripto
* This function cancels transfers that are associated with endpoint and
* disabled endpoint itself.
*
* @param [in] busid busid
* @param [in] ep Endpoint descriptor byte array
*
* @return true if successfully deconfigured and disabled
*/
static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
USB_LOG_INFO("Close ep:0x%02x type:%u\r\n",
ep->bEndpointAddress,
USB_GET_ENDPOINT_TYPE(ep->bmAttributes));
USB_LOG_DBG("Close ep:0x%02x type:%u\r\n",
ep->bEndpointAddress,
USB_GET_ENDPOINT_TYPE(ep->bmAttributes));
return usbd_ep_close(busid, ep->bEndpointAddress) == 0 ? true : false;
}
@@ -138,6 +147,7 @@ static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descrip
* This function parses the list of installed USB descriptors and attempts
* to find the specified USB descriptor.
*
* @param [in] busid busid
* @param [in] type_index Type and index of the descriptor
* @param [out] data Descriptor data
* @param [out] len Descriptor length
@@ -174,11 +184,12 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
break;
}
desc_len = ((desc[CONF_DESC_wTotalLength]) | (desc[CONF_DESC_wTotalLength + 1] << 8));
g_usbd_core[busid].self_powered = (desc[7] & USB_CONFIG_POWERED_MASK) ? true : false;
g_usbd_core[busid].remote_wakeup_support = (desc[7] & USB_CONFIG_REMOTE_WAKEUP) ? true : false;
break;
case USB_DESCRIPTOR_TYPE_STRING:
if (index == USB_OSDESC_STRING_DESC_INDEX) {
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
if (!g_usbd_core[busid].descriptors->msosv1_descriptor) {
found = false;
break;
@@ -244,8 +255,6 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
break;
case USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE:
USB_LOG_INFO("read BOS descriptor string\r\n");
if (!g_usbd_core[busid].descriptors->bos_descriptor) {
found = false;
break;
@@ -283,8 +292,6 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
index = LO_BYTE(type_index);
if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
if (!g_usbd_core[busid].msosv1_desc) {
return false;
}
@@ -295,8 +302,6 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
return true;
} else if (type == USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE) {
USB_LOG_INFO("read BOS descriptor string\r\n");
if (!g_usbd_core[busid].bos_desc) {
return false;
}
@@ -344,6 +349,9 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
*/
*len = (p[CONF_DESC_wTotalLength]) |
(p[CONF_DESC_wTotalLength + 1] << 8);
g_usbd_core[busid].self_powered = (p[7] & USB_CONFIG_POWERED_MASK) ? true : false;
g_usbd_core[busid].remote_wakeup_support = (p[7] & USB_CONFIG_REMOTE_WAKEUP) ? true : false;
} else {
/* normally length is at offset 0 */
*len = p[DESC_bLength];
@@ -366,6 +374,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
* index and alternate setting by parsing the installed USB descriptor list.
* A configuration index of 0 unconfigures the device.
*
* @param [in] busid busid
* @param [in] config_index Configuration index
* @param [in] alt_setting Alternate setting number
*
@@ -435,6 +444,7 @@ static bool usbd_set_configuration(uint8_t busid, uint8_t config_index, uint8_t
/**
* @brief set USB interface
*
* @param [in] busid busid
* @param [in] iface Interface index
* @param [in] alt_setting Alternate setting number
*
@@ -485,10 +495,12 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
if (cur_iface == iface) {
ep_desc = (struct usb_endpoint_descriptor *)p;
if (cur_alt_setting != alt_setting) {
if (alt_setting == 0) {
ret = usbd_reset_endpoint(busid, ep_desc);
} else {
goto find_end;
} else if (cur_alt_setting == alt_setting) {
ret = usbd_set_endpoint(busid, ep_desc);
} else {
}
}
@@ -506,6 +518,7 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
}
}
find_end:
usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
return ret;
@@ -514,6 +527,7 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
/**
* @brief handle a standard device request
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -530,6 +544,12 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
/* bit 0: self-powered */
/* bit 1: remote wakeup */
(*data)[0] = 0x00;
if (g_usbd_core[busid].self_powered) {
(*data)[0] |= USB_GETSTATUS_SELF_POWERED;
}
if (g_usbd_core[busid].remote_wakeup_enabled) {
(*data)[0] |= USB_GETSTATUS_REMOTE_WAKEUP;
}
(*data)[1] = 0x00;
*len = 2;
break;
@@ -538,8 +558,10 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
case USB_REQUEST_SET_FEATURE:
if (value == USB_FEATURE_REMOTE_WAKEUP) {
if (setup->bRequest == USB_REQUEST_SET_FEATURE) {
g_usbd_core[busid].remote_wakeup_enabled = true;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SET_REMOTE_WAKEUP);
} else {
g_usbd_core[busid].remote_wakeup_enabled = false;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CLR_REMOTE_WAKEUP);
}
} else if (value == USB_FEATURE_TEST_MODE) {
@@ -551,6 +573,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
break;
case USB_REQUEST_SET_ADDRESS:
g_usbd_core[busid].device_address = value;
usbd_set_address(busid, value);
*len = 0;
break;
@@ -564,17 +587,20 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
break;
case USB_REQUEST_GET_CONFIGURATION:
*data = (uint8_t *)&g_usbd_core[busid].configuration;
(*data)[0] = g_usbd_core[busid].configuration;
*len = 1;
break;
case USB_REQUEST_SET_CONFIGURATION:
value &= 0xFF;
if (!usbd_set_configuration(busid, value, 0)) {
if (value == 0) {
g_usbd_core[busid].configuration = 0;
} else if (!usbd_set_configuration(busid, value, 0)) {
ret = false;
} else {
g_usbd_core[busid].configuration = value;
g_usbd_core[busid].is_suspend = false;
usbd_class_event_notify_handler(busid, USBD_EVENT_CONFIGURED, NULL);
g_usbd_core[busid].event_handler(busid, USBD_EVENT_CONFIGURED);
}
@@ -597,6 +623,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
/**
* @brief handle a standard interface request
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -608,6 +635,16 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
uint8_t type = HI_BYTE(setup->wValue);
uint8_t intf_num = LO_BYTE(setup->wIndex);
bool ret = true;
const uint8_t *p;
uint32_t desc_len = 0;
uint32_t current_desc_len = 0;
uint8_t cur_iface = 0xFF;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
p = g_usbd_core[busid].descriptors->config_descriptor_callback(g_usbd_core[busid].speed);
#else
p = (uint8_t *)g_usbd_core[busid].descriptors;
#endif
/* Only when device is configured, then interface requests can be valid. */
if (!is_device_configured(busid)) {
@@ -622,9 +659,39 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
break;
case USB_REQUEST_GET_DESCRIPTOR:
if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
USB_LOG_INFO("read hid report descriptor\r\n");
if (type == 0x21) { /* HID_DESCRIPTOR_TYPE_HID */
while (p[DESC_bLength] != 0U) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
current_desc_len = 0;
desc_len = (p[CONF_DESC_wTotalLength]) |
(p[CONF_DESC_wTotalLength + 1] << 8);
break;
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
break;
case 0x21:
if (cur_iface == intf_num) {
*data = (uint8_t *)p;
//memcpy(*data, p, p[DESC_bLength]);
*len = p[DESC_bLength];
return true;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
current_desc_len += p[DESC_bLength];
if (current_desc_len >= desc_len && desc_len) {
break;
}
}
} else if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core[busid].intf[i];
@@ -643,11 +710,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
ret = false;
break;
case USB_REQUEST_GET_INTERFACE:
(*data)[0] = 0;
(*data)[0] = g_usbd_core[busid].intf_altsetting[intf_num];
*len = 1;
break;
case USB_REQUEST_SET_INTERFACE:
g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue);
usbd_set_interface(busid, setup->wIndex, setup->wValue);
*len = 0;
break;
@@ -663,6 +731,7 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
/**
* @brief handle a standard endpoint request
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -673,6 +742,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
{
uint8_t ep = (uint8_t)setup->wIndex;
bool ret = true;
uint8_t stalled;
/* Only when device is configured, then endpoint requests can be valid. */
if (!is_device_configured(busid)) {
@@ -681,7 +751,12 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
switch (setup->bRequest) {
case USB_REQUEST_GET_STATUS:
(*data)[0] = 0x00;
usbd_ep_is_stalled(busid, ep, &stalled);
if (stalled) {
(*data)[0] = 0x01;
} else {
(*data)[0] = 0x00;
}
(*data)[1] = 0x00;
*len = 2;
break;
@@ -721,6 +796,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
/**
* @brief handle standard requests (list in chapter 9)
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -764,8 +840,7 @@ static int usbd_standard_request_handler(uint8_t busid, struct usb_setup_packet
/**
* @brief handler for class requests
*
* If a custom request handler was installed, this handler is called first.
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -797,8 +872,7 @@ static int usbd_class_request_handler(uint8_t busid, struct usb_setup_packet *se
/**
* @brief handler for vendor requests
*
* If a custom request handler was installed, this handler is called first.
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -813,7 +887,6 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
if (setup->bRequest == g_usbd_core[busid].descriptors->msosv1_descriptor->vendor_code) {
switch (setup->wIndex) {
case 0x04:
USB_LOG_INFO("get Compat ID\r\n");
desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[0] +
(g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[1] << 8) +
(g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[2] << 16) +
@@ -824,7 +897,6 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
*len = desclen;
return 0;
case 0x05:
USB_LOG_INFO("get Compat id properties\r\n");
desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][0] +
(g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][1] << 8) +
(g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][2] << 16) +
@@ -843,8 +915,6 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
if (setup->bRequest == g_usbd_core[busid].descriptors->msosv2_descriptor->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
desclen = g_usbd_core[busid].descriptors->msosv2_descriptor->compat_id_len;
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv2_descriptor->compat_id;
//memcpy(*data, g_usbd_core[busid].descriptors->msosv2_descriptor->compat_id, desclen);
@@ -855,12 +925,12 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
return -1;
}
}
} else if (g_usbd_core[busid].descriptors->webusb_url_descriptor) {
}
if (g_usbd_core[busid].descriptors->webusb_url_descriptor) {
if (setup->bRequest == g_usbd_core[busid].descriptors->webusb_url_descriptor->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
USB_LOG_INFO("GET Webusb url Descriptor\r\n");
case WEBUSB_REQUEST_GET_URL:
desclen = g_usbd_core[busid].descriptors->webusb_url_descriptor->string_len;
*data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string;
//memcpy(*data, g_usbd_core[busid].descriptors->webusb_url_descriptor->string, desclen);
@@ -877,7 +947,6 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
if (setup->bRequest == g_usbd_core[busid].msosv1_desc->vendor_code) {
switch (setup->wIndex) {
case 0x04:
USB_LOG_INFO("get Compat ID\r\n");
*data = (uint8_t *)g_usbd_core[busid].msosv1_desc->compat_id;
desclen = g_usbd_core[busid].msosv1_desc->compat_id[0] +
(g_usbd_core[busid].msosv1_desc->compat_id[1] << 8) +
@@ -887,7 +956,6 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
*len = desclen;
return 0;
case 0x05:
USB_LOG_INFO("get Compat id properties\r\n");
*data = (uint8_t *)g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue];
desclen = g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue][0] +
(g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue][1] << 8) +
@@ -905,7 +973,6 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
if (setup->bRequest == g_usbd_core[busid].msosv2_desc->vendor_code) {
switch (setup->wIndex) {
case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
*data = (uint8_t *)g_usbd_core[busid].msosv2_desc->compat_id;
//memcpy(*data, g_usbd_core[busid].msosv2_desc->compat_id, g_usbd_core[busid].msosv2_desc->compat_id_len);
*len = g_usbd_core[busid].msosv2_desc->compat_id_len;
@@ -916,6 +983,22 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
}
}
}
if (g_usbd_core[busid].webusb_url_desc) {
if (setup->bRequest == g_usbd_core[busid].webusb_url_desc->vendor_code) {
switch (setup->wIndex) {
case WEBUSB_REQUEST_GET_URL:
desclen = g_usbd_core[busid].webusb_url_desc->string_len;
*data = (uint8_t *)g_usbd_core[busid].webusb_url_desc->string;
//memcpy(*data, g_usbd_core[busid].webusb_url_desc->string, desclen);
*len = desclen;
return 0;
default:
USB_LOG_ERR("unknown vendor code\r\n");
return -1;
}
}
}
#endif
for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) {
struct usbd_interface *intf = g_usbd_core[busid].intf[i];
@@ -931,6 +1014,7 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
/**
* @brief handle setup request( standard/class/vendor/other)
*
* @param [in] busid busid
* @param [in] setup The setup packet
* @param [in,out] data Data buffer
* @param [in,out] len Pointer to data length
@@ -1004,17 +1088,22 @@ void usbd_event_disconnect_handler(uint8_t busid)
void usbd_event_resume_handler(uint8_t busid)
{
g_usbd_core[busid].is_suspend = false;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESUME);
}
void usbd_event_suspend_handler(uint8_t busid)
{
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
if (g_usbd_core[busid].device_address > 0) {
g_usbd_core[busid].is_suspend = true;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
}
}
void usbd_event_reset_handler(uint8_t busid)
{
usbd_set_address(busid, 0);
g_usbd_core[busid].device_address = 0;
g_usbd_core[busid].configuration = 0;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
@@ -1087,7 +1176,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
#ifdef CONFIG_USBDEV_EP0_INDATA_NO_COPY
g_usbd_core[busid].ep0_data_buf = buf;
#else
memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue);
usb_memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue);
#endif
} else {
/* use memcpy(*data, xxx, len); has copied into ep0 buffer, we do nothing */
@@ -1110,6 +1199,8 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
(void)ep;
g_usbd_core[busid].ep0_data_buf += nbytes;
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
@@ -1149,6 +1240,8 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
(void)ep;
if (nbytes > 0) {
g_usbd_core[busid].ep0_data_buf += nbytes;
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
@@ -1232,6 +1325,11 @@ void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc)
{
g_usbd_core[busid].bos_desc = desc;
}
void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc)
{
g_usbd_core[busid].webusb_url_desc = desc;
}
#endif
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf)
@@ -1275,7 +1373,30 @@ bool usb_device_is_configured(uint8_t busid)
return g_usbd_core[busid].configuration;
}
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
bool usb_device_is_suspend(uint8_t busid)
{
return g_usbd_core[busid].is_suspend;
}
int usbd_send_remote_wakeup(uint8_t busid)
{
if (g_usbd_core[busid].remote_wakeup_support && g_usbd_core[busid].remote_wakeup_enabled && g_usbd_core[busid].is_suspend) {
return usbd_set_remote_wakeup(busid);
} else {
if (!g_usbd_core[busid].remote_wakeup_support) {
USB_LOG_ERR("device does not support remote wakeup\r\n");
}
if (!g_usbd_core[busid].remote_wakeup_enabled) {
USB_LOG_ERR("device remote wakeup is not enabled\r\n");
}
if (!g_usbd_core[busid].is_suspend) {
USB_LOG_ERR("device is not in suspend state\r\n");
}
return -1;
}
}
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
{
int ret;
struct usbd_bus *bus;
@@ -1298,9 +1419,15 @@ int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint
int usbd_deinitialize(uint8_t busid)
{
g_usbd_core[busid].intf_offset = 0;
usb_dc_deinit(busid);
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
if (busid >= CONFIG_USBDEV_MAX_BUS) {
USB_LOG_ERR("bus overflow\r\n");
while (1) {
}
}
g_usbd_core[busid].event_handler(busid, USBD_EVENT_DEINIT);
usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL);
usb_dc_deinit(busid);
g_usbd_core[busid].intf_offset = 0;
return 0;
}

View File

@@ -22,6 +22,8 @@ extern "C" {
#include "usb_list.h"
#include "usb_log.h"
#include "usb_dc.h"
#include "usb_memcpy.h"
#include "usb_version.h"
enum usbd_event_type {
/* USB DCD IRQ */
@@ -70,13 +72,13 @@ struct usb_descriptor {
const char *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
const struct usb_msosv1_descriptor *msosv1_descriptor;
const struct usb_msosv2_descriptor *msosv2_descriptor;
const struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
const struct usb_webusb_descriptor *webusb_url_descriptor;
const struct usb_bos_descriptor *bos_descriptor;
};
struct usbd_bus {
uint8_t busid;
uint32_t reg_base;
uintptr_t reg_base;
};
extern struct usbd_bus g_usbdev_bus[];
@@ -92,6 +94,7 @@ void usbd_desc_register(uint8_t busid, const uint8_t *desc);
void usbd_msosv1_desc_register(uint8_t busid, struct usb_msosv1_descriptor *desc);
void usbd_msosv2_desc_register(uint8_t busid, struct usb_msosv2_descriptor *desc);
void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc);
void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc);
#endif
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
@@ -100,8 +103,10 @@ void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
uint16_t usbd_get_ep_mps(uint8_t busid, uint8_t ep);
uint8_t usbd_get_ep_mult(uint8_t busid, uint8_t ep);
bool usb_device_is_configured(uint8_t busid);
bool usb_device_is_suspend(uint8_t busid);
int usbd_send_remote_wakeup(uint8_t busid);
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
int usbd_deinitialize(uint8_t busid);
#ifdef __cplusplus

View File

@@ -81,13 +81,9 @@ static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
static int usbh_free_devaddr(struct usbh_hubport *hport)
{
#ifndef CONFIG_USBHOST_XHCI
if (hport->dev_addr > 0) {
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
}
#endif
hport->dev_addr = 0;
return 0;
}
@@ -97,19 +93,22 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
struct usbh_class_info *index = NULL;
for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) {
if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) {
if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->bInterfaceClass == class)) {
continue;
}
if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) {
if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->bInterfaceSubClass == subclass)) {
continue;
}
if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == protocol)) {
if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->bInterfaceProtocol == protocol)) {
continue;
}
if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) {
/* scan id table */
uint32_t i;
for (i = 0; index->id_table[i][0] && index->id_table[i][0] != vid && index->id_table[i][1] != pid; i++) {
for (i = 0; index->id_table[i][0]; i++) {
if (index->id_table[i][0] == vid && index->id_table[i][1] == pid) {
break;
}
}
/* do not match, continue next */
if (!index->id_table[i][0]) {
@@ -398,23 +397,12 @@ int usbh_enumerate(struct usbh_hubport *hport)
/* Reconfigure EP0 with the correct maximum packet size */
ep->wMaxPacketSize = ep_mps;
#ifdef CONFIG_USBHOST_XHCI
extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe);
/* Assign a function address to the device connected to this port */
dev_addr = usbh_get_xhci_devaddr(hport->ep0);
if (dev_addr < 0) {
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
goto errout;
}
#else
/* Assign a function address to the device connected to this port */
dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
if (dev_addr < 0) {
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
goto errout;
}
#endif
/* Set the USB device address */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
@@ -501,7 +489,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
goto errout;
}
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
hport->raw_config_desc = usb_malloc(wTotalLength);
hport->raw_config_desc = usb_osal_malloc(wTotalLength + 1);
if (hport->raw_config_desc == NULL) {
ret = -USB_ERR_NOMEM;
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
@@ -510,6 +498,8 @@ int usbh_enumerate(struct usbh_hubport *hport)
config_value = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bConfigurationValue;
memcpy(hport->raw_config_desc, ep0_request_buffer[hport->bus->busid], wTotalLength);
hport->raw_config_desc[wTotalLength] = '\0';
#ifdef CONFIG_USBHOST_GET_STRING_DESC
uint8_t string_buffer[128];
@@ -564,7 +554,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wLength = 16;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0 && (ret != -EPERM)) {
if (ret < 0 && (ret != -USB_ERR_STALL)) {
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
goto errout;
}
@@ -591,7 +581,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
errout:
if (hport->raw_config_desc) {
usb_free(hport->raw_config_desc);
usb_osal_free(hport->raw_config_desc);
hport->raw_config_desc = NULL;
}
return ret;
@@ -615,10 +605,8 @@ void usbh_hubport_release(struct usbh_hubport *hport)
}
}
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_base)
{
struct usbh_hub *hub;
memset(bus, 0, sizeof(struct usbh_bus));
bus->busid = busid;
bus->hcd.hcd_id = busid;
@@ -627,24 +615,10 @@ static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base
/* devaddr 1 is for roothub */
bus->devgen.next = 2;
usb_slist_init(&bus->hub_list);
hub = &bus->hcd.roothub;
hub->connected = true;
hub->index = 1;
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
usb_slist_init(&bus->hub_list);
usb_slist_add_tail(&bus->hub_list, &hub->list);
usb_slist_add_tail(&g_bus_head, &bus->list);
}
int usbh_initialize(uint8_t busid, uint32_t reg_base)
int usbh_initialize(uint8_t busid, uintptr_t reg_base)
{
struct usbh_bus *bus;
@@ -680,11 +654,16 @@ int usbh_deinitialize(uint8_t busid)
{
struct usbh_bus *bus;
if (busid >= CONFIG_USBHOST_MAX_BUS) {
USB_LOG_ERR("bus overflow\r\n");
while (1) {
}
}
bus = &g_usbhost_bus[busid];
usbh_hub_deinitialize(bus);
usb_slist_init(&bus->hub_list);
usb_slist_remove(&g_bus_head, &bus->list);
return 0;
@@ -757,24 +736,29 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett
return usbh_control_transfer(hport, setup, NULL);
}
void *usbh_find_class_instance(const char *devname)
static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devname)
{
struct usbh_hubport *hport;
usb_slist_t *hub_list;
usb_slist_t *bus_list;
struct usbh_hub *hub_next;
void *priv;
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
return hport->config.intf[itf].priv;
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
return hport->config.intf[itf].priv;
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
priv = usbh_list_all_interface_name(hub_next, devname);
if (priv) {
return priv;
}
}
}
}
}
@@ -783,11 +767,151 @@ void *usbh_find_class_instance(const char *devname)
return NULL;
}
static void usbh_list_all_interface_driver(struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
for (uint8_t j = 0; j < hub->index; j++) {
USB_LOG_RAW("\t");
}
USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s, %s\r\n",
hport->port,
hport->dev_addr,
itf,
hport->config.intf[itf].class_driver->driver_name,
speed_table[hport->speed]);
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
usbh_list_all_interface_driver(hub_next);
}
}
}
}
}
}
}
static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
bus->busid,
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
usbh_list_all_interface_desc(bus, hub_next);
}
}
}
}
}
}
}
static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t hub_index, uint8_t hub_port)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
if (hub->index == hub_index) {
hport = &hub->child[hub_port - 1];
return hport;
} else {
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
hport = usbh_list_all_hubport(hub_next, hub_index, hub_port);
if (hport) {
return hport;
}
}
}
}
}
}
}
}
return NULL;
}
void *usbh_find_class_instance(const char *devname)
{
usb_slist_t *bus_list;
struct usbh_hub *hub;
struct usbh_bus *bus;
void *priv;
size_t flags;
flags = usb_osal_enter_critical_section();
usb_slist_for_each(bus_list, &g_bus_head)
{
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
priv = usbh_list_all_interface_name(hub, devname);
if (priv) {
usb_osal_leave_critical_section(flags);
return priv;
}
}
usb_osal_leave_critical_section(flags);
return NULL;
}
struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port)
{
struct usbh_hub *hub;
struct usbh_bus *bus;
struct usbh_hubport *hport;
size_t flags;
flags = usb_osal_enter_critical_section();
bus = &g_usbhost_bus[busid];
hub = &bus->hcd.roothub;
hport = usbh_list_all_hubport(hub, hub_index, hub_port);
usb_osal_leave_critical_section(flags);
return hport;
}
int lsusb(int argc, char **argv)
{
usb_slist_t *hub_list;
usb_slist_t *bus_list;
struct usbh_hubport *hport;
struct usbh_hub *hub;
struct usbh_bus *bus;
size_t flags;
if (argc < 2) {
USB_LOG_RAW("Usage: lsusb [options]...\r\n");
@@ -810,69 +934,36 @@ int lsusb(int argc, char **argv)
return 0;
}
flags = usb_osal_enter_critical_section();
if (strcmp(argv[1], "-V") == 0) {
USB_LOG_RAW("CherryUSB Version %s\r\n", CHERRYUSB_VERSION_STR);
}
if (strcmp(argv[1], "-t") == 0) {
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
if (hub->is_roothub) {
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
bus->busid,
hub->index,
hub->hub_desc.bNbrPorts);
} else {
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, mounted on Hub %02u:Port %u\r\n",
bus->busid,
hub->index,
hub->hub_desc.bNbrPorts,
hub->parent->parent->index,
hub->parent->port);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->driver_name) {
USB_LOG_RAW("\t|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
i,
hport->config.intf[i].class_driver->driver_name);
}
}
}
}
}
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
bus->busid,
hub->index,
hub->nports);
usbh_list_all_interface_driver(hub);
}
}
if (strcmp(argv[1], "-v") == 0) {
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("Bus %u, Hub %02u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
bus->busid,
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
}
}
}
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
usbh_list_all_interface_desc(bus, hub);
}
}
usb_osal_leave_critical_section(flags);
return 0;
}

View File

@@ -20,6 +20,8 @@
#include "usb_hc.h"
#include "usb_osal.h"
#include "usbh_hub.h"
#include "usb_memcpy.h"
#include "usb_version.h"
#ifdef __cplusplus
extern "C" {
@@ -51,17 +53,17 @@ extern "C" {
ep = ep_desc; \
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \
ep_desc->bEndpointAddress, \
USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes), \
ep_desc->bmAttributes, \
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \
ep_desc->bInterval, \
USB_GET_MULT(ep_desc->bmAttributes)); \
USB_GET_MULT(ep_desc->wMaxPacketSize)); \
} while (0)
struct usbh_class_info {
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
uint8_t class; /* Base device class code */
uint8_t subclass; /* Sub-class, depends on base class. Eg. */
uint8_t protocol; /* Protocol, depends on base class. Eg. */
uint8_t bInterfaceClass; /* Base device class code */
uint8_t bInterfaceSubClass; /* Sub-class, depends on base class. Eg. */
uint8_t bInterfaceProtocol; /* Protocol, depends on base class. Eg. */
const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
const struct usbh_class_driver *class_driver;
};
@@ -100,6 +102,9 @@ struct usbh_hubport {
uint8_t port; /* Hub port index */
uint8_t dev_addr; /* device address */
uint8_t speed; /* device speed */
uint8_t depth; /* distance from root hub */
uint8_t route; /* route string */
uint8_t slot_id; /* slot id */
struct usb_device_descriptor device_desc;
struct usbh_configuration config;
const char *iManufacturer;
@@ -108,22 +113,25 @@ struct usbh_hubport {
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
struct usbh_hub *self; /* if this hubport is a hub */
struct usbh_bus *bus;
#ifdef CONFIG_USBHOST_XHCI
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
#endif
struct usb_endpoint_descriptor ep0;
struct usbh_urb ep0_urb;
usb_osal_mutex_t mutex;
};
struct usbh_hub {
usb_slist_t list;
bool connected;
bool is_roothub;
uint8_t index;
uint8_t hub_addr;
struct usb_hub_descriptor hub_desc;
uint8_t speed;
uint8_t nports;
uint8_t powerdelay;
uint8_t tt_think;
bool ismtt;
struct usb_hub_descriptor hub_desc; /* USB 2.0 only */
struct usb_hub_ss_descriptor hub_ss_desc; /* USB 3.0 only */
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_hubport *parent;
struct usbh_bus *bus;
@@ -146,9 +154,9 @@ struct usbh_devaddr_map {
};
struct usbh_hcd {
uint32_t reg_base;
uintptr_t reg_base;
uint8_t hcd_id;
uint8_t roothub_intbuf[1];
uint8_t roothub_intbuf[2]; /* at most 15 roothub ports */
struct usbh_hub roothub;
};
@@ -159,7 +167,6 @@ struct usbh_bus {
struct usbh_devaddr_map devgen;
usb_osal_thread_t hub_thread;
usb_osal_mq_t hub_mq;
usb_slist_t hub_list;
};
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
@@ -265,9 +272,10 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
*/
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
int usbh_initialize(uint8_t busid, uint32_t reg_base);
int usbh_initialize(uint8_t busid, uintptr_t reg_base);
int usbh_deinitialize(uint8_t busid);
void *usbh_find_class_instance(const char *devname);
struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port);
int lsusb(int argc, char **argv);

BIN
demo/CherryUSB.h264 Normal file

Binary file not shown.

BIN
demo/CherryUSB.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

BIN
demo/adb/cherryadb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

330
demo/adb/cherrysh_port.c Normal file
View File

@@ -0,0 +1,330 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
#include "csh.h"
#include "usbd_core.h"
#include "usbd_adb.h"
#include "chry_ringbuffer.h"
static chry_ringbuffer_t shell_rb;
static uint8_t mempool[1024];
#ifndef task_repl_PRIORITY
#define task_repl_PRIORITY (configMAX_PRIORITIES - 4U)
#endif
#ifndef task_exec_PRIORITY
#define task_exec_PRIORITY (configMAX_PRIORITIES - 5U)
#endif
static chry_shell_t csh;
static volatile bool login = false;
static StaticTask_t task_buffer_repl;
static StaticTask_t task_buffer_exec;
static StackType_t task_stack_repl[1024];
static StackType_t task_stack_exec[1024];
static TaskHandle_t task_hdl_repl = NULL;
static TaskHandle_t task_hdl_exec = NULL;
static EventGroupHandle_t event_hdl;
static StaticEventGroup_t event_grp;
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
{
chry_ringbuffer_write(&shell_rb, data, len);
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xEventGroupSetBitsFromISR(event_hdl, 0x10, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void usbd_adb_notify_write_done(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xEventGroupSetBitsFromISR(event_hdl, 0x20, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
static uint16_t csh_sput_cb(chry_readline_t *rl, const void *data, uint16_t size)
{
(void)rl;
if (!usb_device_is_configured(0)) {
return size;
}
if (usbd_adb_can_write() && size) {
usbd_abd_write(ADB_SHELL_LOALID, data, size);
xEventGroupWaitBits(event_hdl, 0x20, pdTRUE, pdFALSE, portMAX_DELAY);
}
return size;
}
static uint16_t csh_sget_cb(chry_readline_t *rl, void *data, uint16_t size)
{
(void)rl;
return chry_ringbuffer_read(&shell_rb, data, size);
}
static void wait_char(void)
{
EventBits_t event;
wait:
/* In order to lock the log from being disrupted , wait for REPL task execution to complete */
event = xEventGroupWaitBits(event_hdl, (0x10 | 0x01 | 0x04), pdTRUE, pdFALSE, portMAX_DELAY);
if ((event & 0x10) == 0) {
if (event & 0x01) {
chry_readline_erase_line(&csh.rl);
xEventGroupSetBits(event_hdl, 0x02);
}
if (event & 0x04) {
chry_readline_edit_refresh(&csh.rl);
xEventGroupSetBits(event_hdl, 0x08);
}
goto wait;
}
}
static void task_repl(void *param)
{
(void)param;
int ret;
volatile uint8_t *pexec = (void *)&csh.exec;
for (;;) {
restart:
if (login) {
goto repl;
} else {
}
ret = csh_login(&csh);
if (ret == 0) {
login = true;
} else if (ret == 1) {
/*!< no enough char */
wait_char();
continue;
} else {
continue;
}
repl:
ret = chry_shell_task_repl(&csh);
if (ret == -1) {
/*!< error */
goto restart;
} else if (ret == 1) {
/*!< no enough char */
wait_char();
} else {
/*!< restart */
}
/*!< check flag */
if (*pexec == CSH_STATUS_EXEC_DONE) {
*pexec = CSH_STATUS_EXEC_IDLE;
chry_readline_auto_refresh(&csh.rl, true);
chry_readline_ignore(&csh.rl, false);
chry_readline_edit_refresh(&csh.rl);
}
if (login == false) {
chry_readline_erase_line(&csh.rl);
csh.rl.noblock = false;
}
}
}
static void task_exec(void *param)
{
(void)param;
/*!< execute shell command */
chry_shell_task_exec(&csh);
/*!< notify REPL task execute done */
xEventGroupSetBits(event_hdl, 0x10);
/*!< wait for REPL task delete */
vTaskSuspend(NULL);
}
int chry_shell_port_create_context(chry_shell_t *csh, int argc, const char **argv)
{
volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
(void)csh;
(void)argc;
(void)argv;
if (*p_task_hdl_exec != NULL) {
vTaskDelete(*p_task_hdl_exec);
}
*p_task_hdl_exec = xTaskCreateStatic(task_exec, "task_exec", 1024U, NULL, task_exec_PRIORITY, task_stack_exec, &task_buffer_exec);
return 0;
}
void chry_shell_port_default_handler(chry_shell_t *csh, int sig)
{
volatile uint8_t *pexec = (void *)&csh->exec;
volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
switch (sig) {
case CSH_SIGINT:
case CSH_SIGQUIT:
case CSH_SIGKILL:
case CSH_SIGTERM:
break;
default:
return;
}
/*!< force delete task */
if (*p_task_hdl_exec != NULL) {
vTaskDelete(task_hdl_exec);
*p_task_hdl_exec = NULL;
}
switch (sig) {
case CSH_SIGINT:
csh->rl.sput(&csh->rl, "^SIGINT" CONFIG_CSH_NEWLINE, sizeof("^SIGINT" CONFIG_CSH_NEWLINE) - 1);
break;
case CSH_SIGQUIT:
csh->rl.sput(&csh->rl, "^SIGQUIT" CONFIG_CSH_NEWLINE, sizeof("^SIGQUIT" CONFIG_CSH_NEWLINE) - 1);
break;
case CSH_SIGKILL:
csh->rl.sput(&csh->rl, "^SIGKILL" CONFIG_CSH_NEWLINE, sizeof("^SIGKILL" CONFIG_CSH_NEWLINE) - 1);
break;
case CSH_SIGTERM:
csh->rl.sput(&csh->rl, "^SIGTERM" CONFIG_CSH_NEWLINE, sizeof("^SIGTERM" CONFIG_CSH_NEWLINE) - 1);
break;
default:
return;
}
*pexec = CSH_STATUS_EXEC_IDLE;
chry_readline_auto_refresh(&csh->rl, true);
chry_readline_ignore(&csh->rl, false);
chry_readline_edit_refresh(&csh->rl);
}
int shell_init(bool need_login)
{
chry_shell_init_t csh_init;
if (chry_ringbuffer_init(&shell_rb, mempool, sizeof(mempool))) {
return -1;
}
if (need_login) {
login = false;
} else {
login = true;
}
/*!< I/O callback */
csh_init.sput = csh_sput_cb;
csh_init.sget = csh_sget_cb;
#if defined(CONFIG_CSH_SYMTAB) && CONFIG_CSH_SYMTAB
extern const int __fsymtab_start;
extern const int __fsymtab_end;
extern const int __vsymtab_start;
extern const int __vsymtab_end;
/*!< get table from ld symbol */
csh_init.command_table_beg = &__fsymtab_start;
csh_init.command_table_end = &__fsymtab_end;
csh_init.variable_table_beg = &__vsymtab_start;
csh_init.variable_table_end = &__vsymtab_end;
#endif
#if defined(CONFIG_CSH_PROMPTEDIT) && CONFIG_CSH_PROMPTEDIT
static char csh_prompt_buffer[128];
/*!< set prompt buffer */
csh_init.prompt_buffer = csh_prompt_buffer;
csh_init.prompt_buffer_size = sizeof(csh_prompt_buffer);
#endif
#if defined(CONFIG_CSH_HISTORY) && CONFIG_CSH_HISTORY
static char csh_history_buffer[128];
/*!< set history buffer */
csh_init.history_buffer = csh_history_buffer;
csh_init.history_buffer_size = sizeof(csh_history_buffer);
#endif
#if defined(CONFIG_CSH_LNBUFF_STATIC) && CONFIG_CSH_LNBUFF_STATIC
static char csh_line_buffer[128];
/*!< set linebuffer */
csh_init.line_buffer = csh_line_buffer;
csh_init.line_buffer_size = sizeof(csh_line_buffer);
#endif
csh_init.uid = 0;
csh_init.user[0] = "cherry";
/*!< The port hash function is required,
and the strcmp attribute is used weakly by default,
int chry_shell_port_hash_strcmp(const char *hash, const char *str); */
csh_init.hash[0] = "12345678"; /*!< If there is no password, set to NULL */
csh_init.host = "cherryadb";
csh_init.user_data = NULL;
int ret = chry_shell_init(&csh, &csh_init);
if (ret) {
return -1;
}
task_hdl_exec = NULL;
event_hdl = xEventGroupCreateStatic(&event_grp);
task_hdl_repl = xTaskCreateStatic(task_repl, "task_repl", 1024U, NULL, task_repl_PRIORITY, task_stack_repl, &task_buffer_repl);
return 0;
}
void shell_lock(void)
{
xEventGroupSetBits(event_hdl, 0x01);
xEventGroupWaitBits(event_hdl, 0x02, pdTRUE, pdTRUE, portMAX_DELAY);
}
void shell_unlock(void)
{
xEventGroupSetBits(event_hdl, 0x04);
xEventGroupWaitBits(event_hdl, 0x08, pdTRUE, pdTRUE, portMAX_DELAY);
}
static int csh_exit(int argc, char **argv)
{
(void)argc;
(void)argv;
usbd_adb_close(ADB_SHELL_LOALID);
return 0;
}
CSH_SCMD_EXPORT_ALIAS(csh_exit, exit, );
#define __ENV_PATH "/sbin:/bin"
const char ENV_PATH[] = __ENV_PATH;
CSH_RVAR_EXPORT(ENV_PATH, PATH, sizeof(__ENV_PATH));
#define __ENV_ZERO ""
const char ENV_ZERO[] = __ENV_ZERO;
CSH_RVAR_EXPORT(ENV_ZERO, ZERO, sizeof(__ENV_ZERO));

View File

@@ -0,0 +1,228 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_adb.h"
/*!< endpoint address */
#define WINUSB_IN_EP 0x81
#define WINUSB_OUT_EP 0x02
#define USBD_VID 0xFFFF
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
#ifdef CONFIG_USB_HS
#define WINUSB_MAX_MPS 512
#else
#define WINUSB_MAX_MPS 64
#endif
#define WCID_VENDOR_CODE 0x17
#define ADB_INTF_NUM 0
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
///////////////////////////////////////
/// MS OS string descriptor
///////////////////////////////////////
0x12, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
/* MSFT100 */
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
WCID_VENDOR_CODE, /* bVendorCode */
0x00, /* bReserved */
};
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
///////////////////////////////////////
/// WCID descriptor
///////////////////////////////////////
0x28, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x04, 0x00, /* wIndex */
0x01, /* bCount */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
///////////////////////////////////////
/// WCID function descriptor
///////////////////////////////////////
ADB_INTF_NUM, /* bFirstInterfaceNumber */
0x01, /* bReserved */
/* Compatible ID */
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8: WINUSB */
/* */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
};
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
///////////////////////////////////////
/// WCID property descriptor
///////////////////////////////////////
0x8e, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x05, 0x00, /* wIndex */
0x01, 0x00, /* wCount */
///////////////////////////////////////
/// registry propter descriptor
///////////////////////////////////////
0x84, 0x00, 0x00, 0x00, /* dwSize */
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
0x28, 0x00, /* wPropertyNameLength */
/* DeviceInterfaceGUID */
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
};
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
WINUSB_IF0_WCIDProperties,
};
struct usb_msosv1_descriptor msosv1_desc = {
.string = WCID_StringDescriptor_MSOS,
.vendor_code = WCID_VENDOR_CODE,
.compat_id = WINUSB_WCIDDescriptor,
.comp_id_property = WINUSB_IFx_WCIDProperties,
};
/*!< global descriptor */
static const uint8_t adb_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
ADB_DESCRIPTOR_INIT(ADB_INTF_NUM, WINUSB_IN_EP, WINUSB_OUT_EP, WINUSB_MAX_MPS),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'A', 0x00, /* wcChar6 */
'D', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x1C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'A', 0x00, /* wcChar6 */
'D', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
'2', 0x00, /* wcChar9 */
'0', 0x00, /* wcChar10 */
'2', 0x00, /* wcChar11 */
'4', 0x00, /* wcChar12 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x40,
0x00,
0x00,
#endif
0x00
};
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
static struct usbd_interface intf0;
extern int shell_init(bool need_login);
void cherryadb_init(uint8_t busid, uint32_t reg_base)
{
/* default password is : 12345678 */
/* shell_init() must be called in-task */
if (0 != shell_init(false)) {
/* shell failed to be initialized */
printf("Failed to initialize shell\r\n");
for (;;) {
;
}
}
usbd_desc_register(busid, adb_descriptor);
usbd_add_interface(busid, usbd_adb_init_intf(busid, &intf0, WINUSB_IN_EP, WINUSB_OUT_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -144,7 +144,7 @@ const uint8_t audio_v1_descriptor[] = {
0x00,
0x00,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -212,7 +212,7 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v1_init(uint8_t busid, uint32_t reg_base)
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));

View File

@@ -139,7 +139,7 @@ const uint8_t audio_v1_descriptor[] = {
0x00,
0x00,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -194,11 +194,11 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
ep_tx_busy_flag = false;
rx_flag = 0;
printf("CLOSE1\r\n");
} else {
tx_flag = 0;
ep_tx_busy_flag = false;
printf("CLOSE2\r\n");
}
}
@@ -238,7 +238,7 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_OUT_EP },
};
void audio_v1_init(uint8_t busid, uint32_t reg_base)
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));

View File

@@ -149,7 +149,7 @@ const uint8_t audio_v2_descriptor[] = {
0x00,
0x00,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -229,7 +229,7 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v2_init(uint8_t busid, uint32_t reg_base)
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));

View File

@@ -196,7 +196,7 @@ uint8_t audio_v2_descriptor[] = {
0x00,
0x00,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -275,7 +275,7 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
rx_flag = 0;
USB_LOG_RAW("CLOSE1\r\n");
} else {
tx_flag = 0;
@@ -346,7 +346,7 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v2_init(uint8_t busid, uint32_t reg_base)
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));

View File

@@ -149,7 +149,7 @@ const uint8_t audio_v2_descriptor[] = {
0x00,
0x00,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -247,7 +247,7 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_OUT_EP },
};
void audio_v2_init(uint8_t busid, uint32_t reg_base)
void audio_v2_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));

463
demo/bootuf2/bootuf2.c Normal file
View File

@@ -0,0 +1,463 @@
/*
* Copyright (c) 2024, sakumisu
* Copyright (c) 2024, Egahp
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "bootuf2.h"
#include "usbd_core.h"
char file_INFO[] = {
"CherryUSB UF2 BOOT\r\n"
"Model: " CONFIG_PRODUCT "\r\n"
"Board-ID: " CONFIG_BOARD "\r\n"
};
const char file_IDEX[] = {
"<!doctype html>\n"
"<html>"
"<body>"
"<script>\n"
"location.replace(\"" CONFIG_BOOTUF2_INDEX_URL "\");\n"
"</script>"
"</body>"
"</html>\n"
};
const char file_JOIN[] = {
"<!doctype html>\n"
"<html>"
"<body>"
"<script>\n"
"location.replace(\"" CONFIG_BOOTUF2_JOIN_URL "\");\n"
"</script>"
"</body>"
"</html>\n"
};
const char file_ID__[12] = BOOTUF2_FAMILYID_ARRAY;
static struct bootuf2_FILE files[] = {
[0] = { .Name = file_ID__, .Content = NULL, .FileSize = 0 },
[1] = { .Name = "INFO_UF2TXT", .Content = file_INFO, .FileSize = sizeof(file_INFO) - 1 },
[2] = { .Name = "INDEX HTM", .Content = file_IDEX, .FileSize = sizeof(file_IDEX) - 1 },
[3] = { .Name = "JOIN HTM", .Content = file_JOIN, .FileSize = sizeof(file_JOIN) - 1 },
};
struct bootuf2_data {
const struct bootuf2_DBR *const DBR;
struct bootuf2_STATE *const STATE;
uint8_t *const fbuff;
uint8_t *const erase;
size_t page_count;
uint8_t *const cache;
const size_t cache_size;
uint32_t cached_address;
size_t cached_bytes;
};
/*!< define DBRs */
static const struct bootuf2_DBR bootuf2_DBR = {
.JMPInstruction = { 0xEB, 0x3C, 0x90 },
.OEM = "UF2 UF2 ",
.BPB = {
.BytesPerSector = CONFIG_BOOTUF2_SECTOR_SIZE,
.SectorsPerCluster = CONFIG_BOOTUF2_SECTOR_PER_CLUSTER,
.ReservedSectors = CONFIG_BOOTUF2_SECTOR_RESERVED,
.NumberOfFAT = CONFIG_BOOTUF2_NUM_OF_FAT,
.RootEntries = CONFIG_BOOTUF2_ROOT_ENTRIES,
.Sectors = (BOOTUF2_SECTORS(0) > 0xFFFF) ? 0 : BOOTUF2_SECTORS(0),
.MediaDescriptor = 0xF8,
.SectorsPerFAT = BOOTUF2_SECTORS_PER_FAT(0),
.SectorsPerTrack = 1,
.Heads = 1,
.HiddenSectors = 0,
.SectorsOver32MB = (BOOTUF2_SECTORS(0) > 0xFFFF) ? BOOTUF2_SECTORS(0) : 0,
.BIOSDrive = 0x80,
.Reserved = 0,
.ExtendBootSignature = 0x29,
.VolumeSerialNumber = 0x00420042,
.VolumeLabel = "CHERRYUF2",
.FileSystem = "FAT16 ",
},
};
/*!< define mask */
static uint8_t __attribute__((aligned(4))) bootuf2_mask[BOOTUF2_BLOCKSMAX / 8 + 1] = { 0 };
/*!< define state */
static struct bootuf2_STATE bootuf2_STATE = {
.NumberOfBlock = 0,
.NumberOfWritten = 0,
.Mask = bootuf2_mask,
.Enable = 1,
};
/*!< define flash cache */
static uint8_t __attribute__((aligned(4))) bootuf2_disk_cache[CONFIG_BOOTUF2_CACHE_SIZE];
/*!< define flash buff */
static uint8_t __attribute__((aligned(4))) bootuf2_disk_fbuff[256];
/*!< define erase flag buff */
static uint8_t __attribute__((aligned(4))) bootuf2_disk_erase[BOOTUF2_DIVCEIL(CONFIG_BOOTUF2_PAGE_COUNTMAX, 8)];
/*!< define disk */
static struct bootuf2_data bootuf2_disk = {
.DBR = &bootuf2_DBR,
.STATE = &bootuf2_STATE,
.fbuff = bootuf2_disk_fbuff,
.erase = bootuf2_disk_erase,
.cache = bootuf2_disk_cache,
.cache_size = sizeof(bootuf2_disk_cache),
};
static void fname_copy(char *dst, char const *src, uint16_t len)
{
for (size_t i = 0; i < len; ++i) {
if (*src)
*dst++ = *src++;
else
*dst++ = ' ';
}
}
static void fcalculate_cluster(struct bootuf2_data *ctx)
{
/*!< init files cluster */
uint16_t cluster_beg = 2;
for (int i = 0; i < ARRAY_SIZE(files); i++) {
files[i].ClusterBeg = cluster_beg;
files[i].ClusterEnd = -1 + cluster_beg +
BOOTUF2_DIVCEIL(files[i].FileSize,
ctx->DBR->BPB.BytesPerSector *
ctx->DBR->BPB.SectorsPerCluster);
cluster_beg = files[i].ClusterEnd + 1;
}
}
static int ffind_by_cluster(uint32_t cluster)
{
if (cluster >= 0xFFF0) {
return -1;
}
for (uint32_t i = 0; i < ARRAY_SIZE(files); i++) {
if ((files[i].ClusterBeg <= cluster) &&
(cluster <= files[i].ClusterEnd)) {
return i;
}
}
return -1;
}
static bool bootuf2block_check_writable(struct bootuf2_STATE *STATE,
struct bootuf2_BLOCK *uf2, uint32_t block_max)
{
if (uf2->NumberOfBlock) {
if (uf2->BlockIndex < block_max) {
uint8_t mask = 1 << (uf2->BlockIndex % 8);
uint32_t pos = uf2->BlockIndex / 8;
if ((STATE->Mask[pos] & mask) == 0) {
return true;
}
}
}
return false;
}
static void bootuf2block_state_update(struct bootuf2_STATE *STATE,
struct bootuf2_BLOCK *uf2, uint32_t block_max)
{
if (uf2->NumberOfBlock) {
if (STATE->NumberOfBlock != uf2->NumberOfBlock) {
if ((uf2->NumberOfBlock >= BOOTUF2_BLOCKSMAX) ||
STATE->NumberOfBlock) {
/*!< uf2 block only can be update once */
/*!< this will cause never auto reboot */
STATE->NumberOfBlock = 0xffffffff;
} else {
STATE->NumberOfBlock = uf2->NumberOfBlock;
}
}
if (uf2->BlockIndex < block_max) {
uint8_t mask = 1 << (uf2->BlockIndex % 8);
uint32_t pos = uf2->BlockIndex / 8;
if ((STATE->Mask[pos] & mask) == 0) {
STATE->Mask[pos] |= mask;
STATE->NumberOfWritten++;
}
}
}
USB_LOG_DBG("UF2 block total %d written %d index %d\r\n",
uf2->NumberOfBlock, STATE->NumberOfWritten, uf2->BlockIndex);
}
static bool bootuf2block_state_check(struct bootuf2_STATE *STATE)
{
return (STATE->NumberOfWritten >= STATE->NumberOfBlock) &&
STATE->NumberOfBlock;
}
static int bootuf2_flash_flush(struct bootuf2_data *ctx)
{
int err;
if (ctx->cached_bytes == 0) {
return 0;
}
err = bootuf2_flash_write(ctx->cached_address, ctx->cache, ctx->cached_bytes);
if (err) {
USB_LOG_ERR("UF2 slot flash write error %d at offset %08lx len %d\r\n",
err, ctx->cached_address, ctx->cached_bytes);
return -1;
}
ctx->cached_bytes = 0;
return 0;
}
int bootuf2_flash_write_internal(struct bootuf2_data *ctx, struct bootuf2_BLOCK *uf2)
{
/*!< 1.cache not empty and address not continue */
/*!< 2.cache full */
if ((ctx->cached_bytes && ((ctx->cached_address + ctx->cached_bytes) != uf2->TargetAddress)) ||
(ctx->cached_bytes == ctx->cache_size)) {
int err = bootuf2_flash_flush(ctx);
if (err)
return err;
}
/*!< write len always is 256, cache_size always is a multiple of 256 */
memcpy(ctx->cache + ctx->cached_bytes, uf2->Data, uf2->PayloadSize);
ctx->cached_address = uf2->TargetAddress - ctx->cached_bytes;
ctx->cached_bytes += uf2->PayloadSize;
return 0;
}
void bootuf2_init(void)
{
struct bootuf2_data *ctx;
ctx = &bootuf2_disk;
fcalculate_cluster(ctx);
ctx->cached_bytes = 0;
ctx->cached_address = 0;
}
int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count)
{
struct bootuf2_data *ctx;
ctx = &bootuf2_disk;
while (sector_count) {
memset(buff, 0, ctx->DBR->BPB.BytesPerSector);
uint32_t sector_relative = start_sector;
/*!< DBR sector */
if (start_sector == BOOTUF2_SECTOR_DBR_END) {
memcpy(buff, ctx->DBR, sizeof(struct bootuf2_DBR));
buff[510] = 0x55;
buff[511] = 0xaa;
}
/*!< FAT sector */
else if (start_sector < BOOTUF2_SECTOR_FAT_END(ctx->DBR)) {
uint16_t *buff16 = (uint16_t *)buff;
sector_relative -= BOOTUF2_SECTOR_RSVD_END(ctx->DBR);
/*!< Perform the same operation on all FAT tables */
while (sector_relative >= ctx->DBR->BPB.SectorsPerFAT) {
sector_relative -= ctx->DBR->BPB.SectorsPerFAT;
}
uint16_t cluster_unused = files[ARRAY_SIZE(files) - 1].ClusterEnd + 1;
uint16_t cluster_absolute_first = sector_relative *
BOOTUF2_FAT16_PER_SECTOR(ctx->DBR);
/*!< cluster used link to chain, or unsed */
for (uint16_t i = 0, cluster_absolute = cluster_absolute_first;
i < BOOTUF2_FAT16_PER_SECTOR(ctx->DBR);
i++, cluster_absolute++) {
if (cluster_absolute >= cluster_unused)
buff16[i] = 0;
else
buff16[i] = cluster_absolute + 1;
}
/*!< cluster 0 and 1 */
if (sector_relative == 0) {
buff[0] = ctx->DBR->BPB.MediaDescriptor;
buff[1] = 0xff;
buff16[1] = 0xffff;
}
/*!< cluster end of file */
for (uint32_t i = 0; i < ARRAY_SIZE(files); i++) {
uint16_t cluster_file_last = files[i].ClusterEnd;
if (cluster_file_last >= cluster_absolute_first) {
uint16_t idx = cluster_file_last - cluster_absolute_first;
if (idx < BOOTUF2_FAT16_PER_SECTOR(ctx->DBR)) {
buff16[idx] = 0xffff;
}
}
}
}
/*!< root entries */
else if (start_sector < BOOTUF2_SECTOR_ROOT_END(ctx->DBR)) {
sector_relative -= BOOTUF2_SECTOR_FAT_END(ctx->DBR);
struct bootuf2_ENTRY *ent = (void *)buff;
int remain_entries = BOOTUF2_ENTRY_PER_SECTOR(ctx->DBR);
uint32_t file_index_first;
/*!< volume label entry */
if (sector_relative == 0) {
fname_copy(ent->Name, (char const *)ctx->DBR->BPB.VolumeLabel, 11);
ent->Attribute = 0x28;
ent++;
remain_entries--;
file_index_first = 0;
} else {
/*!< -1 to account for volume label in first sector */
file_index_first = sector_relative * BOOTUF2_ENTRY_PER_SECTOR(ctx->DBR) - 1;
}
for (uint32_t idx = file_index_first;
(remain_entries > 0) && (idx < ARRAY_SIZE(files));
idx++, ent++) {
const uint32_t cluster_beg = files[idx].ClusterBeg;
const struct bootuf2_FILE *f = &files[idx];
if ((0 == f->FileSize) &&
(0 != idx)) {
continue;
}
fname_copy(ent->Name, f->Name, 11);
ent->Attribute = 0x05;
ent->CreateTimeTeenth = BOOTUF2_SECONDS_INT % 2 * 100;
ent->CreateTime = BOOTUF2_DOS_TIME;
ent->CreateDate = BOOTUF2_DOS_DATE;
ent->LastAccessDate = BOOTUF2_DOS_DATE;
ent->FirstClustH16 = cluster_beg >> 16;
ent->UpdateTime = BOOTUF2_DOS_TIME;
ent->UpdateDate = BOOTUF2_DOS_DATE;
ent->FirstClustL16 = cluster_beg & 0xffff;
ent->FileSize = f->FileSize;
}
}
/*!< data */
else if (start_sector < BOOTUF2_SECTOR_DATA_END(ctx->DBR)) {
sector_relative -= BOOTUF2_SECTOR_ROOT_END(ctx->DBR);
int fid = ffind_by_cluster(2 + sector_relative / ctx->DBR->BPB.SectorsPerCluster);
if (fid >= 0) {
const struct bootuf2_FILE *f = &files[fid];
uint32_t sector_relative_file =
sector_relative -
(files[fid].ClusterBeg - 2) * ctx->DBR->BPB.SectorsPerCluster;
size_t fcontent_offset = sector_relative_file * ctx->DBR->BPB.BytesPerSector;
size_t fcontent_length = f->FileSize;
if (fcontent_length > fcontent_offset) {
const void *src = (void *)((uint8_t *)(f->Content) + fcontent_offset);
size_t copy_size = fcontent_length - fcontent_offset;
if (copy_size > ctx->DBR->BPB.BytesPerSector) {
copy_size = ctx->DBR->BPB.BytesPerSector;
}
memcpy(buff, src, copy_size);
}
}
}
/*!< unknown sector, ignore */
start_sector++;
sector_count--;
buff += ctx->DBR->BPB.BytesPerSector;
}
return 0;
}
int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count)
{
struct bootuf2_data *ctx;
ctx = &bootuf2_disk;
while (sector_count) {
struct bootuf2_BLOCK *uf2 = (void *)buff;
if (!((uf2->MagicStart0 == BOOTUF2_MAGIC_START0) &&
(uf2->MagicStart1 == BOOTUF2_MAGIC_START1) &&
(uf2->MagicEnd == BOOTUF2_MAGIC_END) &&
(uf2->Flags & BOOTUF2_FLAG_FAMILID_PRESENT) &&
!(uf2->Flags & BOOTUF2_FLAG_NOT_MAIN_FLASH))) {
goto next;
}
if (uf2->FamilyID == CONFIG_BOOTUF2_FAMILYID) {
if (bootuf2block_check_writable(ctx->STATE, uf2, CONFIG_BOOTUF2_FLASHMAX)) {
bootuf2_flash_write_internal(ctx, uf2);
bootuf2block_state_update(ctx->STATE, uf2, CONFIG_BOOTUF2_FLASHMAX);
} else {
USB_LOG_DBG("UF2 block %d already written\r\n",
uf2->BlockIndex);
}
} else {
USB_LOG_DBG("UF2 block illegal id %08x\r\n", uf2->FamilyID);
}
next:
start_sector++;
sector_count--;
buff += ctx->DBR->BPB.BytesPerSector;
}
return 0;
}
uint16_t bootuf2_get_sector_size(void)
{
return bootuf2_disk.DBR->BPB.BytesPerSector;
}
uint32_t bootuf2_get_sector_count(void)
{
return bootuf2_disk.DBR->BPB.SectorsOver32MB + bootuf2_disk.DBR->BPB.Sectors;
}
bool bootuf2_is_write_done(void)
{
if (bootuf2block_state_check(bootuf2_disk.STATE)) {
bootuf2_flash_flush(&bootuf2_disk);
USB_LOG_DBG("UF2 update ok\r\n");
return true;
} else {
return false;
}
}

218
demo/bootuf2/bootuf2.h Normal file
View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2024, sakumisu
* Copyright (c) 2024, Egahp
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef BOOTUF2_H
#define BOOTUF2_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <bootuf2_config.h>
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) \
((int)((sizeof(array) / sizeof((array)[0]))))
#endif
struct bootuf2_BLOCK
{
// 32 byte header
uint32_t MagicStart0;
uint32_t MagicStart1;
uint32_t Flags;
uint32_t TargetAddress;
uint32_t PayloadSize;
uint32_t BlockIndex;
uint32_t NumberOfBlock;
uint32_t FamilyID; // or file_size
uint8_t Data[476];
uint32_t MagicEnd;
} __PACKED;
//BUILD_ASSERT(sizeof(struct bootuf2_BLOCK) == 512, "bootuf2_BLOCK not sector sized");
struct bootuf2_STATE
{
uint32_t NumberOfBlock;
uint32_t NumberOfWritten;
uint8_t *const Mask;
uint8_t Enable;
};
struct bootuf2_DBR
{
/*!< offset 0 */
uint8_t JMPInstruction[3];
/*!< offset 3 */
uint8_t OEM[8];
/*!< offset 11 */
struct
{
uint16_t BytesPerSector;
uint8_t SectorsPerCluster;
uint16_t ReservedSectors;
uint8_t NumberOfFAT;
uint16_t RootEntries;
uint16_t Sectors;
uint8_t MediaDescriptor;
uint16_t SectorsPerFAT;
uint16_t SectorsPerTrack;
uint16_t Heads;
uint32_t HiddenSectors;
uint32_t SectorsOver32MB;
uint8_t BIOSDrive;
uint8_t Reserved;
uint8_t ExtendBootSignature;
uint32_t VolumeSerialNumber;
uint8_t VolumeLabel[11];
uint8_t FileSystem[8];
} __PACKED BPB;
/*!< offset 62 */
/*!< BootLoader */
/*!< offset 511 */
/*!< 0x55 0xAA */
} __PACKED;
//BUILD_ASSERT(sizeof(struct bootuf2_DBR) == 62, "bootuf2_DBR size must be 62 byte");
struct bootuf2_ENTRY
{
char Name[11];
uint8_t Attribute;
uint8_t NTReserved;
uint8_t CreateTimeTeenth;
uint16_t CreateTime;
uint16_t CreateDate;
uint16_t LastAccessDate;
uint16_t FirstClustH16;
uint16_t UpdateTime;
uint16_t UpdateDate;
uint16_t FirstClustL16;
uint32_t FileSize;
} __PACKED;
//BUILD_ASSERT(sizeof(struct bootuf2_ENTRY) == 32, "bootuf2_ENTRY size must be 32 byte");
struct bootuf2_FILE
{
const char *const Name;
const void *const Content;
uint32_t FileSize;
uint16_t ClusterBeg;
uint16_t ClusterEnd;
};
#define BOOTUF2_DIVCEIL(_v, _d) (((_v) / (_d)) + ((_v) % (_d) ? 1 : 0))
#define BOOTUF2_MAGIC_START0 0x0A324655u
#define BOOTUF2_MAGIC_START1 0x9E5D5157u
#define BOOTUF2_MAGIC_SERIAL 0x251B18BDu
#define BOOTUF2_MAGIC_END 0x0AB16F30u
#define BOOTUF2_FLAG_NOT_MAIN_FLASH 0x00000001u
#define BOOTUF2_FLAG_FILE_CONTAINER 0x00001000u
#define BOOTUF2_FLAG_FAMILID_PRESENT 0x00002000u
#define BOOTUF2_FLAG_MD5_PRESENT 0x00004000u
#define BOOTUF2_CMD_READ 0
#define BOOTUF2_CMD_SYNC 1
#define BOOTUF2_BLOCKSMAX (((CONFIG_BOOTUF2_FLASHMAX) / 256) + (((CONFIG_BOOTUF2_FLASHMAX) % 256) ? 1 : 0))
#define BOOTUF2_FAMILYID_POSNUM(n) (((CONFIG_BOOTUF2_FAMILYID) / (0x10000000 >> ((n) * 4))) % 0x10)
#define BOOTUF2_FAMILYID_ARRAY \
{ \
((BOOTUF2_FAMILYID_POSNUM(0) >= 10) ? BOOTUF2_FAMILYID_POSNUM(0) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(0) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(1) >= 10) ? BOOTUF2_FAMILYID_POSNUM(1) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(1) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(2) >= 10) ? BOOTUF2_FAMILYID_POSNUM(2) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(2) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(3) >= 10) ? BOOTUF2_FAMILYID_POSNUM(3) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(3) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(4) >= 10) ? BOOTUF2_FAMILYID_POSNUM(4) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(4) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(5) >= 10) ? BOOTUF2_FAMILYID_POSNUM(5) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(5) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(6) >= 10) ? BOOTUF2_FAMILYID_POSNUM(6) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(6) + '0'), \
((BOOTUF2_FAMILYID_POSNUM(7) >= 10) ? BOOTUF2_FAMILYID_POSNUM(7) - 10 + 'A' : BOOTUF2_FAMILYID_POSNUM(7) + '0'), \
('I'), \
('D'), \
(' '), \
('\0'), \
};
#define BOOTUF2_FAT16_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / 2)
#define BOOTUF2_ENTRY_PER_SECTOR(pDBR) (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY))
#define BOOTUF2_CLUSTERSMAX (0xFFF0 - 2)
#define BOOTUF2_SECTOR_DBR_END (0)
#define BOOTUF2_SECTOR_RSVD_END(pDBR) BOOTUF2_SECTOR_DBR_END + (pDBR->BPB.ReservedSectors)
#define BOOTUF2_SECTOR_FAT_END(pDBR) BOOTUF2_SECTOR_RSVD_END(pDBR) + (pDBR->BPB.SectorsPerFAT * pDBR->BPB.NumberOfFAT)
#define BOOTUF2_SECTOR_ROOT_END(pDBR) BOOTUF2_SECTOR_FAT_END(pDBR) + (pDBR->BPB.RootEntries / (pDBR->BPB.BytesPerSector / sizeof(struct bootuf2_ENTRY)))
#define BOOTUF2_SECTOR_DATA_END(pDBR) (pDBR->BPB.Sectors + pDBR->BPB.SectorsOver32MB)
#define BOOTUF2_SECTORS_PER_FAT(n) \
BOOTUF2_DIVCEIL(BOOTUF2_CLUSTERSMAX, (CONFIG_BOOTUF2_SECTOR_SIZE / 2))
#define BOOTUF2_SECTORS_FOR_ENTRIES(n) \
(CONFIG_BOOTUF2_ROOT_ENTRIES / (CONFIG_BOOTUF2_SECTOR_SIZE / sizeof(struct bootuf2_ENTRY)))
#define BOOTUF2_SECTORS(n) \
(CONFIG_BOOTUF2_SECTOR_RESERVED + \
CONFIG_BOOTUF2_NUM_OF_FAT * BOOTUF2_SECTORS_PER_FAT(n) + \
BOOTUF2_SECTORS_FOR_ENTRIES(n) + \
BOOTUF2_CLUSTERSMAX * CONFIG_BOOTUF2_SECTOR_PER_CLUSTER)
#define BOOTUF2_YEAR_INT ( \
(__DATE__[7u] - '0') * 1000u + \
(__DATE__[8u] - '0') * 100u + \
(__DATE__[9u] - '0') * 10u + \
(__DATE__[10u] - '0') * 1u)
#define BOOTUF2_MONTH_INT ( \
(__DATE__[2u] == 'n' && __DATE__[1u] == 'a') ? 1u /*Jan*/ \
: (__DATE__[2u] == 'b') ? 2u /*Feb*/ \
: (__DATE__[2u] == 'r' && __DATE__[1u] == 'a') ? 3u /*Mar*/ \
: (__DATE__[2u] == 'r') ? 4u /*Apr*/ \
: (__DATE__[2u] == 'y') ? 5u /*May*/ \
: (__DATE__[2u] == 'n') ? 6u /*Jun*/ \
: (__DATE__[2u] == 'l') ? 7u /*Jul*/ \
: (__DATE__[2u] == 'g') ? 8u /*Aug*/ \
: (__DATE__[2u] == 'p') ? 9u /*Sep*/ \
: (__DATE__[2u] == 't') ? 10u /*Oct*/ \
: (__DATE__[2u] == 'v') ? 11u /*Nov*/ \
: 12u /*Dec*/)
#define BOOTUF2_DAY_INT ( \
(__DATE__[4u] == ' ' ? 0 : __DATE__[4u] - '0') * 10u + \
(__DATE__[5u] - '0'))
#define BOOTUF2_HOUR_INT ( \
(__TIME__[0u] == '?' ? 0 : __TIME__[0u] - '0') * 10u + (__TIME__[1u] == '?' ? 0 : __TIME__[1u] - '0'))
#define BOOTUF2_MINUTE_INT ( \
(__TIME__[3u] == '?' ? 0 : __TIME__[3u] - '0') * 10u + (__TIME__[4u] == '?' ? 0 : __TIME__[4u] - '0'))
#define BOOTUF2_SECONDS_INT ( \
(__TIME__[6u] == '?' ? 0 : __TIME__[6u] - '0') * 10u + (__TIME__[7u] == '?' ? 0 : __TIME__[7u] - '0'))
#define BOOTUF2_DOS_DATE ( \
((BOOTUF2_YEAR_INT - 1980u) << 9u) | \
(BOOTUF2_MONTH_INT << 5u) | \
(BOOTUF2_DAY_INT << 0u))
#define BOOTUF2_DOS_TIME ( \
(BOOTUF2_HOUR_INT << 11u) | \
(BOOTUF2_MINUTE_INT << 5u) | \
(BOOTUF2_SECONDS_INT << 0u))
void bootuf2_init(void);
int boot2uf2_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t sector_count);
int bootuf2_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t sector_count);
uint16_t bootuf2_get_sector_size(void);
uint32_t bootuf2_get_sector_count(void);
bool bootuf2_is_write_done(void);
void boot2uf2_flash_init(void);
int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size);
#endif /* BOOTUF2_H */

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef BOOTUF2_CONFIG_H
#define BOOTUF2_CONFIG_H
#define CONFIG_PRODUCT "CherryUSB"
#define CONFIG_BOARD "CherryUSB BOARD"
#define CONFIG_BOOTUF2_INDEX_URL "https://github.com/cherry-embedded"
#define CONFIG_BOOTUF2_JOIN_URL "http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GyH2M5XfWTHQzmZis4ClpgvfdObPrvtk&authKey=LmcLhfno%2BiW51wmgVC%2F8WoYwUXqiclzWDHMU1Jy1d6S8cECJ4Q7bfJ%2FTe67RLakI&noverify=0&group_code=642693751"
#define CONFIG_BOOTUF2_CACHE_SIZE 4096
#define CONFIG_BOOTUF2_SECTOR_SIZE 512
#define CONFIG_BOOTUF2_SECTOR_PER_CLUSTER 2
#define CONFIG_BOOTUF2_SECTOR_RESERVED 1
#define CONFIG_BOOTUF2_NUM_OF_FAT 2
#define CONFIG_BOOTUF2_ROOT_ENTRIES 64
#define CONFIG_BOOTUF2_FAMILYID 0xFFFFFFFF
#define CONFIG_BOOTUF2_FLASHMAX 0x800000
#define CONFIG_BOOTUF2_PAGE_COUNTMAX 1024
#endif

BIN
demo/bootuf2/cherryuf2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_msc.h"
#include "bootuf2.h"
#define MSC_IN_EP 0x81
#define MSC_OUT_EP 0x02
#define USBD_VID 0xFFFF
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define MSC_MAX_MPS 512
#else
#define MSC_MAX_MPS 64
#endif
const uint8_t msc_bootuf2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'U', 0x00, /* wcChar10 */
'F', 0x00, /* wcChar11 */
'2', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
bootuf2_init();
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = bootuf2_get_sector_count();
*block_size = bootuf2_get_sector_size();
USB_LOG_INFO("sector count:%d, sector size:%d\n", *block_num, *block_size);
}
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
boot2uf2_read_sector(sector, buffer, length / bootuf2_get_sector_size());
return 0;
}
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
bootuf2_write_sector(sector, buffer, length / bootuf2_get_sector_size());
return 0;
}
static struct usbd_interface intf0;
void msc_bootuf2_init(uint8_t busid, uintptr_t reg_base)
{
boot2uf2_flash_init();
usbd_desc_register(busid, msc_bootuf2_descriptor);
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void boot2uf2_flash_init(void)
{
}
int bootuf2_flash_write(uint32_t address, const uint8_t *data, size_t size)
{
USB_LOG_INFO("address:%08x, size:%d\n", address, size);
return 0;
}

View File

@@ -5,7 +5,7 @@
*/
#include "usbd_core.h"
#include "usbd_msc.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
#include "usbd_hid.h"
/*!< endpoint address */
@@ -147,7 +147,7 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
0x00,
0x00,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -301,7 +301,7 @@ struct usbd_interface intf1;
struct usbd_interface intf2;
struct usbd_interface intf3;
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
@@ -332,14 +332,15 @@ void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
*/
void hid_mouse_test(uint8_t busid)
{
if(usb_device_is_configured(busid) == false) {
return;
}
/*!< move mouse pointer */
mouse_cfg.x += 10;
mouse_cfg.y = 0;
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
if (ret < 0) {
return;
}
hid_state = HID_STATE_BUSY;
usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
while (hid_state == HID_STATE_BUSY) {
}
}

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
#include "usbd_msc.h"
/*!< endpoint address */
@@ -58,7 +58,7 @@ static const uint8_t device_quality_descriptor[] = {
0x02,
0x01,
0x40,
0x01,
0x00,
0x00,
};
@@ -173,7 +173,7 @@ static const uint8_t cdc_msc_descriptor[] = {
0x02,
0x01,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -247,7 +247,7 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
void cdc_acm_msc_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_msc_descriptor);

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
/*!< endpoint address */
#define CDC_IN_EP 0x81
@@ -113,7 +113,7 @@ static const uint8_t cdc_descriptor[] = {
0x02,
0x01,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -223,7 +223,7 @@ struct usbd_interface intf5;
struct usbd_interface intf6;
struct usbd_interface intf7;
void cdc_acm_multi_init(uint8_t busid, uint32_t reg_base)
void cdc_acm_multi_init(uint8_t busid, uintptr_t reg_base)
{
usbd_desc_register(busid, cdc_descriptor);

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
/*!< endpoint address */
#define CDC_IN_EP 0x81
@@ -98,7 +98,7 @@ static const uint8_t cdc_descriptor[] = {
0x02,
0x01,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -174,7 +174,7 @@ struct usbd_endpoint cdc_in_ep = {
static struct usbd_interface intf0;
static struct usbd_interface intf1;
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
void cdc_acm_init(uint8_t busid, uintptr_t reg_base)
{
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };

View File

@@ -6,6 +6,10 @@
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
#ifndef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#error "Please enable CONFIG_USBDEV_CDC_ECM_USING_LWIP for this demo"
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
@@ -124,7 +128,7 @@ static const uint8_t cdc_ecm_descriptor[] = {
0x02,
0x01,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -215,18 +219,19 @@ void cdc_ecm_lwip_init(void)
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, mac, 6);
netif->hwaddr[5] = ~netif->hwaddr[5]; /* device mac can't same as host. */
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, cdc_ecm_if_init, netif_input);
netif_set_default(netif);
while (!netif_is_up(netif)) {
}
// while (dhserv_init(&dhcp_config)) {}
while (dhserv_init(&dhcp_config)) {}
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
}
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
void usbd_cdc_ecm_data_recv_done(uint32_t len)
{
}
@@ -264,14 +269,14 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
/* ecm only supports in linux, and you should input the following command
*
*
* sudo ifconfig enxaabbccddeeff up
* sudo dhcpclient enxaabbccddeeff
*/
void cdc_ecm_init(uint8_t busid, uint32_t reg_base)
void cdc_ecm_init(uint8_t busid, uintptr_t reg_base)
{
cdc_ecm_lwip_init();
usbd_desc_register(busid, cdc_ecm_descriptor);
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_add_interface(busid, usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));

View File

@@ -6,6 +6,10 @@
#include "usbd_core.h"
#include "usbd_rndis.h"
#ifndef CONFIG_USBDEV_RNDIS_USING_LWIP
#error "Please enable CONFIG_USBDEV_RNDIS_USING_LWIP for this demo"
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
@@ -100,7 +104,7 @@ static const uint8_t cdc_descriptor[] = {
0x02,
0x01,
0x40,
0x01,
0x00,
0x00,
#endif
0x00
@@ -143,7 +147,11 @@ static rt_err_t rt_usbd_rndis_control(rt_device_t dev, int cmd, void *args)
/* get mac address */
if (args)
rt_memcpy(args, mac, 6);
{
uint8_t *mac_dev = (uint8_t *)args;
rt_memcpy(mac_dev, mac, 6);
mac_dev[5] = ~mac_dev[5]; /* device mac can't same as host. */
}
else
return -RT_ERROR;
@@ -166,7 +174,7 @@ rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
return usbd_rndis_eth_tx(p);
}
void usbd_rndis_data_recv_done(void)
void usbd_rndis_data_recv_done(uint32_t len)
{
eth_device_ready(&rndis_dev);
}
@@ -247,18 +255,19 @@ void rndis_lwip_init(void)
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, mac, 6);
netif->hwaddr[5] = ~netif->hwaddr[5]; /* device mac can't same as host. */
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, rndisif_init, netif_input);
netif_set_default(netif);
while (!netif_is_up(netif)) {
}
// while (dhserv_init(&dhcp_config)) {}
while (dhserv_init(&dhcp_config)) {}
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
}
void usbd_rndis_data_recv_done(void)
void usbd_rndis_data_recv_done(uint32_t len)
{
}
@@ -299,7 +308,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
struct usbd_interface intf0;
struct usbd_interface intf1;
void cdc_rndis_init(uint8_t busid, uint32_t reg_base)
void cdc_rndis_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef RT_USING_LWIP
rt_usbd_rndis_init();

1734
demo/cherryusb_h264.h Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More