285 Commits

Author SHA1 Message Date
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
sakumisu
3336919e0d release v1.3.0 2024-05-22 18:51:41 +08:00
sakumisu
8b070570a7 fix(port/ehci): fix missing busid 2024-05-22 18:51:41 +08:00
sakumisu
af792eabab fix typo 2024-05-21 16:08:28 +08:00
sakumisu
3be08d16f7 update(port/dwc2): rename struct name to avoid duplicate definitions 2024-05-21 11:50:49 +08:00
sakumisu
5dafdcb895 fix warning 2024-05-21 10:10:31 +08:00
sakumisu
f24c37d3aa update(class/wireless/usbd_rndis): remove ununsed speed field 2024-05-20 18:15:01 +08:00
Zhihong Chen
a7a7afc6bb port: HPMicro: update usb_glue_hpm
- update usb_glue_hpm

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-05-18 10:17:57 +08:00
sakumisu
66b893e64f update: add langid in string desc 2024-05-17 22:18:21 +08:00
sakumisu
3a3de9cb69 update: format log 2024-05-17 17:22:25 +08:00
sakumisu
13e4670f3d update: remove internal configs, you should get config from usb_config.h 2024-05-17 17:04:53 +08:00
sakumisu
1d9a36b61c update(docs): update rst 2024-05-17 17:03:50 +08:00
sakumisu
b1c81a92f5 fix warning 2024-05-16 20:47:37 +08:00
sakumisu
af92236cf4 refactor(core/usbd_core): process string internal, you can use like \"cherryusb\" now 2024-05-16 11:19:58 +08:00
sakumisu
0985a7e5fa fix(port/usb_hc_ehci): clear iaad status 2024-05-16 10:13:52 +08:00
sakumisu
8b805ee6d7 fix(dwc2): check those chips with 1.25KB fifo 2024-05-15 23:07:46 +08:00
sakumisu
5e6bd78f80 update(dwc2): change rx fifo to 1024/4 as default 2024-05-15 22:37:57 +08:00
sakumisu
f2133f5ca2 update(docs): update rst 2024-05-15 12:10:38 +08:00
sakumisu
9657585f1f update(core/usbh_core): remove ununsed urb memset 2024-05-15 09:57:21 +08:00
sakumisu
a225ee383b update(demo/midi): add read api 2024-05-14 21:34:50 +08:00
sakumisu
60747ce435 update(port/musb): add sunxi glue for check 2024-05-14 21:34:15 +08:00
sakumisu
490cac1a0f fix(class): change ifdef to if for LWIP_TCPIP_CORE_LOCKING_INPUT 2024-05-14 13:59:39 +08:00
sakumisu
207fb7b128 update(usbh_ncm/usbh_rndis): limit read size to 16K 2024-05-14 13:53:58 +08:00
sakumisu
d23a8a8d00 update: get mps by usbd_get_ep_mps 2024-05-14 11:33:11 +08:00
sakumisu
4243394225 fix(demo): remove duplicate macro 2024-05-14 11:32:56 +08:00
sakumisu
62c9c8b747 update(demo/usb_host): change eth name index 2024-05-12 20:50:29 +08:00
sakumisu
7b38b4b323 update(demo/usb_host): disable keep timer(no need) 2024-05-12 20:47:42 +08:00
sakumisu
e1aa49e086 fix typo 2024-05-12 20:47:34 +08:00
sakumisu
fabeebd4c5 fix(class/vendor/net/usbh_asix): fix write cmd param 2024-05-12 20:47:34 +08:00
sakumisu
58550b3ed5 update: rename ecm and asix eth macro name 2024-05-12 20:47:34 +08:00
sakumisu
363533be4c update(class/vendor/net/usbh_rtl8152): update eth rx/tx size 2024-05-12 20:47:34 +08:00
sakumisu
074662a50d fix(class/wireless/usbh_rndis): when last data is dummy byte, ignore it 2024-05-12 20:47:33 +08:00
sakumisu
532e05e293 fix nuttx timeout 2024-05-11 15:59:25 +08:00
sakumisu
b55d40e512 change CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE to 1580 default 2024-05-11 14:01:42 +08:00
Zhihong Chen
263a66ed9b port: HPMicro: update hpm usb deivce port file
- update hpm usb deivce port file

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-05-10 12:27:54 +08:00
sakumisu
775ac135de bugfix by ccef9b92 2024-05-10 11:36:17 +08:00
sakumisu
aecae9434b add kconfig template 2024-05-10 10:12:48 +08:00
sakumisu
5a7042fe15 import aic dcd port 2024-05-10 10:12:42 +08:00
sakumisu
18c4454228 add nuttx osal 2024-05-09 10:45:27 +08:00
sakumisu
cd8b103a71 update rtt config check 2024-05-08 19:28:20 +08:00
sakumisu
8ecbd32483 remove qh with iaad 2024-05-08 17:17:57 +08:00
sakumisu
d0f79ff668 update host demo to support multi class 2024-05-05 13:34:36 +08:00
sakumisu
7272ccfc02 update company support 2024-05-05 12:12:00 +08:00
sakumisu
e081642c76 add pl2303 host driver 2024-05-05 11:38:25 +08:00
sakumisu
b51da4fbf9 remove ununsed code 2024-05-04 20:09:04 +08:00
sakumisu
97c5e37453 add check for rtt config 2024-05-04 15:49:54 +08:00
sakumisu
cdd308f3e8 fix typo 2024-05-04 15:48:45 +08:00
sakumisu
6db4fbba4c add check for hpm 2024-05-04 14:21:13 +08:00
sakumisu
102801e45c add comments for macros 2024-05-03 20:34:13 +08:00
sakumisu
0ceb7ef885 zero copy when enables LWIP_TCPIP_CORE_LOCKING_INPUT 2024-05-03 19:53:22 +08:00
sakumisu
ae5a9d1e57 check if eth rx packet is overflow 2024-05-03 19:19:17 +08:00
sakumisu
7ebcafe158 adjust code order 2024-05-03 18:57:09 +08:00
sakumisu
81cebaf78c add vendor serial into cmake 2024-05-03 18:55:12 +08:00
sakumisu
5fec929b93 support id table for multi vid pid 2024-05-03 18:54:36 +08:00
sakumisu
4bf0e126af move usbh_hubport_release api to core 2024-05-03 18:00:59 +08:00
sakumisu
ccef9b92cc bugfix for 183d49, add CONFIG_USBDEV_EP0_INDATA_NO_COPY 2024-05-03 14:07:26 +08:00
Zhihong Chen
9cb992bed7 add USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT and USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT macros
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-04-30 20:05:57 +08:00
sakumisu
183d49efbd copy data into ep0 buffer at a unified location 2024-04-30 14:21:31 +08:00
sakumisu
8d18a8b6e5 change CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE to 2048 default 2024-04-30 14:10:17 +08:00
sakumisu
5f79fdc865 include ehci port path in cmake 2024-04-30 14:08:13 +08:00
sakumisu
2f5f2b906f add usbd_get_ep_mult api 2024-04-29 14:11:24 +08:00
sakumisu
0556ae199b add config for cdc ncm transfer size 2024-04-29 11:46:31 +08:00
sakumisu
2da4edf76b remove port param in usbd_get_port_speed 2024-04-29 11:35:29 +08:00
sakumisu
45e9a2fde8 add usbd_get_ep_mps api 2024-04-29 11:32:54 +08:00
sakumisu
5b72907f6d simplify code for get device qualifier desc 2024-04-29 11:29:52 +08:00
sakumisu
6abe6befa8 fix rndis msg when mss is larger than rndis rx size 2024-04-28 19:54:53 +08:00
sakumisu
7ee77b42ee check class_driver is null 2024-04-25 21:20:24 +08:00
sakumisu
404225ade4 change INFO to DBG 2024-04-25 21:17:56 +08:00
sakumisu
694b201ff7 move get speed before get device desc 2024-04-25 21:11:55 +08:00
sakumisu
23e2787a43 add user_data param in host class for users 2024-04-24 22:40:55 +08:00
sakumisu
a3302584ce remove dfu exe,use url instead 2024-04-24 22:27:52 +08:00
sakumisu
8625e4409e support speed get in when enables CONFIG_USBDEV_ADVANCE_DESC 2024-04-24 22:10:47 +08:00
sakumisu
190fb36c43 add hid host report api 2024-04-23 22:02:16 +08:00
sakumisu
a24d2bdc07 fix rndis send dummy 2024-04-23 21:30:59 +08:00
sakumisu
ceaf0923c5 fix caculate precision 2024-04-23 16:33:02 +08:00
sakumisu
2cb6c598c1 update missing license 2024-04-23 13:04:41 +08:00
sakumisu
4e6b0d0923 format code 2024-04-23 10:52:45 +08:00
sakumisu
017eb5560d fix missing busid 2024-04-19 13:03:54 +08:00
sakumisu
b97fc903c0 clear urb timeout after take sem, follow 76f58b93 2024-04-19 11:52:04 +08:00
sakumisu
81ddf9bded change ep0 buffer to 512 2024-04-18 22:06:20 +08:00
sakumisu
8995cf9568 move rndis config macros into template 2024-04-18 21:27:34 +08:00
sakumisu
76f58b93fe do not clear timeout in irq,urb init will sometime call irq before take sem 2024-04-18 21:11:36 +08:00
sakumisu
70c7f1ccbd use only one dhcp timer, delete timer when stop 2024-04-17 22:09:48 +08:00
sakumisu
29c72f3455 update msh cmd and scons 2024-04-16 22:18:25 +08:00
sakumisu
51b9640489 add missing license 2024-04-16 22:11:30 +08:00
sakumisu
32f96f4248 remove duplicate h7 config 2024-04-16 21:52:52 +08:00
sakumisu
e3886fe99d format comment 2024-04-16 21:48:11 +08:00
zhaofx4534
d8714d8169 enable bit21(VBUSSIG) in gd chips 2024-04-15 21:36:58 +08:00
sakumisu
9d5479e0c3 list all porting macros into template for use 2024-04-14 19:53:20 +08:00
sakumisu
ed8a3ceca3 add ifndef for test macros 2024-04-14 19:36:34 +08:00
sakumisu
3592794393 import bouffalo dcd 2024-04-14 19:35:48 +08:00
Zhihong Chen
4357a1d7d1 osal: freeRTOS: fix enter/exit critical
- fix enter/exit critical

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-04-13 11:08:53 +08:00
sakumisu
c1cb6e397b move queue files 2024-04-11 10:14:43 +08:00
sakumisu
c8be4d6fd3 change INFO to RAW 2024-04-07 23:31:04 +08:00
sakumisu
725d635c76 add cherryrb and cherry pool 2024-04-07 23:30:51 +08:00
sakumisu
1eef5f3e35 add config index to select multi configs 2024-04-07 16:53:53 +08:00
sakumisu
1dd45e3e5a update rst for ld 2024-04-07 13:26:03 +08:00
sakumisu
8119a500b2 change CONFIG_USB_DWC2_ULPI_PHY to CONFIG_USB_HS, support stm32f723 2024-04-07 13:20:33 +08:00
sakumisu
c5f2ffa6f9 export ehci config macros 2024-04-07 13:17:01 +08:00
sakumisu
db10c62b59 read ehci hcor offset from hccr caplength 2024-04-06 20:19:53 +08:00
sakumisu
808cd454a3 init ohci for ehci 2024-04-04 16:43:05 +08:00
sakumisu
a41c66c2c3 change rt_ssize_t to ssize_t, compatible with older rtt version 2024-04-04 12:56:43 +08:00
sakumisu
6ef086a085 add check for dwc2 fifo with ep mps 2024-04-03 15:44:43 +08:00
sakumisu
5494b0e99a add check for wTotalLength 2024-04-03 11:27:28 +08:00
sakumisu
a6d539792f release v1.2.0 2024-03-29 15:31:29 +08:00
sakumisu
7b5d8f29d4 update hid inout for hs 2024-03-29 15:31:29 +08:00
sakumisu
e7616399b7 add hpm5000 macro 2024-03-29 15:31:29 +08:00
sakumisu
a21947ff22 fix timer start in isr 2024-03-29 08:11:56 +08:00
sakumisu
078e21066c mark errorcode with USB_ERR_SHUTDOWN when kill urb 2024-03-28 21:00:18 +08:00
sakumisu
2335e08ef2 update scons 2024-03-28 20:45:35 +08:00
sakumisu
64f8a86569 update readme 2024-03-28 20:45:26 +08:00
sakumisu
4164e687f0 comment test mode api 2024-03-28 20:42:53 +08:00
sakumisu
4da3550582 fix msc buf overflow because of SCSICMD_INQUIRY_SIZEOF 2024-03-28 20:42:31 +08:00
sakumisu
22121bc54d fix warning in 64bit 2024-03-27 21:23:14 +08:00
sakumisu
68708c0f3a fix aic irq param num and add usbh_init api 2024-03-27 20:43:18 +08:00
sakumisu
5cd50410e6 update readme 2024-03-27 19:35:37 +08:00
sakumisu
74bb03b8b4 remove qtd alloc & free, use static pool instead 2024-03-26 20:41:17 +08:00
sakumisu
bc6ed589b0 update aic glue 2024-03-25 21:01:56 +08:00
sakumisu
f99e4ce113 use only one qh for intr, following with linux driver 2024-03-25 19:53:22 +08:00
sakumisu
d6d1b67761 update rst 2024-03-24 14:46:56 +08:00
sakumisu
3c16d7c61c update ehci glue 2024-03-24 14:24:10 +08:00
Zhihong Chen
0d647cf9c0 rndis: fix MessageLength check
- when MessageLength is MPS, PC rndis host will send (MPS + 1) bytes

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-03-23 22:19:15 +08:00
sakumisu
eef3e116b8 update cmake 2024-03-23 19:54:53 +08:00
sakumisu
bfa4490e6c remove init data 2024-03-23 18:09:08 +08:00
sakumisu
2bfb7255cd reset flag in USBD_EVENT_CONFIGURED 2024-03-23 18:08:54 +08:00
sakumisu
f28b1c61ba update cmake file, submodule change ssh to https 2024-03-22 20:39:07 +08:00
sakumisu
f4a0ba9839 dwc2:get next toggle from HCTSIZ 2024-03-22 19:31:47 +08:00
sakumisu
26e2436847 dwc2:add fifo macros for users to config 2024-03-21 23:07:07 +08:00
sakumisu
6cb442503d add usb_hc_low_level_deinit api 2024-03-21 21:04:10 +08:00
sakumisu
9dbc441082 update esp glue 2024-03-21 20:31:35 +08:00
sakumisu
44c408959b dwc2:add HCCHAR register init api, only enable chan halt irq, buffer dma mode just need this 2024-03-21 19:11:56 +08:00
sakumisu
aa1a30d581 dwc2:add register for desc dma mode 2024-03-20 21:54:43 +08:00
sakumisu
235139ad77 dwc2:simplify chan irq code 2024-03-20 21:53:49 +08:00
sakumisu
b2af686e67 dwc2:change dma incr to 16, flush fifo after fifo config 2024-03-20 21:53:22 +08:00
sakumisu
15b97f3348 ehci:fix missing bus param 2024-03-20 21:52:04 +08:00
Zhihong Chen
9145add9af core: host: add "." to section usbh_class_info for IAR
- add "." to section usbh_class_info for IAR

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-03-18 19:20:30 +08:00
sakumisu
ce241024b1 add rtl8152 host driver 2024-03-18 19:16:12 +08:00
sakumisu
1d38fde61a update url 2024-03-17 22:59:33 +08:00
sakumisu
b628c737ec add esp dwc2 glue 2024-03-17 22:48:35 +08:00
sakumisu
e40c72f3a8 add host cdc speed test 2024-03-15 22:59:53 +08:00
sakumisu
b4c455e5e6 must enable RT_USING_TIMER_SOFT when use timer 2024-03-14 19:37:15 +08:00
sakumisu
2660af5d87 add timer to control interrupt transfer 2024-03-14 19:31:52 +08:00
Zhihong Chen
869b5809f3 core: usbh_core: fix ep0_request_buffer index lose
- fix ep0_request_buffer index lose

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-03-13 19:25:07 +08:00
Zhihong Chen
4c062d4442 port: HPMicro: update usb_dc_hpm.c
- support usbd_execute_test_mode() API
- interrupt should be check dtd active status
- update usbd_ep_open() time sequence
- change irq return to break

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-03-13 19:25:07 +08:00
Zhihong Chen
bba4b46fa4 update usb test mode
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-03-13 19:25:07 +08:00
sakumisu
2e862f3864 set config with configvalue 2024-03-12 22:45:12 +08:00
sakumisu
6369ead152 optimise find class driver api 2024-03-12 22:41:01 +08:00
sakumisu
969c0342f0 fix cdc ncm build 2024-03-12 22:37:43 +08:00
sakumisu
5bd8ea8925 add winusbv2 template 2024-03-12 22:31:54 +08:00
sakumisu
7910666998 fix warning 2024-03-11 20:35:03 +08:00
sakumisu
39693f4702 support cdc ncm host 2024-03-10 19:53:33 +08:00
sakumisu
f489619c20 update svg 2024-03-08 17:30:21 +08:00
sakumisu
215534982a fix bt hci recv when CONFIG_BT_RECV_IS_RX_THREAD is disabled 2024-03-07 20:35:00 +08:00
sakumisu
6af1c143d3 remove unused macro 2024-03-06 21:49:57 +08:00
Zhihong Chen
9e9772fde7 HPMicro: port: fix usbd_ep_close() not reset ep_enable flag
- fix usbd_ep_close() not reset ep_enable flag

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-03-04 22:00:21 +08:00
sakumisu
b545830f70 update rtthread rst 2024-03-03 14:55:55 +08:00
299 changed files with 35085 additions and 11782 deletions

4
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth"]
path = third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth
url = git@github.com:sakumisu/zephyr_bluetooth.git
url = https://github.com/sakumisu/zephyr_bluetooth.git
[submodule "third_party/nimble-1.6.0/nimble"]
path = third_party/nimble-1.6.0/nimble
url = git@github.com:sakumisu/mynewt-nimble.git
url = https://github.com/sakumisu/mynewt-nimble.git

View File

@@ -1,57 +1,150 @@
add_library(cherryusb STATIC)
cmake_minimum_required(VERSION 3.15)
target_include_directories(cherryusb PUBLIC
common
core
osal
class/cdc
class/hid
class/msc
class/audio
class/video
class/hub
class/wireless
if(DEFINED ENV{BL_SDK_BASE})
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
set(CONFIG_CHERRYUSB_DEVICE_MSC 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(DEFINED ENV{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)
endif()
idf_component_register(SRCS ${cherryusb_srcs}
INCLUDE_DIRS ${cherryusb_incs}
PRIV_REQUIRES usb
LDFRAGMENTS ${ldfragments}
)
if(CONFIG_CHERRYUSB_DEVICE)
target_sources(cherryusb PRIVATE core/usbd_core.c)
if(CONFIG_CHERRYUSB_DEVICE_CDC)
target_sources(cherryusb PRIVATE class/cdc/usbd_cdc.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_HID)
target_sources(cherryusb PRIVATE class/hid/usbd_hid.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_MSC)
target_sources(cherryusb PRIVATE class/msc/usbd_msc.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
target_sources(cherryusb PRIVATE class/audio/usbd_audio.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
target_sources(cherryusb PRIVATE class/video/usbd_video.c)
endif()
endif()
if(CONFIG_CHERRYUSB_HOST)
target_sources(cherryusb PRIVATE
core/usbh_core.c
class/hub/usbh_hub.c
class/cdc/usbh_cdc_acm.c
class/hid/usbh_hid.c
class/msc/usbh_msc.c
class/audio/usbh_audio.c
class/video/usbh_video.c
class/wireless/usbh_rndis.c
)
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(DEFINED CONFIG_CHERRYUSB_OSAL)
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
target_sources(cherryusb PRIVATE osal/usb_osal_freertos.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
target_sources(cherryusb PRIVATE osal/usb_osal_rtthread.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
target_sources(cherryusb PRIVATE osal/usb_osal_yoc.c)
endif()
if(CONFIG_CHERRYUSB)
set_source_files_properties("class/audio/usbd_audio.c"
PROPERTIES COMPILE_FLAGS
-Wno-maybe-uninitialized)
endif()
endif()

3
CherryUSB.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 38 KiB

325
Kconfig Normal file
View File

@@ -0,0 +1,325 @@
# Kconfig file for CherryUSB
menuconfig CHERRYUSB
bool "CherryUSB Configuration"
default n
if CHERRYUSB
menuconfig CHERRYUSB_DEVICE
bool "Enable usb device mode"
default n
if CHERRYUSB_DEVICE
choice
prompt "Select usb device speed"
default CHERRYUSB_DEVICE_SPEED_FS
config CHERRYUSB_DEVICE_SPEED_FS
bool "FS"
config CHERRYUSB_DEVICE_SPEED_HS
bool "HS"
config CHERRYUSB_DEVICE_SPEED_AUTO
bool "AUTO"
endchoice
choice
prompt "Select usb device ip, and some ip need config in usb_config.h, please check"
default CHERRYUSB_DEVICE_CUSTOM
config CHERRYUSB_DEVICE_CUSTOM
bool "CUSTOM (Implement it yourself)"
config CHERRYUSB_DEVICE_FSDEV
bool "fsdev"
config CHERRYUSB_DEVICE_DWC2_ST
bool "dwc2_st"
config CHERRYUSB_DEVICE_DWC2_ESP
bool "dwc2_esp"
config CHERRYUSB_DEVICE_DWC2_AT
bool "dwc2_at"
config CHERRYUSB_DEVICE_DWC2_GD
bool "dwc2_gd"
config CHERRYUSB_DEVICE_DWC2_HC
bool "dwc2_hc"
config CHERRYUSB_DEVICE_DWC2_CUSTOM
bool "dwc2_custom"
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_CHIPIDEA_MCX
bool "chipidea_mcx"
config CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
bool "chipidea_mcx"
config CHERRYUSB_DEVICE_BL
bool "bouffalo"
config CHERRYUSB_DEVICE_HPM
bool "hpm"
config CHERRYUSB_DEVICE_AIC
bool "aic"
config CHERRYUSB_DEVICE_CH32
bool "ch32"
config CHERRYUSB_DEVICE_PUSB2
bool "pusb2"
endchoice
config CHERRYUSB_DEVICE_CDC_ACM
bool
prompt "Enable usb cdc acm device"
default n
config CHERRYUSB_DEVICE_HID
bool
prompt "Enable usb hid device"
default n
config CHERRYUSB_DEVICE_MSC
bool
prompt "Enable usb msc device"
default n
config CHERRYUSB_DEVICE_AUDIO
bool
prompt "Enable usb audio device"
default n
config CHERRYUSB_DEVICE_VIDEO
bool
prompt "Enable usb video device"
default n
config CHERRYUSB_DEVICE_CDC_RNDIS
bool
prompt "Enable usb cdc rndis device"
default n
config CHERRYUSB_DEVICE_CDC_ECM
bool
prompt "Enable usb cdc ecm device"
default n
config CHERRYUSB_DEVICE_CDC_NCM
bool
prompt "Enable usb cdc ncm device"
default n
config CHERRYUSB_DEVICE_DFU
bool
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_NONE
config CHERRYUSB_DEVICE_TEMPLATE_NONE
bool "none (Implement it yourself)"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
bool "cdc_acm"
config CHERRYUSB_DEVICE_TEMPLATE_MSC
bool "msc"
config CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
bool "hid_keyboard"
config CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
bool "hid_mouse"
config CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
bool "hid_custom"
config CHERRYUSB_DEVICE_TEMPLATE_VIDEO
bool "video"
config CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
bool "audio_v1_mic_speaker_multichan"
config CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
bool "audio_v2_mic_speaker_multichan"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
bool "cdc_rndis"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
bool "cdc_ecm"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
bool "cdc_ncm"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool "cdc_acm_msc"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
bool "cdc_acm_msc_hid"
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
bool "winusbv1"
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
bool "winusbv2_cdc"
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
bool "winusbv2_hid"
endchoice
endif
menuconfig CHERRYUSB_HOST
bool "Enable usb host mode"
default n
if CHERRYUSB_HOST
choice
prompt "Select usb host ip, and some ip need config in usb_config.h, please check"
default CHERRYUSB_HOST_CUSTOM
config CHERRYUSB_HOST_CUSTOM
bool "CUSTOM (Implement it yourself)"
config CHERRYUSB_HOST_EHCI_BL
bool "ehci_bouffalo"
config CHERRYUSB_HOST_EHCI_HPM
bool "ehci_hpm"
config CHERRYUSB_HOST_EHCI_AIC
bool "ehci_aic"
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_CUSTOM
bool "dwc2_custom"
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_PHYTIUM
bool "xhci_phytium"
config CHERRYUSB_HOST_XHCI_CUSTOM
bool "xhci"
endchoice
config CHERRYUSB_HOST_CDC_ACM
bool
prompt "Enable usb cdc acm driver"
default n
config CHERRYUSB_HOST_HID
bool
prompt "Enable usb hid driver"
default n
config CHERRYUSB_HOST_MSC
bool
prompt "Enable usb msc 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
bool
prompt "Enable usb video driver, it is commercial charge"
default n
config CHERRYUSB_HOST_AUDIO
bool
prompt "Enable usb audio driver, it is commercial charge"
default n
config CHERRYUSB_HOST_BLUETOOTH
bool
prompt "Enable usb bluetooth driver"
default n
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
bool
prompt "Enable usb ftdi driver"
default n
config CHERRYUSB_HOST_CH34X
bool
prompt "Enable usb ch34x driver"
default n
config CHERRYUSB_HOST_CP210X
bool
prompt "Enable usb cp210x driver"
default n
config CHERRYUSB_HOST_PL2303
bool
prompt "Enable usb pl2303 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"
default n
if CHERRYUSB_HOST_TEMPLATE
config TEST_USBH_CDC_ACM
int
prompt "demo for test cdc acm"
default 0
depends on CHERRYUSB_HOST_CDC_ACM
config TEST_USBH_HID
int
prompt "demo for test hid"
default 0
depends on CHERRYUSB_HOST_HID
config TEST_USBH_MSC
int
prompt "demo for test msc"
default 0
depends on CHERRYUSB_HOST_MSC
endif
endif
endif

104
README.md
View File

@@ -4,7 +4,7 @@
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
![CherryUSB](./docs/assets/CherryUSB.svg)
![CherryUSB](CherryUSB.svg)
## Why choose
@@ -17,7 +17,7 @@ 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:
@@ -34,29 +34,16 @@ Taking into account USB performance issues and trying to achieve the theoretical
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
- Subcontracting function 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,14 +65,17 @@ 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_core.c | 3516 | 512(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 |
@@ -99,18 +89,19 @@ 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
- Multi-level HUB support, expandable up to 7 levels
- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2 and ehci now)
- Support Communication Device Class (CDC_ACM, CDC_ECM)
- Support Human Interface Device (HID)
- Support 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)
- 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 multi host with the same USB IP
@@ -120,14 +111,14 @@ 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_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|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_rndis.c | ~3900 | 4096 + 2 * 2048(default)| 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 |
@@ -151,6 +142,24 @@ x is affected by the following macros
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
```
## USB IP Support
Only standard and commercial USB IP are listed.
| IP | device | host | Support status |
|:----------------:|:----------:|:--------:|:--------------:|
| OHCI(intel) | none | OHCI | × |
| EHCI(intel) | none | EHCI | √ |
| XHCI(intel) | none | XHCI | √ |
| 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 | × |
## Documentation Tutorial
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
@@ -168,17 +177,38 @@ 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 |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|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 | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | 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
QQ group: 642693751
CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
## Company Support
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/bekencorp.jpg" width="100" height="100" />

View File

@@ -4,7 +4,7 @@
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
![CherryUSB](./docs/assets/CherryUSB.svg)
![CherryUSB](CherryUSB.svg)
## 为什么选择
@@ -36,26 +36,15 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
## 目录结构
```
.
├── 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,14 +65,17 @@ 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_core.c | 3516 | 512(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 |
@@ -97,18 +89,19 @@ CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了
CherryUSB Host 协议栈当前实现以下功能:
- 支持 low speed, full speed, high speed 和 super speed 设备
- 自动加载支持的Class 驱动
- 支持阻塞式传输和异步传输
- 支持复合设备
- 支持多级 HUB,最高可拓展到 7 级
- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,当前仅支持 dwc2 和 ehci)
- 支持 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
- 支持相同 USB IP 的多主机
@@ -118,14 +111,14 @@ 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_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | raw_config_desc |
|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_rndis.c | ~3900 | 4096 + 2 * 2048(default)| 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 |
@@ -149,13 +142,32 @@ x 受以下宏影响:
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
```
## USB IP 支持情况
仅列举标准 USB IP 和商业性 USB IP
| IP | device | host | Support status |
|:----------------:|:----------:|:--------:|:--------------:|
| OHCI(intel) | none | OHCI | × |
| EHCI(intel) | none | EHCI | √ |
| XHCI(intel) | none | XHCI | √ |
| 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 | × |
## 文档教程
CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和例程,参考 [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
## 视频教程
USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [CherryUSB Device 协议栈教程](https://www.bilibili.com/video/BV1Ef4y1t73d).
- USB 基本知识点与 CherryUSB Device 协议栈是如何编写的使用v0.4.1 版本),参考 https://www.bilibili.com/video/BV1Ef4y1t73d.
- CherryUSB 腾讯会议使用v1.1.0 版本),参考 https://www.bilibili.com/video/BV16x421y7mM.
## 图形化界面配置工具
@@ -166,17 +178,39 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
| 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 |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|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 | chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | 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
## 软件包支持
QQ 群:642693751
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 微信群:与我联系后邀请加入
## 支持企业
感谢以下企业支持(顺序不分先后)。
<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/bekencorp.jpg" width="100" height="100" />

View File

@@ -10,8 +10,13 @@ path += [cwd + '/class/audio']
path += [cwd + '/class/video']
path += [cwd + '/class/wireless']
path += [cwd + '/class/dfu']
path += [cwd + '/class/midi']
path += [cwd + '/class/vendor/net']
path += [cwd + '/class/vendor/serial']
src = []
LIBS = []
LIBPATH = []
CPPDEFINES = []
# USB DEVICE
@@ -23,8 +28,63 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
CPPDEFINES+=['CONFIG_USB_HS']
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC']):
src += Glob('class/cdc/usbd_cdc.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']):
src += Glob('port/fsdev/usb_dc_fsdev.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_ST']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_st.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_ESP']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_esp.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_AT']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
src += Glob('port/dwc2/usb_glue_at.c')
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_CUSTOM']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
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_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']):
src += Glob('port/hpm/usb_dc_hpm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AIC']):
src += Glob('port/aic/usb_dc_aic.c')
src += Glob('port/aic/usb_dc_aic_ll.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
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_acm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
src += Glob('class/hid/usbd_hid.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC']):
@@ -33,112 +93,167 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('class/audio/usbd_audio.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO']):
src += Glob('class/video/usbd_video.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_RNDIS']):
src += Glob('class/wireless/usbd_rndis.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ECM']):
src += Glob('class/cdc/usbd_cdc_ecm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_NCM']):
src += Glob('class/cdc/usbd_cdc_ncm.c')
if GetDepend(['PKG_CHERRYUSB_USING_DFU']):
src += Glob('class/dfu/usbd_dfu.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_TEMPLATE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
src += Glob('demo/cdc_acm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_MOUSE_TEMPLATE']):
src += Glob('demo/hid_mouse_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_KEYBOARD_TEMPLATE']):
src += Glob('demo/hid_keyboard_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC']):
src += Glob('demo/msc_ram_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_STORAGE_TEMPLATE']):
src += Glob('demo/msc_storage_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO_TEMPLATE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']):
src += Glob('demo/hid_mouse_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']):
src += Glob('demo/hid_keyboard_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM']):
src += Glob('demo/hid_custom_inout_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_VIDEO']):
src += Glob('demo/video_static_mjpeg_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS_TEMPLATE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER']):
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER']):
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS']):
src += Glob('demo/cdc_rndis_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']):
src += Glob('port/fsdev/usb_dc_fsdev.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_STM32']):
src += Glob('port/dwc2/usb_glue_st.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
src += Glob('port/musb/usb_dc_musb.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
src += Glob('port/hpm/usb_dc_hpm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32_CH32V307']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
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/pusb2/common']
path += [cwd + '/port/pusb2/fpusb2']
src += Glob('port/pusb2/fpusb2' + '/*.c')
src += Glob('port/pusb2/usb_dc_pusb2.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM']):
src += Glob('demo/cdc_ecm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']):
src += Glob('demo/cdc_ncm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']):
src += Glob('demo/cdc_acm_msc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']):
src += Glob('demo/cdc_acm_hid_msc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1']):
src += Glob('demo/winusb1.0_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC']):
src += Glob('demo/winusb2.0_cdc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID']):
src += Glob('demo/winusb2.0_hid_template.c')
# USB HOST
if GetDepend(['PKG_CHERRYUSB_HOST']):
path += [cwd + '/osal']
path += [cwd + '/class/hub']
src += Glob('core/usbh_core.c')
src += Glob('class/hub/usbh_hub.c')
src += Glob('osal/usb_osal_rtthread.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CDC']):
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_BL']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_bouffalo.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_hpm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_AIC']):
path += [cwd + '/port/ehci']
path += [cwd + '/port/ohci']
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_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_MA35D0']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_ma35d0.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_CUSTOM']):
src += Glob('port/ehci/usb_hc_ehci.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ST']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
src += Glob('port/dwc2/usb_glue_st.c')
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_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_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')
if GetDepend(['PKG_CHERRYUSB_HOST_HID']):
src += Glob('class/hid/usbh_hid.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
src += Glob('class/msc/usbh_msc.c')
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_RNDIS']):
src += Glob('class/wireless/usbh_rndis.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
src += Glob('class/cdc/usbh_cdc_ecm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_NCM']):
src += Glob('class/cdc/usbh_cdc_ncm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_VIDEO']):
src += Glob('class/video/usbh_video.c')
if GetDepend(['PKG_CHERRYUSB_HOST_AUDIO']):
src += Glob('class/audio/usbh_audio.c')
if GetDepend(['PKG_CHERRYUSB_HOST_BLUETOOTH']):
src += Glob('class/wireless/usbh_bluetooth.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_STM32']):
src += Glob('port/dwc2/usb_glue_st.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']):
src += Glob('port/musb/usb_hc_musb.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI']):
src += Glob('port/ehci/usb_hc_ehci.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
src += Glob('port/ehci/usb_glue_hpm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
src += Glob('port/xhci/usb_hc_xhci.c')
src += Glob('port/xhci/xhci_dbg.c')
src += Glob('port/xhci/xhci.c')
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
path += [cwd + '/port/pusb2/common']
path += [cwd + '/port/pusb2/fpusb2']
src += Glob('port/pusb2/fpusb2' + '/*.c')
src += Glob('port/pusb2/usb_hc_pusb2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_ASIX']):
src += Glob('class/vendor/net/usbh_asix.c')
if GetDepend(['PKG_CHERRYUSB_HOST_RTL8152']):
src += Glob('class/vendor/net/usbh_rtl8152.c')
if GetDepend(['PKG_CHERRYUSB_HOST_FTDI']):
src += Glob('class/vendor/serial/usbh_ftdi.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CH34X']):
src += Glob('class/vendor/serial/usbh_ch34x.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CP210X']):
src += Glob('class/vendor/serial/usbh_cp210x.c')
if GetDepend(['PKG_CHERRYUSB_HOST_PL2303']):
src += Glob('class/vendor/serial/usbh_pl2303.c')
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')
src += Glob('third_party/rt-thread-5.0/msh_cmd.c')
if GetDepend('RT_USING_DFS') and GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
src += Glob('platform/rtthread/usbh_dfs.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')
src += Glob('platform/rtthread/usb_msh.c')
src += Glob('platform/rtthread/usb_check.c')
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)

View File

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

292
cherryusb.cmake Normal file
View File

@@ -0,0 +1,292 @@
#
# Copyright (c) 2024, sakumisu
#
# SPDX-License-Identifier: Apache-2.0
#
# set(CONFIG_CHERRYUSB_DEVICE 1)
# set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
# set(CONFIG_CHERRYUSB_DEVICE_HID 1)
# set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
# set(CONFIG_CHERRYUSB_DEVICE_DCD "dwc2_st")
# 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_OSAL "freertos")
# set(CONFIG_CHERRYUSB_HOST_HCD "ehci_xxx")
list(APPEND cherryusb_incs
${CMAKE_CURRENT_LIST_DIR}/common
${CMAKE_CURRENT_LIST_DIR}/core
${CMAKE_CURRENT_LIST_DIR}/class/hub
${CMAKE_CURRENT_LIST_DIR}/class/cdc
${CMAKE_CURRENT_LIST_DIR}/class/hid
${CMAKE_CURRENT_LIST_DIR}/class/msc
${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
)
if(CONFIG_CHERRYUSB_DEVICE)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.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)
endif()
if(CONFIG_CHERRYUSB_DEVICE_MSC)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/msc/usbd_msc.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbd_audio.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbd_video.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_CDC_ECM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_ecm.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_CDC_NCM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_ncm.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_CDC_RNDIS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbd_rndis.c)
endif()
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 "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_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 "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 "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 "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()
endif()
if(CONFIG_CHERRYUSB_HOST)
list(APPEND cherryusb_srcs
${CMAKE_CURRENT_LIST_DIR}/core/usbh_core.c
${CMAKE_CURRENT_LIST_DIR}/class/hub/usbh_hub.c
)
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_acm.c)
endif()
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()
if(CONFIG_CHERRYUSB_HOST_HID)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbh_hid.c)
endif()
if(CONFIG_CHERRYUSB_HOST_MSC)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/msc/usbh_msc.c)
if(CONFIG_CHERRYUSB_HOST_MSC_FATFS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/port/fatfs_usbh.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/diskio.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ff.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ffsystem.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ffunicode.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source)
endif()
endif()
if(CONFIG_CHERRYUSB_HOST_VIDEO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbh_video.c)
endif()
if(CONFIG_CHERRYUSB_HOST_AUDIO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
endif()
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
set(BLUETOOTH_PATH ${CMAKE_CURRENT_LIST_DIR}/third_party/zephyr_bluetooth-2.7.5)
list(APPEND cherryusb_srcs
${BLUETOOTH_PATH}/ble_hci_usbh.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/beacon/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_hr/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_ht/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_multilink/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_multilink/src/central_multilink.c
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/handsfree/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/ibeacon/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral/src/cts.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_csc/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_dis/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_esp/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hids/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hids/src/hog.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hr/src/main.c
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ht/src/main.c
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ht/src/hts.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_identity/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_identity/src/peripheral_identity.c
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ots/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_sc_only/src/main.c
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/scan_adv/src/main.c
)
include(${BLUETOOTH_PATH}/zephyr_bluetooth/zephyr_bluetooth.cmake)
list(APPEND cherryusb_srcs ${zephyr_bluetooth_srcs})
list(APPEND cherryusb_incs ${zephyr_bluetooth_incs})
endif()
if(CONFIG_CHERRYUSB_HOST_ASIX)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net/usbh_asix.c)
endif()
if(CONFIG_CHERRYUSB_HOST_RTL8152)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net/usbh_rtl8152.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CH34X)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_ch34x.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CP210X)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_cp210x.c)
endif()
if(CONFIG_CHERRYUSB_HOST_FTDI)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_ftdi.c)
endif()
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(DEFINED CONFIG_CHERRYUSB_HOST_HCD)
if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo")
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_bouffalo.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_hpm")
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_hpm.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_aic")
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_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)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_nuvoton.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "dwc2_st")
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_st.c)
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 "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)
endif()
endif()
endif()
if(DEFINED CONFIG_CHERRYUSB_OSAL)
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_freertos.c)
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
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_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/usbh_uvc_queue.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
endif()

View File

@@ -6,16 +6,10 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x010100
#define CHERRYUSB_VERSION_STR "v1.1.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
@@ -33,14 +27,19 @@
/* ================= USB Device Stack Configuration ================ */
#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
/* Ep0 in and out transfer buffer */
#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
#endif
/* Setup packet log for debug */
// #define CONFIG_USBDEV_SETUP_LOG_PRINT
/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
* Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
*/
// #define CONFIG_USBDEV_EP0_INDATA_NO_COPY
/* Check if the input descriptor is correct */
// #define CONFIG_USBDEV_DESC_CHECK
@@ -67,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
@@ -81,8 +84,9 @@
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
/* rndis transfer buffer size, must be a multiple of (1536 + 44)*/
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
#endif
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
@@ -97,7 +101,6 @@
/* ================ USB HOST Stack Configuration ================== */
#define CONFIG_USBHOST_MAX_BUS 1
#define CONFIG_USBHOST_MAX_RHPORTS 1
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
@@ -123,10 +126,14 @@
//#define CONFIG_USBHOST_GET_STRING_DESC
// #define CONFIG_USBHOST_MSOS_ENABLE
#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
#endif
/* Ep0 max transfer buffer */
#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
#endif
#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
@@ -136,6 +143,51 @@
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
#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_RNDIS_ETH_MAX_RX_SIZE
#define CONFIG_USBHOST_RNDIS_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_RNDIS_ETH_MAX_TX_SIZE
#define CONFIG_USBHOST_RNDIS_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_CDC_NCM_ETH_MAX_RX_SIZE
#define CONFIG_USBHOST_CDC_NCM_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_CDC_NCM_ETH_MAX_TX_SIZE
#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.
*/
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE
#define CONFIG_USBHOST_RTL8152_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_RTL8152_ETH_MAX_TX_SIZE
#define CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE (2048)
#endif
#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
@@ -148,23 +200,75 @@
/* ================ USB Device Port Configuration ================*/
#ifndef CONFIG_USBDEV_MAX_BUS
#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
#endif
#ifndef CONFIG_USBDEV_EP_NUM
#define CONFIG_USBDEV_EP_NUM 8
#endif
/* ---------------- 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_TX2_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX5_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI
/* ================ USB Host Port Configuration ==================*/
#ifndef CONFIG_USBHOST_MAX_BUS
#define CONFIG_USBHOST_MAX_BUS 1
#endif
// #define CONFIG_USBHOST_PIPE_NUM 10
#ifndef CONFIG_USBHOST_PIPE_NUM
#define CONFIG_USBHOST_PIPE_NUM 10
#endif
/* ================ EHCI Configuration ================ */
/* ---------------- EHCI Configuration ---------------- */
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x0)
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x10)
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
// #define CONFIG_USB_EHCI_INFO_ENABLE
#define CONFIG_USB_EHCI_QH_NUM CONFIG_USBHOST_PIPE_NUM
#define CONFIG_USB_EHCI_QTD_NUM 3
#define CONFIG_USB_EHCI_ITD_NUM 20
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_CONFIGFLAG
// #define CONFIG_USB_EHCI_PORT_POWER
// #define CONFIG_USB_EHCI_PRINT_HW_PARAM
// #define CONFIG_USB_EHCI_ISO
// #define CONFIG_USB_EHCI_WITH_OHCI
/* ---------------- OHCI Configuration ---------------- */
#define CONFIG_USB_OHCI_HCOR_OFFSET (0x0)
/* ---------------- XHCI Configuration ---------------- */
#define CONFIG_USB_XHCI_HCCR_OFFSET (0x0)
/* ---------------- DWC2 Configuration ---------------- */
/* largest non-periodic USB packet used / 4 */
// #define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
/* largest periodic USB packet used / 4 */
// #define CONFIG_USB_DWC2_PTX_FIFO_SIZE (1024 / 4)
/*
* (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)
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI
#endif

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 */

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;
@@ -287,7 +287,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,
@@ -314,31 +314,56 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
{
(void)busid;
(void)ep;
(void)ch;
(void)volume;
}
__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

@@ -57,7 +57,7 @@ static void usbh_audio_class_free(struct usbh_audio *audio_class)
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
{
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,6 +65,11 @@ 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;
}
@@ -129,12 +134,17 @@ freq_found:
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;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
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;
@@ -172,12 +182,17 @@ 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)
{
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;
uint16_t volume_hex;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
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;
@@ -205,11 +220,16 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
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;
if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL;
}
setup = audio_class->hport->setup;
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;
@@ -236,27 +256,27 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
void usbh_audio_list_module(struct usbh_audio *audio_class)
{
USB_LOG_INFO("============= Audio module information ===================\r\n");
USB_LOG_INFO("bcdADC :%04x\r\n", audio_class->bcdADC);
USB_LOG_INFO("Num of modules :%u\r\n", audio_class->module_num);
USB_LOG_INFO("Num of altsettings:%u\r\n", audio_class->num_of_intf_altsettings);
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);
for (uint8_t i = 0; i < audio_class->module_num; i++) {
USB_LOG_INFO(" module name :%s\r\n", audio_class->module[i].name);
USB_LOG_INFO(" module feature unit id :%d\r\n", audio_class->module[i].feature_unit_id);
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 j = 0; j < audio_class->num_of_intf_altsettings; j++) {
if (j == 0) {
USB_LOG_INFO(" Ingore altsetting 0\r\n");
USB_LOG_RAW(" Ingore altsetting 0\r\n");
continue;
}
USB_LOG_INFO(" Altsetting %u\r\n", j);
USB_LOG_INFO(" module channels :%u\r\n", audio_class->module[i].altsetting[j].channels);
//USB_LOG_INFO(" module format_type :%u\r\n",audio_class->module[i].altsetting[j].format_type);
USB_LOG_INFO(" module bitresolution :%u\r\n", audio_class->module[i].altsetting[j].bitresolution);
USB_LOG_INFO(" module sampfreq num :%u\r\n", audio_class->module[i].altsetting[j].sampfreq_num);
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);
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
USB_LOG_INFO(" module sampfreq :%d hz\r\n", audio_class->module[i].altsetting[j].sampfreq[k]);
USB_LOG_RAW(" module sampfreq :%d hz\r\n", audio_class->module[i].altsetting[j].sampfreq[k]);
}
}
}
@@ -367,9 +387,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
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);
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq[j] = (uint32_t)(p[10 + j * 3] << 16) |
(uint32_t)(p[9 + j * 3] << 8) |
(uint32_t)(p[8 + j * 3] << 0);
}
if (cur_alt_setting == (hport->config.intf[intf + 1].altsetting_num - 1)) {
format_offset++;
@@ -436,20 +456,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 = {
@@ -469,8 +495,7 @@ CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = {
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOCONTROL,
.protocol = 0x00,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &audio_ctrl_class_driver
};
@@ -479,7 +504,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info =
.class = USB_DEVICE_CLASS_AUDIO,
.subclass = AUDIO_SUBCLASS_AUDIOSTREAMING,
.protocol = 0x00,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &audio_streaming_class_driver
};

View File

@@ -53,6 +53,8 @@ struct usbh_audio {
uint8_t num_of_intf_altsettings;
struct usbh_audio_module module[2];
uint8_t module_num;
void *user_data;
};
#ifdef __cplusplus

View File

@@ -117,6 +117,7 @@
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
#define CDC_FUNC_DESC_NCM 0x1A
/* CDC class-specific request codes */
/* (usbcdc11.pdf, 6.2, Table 46) */
@@ -156,6 +157,17 @@
#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
#define CDC_REQUEST_GET_NTB_PARAMETERS 0x80
#define CDC_REQUEST_GET_NET_ADDRESS 0x81
#define CDC_REQUEST_SET_NET_ADDRESS 0x82
#define CDC_REQUEST_GET_NTB_FORMAT 0x83
#define CDC_REQUEST_SET_NTB_FORMAT 0x84
#define CDC_REQUEST_GET_NTB_INPUT_SIZE 0x85
#define CDC_REQUEST_SET_NTB_INPUT_SIZE 0x86
#define CDC_REQUEST_GET_MAX_DATAGRAM_SIZE 0x87
#define CDC_REQUEST_SET_MAX_DATAGRAM_SIZE 0x88
#define CDC_REQUEST_GET_CRC_MODE 0x89
#define CDC_REQUEST_SET_CRC_MODE 0x90
/* Communication feature selector codes */
/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
@@ -263,6 +275,10 @@
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
#define CDC_NCM_NTH16_SIGNATURE 0x484D434E
#define CDC_NCM_NDP16_SIGNATURE_NCM0 0x304D434E
#define CDC_NCM_NDP16_SIGNATURE_NCM1 0x314D434E
/*------------------------------------------------------------------------------
* Structures based on usbcdc11.pdf (www.usb.org)
*----------------------------------------------------------------------------*/
@@ -339,7 +355,7 @@ struct cdc_acm_notification {
} __PACKED;
/** Ethernet Networking Functional Descriptor */
struct cdc_ecm_descriptor {
struct cdc_eth_descriptor {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
@@ -350,7 +366,7 @@ struct cdc_ecm_descriptor {
uint8_t bNumberPowerFilters;
} __PACKED;
struct cdc_ecm_notification {
struct cdc_eth_notification {
uint8_t bmRequestType;
uint8_t bNotificationType;
uint16_t wValue;
@@ -359,6 +375,41 @@ struct cdc_ecm_notification {
uint8_t data[8];
} __PACKED;
struct cdc_ncm_ntb_parameters {
uint16_t wLength;
uint16_t bmNtbFormatsSupported;
uint32_t dwNtbInMaxSize;
uint16_t wNdbInDivisor;
uint16_t wNdbInPayloadRemainder;
uint16_t wNdbInAlignment;
uint16_t wReserved;
uint32_t dwNtbOutMaxSize;
uint16_t wNdbOutDivisor;
uint16_t wNdbOutPayloadRemainder;
uint16_t wNdbOutAlignment;
uint16_t wNtbOutMaxDatagrams;
};
struct cdc_ncm_nth16 {
uint32_t dwSignature;
uint16_t wHeaderLength;
uint16_t wSequence;
uint16_t wBlockLength;
uint16_t wNdpIndex;
};
struct cdc_ncm_ndp16_datagram {
uint16_t wDatagramIndex;
uint16_t wDatagramLength;
};
struct cdc_ncm_ndp16 {
uint32_t dwSignature;
uint16_t wLength;
uint16_t wNextNdpIndex;
struct cdc_ncm_ndp16_datagram datagram[];
};
/*Length of template descriptor: 66 bytes*/
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
@@ -499,7 +550,7 @@ struct cdc_ecm_notification {
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
/*Length of template descriptor: 66 bytes*/
/*Length of template descriptor: 71 bytes*/
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
@@ -537,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 */ \
@@ -569,4 +620,79 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx)
0x00 /* bInterval */
// clang-format on
/*Length of template descriptor: 77 bytes*/
#define CDC_NCM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 6 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_NCM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
CDC_NETWORK_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_NETWORK_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
WBVAL(CDC_V1_10), /* bcdCDC */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
/* CDC ETH Functional Descriptor */ \
0x0D, /* bFunctionLength */\
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
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(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
0x06, \
CDC_CS_INTERFACE, \
CDC_FUNC_DESC_NCM, \
0x00, 0x01, \
0x23, \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
0x00, /* bInterfaceSubClass */ \
0x00, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
// clang-format on
#endif /* USB_CDC_H */

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

@@ -13,12 +13,6 @@
/* Describe EndPoints configuration */
static struct usbd_endpoint cdc_ecm_ep_data[3];
#ifdef CONFIG_USB_HS
#define CDC_ECM_MAX_PACKET_SIZE 512
#else
#define CDC_ECM_MAX_PACKET_SIZE 64
#endif
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];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
@@ -35,7 +29,7 @@ static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
{
struct cdc_ecm_notification *notify = (struct cdc_ecm_notification *)g_cdc_ecm_notify_buf;
struct cdc_eth_notification *notify = (struct cdc_eth_notification *)g_cdc_ecm_notify_buf;
uint8_t bytes2send = 0;
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
@@ -85,11 +79,15 @@ 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) {
case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
/* bit0 Promiscuous
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
@@ -111,6 +109,9 @@ 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;
@@ -119,7 +120,7 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
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], CDC_ECM_MAX_PACKET_SIZE);
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));
break;
default:
@@ -129,19 +130,23 @@ 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)
{
(void)busid;
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
if (nbytes < usbd_get_ep_mps(0, 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], CDC_ECM_MAX_PACKET_SIZE);
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep));
}
}
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 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 {
@@ -151,6 +156,10 @@ void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
(void)busid;
(void)ep;
(void)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);
@@ -173,7 +182,7 @@ void usbd_cdc_ecm_start_read_next(void)
{
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, CDC_ECM_MAX_PACKET_SIZE);
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(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
@@ -189,7 +198,7 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void)
usbd_cdc_ecm_start_read_next();
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);
@@ -212,13 +221,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
@@ -250,4 +257,6 @@ void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
}
(void)buf;
(void)len;
}

View File

@@ -12,7 +12,7 @@
#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;
@@ -44,7 +44,12 @@ static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
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 = {
@@ -249,8 +270,7 @@ CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &cdc_acm_class_driver
};
@@ -259,7 +279,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
.class = USB_DEVICE_CLASS_CDC_DATA,
.subclass = 0x00,
.protocol = 0x00,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &cdc_data_class_driver
};

View File

@@ -25,6 +25,8 @@ struct usbh_cdc_acm {
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -21,18 +21,23 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE 1514U
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE 1514U
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
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;
@@ -95,7 +100,7 @@ static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
break;
case CDC_CS_INTERFACE:
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
struct cdc_ecm_descriptor *desc = (struct cdc_ecm_descriptor *)p;
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
mac_str_idx = desc->iMACAddress;
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
goto get_mac;
@@ -139,8 +144,8 @@ get_mac:
cdc_ecm_class->mac[4],
cdc_ecm_class->mac[5]);
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE) {
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE, cdc_ecm_class->max_segment_size);
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE) {
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, cdc_ecm_class->max_segment_size);
} else {
USB_LOG_INFO("CDC ECM Max Segment Size:%u\r\n", cdc_ecm_class->max_segment_size);
}
@@ -176,7 +181,7 @@ get_mac:
}
}
/* bit0 Promiscuous
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
@@ -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,10 +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;
struct netif *netif = (struct netif *)argument;
(void)argument;
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
// clang-format off
find_class:
@@ -249,36 +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], USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize), 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_class.bulkin_urb.actual_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, PBUF_POOL);
if (p != NULL) {
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
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 */
/* There's no way to run here. */
}
}
// clang-format off
@@ -288,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 = {
@@ -333,7 +326,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &cdc_ecm_class_driver
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -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 */
@@ -23,15 +20,13 @@ struct usbh_cdc_ecm {
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
uint8_t mac[6];
bool connect_status;
uint16_t max_segment_size;
uint32_t speed[2];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
#ifdef __cplusplus
@@ -43,11 +38,13 @@ 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
}
#endif
#endif /* USBH_CDC_ACM_H */
#endif /* USBH_CDC_ECM_H */

411
class/cdc/usbh_cdc_ncm.c Normal file
View File

@@ -0,0 +1,411 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_ncm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_ncm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/cdc_ncm"
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
/* interface descriptor field offsets */
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE 1514U
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_rx_buffer[CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_tx_buffer[CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_inttx_buffer[16];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_buf[32];
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;
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;
setup->wIndex = cdc_ncm_class->ctrl_intf;
setup->wLength = 28;
ret = usbh_control_transfer(cdc_ncm_class->hport, setup, g_cdc_ncm_buf);
if (ret < 0) {
return ret;
}
memcpy((uint8_t *)param, g_cdc_ncm_buf, ret - 8);
return 0;
}
static void print_ntb_parameters(struct cdc_ncm_ntb_parameters *param)
{
USB_LOG_RAW("CDC NCM ntb parameters:\r\n");
USB_LOG_RAW("wLength: 0x%02x \r\n", param->wLength);
USB_LOG_RAW("bmNtbFormatsSupported: %s \r\n", param->bmNtbFormatsSupported ? "NTB16" : "NTB32");
USB_LOG_RAW("dwNtbInMaxSize: 0x%04x \r\n", param->dwNtbInMaxSize);
USB_LOG_RAW("wNdbInDivisor: 0x%02x \r\n", param->wNdbInDivisor);
USB_LOG_RAW("wNdbInPayloadRemainder: 0x%02x \r\n", param->wNdbInPayloadRemainder);
USB_LOG_RAW("wNdbInAlignment: 0x%02x \r\n", param->wNdbInAlignment);
USB_LOG_RAW("dwNtbOutMaxSize: 0x%04x \r\n", param->dwNtbOutMaxSize);
USB_LOG_RAW("wNdbOutDivisor: 0x%02x \r\n", param->wNdbOutDivisor);
USB_LOG_RAW("wNdbOutPayloadRemainder: 0x%02x \r\n", param->wNdbOutPayloadRemainder);
USB_LOG_RAW("wNdbOutAlignment: 0x%02x \r\n", param->wNdbOutAlignment);
USB_LOG_RAW("wNtbOutMaxDatagrams: 0x%02x \r\n", param->wNtbOutMaxDatagrams);
}
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class)
{
int ret;
usbh_int_urb_fill(&cdc_ncm_class->intin_urb, cdc_ncm_class->hport, cdc_ncm_class->intin, g_cdc_ncm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&cdc_ncm_class->intin_urb);
if (ret < 0) {
return ret;
}
if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
if (g_cdc_ncm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
cdc_ncm_class->connect_status = true;
} else {
cdc_ncm_class->connect_status = false;
}
} else if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
memcpy(cdc_ncm_class->speed, &g_cdc_ncm_inttx_buffer[8], 8);
}
return 0;
}
static int usbh_cdc_ncm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint8_t altsetting = 0;
char mac_buffer[12];
uint8_t *p;
uint8_t cur_iface = 0xff;
uint8_t mac_str_idx = 0xff;
struct usbh_cdc_ncm *cdc_ncm_class = &g_cdc_ncm_class;
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
cdc_ncm_class->hport = hport;
cdc_ncm_class->ctrl_intf = intf;
cdc_ncm_class->data_intf = intf + 1;
hport->config.intf[intf].priv = cdc_ncm_class;
hport->config.intf[intf + 1].priv = NULL;
p = hport->raw_config_desc;
while (p[DESC_bLength]) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
cur_iface = p[INTF_DESC_bInterfaceNumber];
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
break;
case CDC_CS_INTERFACE:
if ((cur_iface == cdc_ncm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
mac_str_idx = desc->iMACAddress;
cdc_ncm_class->max_segment_size = desc->wMaxSegmentSize;
goto get_mac;
}
break;
default:
break;
}
/* skip to next descriptor */
p += p[DESC_bLength];
}
get_mac:
if (mac_str_idx == 0xff) {
USB_LOG_ERR("Do not find cdc ncm mac string\r\n");
return -1;
}
memset(mac_buffer, 0, 12);
ret = usbh_get_string_desc(cdc_ncm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
if (ret < 0) {
return ret;
}
for (int i = 0, j = 0; i < 12; i += 2, j++) {
char byte_str[3];
byte_str[0] = mac_buffer[i];
byte_str[1] = mac_buffer[i + 1];
byte_str[2] = '\0';
uint32_t byte = strtoul(byte_str, NULL, 16);
cdc_ncm_class->mac[j] = (unsigned char)byte;
}
USB_LOG_INFO("CDC NCM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
cdc_ncm_class->mac[0],
cdc_ncm_class->mac[1],
cdc_ncm_class->mac[2],
cdc_ncm_class->mac[3],
cdc_ncm_class->mac[4],
cdc_ncm_class->mac[5]);
if (cdc_ncm_class->max_segment_size > CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE) {
USB_LOG_ERR("CDC NCM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE, cdc_ncm_class->max_segment_size);
} else {
USB_LOG_INFO("CDC NCM Max Segment Size:%u\r\n", cdc_ncm_class->max_segment_size);
}
usbh_cdc_ncm_get_ntb_parameters(cdc_ncm_class, &cdc_ncm_class->ntb_param);
print_ntb_parameters(&cdc_ncm_class->ntb_param);
/* enable int ep */
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
USBH_EP_INIT(cdc_ncm_class->intin, ep_desc);
if (hport->config.intf[intf + 1].altsetting_num > 1) {
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
}
}
USB_LOG_INFO("Select cdc ncm altsetting: %d\r\n", altsetting);
usbh_set_interface(cdc_ncm_class->hport, cdc_ncm_class->data_intf, altsetting);
} else {
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
}
}
}
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);
usbh_cdc_ncm_run(cdc_ncm_class);
return ret;
}
static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)hport->config.intf[intf].priv;
if (cdc_ncm_class) {
if (cdc_ncm_class->bulkin) {
usbh_kill_urb(&cdc_ncm_class->bulkin_urb);
}
if (cdc_ncm_class->bulkout) {
usbh_kill_urb(&cdc_ncm_class->bulkout_urb);
}
if (cdc_ncm_class->intin) {
usbh_kill_urb(&cdc_ncm_class->intin_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ncm_stop(cdc_ncm_class);
}
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
}
return ret;
}
void usbh_cdc_ncm_rx_thread(void *argument)
{
uint32_t g_cdc_ncm_rx_length;
int ret;
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE;
#else
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
// clang-format off
find_class:
// clang-format on
g_cdc_ncm_class.connect_status = false;
if (usbh_find_class_instance("/dev/cdc_ncm") == NULL) {
goto delete;
}
while (g_cdc_ncm_class.connect_status == false) {
ret = usbh_cdc_ncm_get_connect_status(&g_cdc_ncm_class);
if (ret < 0) {
usb_osal_msleep(100);
goto 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], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_cdc_ncm_rx_length += g_cdc_ncm_class.bulkin_urb.actual_length;
/* 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];
if ((nth16->dwSignature != CDC_NCM_NTH16_SIGNATURE) ||
(nth16->wHeaderLength != 12) ||
(nth16->wBlockLength != g_cdc_ncm_rx_length)) {
USB_LOG_ERR("invalid rx nth16\r\n");
g_cdc_ncm_rx_length = 0;
continue;
}
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex];
if ((ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM0) && (ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM1)) {
USB_LOG_ERR("invalid rx ndp16\r\n");
g_cdc_ncm_rx_length = 0;
continue;
}
uint16_t datagram_num = (ndp16->wLength - 8) / 4;
USB_LOG_DBG("datagram num:%02x\r\n", datagram_num);
for (uint16_t i = 0; i < datagram_num; i++) {
struct cdc_ncm_ndp16_datagram *ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex + 8 + 4 * i];
if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
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 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) {
}
}
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete cdc ncm rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
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)
{
struct cdc_ncm_ndp16_datagram *ndp16_datagram;
if (g_cdc_ncm_class.connect_status == false) {
return -USB_ERR_NOTCONN;
}
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_tx_buffer[0];
nth16->dwSignature = CDC_NCM_NTH16_SIGNATURE;
nth16->wHeaderLength = 12;
nth16->wSequence = g_cdc_ncm_class.bulkout_sequence++;
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];
ndp16->dwSignature = CDC_NCM_NDP16_SIGNATURE_NCM0;
ndp16->wLength = 16;
ndp16->wNextNdpIndex = 0;
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 0];
ndp16_datagram->wDatagramIndex = 16;
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;
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);
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 = {
.driver_name = "cdc_ncm",
.connect = usbh_cdc_ncm_connect,
.disconnect = usbh_cdc_ncm_disconnect
};
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,
.id_table = NULL,
.class_driver = &cdc_ncm_class_driver
};

54
class/cdc/usbh_cdc_ncm.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_NCM_H
#define USBH_CDC_NCM_H
#include "usb_cdc.h"
struct usbh_cdc_ncm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
struct cdc_ncm_ntb_parameters ntb_param;
uint16_t bulkin_sequence;
uint16_t bulkout_sequence;
uint8_t mac[6];
bool connect_status;
uint16_t max_segment_size;
uint32_t speed[2];
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
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);
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
}
#endif
#endif /* USBH_CDC_NCM_H */

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,7 +12,15 @@
#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(256, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
static uint32_t g_devinuse = 0;
@@ -44,26 +52,36 @@ static void usbh_hid_class_free(struct usbh_hid *hid_class)
static int usbh_hid_get_report_descriptor(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_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 = hid_class->report_size;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hid_buf, ret - 8);
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
return ret;
}
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 +94,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);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
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;
@@ -106,10 +134,55 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
return usbh_control_transfer(hid_class->hport, setup, NULL);
}
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;
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;
setup->wValue = (uint16_t)(((uint32_t)report_type << 8U) | (uint32_t)report_id);
setup->wIndex = 0;
setup->wLength = buflen;
return usbh_control_transfer(hid_class->hport, setup, buffer);
}
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;
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;
setup->wValue = (uint16_t)(((uint32_t)report_type << 8U) | (uint32_t)report_id);
setup->wIndex = 0;
setup->wLength = buflen;
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
if (ret < 0) {
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) {
@@ -122,6 +195,47 @@ 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;
if (hid_class->report_size > sizeof(g_hid_buf[hid_class->minor])) {
USB_LOG_ERR("HID report descriptor too large\r\n");
return -USB_ERR_INVAL;
}
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) {
@@ -183,10 +297,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 = {
@@ -200,7 +316,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
.class = USB_DEVICE_CLASS_HID,
.subclass = 0x00,
.protocol = 0x00,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &hid_class_driver
};

View File

@@ -15,9 +15,14 @@ struct usbh_hid {
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb intout_urb; /* INTR OUT urb */
uint8_t report_desc[128];
uint8_t report_desc[256];
uint16_t report_size;
uint8_t protocol;
uint8_t intf; /* interface number */
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus
@@ -26,6 +31,8 @@ extern "C" {
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);
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
void usbh_hid_run(struct usbh_hid *hid_class);
void usbh_hid_stop(struct usbh_hid *hid_class);

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

@@ -22,18 +22,11 @@
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][USB_ALIGN_UP(1, CONFIG_USB_ALIGN_SIZE)];
extern int usbh_free_devaddr(struct usbh_hubport *hport);
extern int usbh_enumerate(struct usbh_hubport *hport);
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;
@@ -62,9 +55,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
}
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;
@@ -91,11 +74,11 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
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->wIndex = 0;
setup->wLength = 2;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
setup->wIndex = 0;
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, 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)
@@ -280,22 +288,6 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
}
}
static void usbh_hubport_release(struct usbh_hubport *child)
{
if (child->connected) {
child->connected = false;
usbh_free_devaddr(child);
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(child, i);
}
}
child->config.config_desc.bNumInterfaces = 0;
usbh_kill_urb(&child->ep0_urb);
usb_osal_mutex_delete(child->mutex);
}
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static void hub_int_complete_callback(void *arg, int nbytes)
{
@@ -304,11 +296,21 @@ static void hub_int_complete_callback(void *arg, int nbytes)
if (nbytes > 0) {
usbh_hub_thread_wakeup(hub);
} else if (nbytes == -USB_ERR_NAK) {
usbh_submit_urb(&hub->intin_urb);
/* Restart timer to submit urb again */
USB_LOG_DBG("Restart timer\r\n");
usb_osal_timer_start(hub->int_timer);
} else {
}
}
static void hub_int_timeout(void *arg)
{
struct usbh_hub *hub = (struct usbh_hub *)arg;
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
usbh_submit_urb(&hub->intin_urb);
}
static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
@@ -324,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);
@@ -347,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) {
@@ -379,13 +412,16 @@ 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];
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
usbh_submit_urb(&hub->intin_urb);
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0);
if (hub->int_timer == NULL) {
USB_LOG_ERR("No memory to alloc int_timer\r\n");
return -USB_ERR_NOMEM;
}
usb_osal_timer_start(hub->int_timer);
return 0;
}
@@ -401,7 +437,11 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
usbh_kill_urb(&hub->intin_urb);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
if (hub->int_timer) {
usb_osal_timer_delete(hub->int_timer);
}
for (uint8_t port = 0; port < hub->nports; port++) {
child = &hub->child[port];
usbh_hubport_release(child);
child->parent = NULL;
@@ -409,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);
@@ -418,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)))) {
@@ -555,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 */
@@ -585,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;
@@ -593,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 */
@@ -616,7 +644,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
/* Start next hub int transfer */
if (!hub->is_roothub && hub->connected) {
usbh_submit_urb(&hub->intin_urb);
usb_osal_timer_start(hub->int_timer);
}
}
@@ -645,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) {
@@ -663,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,8 +737,7 @@ CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
.class = USB_DEVICE_CLASS_HUB,
.subclass = 0,
.protocol = 0,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &hub_class_driver
};
#endif

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,9 +100,11 @@ 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");
@@ -105,10 +113,12 @@ void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
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,8 +535,10 @@ 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);
#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);
@@ -532,6 +547,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,8 +572,10 @@ 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);
#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);
@@ -565,6 +585,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 +618,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 +831,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 +845,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 +868,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,7 +908,7 @@ 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;
@@ -882,7 +920,26 @@ static void usbdev_msc_thread(void *argument)
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*/
@@ -932,7 +989,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[32];
#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;
@@ -46,7 +48,12 @@ static void usbh_msc_class_free(struct usbh_msc *msc_class)
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,12 @@ 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;
}
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;
@@ -369,7 +378,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
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 +389,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 +397,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 +409,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 +423,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 = {
@@ -431,7 +442,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = {
.class = USB_DEVICE_CLASS_MASS_STORAGE,
.subclass = MSC_SUBCLASS_SCSI,
.protocol = MSC_PROTOCOL_BULK_ONLY,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &msc_class_driver
};

View File

@@ -20,6 +20,8 @@ struct usbh_msc {
uint8_t sdchar;
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
uint16_t blocksize; /* Block size of USB mass storage device */
void *user_data;
};
struct usbh_msc_modeswitch_config {

View File

@@ -92,7 +92,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
.class = 0,
.subclass = 0,
.protocol = 0,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &xxx_class_driver
};

View File

@@ -12,6 +12,8 @@ struct usbh_xxx {
uint8_t intf; /* interface number */
uint8_t minor;
void *user_data;
};
void usbh_xxx_run(struct usbh_xxx *xxx_class);

View File

@@ -14,10 +14,9 @@
#define DEV_FORMAT "/dev/asix"
static struct usbh_asix g_asix_class;
#define CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE (1514U + 8)
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE];
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;
@@ -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;
@@ -263,6 +272,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);
@@ -358,7 +376,7 @@ static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class)
if (ret < 0)
goto out;
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, 0, NULL);
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret);
goto out;
@@ -422,7 +440,7 @@ static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class)
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, 0, NULL);
AX88772_IPG2_DEFAULT, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret);
goto out;
@@ -589,7 +607,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,12 +671,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;
struct netif *netif = (struct netif *)argument;
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
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create asix rx thread\r\n");
// clang-format off
find_class:
@@ -674,11 +696,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], USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize), 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;
@@ -686,31 +709,44 @@ 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, PBUF_POOL);
if (p != NULL) {
memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len);
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 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) {
}
}
}
}
// clang-format off
@@ -720,78 +756,67 @@ 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] = {
{ 0x0B95, 0x772B },
{ 0x0B95, 0x7720 },
{ 0, 0 },
};
static const struct usbh_class_driver asix_class_driver = {
.driver_name = "asix",
.connect = usbh_asix_connect,
.disconnect = usbh_asix_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info ax88772b_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
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,
.vid = 0x0B95,
.pid = 0x772B,
.id_table = asix_id_table,
.class_driver = &asix_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info ax88772_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.vid = 0x0B95,
.pid = 0x7720,
.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,9 +153,7 @@ 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;
};
#ifdef __cplusplus
@@ -170,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
}

2278
class/vendor/net/usbh_rtl8152.c vendored Normal file

File diff suppressed because it is too large Load Diff

68
class/vendor/net/usbh_rtl8152.h vendored Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_RTL8152_H
#define USBH_RTL8152_H
struct usbh_rtl8152 {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
struct usbh_urb intin_urb;
uint8_t intf;
uint8_t mac[6];
bool connect_status;
uint32_t speed[2];
uint8_t version;
uint8_t eee_adv;
uint8_t eee_en;
uint8_t supports_gmii;
uint16_t min_mtu;
uint16_t max_mtu;
uint16_t ocp_base;
uint32_t saved_wolopts;
uint32_t rx_buf_sz;
struct rtl_ops {
void (*init)(struct usbh_rtl8152 *tp);
int (*enable)(struct usbh_rtl8152 *tp);
void (*disable)(struct usbh_rtl8152 *tp);
void (*up)(struct usbh_rtl8152 *tp);
void (*down)(struct usbh_rtl8152 *tp);
void (*unload)(struct usbh_rtl8152 *tp);
bool (*in_nway)(struct usbh_rtl8152 *tp);
void (*hw_phy_cfg)(struct usbh_rtl8152 *tp);
void (*autosuspend_en)(struct usbh_rtl8152 *tp, bool enable);
void (*change_mtu)(struct usbh_rtl8152 *tp);
} rtl_ops;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
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);
#ifdef __cplusplus
}
#endif
#endif /* USBH_RTL8152_H */

View File

@@ -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,12 +349,19 @@ 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] = {
{ 0x1A86, 0x7523 },
{ 0, 0 },
};
const struct usbh_class_driver ch34x_class_driver = {
.driver_name = "ch34x",
.connect = usbh_ch34x_connect,
@@ -342,11 +369,10 @@ const struct usbh_class_driver ch34x_class_driver = {
};
CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0xff,
.protocol = 0xff,
.vid = 0x1A86,
.pid = 0x7523,
.subclass = 0x00,
.protocol = 0x00,
.id_table = ch34x_id_table,
.class_driver = &ch34x_class_driver
};

View File

@@ -51,6 +51,8 @@ struct usbh_ch34x {
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus

View File

@@ -10,7 +10,7 @@
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;
@@ -42,7 +42,12 @@ static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class)
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,12 +298,19 @@ 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] = {
{ 0x10C4, 0xEA60 },
{ 0, 0 },
};
const struct usbh_class_driver cp210x_class_driver = {
.driver_name = "cp210x",
.connect = usbh_cp210x_connect,
@@ -281,11 +318,10 @@ const struct usbh_class_driver cp210x_class_driver = {
};
CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0xff,
.protocol = 0xff,
.vid = 0x10C4,
.pid = 0xEA60,
.subclass = 0x00,
.protocol = 0x00,
.id_table = cp210x_id_table,
.class_driver = &cp210x_class_driver
};

View File

@@ -17,7 +17,7 @@
#define CP210X_SET_BREAK 0x05
#define CP210X_IMM_CHAR 0x06
#define CP210X_SET_MHS 0x07 // Set DTR, RTS
#define CP210X_GET_MDMSTS 0x08
#define CP210X_GET_MDMSTS 0x08
#define CP210X_SET_XON 0x09
#define CP210X_SET_XOFF 0x0A
#define CP210X_SET_EVENTMASK 0x0B
@@ -33,9 +33,9 @@
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
#define CP210X_GET_BAUDRATE 0x1D
#define CP210X_GET_BAUDRATE 0x1D
#define CP210X_SET_BAUDRATE 0x1E // Set baudrate
#define CP210X_VENDOR_SPECIFIC 0xFF
#define CP210X_VENDOR_SPECIFIC 0xFF
struct usbh_cp210x {
struct usbh_hubport *hport;
@@ -45,9 +45,11 @@ struct usbh_cp210x {
struct usbh_urb bulkin_urb;
struct cdc_line_coding line_coding;
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus

View File

@@ -10,7 +10,7 @@
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;
@@ -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;
@@ -120,13 +135,18 @@ static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t datab
/**
* D0-D7 databits BITS_7=7, BITS_8=8
* D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4
* D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2
* 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,34 +370,31 @@ 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] = {
{ 0x0403, 0x6001 },
{ 0x0403, 0x6010 },
{ 0, 0 },
};
const struct usbh_class_driver ftdi_class_driver = {
.driver_name = "ftdi",
.connect = usbh_ftdi_connect,
.disconnect = usbh_ftdi_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info ftdi1_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
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 = 0xff,
.protocol = 0xff,
.vid = 0x0403,
.pid = 0x6001,
.class_driver = &ftdi_class_driver
};
CLASS_INFO_DEFINE const struct usbh_class_info ftdi2_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0xff,
.protocol = 0xff,
.vid = 0x0403,
.pid = 0x6010,
.subclass = 0x00,
.protocol = 0x00,
.id_table = ftdi_id_table,
.class_driver = &ftdi_class_driver
};

View File

@@ -51,6 +51,8 @@ struct usbh_ftdi {
uint8_t intf;
uint8_t minor;
uint8_t modem_status[2];
void *user_data;
};
#ifdef __cplusplus

448
class/vendor/serial/usbh_pl2303.c vendored Normal file
View File

@@ -0,0 +1,448 @@
/*
* Copyright (c) 2024, sakumisu
* Copyright (c) 2024, Derek Konigsberg
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_pl2303.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_pl2303"
#include "usb_log.h"
#define DEV_FORMAT "/dev/ttyUSB%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_pl2303_buf[64];
#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)
static struct usbh_pl2303 g_pl2303_class[CONFIG_USBHOST_MAX_PL2303_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_pl2303 *usbh_pl2303_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_PL2303_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_pl2303_class[devno], 0, sizeof(struct usbh_pl2303));
g_pl2303_class[devno].minor = devno;
return &g_pl2303_class[devno];
}
}
return NULL;
}
static void usbh_pl2303_class_free(struct usbh_pl2303 *pl2303_class)
{
int devno = pl2303_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(pl2303_class, 0, sizeof(struct usbh_pl2303));
}
static int usbh_pl2303_get_chiptype(struct usbh_pl2303 *pl2303_class)
{
int ret = 0;
switch (pl2303_class->hport->device_desc.bcdDevice) {
case 0x0300:
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HX;
/* or TA, that is HX with external crystal */
break;
case 0x0400:
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HXD;
/* or EA, that is HXD with ESD protection */
/* or RA, that has internal voltage level converter that works only up to 1Mbaud (!) */
break;
case 0x0500:
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HXD;
/* in fact it's TB, that is HXD with external crystal */
break;
default:
/* NOTE: I have no info about the bcdDevice for the base PL2303 (up to 1.2Mbaud,
only fixed rates) and for PL2303SA (8-pin chip, up to 115200 baud */
/* Determine the chip type. This algorithm is taken from Linux. */
if (pl2303_class->hport->device_desc.bDeviceClass == 0x02) {
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303;
} else if (pl2303_class->hport->device_desc.bMaxPacketSize0 == 0x40) {
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HX;
} else {
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303;
}
break;
}
/*
* The new chip revision PL2303HXN is only compatible with the new
* PLCOM_SET_REQUEST_PL2303HXN command. Issuing the old command
* PLCOM_SET_REQUEST to the new chip raises an error. Thus, PL2303HX
* and PL2303HXN can be distinguished by issuing an old-style request
* (on a status register) to the new chip and checking the error.
*/
if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HX) {
struct usb_setup_packet *setup = pl2303_class->hport->setup;
setup->bmRequestType = UT_READ_VENDOR_DEVICE;
setup->bRequest = PL2303_SET_REQUEST;
setup->wValue = PL2303_STATUS_REG_PL2303HX;
setup->wIndex = 0;
setup->wLength = 1;
ret = usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
if (ret == -USB_ERR_STALL) {
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HXN;
ret = 0;
} else if (ret < 0) {
USB_LOG_WRN("Error checking chip type: %d\r\n", ret);
return ret;
}
}
switch (pl2303_class->chiptype) {
case USBH_PL2303_TYPE_PL2303:
USB_LOG_INFO("chiptype = 2303\r\n");
break;
case USBH_PL2303_TYPE_PL2303HX:
USB_LOG_INFO("chiptype = 2303HX/TA\r\n");
break;
case USBH_PL2303_TYPE_PL2303HXN:
USB_LOG_INFO("chiptype = 2303HXN\r\n");
break;
case USBH_PL2303_TYPE_PL2303HXD:
USB_LOG_INFO("chiptype = 2303HXD/TB/RA/EA\r\n");
break;
default:
USB_LOG_INFO("chiptype = [%d]\r\n", pl2303_class->chiptype);
break;
}
return ret;
}
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;
if (!pl2303_class || !pl2303_class->hport) {
return -USB_ERR_INVAL;
}
setup = pl2303_class->hport->setup;
setup->bmRequestType = req_type;
setup->bRequest = request;
setup->wValue = value;
setup->wIndex = index;
setup->wLength = length;
return usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
}
int usbh_pl2303_set_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding)
{
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;
setup->wValue = 0;
setup->wIndex = pl2303_class->intf;
setup->wLength = 7;
memcpy(g_pl2303_buf, line_coding, sizeof(struct cdc_line_coding));
return usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
}
int usbh_pl2303_get_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding)
{
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;
setup->wIndex = pl2303_class->intf;
setup->wLength = 7;
ret = usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
if (ret < 0) {
return ret;
}
memcpy(line_coding, g_pl2303_buf, sizeof(struct cdc_line_coding));
return ret;
}
int usbh_pl2303_set_line_state(struct usbh_pl2303 *pl2303_class, bool dtr, bool rts)
{
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;
setup->wValue = (dtr << 0) | (rts << 1);
setup->wIndex = pl2303_class->intf;
setup->wLength = 0;
return usbh_control_transfer(pl2303_class->hport, setup, NULL);
}
static int usbh_pl2303_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_pl2303 *pl2303_class = usbh_pl2303_class_alloc();
if (pl2303_class == NULL) {
USB_LOG_ERR("Fail to alloc pl2303_class\r\n");
return -USB_ERR_NOMEM;
}
pl2303_class->hport = hport;
pl2303_class->intf = intf;
hport->config.intf[intf].priv = pl2303_class;
do {
ret = usbh_pl2303_get_chiptype(pl2303_class);
if (ret < 0) {
break;
}
/* Startup reset sequence, if necessary for the chip type */
if (pl2303_class->chiptype != USBH_PL2303_TYPE_PL2303HXN) {
struct usb_setup_packet *setup = pl2303_class->hport->setup;
setup->bmRequestType = UT_WRITE_VENDOR_DEVICE;
setup->bRequest = PL2303_SET_REQUEST;
setup->wValue = 0;
setup->wIndex = pl2303_class->intf;
setup->wLength = 0;
ret = usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
if (ret < 0) {
USB_LOG_WRN("Initialization reset failed: %d\r\n", ret);
break;
}
}
if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303) {
/* HX variants seem to lock up after a clear stall request. */
/*
* The FreeBSD code sets the stall flags on the in and out pipes
* here. Have no idea exactly how to do this, or if it is necessary.
* May just leave this code unwritten until test hardware is available.
*/
} else if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HX || pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HXD) {
/* Reset upstream data pipes */
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 8, 0, 0);
if (ret < 0) {
USB_LOG_WRN("Could not reset upstream data pipes (8,0): %d\r\n", ret);
break;
}
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 9, 0, 0);
if (ret < 0) {
USB_LOG_WRN("Could not reset upstream data pipes (9,0): %d\r\n", ret);
break;
}
} else if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HXN) {
/* Reset upstream data pipes */
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST_PL2303HXN, 0x07, 0x03, 0);
if (ret < 0) {
USB_LOG_WRN("Could not reset upstream data pipes (7,3): %d\r\n", ret);
break;
}
}
/* Final device initialization, if necessary for the chip type */
if (pl2303_class->chiptype != USBH_PL2303_TYPE_PL2303HXN) {
if (usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x0404, 0, 0) < 0 ||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8383, 0, 1) < 0 ||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x0404, 1, 0) < 0 ||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8383, 0, 1) < 0 ||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 0, 1, 0) < 0 ||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 1, 0, 0) < 0) {
USB_LOG_WRN("Could not complete init sequence\r\n");
ret = -USB_ERR_INVAL;
break;
}
if (pl2303_class->chiptype != USBH_PL2303_TYPE_PL2303) {
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 2, 0x44, 0);
} else {
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 2, 0x24, 0);
}
if (ret < 0) {
USB_LOG_WRN("Could not complete final init request: %d\r\n", ret);
break;
}
}
} while (0);
if (ret < 0) {
USB_LOG_ERR("Failed to initialize PL2303 device: %d\r\n", ret);
return ret;
}
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 (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
continue;
} else {
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(pl2303_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(pl2303_class->bulkout, ep_desc);
}
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, pl2303_class->minor);
USB_LOG_INFO("Register PL2303 Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test pl2303 rx and tx and rx for 5 times, baudrate is 115200\r\n");
struct cdc_line_coding linecoding;
uint8_t count = 5;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_pl2303_set_line_coding(pl2303_class, &linecoding);
usbh_pl2303_set_line_state(pl2303_class, true, false);
memset(g_pl2303_buf, 'a', sizeof(g_pl2303_buf));
ret = usbh_pl2303_bulk_out_transfer(pl2303_class, g_pl2303_buf, sizeof(g_pl2303_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_pl2303_bulk_in_transfer(pl2303_class, g_pl2303_buf, sizeof(g_pl2303_buf), 0xfffffff);
USB_LOG_RAW("in ret:%d\r\n", ret);
if (ret > 0) {
for (uint32_t i = 0; i < ret; i++) {
USB_LOG_RAW("%02x ", g_pl2303_buf[i]);
}
}
USB_LOG_RAW("\r\n");
}
#endif
usbh_pl2303_run(pl2303_class);
return ret;
}
static int usbh_pl2303_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_pl2303 *pl2303_class = (struct usbh_pl2303 *)hport->config.intf[intf].priv;
if (pl2303_class) {
if (pl2303_class->bulkin) {
usbh_kill_urb(&pl2303_class->bulkin_urb);
}
if (pl2303_class->bulkout) {
usbh_kill_urb(&pl2303_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister PL2303 Class:%s\r\n", hport->config.intf[intf].devname);
usbh_pl2303_stop(pl2303_class);
}
usbh_pl2303_class_free(pl2303_class);
}
return ret;
}
int usbh_pl2303_bulk_in_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &pl2303_class->bulkin_urb;
usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &pl2303_class->bulkout_urb;
usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
__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] = {
{ 0x067B, 0x2303 }, // PL2303 Serial (ATEN/IOGEAR UC232A)
{ 0x067B, 0x23A3 }, // PL2303HXN Serial, type GC
{ 0x067B, 0x23B3 }, // PL2303HXN Serial, type GB
{ 0x067B, 0x23C3 }, // PL2303HXN Serial, type GT
{ 0x067B, 0x23D3 }, // PL2303HXN Serial, type GL
{ 0x067B, 0x23E3 }, // PL2303HXN Serial, type GE
{ 0x067B, 0x23F3 }, // PL2303HXN Serial, type GS
{ 0, 0 },
};
const struct usbh_class_driver pl2303_class_driver = {
.driver_name = "pl2303",
.connect = usbh_pl2303_connect,
.disconnect = usbh_pl2303_disconnect
};
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,
.id_table = pl2303_id_table,
.class_driver = &pl2303_class_driver
};

62
class/vendor/serial/usbh_pl2303.h vendored Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_PL2303_H
#define USBH_PL2303_H
#include "usb_cdc.h"
#define PL2303_SET_REQUEST 0x01
#define PL2303_SET_REQUEST_PL2303HXN 0x80
#define PL2303_SET_CRTSCTS 0x41
#define PL2303_SET_CRTSCTS_PL2303X 0x61
#define PL2303_SET_CRTSCTS_PL2303HXN 0xFA
#define PL2303_CLEAR_CRTSCTS_PL2303HXN 0xFF
#define PL2303_CRTSCTS_REG_PL2303HXN 0x0A
#define PL2303_STATUS_REG_PL2303HX 0x8080
/* Different PL2303 IC types */
#define USBH_PL2303_TYPE_UNKNOWN 0
#define USBH_PL2303_TYPE_PL2303 1
#define USBH_PL2303_TYPE_PL2303HX 2
#define USBH_PL2303_TYPE_PL2303HXD 3
#define USBH_PL2303_TYPE_PL2303HXN 4
struct usbh_pl2303 {
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;
struct cdc_line_coding linecoding;
uint8_t intf;
uint8_t minor;
uint8_t chiptype;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_pl2303_set_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding);
int usbh_pl2303_get_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding);
int usbh_pl2303_set_line_state(struct usbh_pl2303 *pl2303_class, bool dtr, bool rts);
int usbh_pl2303_bulk_in_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class);
void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_PL2303_H */

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,
.class = 0xff,
.subclass = 0x00,
.protocol = 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)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_XBOX_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << 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)
{
int devno = xbox_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << 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,
.class = USB_DEVICE_CLASS_VEND_SPECIFIC,
.subclass = 0x5d,
.protocol = 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

@@ -24,6 +24,8 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
{
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 +297,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;
@@ -762,7 +763,7 @@ 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)
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
{
uint32_t packets;
uint32_t last_packet_size;

View File

@@ -20,7 +20,7 @@ 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);
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
#ifdef __cplusplus
}

View File

@@ -59,10 +59,15 @@ static void usbh_video_class_free(struct usbh_video *video_class)
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;
}
@@ -180,7 +195,7 @@ int usbh_video_open(struct usbh_video *video_class,
* Get MIN request (probe)
* Get CUR request (probe)
* Set CUR request (commit)
*
*
*/
step = 0;
ret = usbh_videostreaming_get_cur_probe(video_class);
@@ -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;
@@ -300,12 +320,12 @@ void usbh_video_list_info(struct usbh_video *video_class)
uint16_t mps;
USB_LOG_INFO("============= Video device information ===================\r\n");
USB_LOG_INFO("bcdVDC:%04x\r\n", video_class->bcdVDC);
USB_LOG_INFO("Num of altsettings:%u\r\n", video_class->num_of_intf_altsettings);
USB_LOG_RAW("bcdVDC:%04x\r\n", video_class->bcdVDC);
USB_LOG_RAW("Num of altsettings:%u\r\n", video_class->num_of_intf_altsettings);
for (uint8_t i = 0; i < video_class->num_of_intf_altsettings; i++) {
if (i == 0) {
USB_LOG_INFO("Ingore altsetting 0\r\n");
USB_LOG_RAW("Ingore altsetting 0\r\n");
continue;
}
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
@@ -313,7 +333,7 @@ void usbh_video_list_info(struct usbh_video *video_class)
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
USB_LOG_INFO("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
USB_LOG_RAW("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
i,
ep_desc->bEndpointAddress,
ep_desc->bmAttributes,
@@ -322,15 +342,15 @@ void usbh_video_list_info(struct usbh_video *video_class)
mult);
}
USB_LOG_INFO("bNumFormats:%u\r\n", video_class->num_of_formats);
USB_LOG_RAW("bNumFormats:%u\r\n", video_class->num_of_formats);
for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
USB_LOG_INFO(" FormatIndex:%u\r\n", i + 1);
USB_LOG_INFO(" FormatType:%s\r\n", format_type[video_class->format[i].format_type]);
USB_LOG_INFO(" bNumFrames:%u\r\n", video_class->format[i].num_of_frames);
USB_LOG_INFO(" Resolution:\r\n");
USB_LOG_RAW(" FormatIndex:%u\r\n", i + 1);
USB_LOG_RAW(" FormatType:%s\r\n", format_type[video_class->format[i].format_type]);
USB_LOG_RAW(" bNumFrames:%u\r\n", video_class->format[i].num_of_frames);
USB_LOG_RAW(" Resolution:\r\n");
for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) {
USB_LOG_INFO(" FrameIndex:%u\r\n", j + 1);
USB_LOG_INFO(" wWidth: %d, wHeight: %d\r\n",
USB_LOG_RAW(" FrameIndex:%u\r\n", j + 1);
USB_LOG_RAW(" wWidth: %d, wHeight: %d\r\n",
video_class->format[i].frame[j].wWidth,
video_class->format[i].frame[j].wHeight);
}
@@ -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 = {
@@ -508,8 +534,7 @@ CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
.class = USB_DEVICE_CLASS_VIDEO,
.subclass = VIDEO_SC_VIDEOCONTROL,
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &video_ctrl_class_driver
};
@@ -518,7 +543,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
.class = USB_DEVICE_CLASS_VIDEO,
.subclass = VIDEO_SC_VIDEOSTREAMING,
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &video_streaming_class_driver
};

View File

@@ -22,12 +22,19 @@ struct usbh_video_format {
uint8_t num_of_frames;
};
struct usbh_videoframe {
uint8_t *frame_buf;
uint32_t frame_bufsize;
uint32_t frame_format;
uint32_t frame_size;
};
struct usbh_videostreaming {
struct usbh_videoframe *frame;
uint32_t frame_format;
uint32_t bufoffset;
uint32_t buflen;
uint16_t width;
uint16_t heigth;
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
uint16_t height;
};
struct usbh_video {
@@ -48,6 +55,8 @@ struct usbh_video {
uint8_t num_of_intf_altsettings;
uint8_t num_of_formats;
struct usbh_video_format format[3];
void *user_data;
};
#ifdef __cplusplus

View File

@@ -17,23 +17,10 @@ static struct usbd_endpoint rndis_ep_data[3];
#define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
#define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
#ifdef CONFIG_USB_HS
#define RNDIS_MAX_PACKET_SIZE 512
#else
#define RNDIS_MAX_PACKET_SIZE 64
#endif
#ifndef CONFIG_USB_HS
#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */
#else
#define RNDIS_LINK_SPEED 480000000 /* Link baudrate (480Mbit/s for USB-HS) */
#endif
/* Device data structure */
struct usbd_rndis_priv {
uint32_t drv_version;
uint32_t link_status;
uint32_t speed;
uint32_t net_filter;
usb_eth_stat_t eth_state;
rndis_state_t init_state;
@@ -45,8 +32,13 @@ struct usbd_rndis_priv {
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
#if CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE < 1580
#undef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
#endif
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
@@ -110,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);
@@ -160,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;
@@ -169,8 +165,8 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
resp->Status = RNDIS_STATUS_SUCCESS;
resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
resp->Medium = RNDIS_MEDIUM_802_3;
resp->MaxPacketsPerTransfer = 1;
resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + sizeof(rndis_data_packet_t);
resp->MaxPacketsPerTransfer = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE / 1580;
resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE;
resp->PacketAlignmentFactor = 0;
resp->AfListOffset = 0;
resp->AfListSize = 0;
@@ -185,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;
@@ -200,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;
@@ -225,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(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE);
RNDIS_INQUIRY_PUT_LE32(0x05DC); /* mtu 1500 */
infomation_len = 4;
break;
case OID_GEN_VENDOR_ID:
@@ -250,7 +251,12 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_LINK_SPEED:
RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
if (usbd_get_ep_mps(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr) > 64) {
RNDIS_INQUIRY_PUT_LE32(480000000 / 100);
} else {
RNDIS_INQUIRY_PUT_LE32(12000000 / 100);
}
infomation_len = 4;
break;
case OID_GEN_CURRENT_PACKET_FILTER:
@@ -258,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:
@@ -341,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;
@@ -397,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);
@@ -415,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;
@@ -428,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;
@@ -448,9 +464,12 @@ 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 != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return;
}
@@ -464,7 +483,9 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 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 {
@@ -474,6 +495,10 @@ void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
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);
}
@@ -491,7 +516,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);
@@ -508,7 +533,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
rndis_data_packet_t *hdr;
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
return 0;
return -USB_ERR_NOTCONN;
}
if (g_rndis_tx_data_length > 0) {
@@ -521,7 +546,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;
}
@@ -548,7 +573,6 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
g_usbd_rndis.drv_version = 0x0001;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
g_usbd_rndis.speed = RNDIS_LINK_SPEED;
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;

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;
@@ -224,7 +224,7 @@ void usbh_bluetooth_hci_rx_thread(void *argument)
}
}
// clang-format off
delete :
delete :
USB_LOG_INFO("Delete hc acl rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
@@ -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;
@@ -309,7 +314,7 @@ void usbh_bluetooth_hci_evt_rx_thread(void *argument)
usb_osal_msleep(interval);
}
// clang-format off
delete :
delete :
USB_LOG_INFO("Delete hc event rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
@@ -351,7 +356,7 @@ void usbh_bluetooth_hci_acl_rx_thread(void *argument)
}
}
// clang-format off
delete :
delete :
USB_LOG_INFO("Delete hc acl rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
@@ -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 = {
@@ -377,13 +386,17 @@ static const struct usbh_class_driver bluetooth_class_driver = {
};
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
static const uint16_t bluetooth_id_table[][2] = {
{ 0x2fe3, 0x000c },
{ 0, 0 },
};
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.vid = 0x2fe3,
.pid = 0x000c,
.id_table = bluetooth_id_table,
.class_driver = &bluetooth_class_driver
};
#else
@@ -392,8 +405,7 @@ CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x01,
.vid = 0x00,
.pid = 0x00,
.id_table = NULL,
.class_driver = &bluetooth_class_driver
};
#endif

View File

@@ -29,6 +29,8 @@ struct usbh_bluetooth {
struct usbh_urb *isoout_urb; /* Bulk OUT urb */
uint8_t num_of_intf_altsettings;
#endif
void *user_data;
};
#ifdef __cplusplus

View File

@@ -18,10 +18,6 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
/* eth rx size must be a multiple of 512 or 64 */
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE];
// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[16];
@@ -30,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;
@@ -44,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;
@@ -86,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;
@@ -142,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;
@@ -209,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;
@@ -386,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);
@@ -429,14 +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;
uint32_t payload_offset;
int ret;
err_t err;
struct pbuf *p, *q;
uint32_t pmg_offset;
rndis_data_packet_t *pmsg;
rndis_data_packet_t temp;
struct netif *netif = (struct netif *)argument;
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
uint32_t transfer_size = CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE;
#else
uint32_t transfer_size = (16 * 1024);
#endif
(void)argument;
USB_LOG_INFO("Create rndis rx thread\r\n");
// clang-format off
@@ -453,52 +478,65 @@ find_class:
usb_osal_msleep(100);
goto find_class;
}
usb_osal_msleep(128);
}
g_rndis_rx_length = 0;
while (1) {
g_rndis_rx_length = 0;
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, 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;
pmg_offset = 0;
while (g_rndis_rx_length > 0) {
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
g_rndis_rx_length += g_rndis_class.bulkin_urb.actual_length;
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
/* 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;
/* Not word-aligned case */
if (pmg_offset & 0x3) {
memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
pmsg = &temp;
}
uint32_t total_len = g_rndis_rx_length;
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL);
if (p != NULL) {
payload_offset = 0;
for (q = p; q != NULL; q = q->next) {
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset + payload_offset);
memcpy(q->payload, src, q->len);
payload_offset += q->len;
}
while (g_rndis_rx_length > 0) {
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
/* Not word-aligned case */
if (pmg_offset & 0x3) {
usb_memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
pmsg = &temp;
}
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
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;
}
} else {
USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
g_rndis_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
USB_LOG_ERR("Error rndis packet message\r\n");
}
}
} else {
#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) {
}
} else {
g_rndis_rx_length = 0;
USB_LOG_ERR("Error rndis packet message\r\n");
}
}
}
@@ -510,53 +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)) {
hdr->MessageLength += 1;
if (!(len % g_rndis_class.bulkout->wMaxPacketSize)) {
len += 1;
}
USB_LOG_DBG("txlen:%d\r\n", hdr->MessageLength);
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, hdr->MessageLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
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);
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 = {
@@ -570,7 +603,6 @@ CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x03,
.vid = 0x00,
.pid = 0x00,
.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,14 +22,15 @@ 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;
};
#ifdef __cplusplus
@@ -45,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,14 +33,21 @@ 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
*
* @param[in] port port index
* @param[in] busid bus index
*
* @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH
*/
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port);
uint8_t usbd_get_port_speed(uint8_t busid);
/**
* @brief configure and enable endpoint.
@@ -178,6 +185,15 @@ void usbd_event_ep_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyte
*/
void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
#ifdef CONFIG_USBDEV_TEST_MODE
/**
* @brief Usb execute test mode
* @param[in] busid device busid
* @param[in] test_mode usb test mode
*/
void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -34,6 +34,10 @@
/**< maximum packet size (MPS) for EP 0 */
#define USB_CTRL_EP_MPS 64
/**< maximum packet size (MPS) for bulk EP */
#define USB_BULK_EP_MPS_HS 512
#define USB_BULK_EP_MPS_FS 64
/* USB PID Types */
#define USB_PID_OUT (0x01) /* Tokens */
#define USB_PID_IN (0x09)
@@ -538,7 +542,7 @@ struct usb_msosv2_subset_function_descriptor {
} __PACKED;
struct usb_msosv2_descriptor {
uint8_t *compat_id;
const uint8_t *compat_id;
uint16_t compat_id_len;
uint8_t vendor_code;
};
@@ -610,14 +614,14 @@ struct usb_webusb_url_descriptor {
char URL[];
} __PACKED;
struct usb_webusb_url_ex_descriptor {
struct usb_webusb_descriptor {
uint8_t vendor_code;
uint8_t *string;
const uint8_t *string;
uint32_t string_len;
} __PACKED;
struct usb_bos_descriptor {
uint8_t *string;
const uint8_t *string;
uint32_t string_len;
};
@@ -660,6 +664,27 @@ struct usb_desc_header {
bmAttributes, /* bmAttributes */ \
USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bNumConfigurations) \
0x0A, /* bLength */ \
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, /* bDescriptorType */ \
WBVAL(bcdUSB), /* bcdUSB */ \
bDeviceClass, /* bDeviceClass */ \
bDeviceSubClass, /* bDeviceSubClass */ \
bDeviceProtocol, /* bDeviceProtocol */ \
0x40, /* bMaxPacketSize */ \
bNumConfigurations, /* bNumConfigurations */ \
0x00 /* bReserved */
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_OTHER_SPEED, /* bDescriptorType */ \
WBVAL(wTotalLength), /* wTotalLength */ \
bNumInterfaces, /* bNumInterfaces */ \
bConfigurationValue, /* bConfigurationValue */ \
0x00, /* iConfiguration */ \
bmAttributes, /* bmAttributes */ \
USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints, \
bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
0x09, /* bLength */ \

View File

@@ -34,10 +34,12 @@ 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;
uint8_t data_toggle;
uint8_t interval;
struct usb_setup_packet *setup;
uint8_t *transfer_buffer;
uint32_t transfer_buffer_length;

View File

@@ -82,4 +82,31 @@ 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;
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

@@ -8,6 +8,7 @@
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
@@ -16,6 +17,14 @@ typedef void *usb_osal_sem_t;
typedef void *usb_osal_mutex_t;
typedef void *usb_osal_mq_t;
typedef void (*usb_thread_entry_t)(void *argument);
typedef void (*usb_timer_handler_t)(void *argument);
struct usb_osal_timer {
usb_timer_handler_t handler;
void *argument;
bool is_period;
uint32_t ticks;
void *timer;
};
/*
* Task with smaller priority value indicates higher task priority
@@ -39,9 +48,17 @@ void usb_osal_mq_delete(usb_osal_mq_t mq);
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period);
void usb_osal_timer_delete(struct usb_osal_timer *timer);
void usb_osal_timer_start(struct usb_osal_timer *timer);
void usb_osal_timer_stop(struct usb_osal_timer *timer);
size_t usb_osal_enter_critical_section(void);
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 0x010400
#define CHERRYUSB_VERSION_STR "v1.4.0"
#endif

View File

@@ -20,6 +20,8 @@
struct usbd_tx_rx_msg {
uint8_t ep;
uint8_t ep_mult;
uint16_t ep_mps;
uint32_t nbytes;
usbd_endpoint_callback cb;
};
@@ -43,17 +45,25 @@ 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;
#ifdef CONFIG_USBDEV_TEST_MODE
bool test_mode;
#endif
struct usbd_interface *intf[8];
#ifdef CONFIG_USBDEV_TEST_MODE
bool test_req;
#endif
struct usbd_interface *intf[16];
uint8_t intf_offset;
struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_EP_NUM];
@@ -94,10 +104,18 @@ static bool is_device_configured(uint8_t busid)
*/
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);
g_usbd_core[busid].tx_msg[ep->bEndpointAddress & 0x7f].ep_mult = USB_GET_MULT(ep->wMaxPacketSize);
} else {
g_usbd_core[busid].rx_msg[ep->bEndpointAddress & 0x7f].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_usbd_core[busid].rx_msg[ep->bEndpointAddress & 0x7f].ep_mult = USB_GET_MULT(ep->wMaxPacketSize);
}
return usbd_ep_open(busid, ep) == 0 ? true : false;
}
@@ -113,9 +131,9 @@ static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descripto
*/
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;
}
@@ -139,6 +157,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
uint8_t index = 0U;
bool found = true;
uint32_t desc_len = 0;
const char *string = NULL;
const uint8_t *desc = NULL;
type = HI_BYTE(type_index);
@@ -146,6 +165,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
switch (type) {
case USB_DESCRIPTOR_TYPE_DEVICE:
g_usbd_core[busid].speed = usbd_get_port_speed(busid); /* before we get device descriptor, we have known steady port speed */
desc = g_usbd_core[busid].descriptors->device_descriptor_callback(g_usbd_core[busid].speed);
if (desc == NULL) {
found = false;
@@ -160,11 +180,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;
@@ -173,15 +194,45 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
desc = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->string;
desc_len = g_usbd_core[busid].descriptors->msosv1_descriptor->string[0];
} else {
desc = g_usbd_core[busid].descriptors->string_descriptor_callback(g_usbd_core[busid].speed, index);
if (desc == NULL) {
string = g_usbd_core[busid].descriptors->string_descriptor_callback(g_usbd_core[busid].speed, index);
if (string == NULL) {
found = false;
break;
}
desc_len = desc[0];
if (index == USB_STRING_LANGID_INDEX) {
(*data)[0] = 4;
(*data)[1] = USB_DESCRIPTOR_TYPE_STRING;
(*data)[2] = string[0];
(*data)[3] = string[1];
*len = 4;
return true;
}
uint16_t str_size = strlen(string);
uint16_t total_size = 2 * str_size + 2;
if (total_size > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
USB_LOG_ERR("string size overflow\r\n");
return false;
}
(*data)[0] = total_size;
(*data)[1] = USB_DESCRIPTOR_TYPE_STRING;
for (uint16_t i = 0; i < str_size; i++) {
(*data)[2 * i + 2] = string[i];
(*data)[2 * i + 3] = 0x00;
}
*len = total_size;
return true;
}
break;
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
#ifndef CONFIG_USB_HS
return false;
#else
desc = g_usbd_core[busid].descriptors->device_quality_descriptor_callback(g_usbd_core[busid].speed);
if (desc == NULL) {
found = false;
@@ -189,6 +240,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
}
desc_len = desc[0];
break;
#endif
case USB_DESCRIPTOR_TYPE_OTHER_SPEED:
desc = g_usbd_core[busid].descriptors->other_speed_descriptor_callback(g_usbd_core[busid].speed);
if (desc == NULL) {
@@ -199,8 +251,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;
@@ -219,8 +269,8 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da
/* nothing found */
USB_LOG_ERR("descriptor <type:%x,index:%x> not found!\r\n", type, index);
} else {
// *data = desc;
memcpy(*data, desc, desc_len);
*data = (uint8_t *)desc;
//memcpy(*data, desc, desc_len);
*len = desc_len;
}
return found;
@@ -238,26 +288,22 @@ 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;
}
//*data = (uint8_t *)g_usbd_core[busid].msosv1_desc->string;
memcpy(*data, (uint8_t *)g_usbd_core[busid].msosv1_desc->string, g_usbd_core[busid].msosv1_desc->string[0]);
*data = (uint8_t *)g_usbd_core[busid].msosv1_desc->string;
//memcpy(*data, (uint8_t *)g_usbd_core[busid].msosv1_desc->string, g_usbd_core[busid].msosv1_desc->string[0]);
*len = g_usbd_core[busid].msosv1_desc->string[0];
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;
}
//*data = g_usbd_core[busid].bos_desc->string;
memcpy(*data, (uint8_t *)g_usbd_core[busid].bos_desc->string, g_usbd_core[busid].bos_desc->string_len);
*data = (uint8_t *)g_usbd_core[busid].bos_desc->string;
//memcpy(*data, (uint8_t *)g_usbd_core[busid].bos_desc->string, g_usbd_core[busid].bos_desc->string_len);
*len = g_usbd_core[busid].bos_desc->string_len;
return true;
}
@@ -299,11 +345,15 @@ 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];
}
memcpy(*data, p, *len);
*data = p;
//memcpy(*data, p, *len);
} else {
/* nothing found */
USB_LOG_ERR("descriptor <type:0x%02x,index:0x%02x> not found!\r\n", type, index);
@@ -484,6 +534,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;
@@ -492,20 +548,22 @@ 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) {
#ifdef CONFIG_USBDEV_TEST_MODE
g_usbd_core[busid].test_mode = true;
usbd_execute_test_mode(busid, setup);
g_usbd_core[busid].test_req = true;
#endif
}
*len = 0;
break;
case USB_REQUEST_SET_ADDRESS:
g_usbd_core[busid].device_address = value;
usbd_set_address(busid, value);
*len = 0;
break;
@@ -519,17 +577,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);
}
@@ -563,6 +624,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)) {
@@ -577,15 +648,45 @@ 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];
if (intf && (intf->intf_num == intf_num)) {
//*data = (uint8_t *)intf->hid_report_descriptor;
memcpy(*data, intf->hid_report_descriptor, intf->hid_report_descriptor_len);
*data = (uint8_t *)intf->hid_report_descriptor;
//memcpy(*data, intf->hid_report_descriptor, intf->hid_report_descriptor_len);
*len = intf->hid_report_descriptor_len;
return true;
}
@@ -628,6 +729,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)) {
@@ -636,7 +738,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;
@@ -768,25 +875,23 @@ 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) +
(g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[3] << 24);
//*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id;
memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id, desclen);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id;
//memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id, desclen);
*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) +
(g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][3] << 24);
//*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue], desclen);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
//memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue], desclen);
*len = desclen;
return 0;
default:
@@ -798,11 +903,9 @@ 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);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv2_descriptor->compat_id;
//memcpy(*data, g_usbd_core[busid].descriptors->msosv2_descriptor->compat_id, desclen);
*len = g_usbd_core[busid].descriptors->msosv2_descriptor->compat_id_len;
return 0;
default:
@@ -810,15 +913,15 @@ 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);
*data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string;
//memcpy(*data, g_usbd_core[busid].descriptors->webusb_url_descriptor->string, desclen);
*len = desclen;
return 0;
default:
@@ -832,23 +935,21 @@ 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 *)msosv1_desc->compat_id;
*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) +
(g_usbd_core[busid].msosv1_desc->compat_id[2] << 16) +
(g_usbd_core[busid].msosv1_desc->compat_id[3] << 24);
memcpy(*data, g_usbd_core[busid].msosv1_desc->compat_id, desclen);
//memcpy(*data, g_usbd_core[busid].msosv1_desc->compat_id, desclen);
*len = desclen;
return 0;
case 0x05:
USB_LOG_INFO("get Compat id properties\r\n");
//*data = (uint8_t *)msosv1_desc->comp_id_property[setup->wValue];
*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) +
(g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue][2] << 16) +
(g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue][3] << 24);
memcpy(*data, g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue], desclen);
//memcpy(*data, g_usbd_core[busid].msosv1_desc->comp_id_property[setup->wValue], desclen);
*len = desclen;
return 0;
default:
@@ -860,9 +961,8 @@ 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 *)msosv2_desc->compat_id;
memcpy(*data, g_usbd_core[busid].msosv2_desc->compat_id, g_usbd_core[busid].msosv2_desc->compat_id_len);
*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;
return 0;
default:
@@ -871,6 +971,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];
@@ -896,14 +1012,12 @@ static bool usbd_setup_request_handler(uint8_t busid, struct usb_setup_packet *s
{
switch (setup->bmRequestType & USB_REQUEST_TYPE_MASK) {
case USB_REQUEST_STANDARD:
#ifndef CONFIG_USB_HS
//g_usbd_core[busid].speed = USB_SPEED_FULL; /* next time will support getting device speed */
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600) && (g_usbd_core[busid].speed <= USB_SPEED_FULL)) {
USB_LOG_WRN("Ignore DQD in fs\r\n"); /* Device Qualifier Descriptor */
return false;
}
#endif
if (usbd_standard_request_handler(busid, setup, data, len) < 0) {
/* Ignore error log for getting Device Qualifier Descriptor request */
if ((setup->bRequest == 0x06) && (setup->wValue == 0x0600)) {
//USB_LOG_DBG("Ignore DQD in fs\r\n");
return false;
}
USB_LOG_ERR("standard request error\r\n");
usbd_print_setup(setup);
return false;
@@ -961,21 +1075,25 @@ 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_TEST_MODE
g_usbd_core[busid].test_mode = false;
#ifdef CONFIG_USBDEV_ADVANCE_DESC
g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
#endif
struct usb_endpoint_descriptor ep0;
@@ -997,6 +1115,7 @@ void usbd_event_reset_handler(uint8_t busid)
void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
{
struct usb_setup_packet *setup = &g_usbd_core[busid].setup;
uint8_t *buf;
memcpy(setup, psetup, 8);
#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
@@ -1014,6 +1133,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
g_usbd_core[busid].ep0_data_buf_residue = setup->wLength;
g_usbd_core[busid].ep0_data_buf_len = setup->wLength;
g_usbd_core[busid].zlp_flag = false;
buf = g_usbd_core[busid].ep0_data_buf;
/* handle class request when all the data is received */
if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
@@ -1023,24 +1143,32 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup)
}
/* Ask installed handler to process request */
if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) {
if (!usbd_setup_request_handler(busid, setup, &buf, &g_usbd_core[busid].ep0_data_buf_len)) {
usbd_ep_set_stall(busid, USB_CONTROL_IN_EP0);
return;
}
#ifdef CONFIG_USBDEV_TEST_MODE
/* send status in test mode, so do not execute downward, just return */
if (g_usbd_core[busid].test_mode) {
g_usbd_core[busid].test_mode = false;
return;
}
#endif
/* Send smallest of requested and offered length */
g_usbd_core[busid].ep0_data_buf_residue = MIN(g_usbd_core[busid].ep0_data_buf_len, setup->wLength);
if (g_usbd_core[busid].ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
USB_LOG_ERR("Request buffer too small\r\n");
usbd_ep_set_stall(busid, USB_CONTROL_IN_EP0);
return;
}
/* use *data = xxx; g_usbd_core[busid].ep0_data_buf records real data address, we should copy data into ep0 buffer.
* Why we should copy once? because some chips are not access to flash with dma if real data address is in flash address(such as ch32).
*/
if (buf != g_usbd_core[busid].ep0_data_buf) {
#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);
#endif
} else {
/* use memcpy(*data, xxx, len); has copied into ep0 buffer, we do nothing */
}
/* Send data or status to host */
usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, g_usbd_core[busid].ep0_data_buf, g_usbd_core[busid].ep0_data_buf_residue);
/*
@@ -1058,6 +1186,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;
@@ -1082,6 +1212,13 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
/* if all data has sent completely, start reading out status */
usbd_ep_start_read(busid, USB_CONTROL_OUT_EP0, NULL, 0);
}
#ifdef CONFIG_USBDEV_TEST_MODE
if (g_usbd_core[busid].test_req) {
usbd_execute_test_mode(busid, HI_BYTE(setup->wIndex));
g_usbd_core[busid].test_req = false;
}
#endif
}
}
}
@@ -1090,6 +1227,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;
@@ -1173,6 +1312,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)
@@ -1193,12 +1337,53 @@ void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep)
}
}
uint16_t usbd_get_ep_mps(uint8_t busid, uint8_t ep)
{
if (ep & 0x80) {
return g_usbd_core[busid].tx_msg[ep & 0x7f].ep_mps;
} else {
return g_usbd_core[busid].rx_msg[ep & 0x7f].ep_mps;
}
}
uint8_t usbd_get_ep_mult(uint8_t busid, uint8_t ep)
{
if (ep & 0x80) {
return g_usbd_core[busid].tx_msg[ep & 0x7f].ep_mult;
} else {
return g_usbd_core[busid].rx_msg[ep & 0x7f].ep_mult;
}
}
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;
@@ -1221,9 +1406,9 @@ 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);
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 */
@@ -67,16 +69,16 @@ struct usb_descriptor {
const uint8_t *(*config_descriptor_callback)(uint8_t speed);
const uint8_t *(*device_quality_descriptor_callback)(uint8_t speed);
const uint8_t *(*other_speed_descriptor_callback)(uint8_t speed);
const uint8_t *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
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,13 +94,19 @@ 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);
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);
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);
int usbd_send_remote_wakeup(uint8_t busid);
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

@@ -79,37 +79,40 @@ static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
return 0;
}
static int usbh_free_devaddr(struct usbh_hubport *hport)
{
if (hport->dev_addr > 0) {
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
}
return 0;
}
static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol,
uint16_t vid, uint16_t pid)
{
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_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) ==
(USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) {
if (index->vid == vid && index->pid == pid &&
index->class == class && index->subclass == subclass && index->protocol == protocol) {
return index->class_driver;
if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) {
continue;
}
if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) {
continue;
}
if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == 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++) {
}
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) ==
(USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) {
if (index->class == class && index->subclass == subclass && index->protocol == protocol) {
return index->class_driver;
}
} else if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) ==
(USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) {
if (index->vid == vid && index->pid == pid && index->class == class) {
return index->class_driver;
}
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) == (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS)) {
if (index->class == class && index->subclass == subclass) {
return index->class_driver;
}
} else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) == USB_CLASS_MATCH_INTF_CLASS) {
if (index->class == class) {
return index->class_driver;
/* do not match, continue next */
if (!index->id_table[i][0]) {
continue;
}
}
return index->class_driver;
}
return NULL;
}
@@ -334,18 +337,346 @@ static int usbh_get_default_mps(int speed)
}
}
int usbh_free_devaddr(struct usbh_hubport *hport)
int usbh_enumerate(struct usbh_hubport *hport)
{
#ifndef CONFIG_USBHOST_XHCI
if (hport->dev_addr > 0) {
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
struct usb_interface_descriptor *intf_desc;
struct usb_setup_packet *setup;
struct usb_device_descriptor *dev_desc;
struct usb_endpoint_descriptor *ep;
int dev_addr;
uint16_t ep_mps;
uint8_t config_value;
uint8_t config_index;
int ret;
hport->setup = &g_setup_buffer[hport->bus->busid][hport->parent->index - 1][hport->port - 1];
setup = hport->setup;
ep = &hport->ep0;
/* Config EP0 mps from speed */
ep->bEndpointAddress = 0x00;
ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
ep->wMaxPacketSize = usbh_get_default_mps(hport->speed);
ep->bInterval = 0;
ep->bLength = 7;
/* Configure EP0 with zero address */
hport->dev_addr = 0;
/* Read the first 8 bytes of the device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
setup->wIndex = 0;
setup->wLength = 8;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], 8);
/* Extract the correct max packetsize from the device descriptor */
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
if (dev_desc->bcdUSB >= USB_3_0) {
ep_mps = 1 << dev_desc->bMaxPacketSize0;
} else {
ep_mps = dev_desc->bMaxPacketSize0;
}
USB_LOG_DBG("Device rev=%04x cls=%02x sub=%02x proto=%02x size=%d\r\n",
dev_desc->bcdUSB, dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
dev_desc->bDeviceProtocol, ep_mps);
/* Reconfigure EP0 with the correct maximum packet size */
ep->wMaxPacketSize = ep_mps;
/* 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;
}
/* Set the USB device address */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_SET_ADDRESS;
setup->wValue = dev_addr;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
goto errout;
}
/* Wait device set address completely */
usb_osal_msleep(2);
/*Reconfigure EP0 with the correct address */
hport->dev_addr = dev_addr;
/* Read the full device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_DEVICE_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bcdDevice);
USB_LOG_INFO("The device has %d bNumConfigurations\r\n", ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumConfigurations);
config_index = 0;
USB_LOG_DBG("The device selects config %d\r\n", config_index);
/* Read the first 9 bytes of the config descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_CONFIG_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_CONFIG_DESC);
/* Read the full size of the configuration data */
uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->wTotalLength;
if (wTotalLength > CONFIG_USBHOST_REQUEST_BUFFER_LEN) {
ret = -USB_ERR_NOMEM;
USB_LOG_ERR("wTotalLength %d is overflow, default is %d\r\n", wTotalLength, CONFIG_USBHOST_REQUEST_BUFFER_LEN);
goto errout;
}
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
setup->wIndex = 0;
setup->wLength = wTotalLength;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], wTotalLength);
if (ret < 0) {
USB_LOG_ERR("Parse config fail\r\n");
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_osal_malloc(wTotalLength);
if (hport->raw_config_desc == NULL) {
ret = -USB_ERR_NOMEM;
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
goto errout;
}
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);
#ifdef CONFIG_USBHOST_GET_STRING_DESC
uint8_t string_buffer[128];
/* Get Manufacturer string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_MFC_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
/* Get Product string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_PRODUCT_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("Product: %s\r\n", string_buffer);
/* Get SerialNumber string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_SERIAL_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("SerialNumber: %s\r\n", string_buffer);
#endif
/* Select device configuration 1 */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
setup->wValue = config_value;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
goto errout;
}
#ifdef CONFIG_USBHOST_MSOS_ENABLE
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
setup->wValue = 0;
setup->wIndex = 0x0004;
setup->wLength = 16;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0 && (ret != -USB_ERR_STALL)) {
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
goto errout;
}
#endif
USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
/*search supported class driver*/
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
hport->dev_addr = 0;
struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct);
if (class_driver == NULL) {
USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n",
intf_desc->bInterfaceClass,
intf_desc->bInterfaceSubClass,
intf_desc->bInterfaceProtocol);
continue;
}
hport->config.intf[i].class_driver = class_driver;
USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
ret = CLASS_CONNECT(hport, i);
}
errout:
if (hport->raw_config_desc) {
usb_osal_free(hport->raw_config_desc);
hport->raw_config_desc = NULL;
}
return ret;
}
void usbh_hubport_release(struct usbh_hubport *hport)
{
if (hport->connected) {
hport->connected = false;
usbh_free_devaddr(hport);
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->disconnect) {
CLASS_DISCONNECT(hport, i);
}
}
hport->config.config_desc.bNumInterfaces = 0;
usbh_kill_urb(&hport->ep0_urb);
if (hport->mutex) {
usb_osal_mutex_delete(hport->mutex);
}
}
}
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_base)
{
memset(bus, 0, sizeof(struct usbh_bus));
bus->busid = busid;
bus->hcd.hcd_id = busid;
bus->hcd.reg_base = reg_base;
/* devaddr 1 is for roothub */
bus->devgen.next = 2;
usb_slist_add_tail(&g_bus_head, &bus->list);
}
int usbh_initialize(uint8_t busid, uintptr_t reg_base)
{
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_bus_init(bus, busid, reg_base);
#ifdef __ARMCC_VERSION /* ARM C Compiler */
extern const int usbh_class_info$$Base;
extern const int usbh_class_info$$Limit;
usbh_class_info_table_begin = (struct usbh_class_info *)&usbh_class_info$$Base;
usbh_class_info_table_end = (struct usbh_class_info *)&usbh_class_info$$Limit;
#elif defined(__GNUC__)
extern uint32_t __usbh_class_info_start__;
extern uint32_t __usbh_class_info_end__;
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin(".usbh_class_info");
usbh_class_info_table_end = (struct usbh_class_info *)__section_end(".usbh_class_info");
#endif
usbh_hub_initialize(bus);
return 0;
}
int usbh_deinitialize(uint8_t busid)
{
struct usbh_bus *bus;
bus = &g_usbhost_bus[busid];
usbh_hub_deinitialize(bus);
usb_slist_remove(&g_bus_head, &bus->list);
return 0;
}
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
{
struct usbh_urb *urb;
int ret;
urb = &hport->ep0_urb;
usb_osal_mutex_take(hport->mutex);
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
usb_osal_mutex_give(hport->mutex);
return ret;
}
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
{
struct usb_setup_packet *setup = hport->setup;
@@ -394,360 +725,29 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett
return usbh_control_transfer(hport, setup, NULL);
}
int usbh_enumerate(struct usbh_hubport *hport)
{
struct usb_interface_descriptor *intf_desc;
struct usb_setup_packet *setup;
struct usb_device_descriptor *dev_desc;
struct usb_endpoint_descriptor *ep;
int dev_addr;
uint16_t ep_mps;
int ret;
hport->setup = &g_setup_buffer[hport->bus->busid][hport->parent->index - 1][hport->port - 1];
setup = hport->setup;
ep = &hport->ep0;
/* Config EP0 mps from speed */
ep->bEndpointAddress = 0x00;
ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
ep->wMaxPacketSize = usbh_get_default_mps(hport->speed);
ep->bInterval = 0;
ep->bLength = 7;
/* Configure EP0 with zero address */
hport->dev_addr = 0;
/* Read the first 8 bytes of the device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
setup->wIndex = 0;
setup->wLength = 8;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], 8);
/* Extract the correct max packetsize from the device descriptor */
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
if (dev_desc->bcdUSB >= USB_3_0) {
ep_mps = 1 << dev_desc->bMaxPacketSize0;
} else {
ep_mps = dev_desc->bMaxPacketSize0;
}
USB_LOG_DBG("Device rev=%04x cls=%02x sub=%02x proto=%02x size=%d\r\n",
dev_desc->bcdUSB, dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
dev_desc->bDeviceProtocol, ep_mps);
/* 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;
setup->bRequest = USB_REQUEST_SET_ADDRESS;
setup->wValue = dev_addr;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
goto errout;
}
/* Wait device set address completely */
usb_osal_msleep(2);
/*Reconfigure EP0 with the correct address */
hport->dev_addr = dev_addr;
/* Read the full device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_DEVICE_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bcdDevice);
/* Read the first 9 bytes of the config descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | 0);
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_CONFIG_DESC;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, USB_SIZEOF_CONFIG_DESC);
/* Read the full size of the configuration data */
uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer)->wTotalLength;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | 0);
setup->wIndex = 0;
setup->wLength = wTotalLength;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
goto errout;
}
ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], wTotalLength);
if (ret < 0) {
USB_LOG_ERR("Parse config fail\r\n");
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);
if (hport->raw_config_desc == NULL) {
ret = -USB_ERR_NOMEM;
USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
goto errout;
}
memcpy(hport->raw_config_desc, ep0_request_buffer, wTotalLength);
#ifdef CONFIG_USBHOST_GET_STRING_DESC
uint8_t string_buffer[128];
/* Get Manufacturer string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_MFC_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
/* Get Product string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_PRODUCT_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("Product: %s\r\n", string_buffer);
/* Get SerialNumber string */
memset(string_buffer, 0, 128);
ret = usbh_get_string_desc(hport, USB_STRING_SERIAL_INDEX, string_buffer);
if (ret < 0) {
USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret);
goto errout;
}
USB_LOG_INFO("SerialNumber: %s\r\n", string_buffer);
#endif
/* Select device configuration 1 */
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
setup->wValue = 1;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
goto errout;
}
#ifdef CONFIG_USBHOST_MSOS_ENABLE
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
setup->wValue = 0;
setup->wIndex = 0x0004;
setup->wLength = 16;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
if (ret < 0 && (ret != -EPERM)) {
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
goto errout;
}
#endif
USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
/*search supported class driver*/
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct);
if (class_driver == NULL) {
USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n",
intf_desc->bInterfaceClass,
intf_desc->bInterfaceSubClass,
intf_desc->bInterfaceProtocol);
continue;
}
hport->config.intf[i].class_driver = class_driver;
USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
ret = CLASS_CONNECT(hport, i);
}
errout:
if (hport->raw_config_desc) {
usb_free(hport->raw_config_desc);
hport->raw_config_desc = NULL;
}
return ret;
}
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
{
struct usbh_hub *hub;
memset(bus, 0, sizeof(struct usbh_bus));
bus->busid = busid;
bus->hcd.hcd_id = busid;
bus->hcd.reg_base = 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)
{
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_bus_init(bus, busid, reg_base);
#ifdef __ARMCC_VERSION /* ARM C Compiler */
extern const int usbh_class_info$$Base;
extern const int usbh_class_info$$Limit;
usbh_class_info_table_begin = (struct usbh_class_info *)&usbh_class_info$$Base;
usbh_class_info_table_end = (struct usbh_class_info *)&usbh_class_info$$Limit;
#elif defined(__GNUC__)
extern uint32_t __usbh_class_info_start__;
extern uint32_t __usbh_class_info_end__;
usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin("usbh_class_info");
usbh_class_info_table_end = (struct usbh_class_info *)__section_end("usbh_class_info");
#endif
usbh_hub_initialize(bus);
return 0;
}
int usbh_deinitialize(uint8_t busid)
{
struct usbh_bus *bus;
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;
}
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
{
struct usbh_urb *urb;
int ret;
urb = &hport->ep0_urb;
usb_osal_mutex_take(hport->mutex);
memset(urb, 0, sizeof(struct usbh_urb));
usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
usb_osal_mutex_give(hport->mutex);
return ret;
}
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;
}
}
}
}
}
@@ -756,11 +756,103 @@ 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);
}
}
}
}
}
}
}
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;
}
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");
@@ -783,69 +875,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->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" {
@@ -30,6 +32,7 @@ extern "C" {
#define USB_CLASS_MATCH_INTF_CLASS 0x0004
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
#define USB_CLASS_MATCH_VID_PID (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT)
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
@@ -39,28 +42,29 @@ extern "C" {
#elif defined(__GNUC__)
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
#pragma section = "usbh_class_info"
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
#pragma section = ".usbh_class_info"
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#endif
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? interval : (1 << (interval - 1)))
#define USBH_EP_INIT(ep, ep_desc) \
do { \
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. */
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
uint16_t pid; /* Product ID (for vendor/product specific devices) */
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. */
const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
const struct usbh_class_driver *class_driver;
};
@@ -98,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;
@@ -106,28 +113,32 @@ 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;
struct usb_endpoint_descriptor *intin;
struct usbh_urb intin_urb;
uint8_t *int_buffer;
struct usb_osal_timer *int_timer;
};
struct usbh_devaddr_map {
@@ -143,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;
};
@@ -156,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,
@@ -214,6 +224,7 @@ static inline void usbh_int_urb_fill(struct usbh_urb *urb,
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
urb->interval = USBH_GET_URB_INTERVAL(ep->bInterval, hport->speed);
}
extern struct usbh_bus g_usbhost_bus[];
@@ -235,11 +246,11 @@ int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *s
/**
* @brief Retrieves a USB string descriptor from a specific hub port.
*
*
* This function is responsible for retrieving the USB string descriptor
* with the specified index from the USB device connected to the given hub port.
* The retrieved descriptor is stored in the output buffer provided.
*
*
* @param hport Pointer to the USB hub port structure.
* @param index Index of the string descriptor to retrieve.
* @param output Pointer to the buffer where the retrieved descriptor will be stored.
@@ -249,11 +260,11 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
/**
* @brief Sets the alternate setting for a USB interface on a specific hub port.
*
*
* This function is responsible for setting the alternate setting of the
* specified USB interface on the USB device connected to the given hub port.
* The interface and alternate setting are identified by the respective parameters.
*
*
* @param hport Pointer to the USB hub port structure.
* @param intf Interface number to set the alternate setting for.
* @param altsetting Alternate setting value to set for the interface.
@@ -261,7 +272,7 @@ 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);

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,
0x01,
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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -176,12 +181,14 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
tx_flag = 1;
ep_tx_busy_flag = false;
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
ep_tx_busy_flag = false;
tx_flag = 0;
}
@@ -205,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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -181,6 +186,7 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
printf("OPEN1\r\n");
} else {
tx_flag = 1;
ep_tx_busy_flag = false;
printf("OPEN2\r\n");
}
}
@@ -188,10 +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;
rx_flag = 0;
printf("CLOSE1\r\n");
} else {
tx_flag = 0;
ep_tx_busy_flag = false;
printf("CLOSE2\r\n");
}
}
@@ -231,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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -224,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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -270,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;
@@ -341,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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -242,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,
0x01,
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

@@ -1,6 +1,11 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_msc.h"
#include "usbd_cdc.h"
#include "usbd_cdc_acm.h"
#include "usbd_hid.h"
/*!< endpoint address */
@@ -228,16 +233,10 @@ static struct usbd_endpoint hid_in_ep = {
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
volatile bool ep_tx_busy_flag = false;
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
@@ -252,6 +251,8 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
ep_tx_busy_flag = false;
hid_state = HID_STATE_IDLE;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
@@ -276,7 +277,7 @@ void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
@@ -300,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);

View File

@@ -1,5 +1,10 @@
/*
* Copyright (c) 2024, sakumisu
*
* 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 */
@@ -57,76 +62,13 @@ static const uint8_t device_quality_descriptor[] = {
0x00,
};
static const uint8_t string0_descriptor[] = {
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC MSC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t string1_descriptor[] = {
///////////////////////////////////////
/// 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 */
};
static const uint8_t string2_descriptor[] = {
///////////////////////////////////////
/// 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 */
'C', 0x00, /* wcChar10 */
'-', 0x00, /* wcChar11 */
'M', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
};
static const uint8_t string3_descriptor[] = {
///////////////////////////////////////
/// 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 */
};
static const uint8_t *string_descriptors[4] = { string0_descriptor, string1_descriptor, string2_descriptor, string3_descriptor };
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
@@ -142,7 +84,7 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
return device_quality_descriptor;
}
static const uint8_t *string_descriptor_callback(uint8_t speed, uint8_t index)
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
@@ -238,17 +180,11 @@ static const uint8_t cdc_msc_descriptor[] = {
};
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
volatile bool ep_tx_busy_flag = false;
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
@@ -263,6 +199,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
ep_tx_busy_flag = false;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
@@ -287,7 +224,7 @@ void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
@@ -310,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

@@ -1,5 +1,10 @@
/*
* Copyright (c) 2024, sakumisu
*
* 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
@@ -115,16 +120,10 @@ static const uint8_t cdc_descriptor[] = {
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[4][2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[4][2048] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[4][2048];
volatile bool ep_tx_busy_flag = false;
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
@@ -139,6 +138,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
ep_tx_busy_flag = false;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP2, read_buffer, 2048);
@@ -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

@@ -1,5 +1,10 @@
/*
* Copyright (c) 2024, sakumisu
*
* 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
@@ -99,17 +104,11 @@ static const uint8_t cdc_descriptor[] = {
0x00
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
volatile bool ep_tx_busy_flag = false;
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
@@ -124,6 +123,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
ep_tx_busy_flag = false;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
@@ -152,7 +152,7 @@ void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
@@ -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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
@@ -210,6 +215,7 @@ 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);
@@ -259,14 +265,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

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_rndis.h"
@@ -138,7 +143,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;
@@ -242,6 +251,7 @@ 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);
@@ -294,7 +304,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