318 Commits

Author SHA1 Message Date
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
sakumisu
850e96577c fix missing bus in sunxi 2024-03-02 13:14:58 +08:00
sakumisu
384b11eb88 release v1.1.0 2024-02-25 21:07:13 +08:00
sakumisu
cfbe5615c4 disable device shell cmd 2024-02-25 21:06:03 +08:00
sakumisu
cbefa69715 disable net class 2024-02-24 16:41:37 +08:00
sakumisu
9e0cc8347c align for some buffers 2024-02-24 16:38:57 +08:00
sakumisu
8c72947794 fix bl glue 2024-02-24 16:34:43 +08:00
sakumisu
d5b4cdd4bd update img 2024-02-24 15:01:28 +08:00
sakumisu
3508879e1d fix asix output zlp 2024-02-24 14:57:01 +08:00
sakumisu
5c36affc3c classify vendor class 2024-02-24 13:35:41 +08:00
sakumisu
762c3cbb2f add get_connect_status api for rndis/cdc_ecm/asix 2024-02-24 10:49:11 +08:00
Zhihong Chen
b4e952b371 port: HPMicro: call suspend/connect/disconnect event
- call suspend/connect/disconnect event

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-23 16:55:58 +08:00
Zhihong Chen
756987050f class: msc: stage change should be before usbd_ep_start_write()
- stage change should be before usbd_ep_start_write()

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-23 10:42:53 +08:00
sakumisu
64773ab5e8 remove duplicate class info 2024-02-22 22:32:27 +08:00
Zhihong Chen
743669861e port: HPMicro: fix transfer_len not reset
- fix transfer_len not reset

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-20 22:10:56 +08:00
Zhihong Chen
0e3e9477cc port: HPMicro: decoupling the relationship between busid and usbid
- decoupling the relationship between busid and usbid

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-20 14:28:10 +08:00
sakumisu
56c90ab6f9 update rst 2024-02-19 20:31:19 +08:00
sakumisu
9c247f6e6b update asix phy config 2024-02-19 20:22:07 +08:00
Zhihong Chen
556fd6af63 HPMicro: port: fix _dcd_data align to 2048
- fix _dcd_data align to 2048

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-19 20:19:48 +08:00
Zhihong Chen
4803a6826b update endpoint number usage and fix busid check
Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-19 20:19:48 +08:00
sakumisu
e0551b3e7b config busid and regbase in usbh_initialize and usbd_initialize 2024-02-18 21:15:04 +08:00
sakumisu
31fa2b99c5 enable asix host driver 2024-02-15 22:54:14 +08:00
sakumisu
4313a2666e check if device is on extern hub 2024-02-09 12:35:44 +08:00
sakumisu
466d241c31 update doc 2024-02-09 12:21:40 +08:00
sakumisu
49116c6fbc format code 2024-02-09 12:08:08 +08:00
sakumisu
e7a57289ce update license year 2024-02-09 12:07:29 +08:00
sakumisu
e34ecc6cbb add volatile for HcEpType & ChannelEna 2024-02-07 21:37:17 +08:00
sakumisu
d1c7fa8c19 support multi port api for device 2024-02-06 19:52:22 +08:00
Zhihong Chen
920b02cb7c class: msc device: support multi lun
- support multi lun

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-06 18:31:47 +08:00
Zhihong Chen
3f89d1b003 usbd: change endpoint number from 8 to 16
- Because the maximum number of endpoints specified in the USB protocol is 16, and some vendors support 16 endpoints

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-02-06 18:31:47 +08:00
sakumisu
5897edffed make serial driver standard for cdc acm, ftdi, cp210x, ch34x 2024-02-03 22:20:58 +08:00
sakumisu
a01c08ddaa use cdc_linecoding and line state for ftdi 2024-02-02 23:37:46 +08:00
sakumisu
dcad369d06 add ftdi host 2024-02-02 22:53:54 +08:00
sakumisu
8232f64775 add nrf usbhci firmware 2024-02-01 20:49:31 +08:00
sakumisu
6fb3f31cbe add usbhci_h4 log and update bluetooth submodule 2024-01-31 20:52:01 +08:00
sakumisu
eeb304ae08 update log tag 2024-01-30 23:04:35 +08:00
sakumisu
fc80972284 add nimble submodule 2024-01-29 21:16:05 +08:00
sakumisu
feb69dcd95 add zephyr bluetooth submodule 2024-01-29 21:14:35 +08:00
sakumisu
cdfb7c3fb2 support hci usb h4 for usb bluetooth 2024-01-25 22:06:39 +08:00
sakumisu
24511c4d4b fix actual len position 2024-01-23 22:05:10 +08:00
sakumisu
c7cf09f6c3 update nimble porting with freertos 2024-01-22 19:49:23 +08:00
sakumisu
6b0a0135ac remove ununsed macro 2024-01-23 07:39:41 +08:00
sakumisu
04a300d803 remove ununsed header 2024-01-19 23:08:04 +08:00
sakumisu
0f5e05052f add usbd init and deinit event macro 2024-01-16 22:50:48 +08:00
sakumisu
b773cecd2e add ecm device write and read api 2024-01-14 18:49:41 +08:00
Zhihong Chen
c4a65146e8 port: hpmicro: fix usb_dc_deinit()
- fix usb_dc_deinit()

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-01-14 17:00:40 +08:00
Zhihong Chen
6bc6b06076 usbh_core: add iar risc-v support
- add iar risc-v support

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2024-01-14 17:00:40 +08:00
sakumisu
125aad65d6 dwc2 use fifo not dma as default because users may have problems in cache 2024-01-13 00:22:03 +08:00
sakumisu
07ced6d023 fix cdc ecm zlp check 2024-01-09 21:20:38 +08:00
sakumisu
45cca3930b update bluetooth rx callback, add zephyr bluetooth stack porting 2024-01-09 21:18:59 +08:00
sakumisu
eff338f8a7 add ehci hccr offset macro 2024-01-09 20:59:04 +08:00
sakumisu
1158fc3d8c support multi USB IP for host 2024-01-08 22:47:28 +08:00
sakumisu
d517f2594e fix macro name 2024-01-06 17:47:22 +08:00
sakumisu
b37f494304 support usb ble host 2024-01-06 12:53:22 +08:00
sakumisu
5fe66b4f0d dwc2: ctrl and bulk no need nak irq, when intr calls nak, retry by user 2024-01-06 01:09:55 +08:00
sakumisu
249e650c37 rename CONFIG_USBDEV_MSC_BLOCK_SIZE to CONFIG_USBDEV_MSC_MAX_BUFSIZE 2024-01-06 01:07:39 +08:00
sakumisu
cbfac7ec0c dwc2 low level deinit after usb register reset 2024-01-06 01:07:39 +08:00
sakumisu
7df43ba6a2 release v1.0.0 2023-12-30 15:42:23 +08:00
sakumisu
e58a78c070 add aic & intel ehci glue, add rtems osal 2023-12-30 15:01:20 +08:00
sakumisu
1492b8cca9 remove ch32 host, nrf5x, rp2040 port 2023-12-30 14:44:52 +08:00
sakumisu
67a3bbe02e fix hctsiz macro name 2023-12-30 14:39:34 +08:00
sakumisu
65b2de960b update gccfg for stm32h7/f7 2023-12-30 14:39:26 +08:00
sakumisu
019c9cff6e fix dwc2 out chan actual len 2023-12-28 20:57:50 +08:00
sakumisu
2662a3497d add \t for hub info log 2023-12-27 20:21:10 +08:00
sakumisu
7f7add7cec update memory usage 2023-12-27 20:20:25 +08:00
sakumisu
fa2900d4cd fix rst grammar 2023-12-26 23:04:54 +08:00
sakumisu
d30d08ca3a musb do not use alloc pipe 2023-12-26 22:52:32 +08:00
sakumisu
02685793aa update demo version 2023-12-26 20:37:23 +08:00
sakumisu
8cd31e6be0 add check for dwc2 ramsize and ep num 2023-12-26 20:11:23 +08:00
sakumisu
56c2b34131 update stm32 demo rst 2023-12-25 22:06:35 +08:00
sakumisu
f68a86ea89 add usbh_deinitialize api 2023-12-24 23:37:47 +08:00
sakumisu
8a831cdaa5 user must define some configs in usb_config.h when use fsdev/musb/dwc2 2023-12-21 21:58:08 +08:00
sakumisu
44e9c1cf4f register desc with callback when enable CONFIG_USBDEV_ADVANCE_DESC 2023-12-20 20:24:47 +08:00
sakumisu
e201439722 create lwip rx thread by user 2023-12-19 21:38:55 +08:00
sakumisu
01f9025b6b init demo thread in xxx_run api, and delete by itself 2023-12-18 20:52:26 +08:00
sakumisu
bb709437aa fix musb submit_urb by 5bbe2a97 2023-12-18 20:52:07 +08:00
sakumisu
7b936db889 remove vendor host class because its version is too old 2023-12-16 23:22:41 +08:00
sakumisu
6db1ef3a40 update demo version 2023-12-16 23:19:57 +08:00
sakumisu
8f991699cb remove mtp & printer class 2023-12-16 17:20:52 +08:00
sakumisu
29d45ef5c7 replace struct usbd_endpoint_cfg with struct usb_endpoint_descriptor in usbh_ep_open api 2023-12-10 22:34:01 +08:00
FanHuaCloud
a1ed27523c AT32 gccfg adds the vbusig flag by default 2023-12-09 14:45:14 +08:00
sakumisu
ce2a438c99 fix uninitialized warning 2023-12-05 21:39:36 +08:00
sakumisu
297852ce16 update host api rst 2023-12-05 21:35:00 +08:00
sakumisu
b1e95f0ca3 update hc template 2023-12-05 21:34:51 +08:00
sakumisu
14f1f597f1 add usb errno, do not use system errno 2023-12-05 21:34:32 +08:00
sakumisu
48730e20be add usb_osal_sem_reset api 2023-12-05 20:49:26 +08:00
sakumisu
11e389f922 Revert "reset sem before taking"
This reverts commit b5f0c043e7.
2023-12-05 20:45:21 +08:00
sakumisu
82cd79989c check token only with qtd, not use token in qh 2023-12-05 20:44:30 +08:00
sakumisu
fe18d36fe0 implement rtt eth_device control and eth_tx api 2023-12-01 20:44:24 +08:00
sakumisu
d414fd21d8 add config for rndis & ecm thread 2023-12-01 20:43:13 +08:00
sakumisu
c8a11be013 add two dhcp timer 2023-11-30 21:34:18 +08:00
sakumisu
fb6a463cc1 implement rt_hw_cpu_dcache_ops api 2023-11-30 21:33:22 +08:00
sakumisu
7e3795c191 auto enable lwip demo with __has_include 2023-11-29 21:04:50 +08:00
sakumisu
22d60b4300 add align check for rtt disk port 2023-11-29 21:03:19 +08:00
sakumisu
85e73197f9 update rtt dfs port 2023-11-28 20:41:58 +08:00
sakumisu
c90f273e24 port and add comment for gccfg with gd/at/st 2023-11-27 20:30:15 +08:00
sakumisu
b14976dd56 fix usbh_set_interface api, correct wValue for altsetting 2023-11-27 20:29:24 +08:00
sakumisu
9cd88c0ca3 update dwc2 rst 2023-11-26 23:06:09 +08:00
sakumisu
3440e0cc1d move out dwc2 ggcfg register and config by user 2023-11-26 22:59:41 +08:00
ovo
849ea98853 bugfix: send zlp won't trigger ep tx interrupt 2023-11-26 18:48:11 +08:00
sakumisu
b5f0c043e7 reset sem before taking 2023-11-24 21:11:25 +08:00
sakumisu
84299ce80b delete lwip rx thread in self 2023-11-24 21:11:05 +08:00
sakumisu
8e0c5b4e7e find roothub port to check if device is connecting 2023-11-24 21:09:45 +08:00
sakumisu
8ae4453ca4 fix en colon 2023-11-23 22:50:07 +08:00
Zhihong Chen
86c7e435a3 hpmicro: update port files
- update port files

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-11-23 15:21:11 +08:00
sakumisu
074f30a7b4 disable device not find log 2023-11-22 21:45:13 +08:00
sakumisu
50e1cd3471 add mutex for ep0 urb to avoid multithreading 2023-11-22 21:44:51 +08:00
sakumisu
b7d02b7125 reset rx length when pbuf allocs failed 2023-11-22 21:43:57 +08:00
sakumisu
5b32482c3e free pipe after sem giving 2023-11-22 21:42:56 +08:00
sakumisu
18eed18413 add some delay to avoid too much error log when device is disconnected 2023-11-22 19:28:30 +08:00
sakumisu
98c6ac25ec update readme 2023-11-22 19:28:30 +08:00
sakumisu
af1484882d support ehci suspend & resume 2023-11-22 19:28:30 +08:00
sakumisu
e3c9fdbb86 reduce qtd num 2023-11-22 19:28:30 +08:00
sakumisu
03db11f4af add ecm and rndis thread delete for dynamic netif 2023-11-22 19:28:30 +08:00
sakumisu
d6bd89f274 set CONFIG_USBHOST_PSC_PRIO to zero to making usb prio highest 2023-11-22 19:28:30 +08:00
sakumisu
9ea2121c7c make hub_set_feature and hub_clear_feature api public 2023-11-20 22:15:43 +08:00
sakumisu
bbcb433564 support host demo with timer for rtthread 2023-11-20 22:15:33 +08:00
sakumisu
7989708bfe add dhcp timer for getting ip addr 2023-11-20 16:59:18 +08:00
sakumisu
07fa211f40 remove rndis code in third party because it is implemented internally 2023-11-17 23:37:15 +08:00
sakumisu
73eb69bfa2 remove usb_mem.h 2023-11-17 21:05:31 +08:00
sakumisu
a08097c90e use static urb for ep0 2023-11-17 21:05:07 +08:00
sakumisu
5bbe2a97f2 refactor urb, add ep & hport in urb to make hardware pipe more reusable 2023-11-16 19:56:52 +08:00
sakumisu
c1435548e7 release v0.10.2 2023-11-15 22:02:16 +08:00
sakumisu
a8d40eb706 fix ecm mac buffer size 2023-11-15 22:02:07 +08:00
zhugengyu
aeffaea016 add pusb2 port, fix issue for rt-thread, add msc storage demo for rt-thread 2023-11-15 16:48:07 +08:00
sakumisu
9ce7b0ceb7 fix rndis query & set msg wLength, only support one rndis device 2023-11-13 20:03:35 +08:00
sakumisu
1c31156a37 add ms os request 2023-11-13 19:51:53 +08:00
sakumisu
e795ab73a0 check and execute modeswitch first 2023-11-13 19:50:37 +08:00
sakumisu
5e689dfe15 fix class api name 2023-11-13 19:50:04 +08:00
sakumisu
d10cbd5daf check if token is active without errors, if token has errors, go to wakeup sem 2023-11-13 19:49:49 +08:00
sakumisu
40a019e063 add ecm host demo 2023-11-13 19:49:27 +08:00
sakumisu
2080cf1206 add usbh_set_interface api 2023-11-11 14:00:29 +08:00
Yang Xijing
ae521bf95c add nuvoton port(not release) 2023-11-05 14:38:26 +08:00
sakumisu
a2f7b67dc4 update config rst 2023-11-04 17:16:43 +08:00
sakumisu
e79319cac9 add cdc ecm host 2023-11-04 17:16:24 +08:00
sakumisu
7acb667e20 support usb modeswitch 2023-11-04 16:45:20 +08:00
sakumisu
a04b1fa551 add cdc ecm device 2023-11-04 16:44:02 +08:00
sakumisu
c37c60c7c7 add usbh_get_string_desc api 2023-11-04 15:24:15 +08:00
sakumisu
0738c09a4d check qtd active status to fix nbytes = 0 in nak or ping status 2023-11-03 22:18:58 +08:00
sakumisu
cf4dfde49d update quick start, add readthedocs yaml 2023-10-13 20:39:11 +08:00
Zhihong Chen
d4ba2eef57 osal: add USB_OSAL_WAITING_FOREVER for Semaphore and Queue use
- add USB_OSAL_WAITING_FOREVER for Semaphore and Queue use

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-10-12 14:38:13 +08:00
Chen Leeren
3d96f64f94 Fix possible errors in endpoint 0 datapid 2023-10-07 23:46:28 +08:00
sakumisu
a746eb4bb1 update demo version 2023-10-05 17:12:32 +08:00
sakumisu
c84e769f78 remove ununsed input variable 2023-09-30 22:01:12 +08:00
helloeagleyang
d11260ef67 [common] Avoid IAR compiling error on USB HOST stack
- Avoided using a structure with zero-length array as a field in another
  structure when IAR toolchain is used.

Signed-off-by: helloeagleyang <helloeagleyang@163.com>
2023-09-18 00:10:39 +08:00
Wayne Lin
e6193bd131 Revert original parameter. 2023-09-07 15:07:04 +08:00
Wayne Lin
dd1f1d3ba8 Update hcd-ehci, dcd-dwc2 and examples.
1. Add some example Msh commands.
2. Fix device enumeration on EXT hub.
3. Re-file some templates.
4. Extend end-point number of dwc2 device driver.
5. Re-file rndis_host implementation includes
   a. rt_mutex_take in ISR
   b. 2rd pmsg is unaligned issue.
   c. destroy u0 ethernet resource after removing dongle.
2023-09-07 15:07:04 +08:00
sakumisu
bc1e7c4bd5 ignore dwc2 EPENA check 2023-09-04 15:43:32 +08:00
Runcheng Lu
7d76b4bae1 third_party: rtthread: add rndis to adapt lwip2.1.2 2023-09-01 16:13:34 +08:00
sakumisu
7c0ef50bb3 release v0.10.1 2023-08-30 20:05:04 +08:00
sakumisu
0f2cb9f900 fix warning 2023-08-30 20:03:18 +08:00
sakumisu
7c1fae04b2 fix video packet caculation 2023-08-30 17:43:13 +08:00
sakimisu
14f5dd2dd3 implement msc device thread,remove other unused os thread 2023-08-29 14:40:03 +08:00
sakimisu
9029f8c5b1 fix warning 2023-08-27 13:38:13 +08:00
Zhihong Chen
b9915e0e1b port: hpmicro: separate host and device USB instance config
- separate host and device USB instance config

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-26 12:45:31 +08:00
sakimisu
1387790744 add config for hpmicro usb instance and irq 2023-08-26 01:09:33 +08:00
sakimisu
c5fc9f338e fix macro spelling 2023-08-25 21:37:14 +08:00
sakimisu
4d61e5e053 copy bouffalo ehci glue from official sdk 2023-08-25 21:36:58 +08:00
sakimisu
1a7259649b standardize video control api 2023-08-25 21:36:27 +08:00
sakimisu
628e4ee928 improve ehci driver, enable iaad feature 2023-08-25 21:36:14 +08:00
sakimisu
749369b6fc remove usb_phy_init, because hpm sdk v1.2 implement it 2023-08-25 21:35:42 +08:00
Fan YANG
89cd77374c common: Add support for IAR for risc-v toolchain
- Added support for the IAR for risc-v toolchain

Signed-off-by: Fan YANG <fan.yang@hpmicro.com>
2023-08-18 23:33:02 +08:00
sakumisu
3792ad4905 add test scripts 2023-08-15 14:33:54 +08:00
heyuanjie87
2789633b50 [hub 修正] 快速断开的情况下无法处理断开事件 2023-08-13 09:40:01 +08:00
289 changed files with 58337 additions and 23144 deletions

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth"]
path = third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth
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 = https://github.com/sakumisu/mynewt-nimble.git

35
.readthedocs.yaml Normal file
View File

@@ -0,0 +1,35 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/source/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
# fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt

View File

@@ -1,57 +0,0 @@
add_library(cherryusb STATIC)
target_include_directories(cherryusb PUBLIC
common
core
osal
class/cdc
class/hid
class/msc
class/audio
class/video
class/hub
class/wireless
)
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
)
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()
endif()

3
CherryUSB.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 38 KiB

304
Kconfig.cherryusb Normal file
View File

@@ -0,0 +1,304 @@
# Kconfig file for CherryUSB
menuconfig CHERRYUSB
bool "Using CherryUSB"
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_CUSTOM
bool "dwc2_custom"
config CHERRYUSB_DEVICE_MUSB_STANDARD
bool "musb_standard"
config CHERRYUSB_DEVICE_MUSB_SUNXI
bool "musb_sunxi"
config CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
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
choice
prompt "Select usb device template"
default CHERRYUSB_DEVICE_TEMPLATE
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_NUVOTON_NUC980
bool "ehci_nuvoton_nuc980"
config CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0
bool "ehci_nuvoton_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_CUSTOM
bool "dwc2_custom"
config CHERRYUSB_HOST_MUSB_STANDARD
bool "musb_standard"
config CHERRYUSB_HOST_MUSB_SUNXI
bool "musb_sunxi"
config CHERRYUSB_HOST_MUSB_CUSTOM
bool "musb_custom"
config CHERRYUSB_HOST_PUSB2
bool "pusb2"
config CHERRYUSB_HOST_XHCI
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_RNDIS
bool
prompt "Enable usb rndis driver"
default n
config CHERRYUSB_HOST_CDC_ECM
bool
prompt "Enable usb cdc ecm driver"
default n
config CHERRYUSB_HOST_CDC_NCM
bool
prompt "Enable usb cdc ncm driver"
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"
default n
config CHERRYUSB_HOST_RTL8152
bool
prompt "Enable usb rtl8152 driver"
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_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, do not enable because it has used dfs instead"
default 0
depends on CHERRYUSB_HOST_MSC
config TEST_USBH_CDC_ECM
int
prompt "demo for test cdc ecm"
default 0
depends on CHERRYUSB_HOST_CDC_ECM
config TEST_USBH_CDC_NCM
int
prompt "demo for test cdc ncm"
default 0
depends on CHERRYUSB_HOST_CDC_NCM
config TEST_USBH_RNDIS
int
prompt "demo for test cdc rndis"
default 0
depends on CHERRYUSB_HOST_CDC_RNDIS
config TEST_USBH_ASIX
int
prompt "demo for test asix"
default 0
depends on CHERRYUSB_HOST_ASIX
config TEST_USBH_RTL8152
int
prompt "demo for test rtl8152"
default 0
depends on CHERRYUSB_HOST_RTL8152
endif
endif
endif

100
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
@@ -70,7 +70,7 @@ CherryUSB Device Stack has the following functions
- Support USB2.0 full and high speed, USB3.0 super speed
- Support endpoint irq callback register by users, let users do whatever they wants in endpoint irq callback.
- Support Composite Device
- Support Communication Device Class (CDC)
- Support Communication Device Class (CDC_ACM, CDC_ECM)
- Support Human Interface Device (HID)
- Support Mass Storage Class (MSC)
- Support USB VIDEO CLASS (UVC1.0、UVC1.5)
@@ -80,6 +80,7 @@ CherryUSB Device Stack has the following functions
- Support Remote NDIS (RNDIS)
- Support WINUSB1.0、WINUSB2.0(with BOS)
- Support Vendor class
- Support multi device with the same USB IP
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
@@ -102,37 +103,42 @@ CherryUSB Host Stack has the following functions
- Automatic loading of supported Class drivers
- Support blocking transfers and asynchronous transfers
- Support Composite Device
- Multi-level HUB support, expandable up to 7 levels
- Support Communication Device Class (CDC)
- 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 (commercial charge)
- Support USB Audio CLASS (commercial charge)
- 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 USB modeswitch
- Support multi host with the same USB IP
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros
```
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
#define CONFIG_USBHOST_MAX_INTERFACES 6
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
#define CONFIG_USBHOST_MAX_INTERFACES 8
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
```
@@ -144,10 +150,25 @@ x is affected by the following macros
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_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 | √ |
| 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/)
@@ -162,24 +183,27 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
## Demo Repo
| Manufacturer | CHIP or Series | USB IP| Repo Url |Corresponds to master version|
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.9.0 |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.8.0 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|latest |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.9.0 |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|latest |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|latest |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|latest |
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## 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" />

View File

@@ -4,7 +4,7 @@
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
![CherryUSB](./docs/assets/CherryUSB.svg)
![CherryUSB](CherryUSB.svg)
## 为什么选择
@@ -68,7 +68,7 @@ CherryUSB Device 协议栈当前实现以下功能:
- 支持 USB2.0 全速和高速设备USB3.0 超速设备
- 支持端点中断注册功能porting 给用户自己处理中断里的数据
- 支持复合设备
- 支持 Communication Device Class (CDC)
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
- 支持 Human Interface Device (HID)
- 支持 Mass Storage Class (MSC)
- 支持 USB VIDEO CLASS (UVC1.0、UVC1.5)
@@ -78,6 +78,7 @@ CherryUSB Device 协议栈当前实现以下功能:
- 支持 Remote NDIS (RNDIS)
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
- 支持 Vendor 类 class
- 支持相同 USB IP 的多从机
CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
@@ -100,37 +101,42 @@ CherryUSB Host 协议栈当前实现以下功能:
- 自动加载支持的Class 驱动
- 支持阻塞式传输和异步传输
- 支持复合设备
- 支持多级 HUB,最高可拓展到 7 级
- 支持 Communication Device Class (CDC)
- 支持多级 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(商业收费)
- Support USB Audio CLASS(商业收费)
- 支持 Remote NDIS (RNDIS)
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
- 支持 Vendor 类 class
- 支持 USB modeswitch
- 支持相同 USB IP 的多主机
同时CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
|usbh_core.c | 4237 | 512 + 8 * (1+x) *n | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 2919 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | 1099 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | 2502 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | 956 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | 2330 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | 3168 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | 3030 | 4096 | 4 + sizeof(struct usbh_rndis) * x | 0 |
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
其中,`sizeof(struct usbh_hub)``sizeof(struct usbh_hubport)` 受以下宏影响:
```
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
#define CONFIG_USBHOST_MAX_INTERFACES 6
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
#define CONFIG_USBHOST_MAX_INTERFACES 8
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
```
@@ -142,17 +148,33 @@ x 受以下宏影响:
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_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 | √ |
| 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.
## 图形化界面配置工具
@@ -160,24 +182,28 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
## 示例仓库
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| v0.9.0 |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|latest |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.8.0 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|latest |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|Phytium | e2000 | xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.9.0 |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|latest |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|latest |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|latest |
|Bekencorp | BK72xx | musb |[armino](https://github.com/CherryUSB/armino)|v0.7.0 |
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)|v0.7.0 |
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|Espressif | esp32s2/esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Contact
QQ 群:642693751
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" />

View File

@@ -10,18 +10,59 @@ 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 = []
CPPDEFINES = []
# USB DEVICE
if GetDepend(['PKG_CHERRYUSB_DEVICE']):
path += [cwd + '/osal']
src += Glob('core/usbd_core.c')
src += Glob('osal/usb_osal_rtthread.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
CPPDEFINES+=['CONFIG_USB_HS']
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC']):
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_CUSTOM']):
src += Glob('port/dwc2/usb_dc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_STANDARD']):
src += Glob('port/musb/usb_dc_musb.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_CUSTOM']):
src += Glob('port/musb/usb_dc_musb.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_CDC_ACM']):
src += Glob('class/cdc/usbd_cdc.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
src += Glob('class/hid/usbd_hid.c')
@@ -31,93 +72,130 @@ 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_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_PORT_FS']):
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=FS_PORT']
elif GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_HS']):
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=HS_PORT']
if GetDepend(['SOC_SERIES_STM32F7']):
CPPDEFINES += ['STM32F7']
elif GetDepend(['SOC_SERIES_STM32H7']):
CPPDEFINES += ['STM32H7']
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_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_NUVOTON_NUC980']):
src += Glob('port/ehci/usb_hc_ehci.c')
src += Glob('port/ehci/usb_glue_nuc980.c')
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUVOTON_MA35D0']):
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_SUNXI']):
src += Glob('port/musb/usb_hc_musb.c')
src += Glob('port/musb/usb_glue_sunxi.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
src += Glob('port/musb/usb_hc_musb.c')
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_DWC2']):
src += Glob('port/dwc2/usb_hc_dwc2.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_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_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(['PKG_CHERRYUSB_HOST_CP210X']):
path += [cwd + '/class/vendor/cp201x']
src += Glob('class/vendor/cp201x/usbh_cp210x.c')
src += Glob('third_party/rt-thread-4.1.1/dfs/drv_usbh_cp210x_rtt.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/usb_msh.c')
src += Glob('third_party/rt-thread-5.0/usb_check.c')
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)

5
VERSION Normal file
View File

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

241
cherryusb.cmake Normal file
View File

@@ -0,0 +1,241 @@
#
# 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/vendor/net
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
)
if(CONFIG_CHERRYUSB_DEVICE)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
if(CONFIG_CHERRYUSB_DEVICE_CDC)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc.c)
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(DEFINED CONFIG_CHERRYUSB_DEVICE_DCD)
if("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_st")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_st.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_esp")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_aic")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_aic.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "dwc2_at")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_at.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "fsdev")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/bouffalolab/usb_dc_bl.c)
elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
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_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)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/chry_pool.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool/usbh_uvc_queue.c)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrypool)
endif()
if(CONFIG_CHERRYUSB_HOST_AUDIO)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
endif()
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
endif()
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
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(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_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 "musb")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.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)
endif()
endif()

View File

@@ -6,7 +6,8 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x001000
#define CHERRYUSB_VERSION 0x010300
#define CHERRYUSB_VERSION_STR "v1.3.0"
/* ================ USB common Configuration ================ */
@@ -32,41 +33,31 @@
/* ================= USB Device Stack Configuration ================ */
/* 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
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
//#define CONFIG_USBDEV_TX_THREAD
//#define CONFIG_USBDEV_RX_THREAD
#ifdef CONFIG_USBDEV_TX_THREAD
#ifndef CONFIG_USBDEV_TX_PRIO
#define CONFIG_USBDEV_TX_PRIO 4
#endif
#ifndef CONFIG_USBDEV_TX_STACKSIZE
#define CONFIG_USBDEV_TX_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
#define CONFIG_USBDEV_MSC_MAX_LUN 1
#endif
#ifdef CONFIG_USBDEV_RX_THREAD
#ifndef CONFIG_USBDEV_RX_PRIO
#define CONFIG_USBDEV_RX_PRIO 4
#endif
#ifndef CONFIG_USBDEV_RX_STACKSIZE
#define CONFIG_USBDEV_RX_STACKSIZE 2048
#endif
#endif
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
#endif
#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
@@ -81,12 +72,23 @@
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
// #define CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_PRIO
#define CONFIG_USBDEV_MSC_PRIO 4
#endif
#ifndef CONFIG_USBDEV_MSC_STACKSIZE
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#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
@@ -104,8 +106,8 @@
#define CONFIG_USBHOST_MAX_RHPORTS 1
#define CONFIG_USBHOST_MAX_EXTHUBS 1
#define CONFIG_USBHOST_MAX_EHPORTS 4
#define CONFIG_USBHOST_MAX_INTERFACES 6
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
#define CONFIG_USBHOST_MAX_INTERFACES 8
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
@@ -113,12 +115,11 @@
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
#define CONFIG_USBHOST_DEV_NAMELEN 16
#ifndef CONFIG_USBHOST_PSC_PRIO
#define CONFIG_USBHOST_PSC_PRIO 4
#define CONFIG_USBHOST_PSC_PRIO 0
#endif
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
@@ -126,8 +127,15 @@
//#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
@@ -137,24 +145,117 @@
#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_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
#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
#endif
#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
#endif
/* ================ USB Device Port Configuration ================*/
//#define USBD_IRQHandler USBD_IRQHandler
//#define USB_BASE (0x40080000UL)
//#define USB_NUM_BIDIR_ENDPOINTS 4
#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 ---------------- */
// #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 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
#ifndef CONFIG_USBHOST_PIPE_NUM
#define CONFIG_USBHOST_PIPE_NUM 10
#endif
/* ================ EHCI Configuration ================ */
/* ---------------- EHCI Configuration ---------------- */
#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000)
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x0)
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
// #define CONFIG_USB_EHCI_INFO_ENABLE
// #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
#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_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

View File

@@ -17,9 +17,9 @@ struct usbd_audio_priv {
struct audio_entity_info *table;
uint8_t num;
uint16_t uac_version;
} g_usbd_audio;
} g_usbd_audio[CONFIG_USBDEV_MAX_BUS];
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector;
uint32_t sampling_freq = 0;
@@ -34,13 +34,13 @@ static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup,
case AUDIO_REQUEST_SET_CUR:
memcpy((uint8_t *)&sampling_freq, *data, *len);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(ep, sampling_freq);
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
break;
case AUDIO_REQUEST_GET_CUR:
case AUDIO_REQUEST_GET_MIN:
case AUDIO_REQUEST_GET_MAX:
case AUDIO_REQUEST_GET_RES:
sampling_freq = usbd_audio_get_sampling_freq(ep);
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
memcpy(*data, &sampling_freq, 3);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 3;
@@ -55,7 +55,7 @@ static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup,
return 0;
}
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("Audio Class request: "
"bRequest 0x%02x\r\n",
@@ -79,10 +79,10 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
ARG_UNUSED(mute_string);
for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
if (g_usbd_audio.table[i].bEntityId == entity_id) {
subtype = g_usbd_audio.table[i].bDescriptorSubtype;
ep = g_usbd_audio.table[i].ep;
for (uint8_t i = 0; i < g_usbd_audio[busid].num; i++) {
if (g_usbd_audio[busid].table[i].bEntityId == entity_id) {
subtype = g_usbd_audio[busid].table[i].bDescriptorSubtype;
ep = g_usbd_audio[busid].table[i].ep;
break;
}
}
@@ -98,14 +98,14 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
case AUDIO_CONTROL_FEATURE_UNIT:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (g_usbd_audio.uac_version < 0x0200) {
if (g_usbd_audio[busid].uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
usbd_audio_set_mute(busid, ep, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = usbd_audio_get_mute(ep, ch);
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
*len = 1;
break;
default:
@@ -116,11 +116,11 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = usbd_audio_get_mute(ep, ch);
(*data)[0] = usbd_audio_get_mute(busid, ep, ch);
*len = 1;
} else {
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
usbd_audio_set_mute(busid, ep, ch, mute);
}
break;
default:
@@ -130,7 +130,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (g_usbd_audio.uac_version < 0x0200) {
if (g_usbd_audio[busid].uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy(&volume, *data, *len);
@@ -141,10 +141,10 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
}
volume_db += 128; /* 0 ~ 255 */
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db);
break;
case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(ep, ch);
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume_db -= 128;
if (volume_db >= 0) {
volume = volume_db * 256;
@@ -177,7 +177,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(ep, ch);
volume_db = usbd_audio_get_volume(busid, ep, ch);
volume = volume_db;
memcpy(*data, &volume, 2);
*len = 2;
@@ -185,7 +185,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
memcpy(&volume, *data, *len);
volume_db = volume;
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db);
}
break;
case AUDIO_REQUEST_RANGE:
@@ -216,14 +216,14 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
sampling_freq = usbd_audio_get_sampling_freq(ep);
sampling_freq = usbd_audio_get_sampling_freq(busid, ep);
memcpy(*data, &sampling_freq, 4);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 4;
} else {
memcpy(&sampling_freq, *data, setup->wLength);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(ep, sampling_freq);
usbd_audio_set_sampling_freq(busid, ep, sampling_freq);
}
break;
case AUDIO_REQUEST_RANGE:
@@ -231,7 +231,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
usbd_audio_get_sampling_freq_table(busid, ep, &sampling_freq_table);
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
memcpy(*data, sampling_freq_table, (12 * num + 2));
*len = (12 * num + 2);
@@ -264,7 +264,7 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
return 0;
}
static void audio_notify_handler(uint8_t event, void *arg)
static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -274,9 +274,9 @@ static void audio_notify_handler(uint8_t event, void *arg)
case USBD_EVENT_SET_INTERFACE: {
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
if (intf->bAlternateSetting) {
usbd_audio_open(intf->bInterfaceNumber);
usbd_audio_open(busid, intf->bInterfaceNumber);
} else {
usbd_audio_close(intf->bInterfaceNumber);
usbd_audio_close(busid, intf->bInterfaceNumber);
}
}
@@ -287,7 +287,8 @@ static void audio_notify_handler(uint8_t event, void *arg)
}
}
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num)
@@ -304,40 +305,40 @@ struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
intf->notify_handler = audio_notify_handler;
}
g_usbd_audio.uac_version = uac_version;
g_usbd_audio.table = table;
g_usbd_audio.num = num;
g_usbd_audio[busid].uac_version = uac_version;
g_usbd_audio[busid].table = table;
g_usbd_audio[busid].num = num;
return intf;
}
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
{
}
__WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
{
}
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
}
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
}

View File

@@ -19,22 +19,22 @@ struct audio_entity_info {
};
/* Init audio interface driver */
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num);
void usbd_audio_open(uint8_t intf);
void usbd_audio_close(uint8_t intf);
void usbd_audio_open(uint8_t busid, uint8_t intf);
void usbd_audio_close(uint8_t busid, uint8_t intf);
void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume);
int usbd_audio_get_volume(uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t ep, uint8_t ch);
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq);
uint32_t usbd_audio_get_sampling_freq(uint8_t ep);
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq);
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep);
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table);
#ifdef __cplusplus
}

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_audio.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_audio"
#include "usb_log.h"
#define DEV_FORMAT "/dev/audio%d"
/* general descriptor field offsets */
@@ -62,7 +66,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
uint8_t altsetting = 1;
if (audio_class->is_opened) {
return -EMFILE;
return 0;
}
for (uint8_t i = 0; i < audio_class->module_num; i++) {
@@ -79,7 +83,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
}
}
return -ENODEV;
return -USB_ERR_NODEV;
freq_found:
@@ -89,7 +93,7 @@ freq_found:
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
if (ret < 0) {
return ret;
}
@@ -103,7 +107,7 @@ freq_found:
setup->wLength = 3;
memcpy(g_audio_buf, &samp_freq, 3);
ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
if (ret < 0) {
return ret;
}
@@ -112,10 +116,10 @@ freq_found:
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
if (ep_desc->bEndpointAddress & 0x80) {
audio_class->isoin_mps = mps * (mult + 1);
usbh_hport_activate_epx(&audio_class->isoin, audio_class->hport, ep_desc);
USBH_EP_INIT(audio_class->isoin, ep_desc);
} else {
audio_class->isoout_mps = mps * (mult + 1);
usbh_hport_activate_epx(&audio_class->isoout, audio_class->hport, ep_desc);
USBH_EP_INIT(audio_class->isoout, ep_desc);
}
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
@@ -138,7 +142,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
}
if (intf == 0xff) {
return -ENODEV;
return -USB_ERR_NODEV;
}
USB_LOG_INFO("Close audio module :%s\r\n", name);
@@ -147,12 +151,10 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
if (audio_class->isoin) {
usbh_pipe_free(audio_class->isoin);
audio_class->isoin = NULL;
}
} else {
if (audio_class->isoout) {
usbh_pipe_free(audio_class->isoout);
audio_class->isoout = NULL;
}
}
@@ -163,7 +165,7 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
setup->wIndex = intf;
setup->wLength = 0;
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
@@ -184,7 +186,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
}
if (intf == 0xff) {
return -ENODEV;
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
@@ -196,7 +198,7 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
memcpy(g_audio_buf, &volume_hex, 2);
ret = usbh_control_transfer(audio_class->hport->ep0, setup, NULL);
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
@@ -216,7 +218,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
}
if (intf == 0xff) {
return -ENODEV;
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
@@ -226,7 +228,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
setup->wLength = 1;
memcpy(g_audio_buf, &mute, 1);
ret = usbh_control_transfer(audio_class->hport->ep0, setup, g_audio_buf);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
return ret;
}
@@ -234,27 +236,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]);
}
}
}
@@ -277,7 +279,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_audio *audio_class = usbh_audio_class_alloc();
if (audio_class == NULL) {
USB_LOG_ERR("Fail to alloc audio_class\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
audio_class->hport = hport;
@@ -386,7 +388,7 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
}
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
return -EINVAL;
return -USB_ERR_INVAL;
}
audio_class->module_num = input_offset;
@@ -416,11 +418,9 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (audio_class) {
if (audio_class->isoin) {
usbh_pipe_free(audio_class->isoin);
}
if (audio_class->isoout) {
usbh_pipe_free(audio_class->isoout);
}
if (hport->config.intf[intf].devname[0] != '\0') {
@@ -469,8 +469,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 +478,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

@@ -40,11 +40,11 @@ struct usbh_audio_module {
struct usbh_audio {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
uint8_t ctrl_intf; /* interface number */
uint8_t minor;
usbh_pipe_t isoin; /* ISO IN endpoint */
usbh_pipe_t isoout; /* ISO OUT endpoint */
uint16_t isoin_mps;
uint16_t isoout_mps;
bool is_opened;
@@ -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) */
@@ -212,6 +224,61 @@
#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0)
#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos)
#define CDC_ECM_XMIT_OK (1 << 0)
#define CDC_ECM_RVC_OK (1 << 1)
#define CDC_ECM_XMIT_ERROR (1 << 2)
#define CDC_ECM_RCV_ERROR (1 << 3)
#define CDC_ECM_RCV_NO_BUFFER (1 << 4)
#define CDC_ECM_DIRECTED_BYTES_XMIT (1 << 5)
#define CDC_ECM_DIRECTED_FRAMES_XMIT (1 << 6)
#define CDC_ECM_MULTICAST_BYTES_XMIT (1 << 7)
#define CDC_ECM_MULTICAST_FRAMES_XMIT (1 << 8)
#define CDC_ECM_BROADCAST_BYTES_XMIT (1 << 9)
#define CDC_ECM_BROADCAST_FRAMES_XMIT (1 << 10)
#define CDC_ECM_DIRECTED_BYTES_RCV (1 << 11)
#define CDC_ECM_DIRECTED_FRAMES_RCV (1 << 12)
#define CDC_ECM_MULTICAST_BYTES_RCV (1 << 13)
#define CDC_ECM_MULTICAST_FRAMES_RCV (1 << 14)
#define CDC_ECM_BROADCAST_BYTES_RCV (1 << 15)
#define CDC_ECM_BROADCAST_FRAMES_RCV (1 << 16)
#define CDC_ECM_RCV_CRC_ERROR (1 << 17)
#define CDC_ECM_TRANSMIT_QUEUE_LENGTH (1 << 18)
#define CDC_ECM_RCV_ERROR_ALIGNMENT (1 << 19)
#define CDC_ECM_XMIT_ONE_COLLISION (1 << 20)
#define CDC_ECM_XMIT_MORE_COLLISIONS (1 << 21)
#define CDC_ECM_XMIT_DEFERRED (1 << 22)
#define CDC_ECM_XMIT_MAX_COLLISIONS (1 << 23)
#define CDC_ECM_RCV_OVERRUN (1 << 24)
#define CDC_ECM_XMIT_UNDERRUN (1 << 25)
#define CDC_ECM_XMIT_HEARTBEAT_FAILURE (1 << 26)
#define CDC_ECM_XMIT_TIMES_CRS_LOST (1 << 27)
#define CDC_ECM_XMIT_LATE_COLLISIONS (1 << 28)
#define CDC_ECM_MAC_STR_DESC (uint8_t *)"010202030000"
#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */
#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */
#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */
#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */
#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */
#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */
#define CDC_ECM_NET_DISCONNECTED 0x00U
#define CDC_ECM_NET_CONNECTED 0x01U
#define CDC_ECM_ETH_STATS_RESERVED 0xE0U
#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U
#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */
#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */
#define CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION 0x00
#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)
*----------------------------------------------------------------------------*/
@@ -288,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;
@@ -299,6 +366,50 @@ struct cdc_ecm_descriptor {
uint8_t bNumberPowerFilters;
} __PACKED;
struct cdc_eth_notification {
uint8_t bmRequestType;
uint8_t bNotificationType;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
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
@@ -437,4 +548,151 @@ struct cdc_ecm_descriptor {
0x00 /* bInterval */
// clang-format on
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
/*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, \
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_ETHERNET_NETWORKING_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_ETHERNET_NETWORKING_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_ECM 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 */\
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
/*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

@@ -9,7 +9,7 @@
const char *stop_name[] = { "1", "1.5", "2" };
const char *parity_name[] = { "N", "O", "E", "M", "S" };
static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC Class request: "
"bRequest 0x%02x\r\n",
@@ -47,7 +47,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
parity_name[line_coding.bParityType],
stop_name[line_coding.bCharFormat]);
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
usbd_cdc_acm_set_line_coding(busid, intf_num, &line_coding);
break;
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
@@ -57,12 +57,12 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
intf_num,
dtr,
rts);
usbd_cdc_acm_set_dtr(intf_num, dtr);
usbd_cdc_acm_set_rts(intf_num, rts);
usbd_cdc_acm_set_dtr(busid, intf_num, dtr);
usbd_cdc_acm_set_rts(busid, intf_num, rts);
break;
case CDC_REQUEST_GET_LINE_CODING:
usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
usbd_cdc_acm_get_line_coding(busid, intf_num, &line_coding);
memcpy(*data, &line_coding, 7);
*len = 7;
USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
@@ -73,7 +73,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
line_coding.bDataBits);
break;
case CDC_REQUEST_SEND_BREAK:
usbd_cdc_acm_send_break(intf_num);
usbd_cdc_acm_send_break(busid, intf_num);
break;
default:
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
@@ -83,7 +83,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
return 0;
}
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
{
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
@@ -93,11 +93,11 @@ struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
return intf;
}
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
}
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
{
line_coding->dwDTERate = 2000000;
line_coding->bDataBits = 8;
@@ -105,14 +105,14 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *l
line_coding->bCharFormat = 0;
}
__WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
}
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
{
}
__WEAK void usbd_cdc_acm_send_break(uint8_t intf)
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
{
}

View File

@@ -13,14 +13,14 @@ extern "C" {
#endif
/* Init cdc acm interface driver */
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf);
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 intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
void usbd_cdc_acm_send_break(uint8_t intf);
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
}

247
class/cdc/usbd_cdc_ecm.c Normal file
View File

@@ -0,0 +1,247 @@
/*
* Copyright (c) 2023, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
#define CDC_ECM_OUT_EP_IDX 0
#define CDC_ECM_IN_EP_IDX 1
#define CDC_ECM_INT_EP_IDX 2
/* Describe EndPoints configuration */
static struct usbd_endpoint cdc_ecm_ep_data[3];
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];
volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL;
volatile uint32_t g_cdc_ecm_rx_data_length = 0;
volatile uint32_t g_cdc_ecm_tx_data_length = 0;
static volatile uint8_t g_current_net_status = 0;
static volatile uint8_t g_cmd_intf = 0;
static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
CDC_ECM_CONNECT_SPEED_DOWNSTREAM };
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
{
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;
notify->bNotificationType = notifycode;
switch (notifycode) {
case CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION:
notify->wValue = value;
notify->wIndex = g_cmd_intf;
notify->wLength = 0U;
for (uint8_t i = 0U; i < 8U; i++) {
notify->data[i] = 0U;
}
bytes2send = 8U;
break;
case CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE:
notify->wValue = 0U;
notify->wIndex = g_cmd_intf;
notify->wLength = 0U;
for (uint8_t i = 0U; i < 8U; i++) {
notify->data[i] = 0U;
}
bytes2send = 8U;
break;
case CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE:
notify->wValue = 0U;
notify->wIndex = g_cmd_intf;
notify->wLength = 0x0008U;
bytes2send = 16U;
memcpy(notify->data, speed, 8);
break;
default:
break;
}
if (bytes2send) {
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
}
}
static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("CDC ECM Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
g_cmd_intf = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
* bit4 Multicast
*/
if (g_current_net_status == 0) {
g_current_net_status = 1;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
}
break;
default:
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
g_current_net_status = 0;
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_tx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
break;
case USBD_EVENT_CONFIGURED:
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
break;
default:
break;
}
}
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < usbd_get_ep_mps(busid, ep)) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
} else {
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, ep));
}
}
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(0, ep, NULL, 0);
} else {
g_cdc_ecm_tx_data_length = 0;
}
}
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if (g_current_net_status == 1) {
g_current_net_status = 2;
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
}
}
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
{
if (g_cdc_ecm_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
g_cdc_ecm_tx_data_length = len;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
}
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, usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr));
}
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
struct pbuf *usbd_cdc_ecm_eth_rx(void)
{
struct pbuf *p;
if (g_cdc_ecm_rx_data_buffer == NULL) {
return NULL;
}
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
if (p == NULL) {
usbd_cdc_ecm_start_read_next();
return NULL;
}
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
p->len = g_cdc_ecm_rx_data_length;
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
usbd_cdc_ecm_start_read_next();
return p;
}
int usbd_cdc_ecm_eth_tx(struct pbuf *p)
{
struct pbuf *q;
uint8_t *buffer;
if (g_cdc_ecm_tx_data_length > 0) {
return -USB_ERR_BUSY;
}
if (p->tot_len > sizeof(g_cdc_ecm_tx_buffer)) {
p->tot_len = sizeof(g_cdc_ecm_tx_buffer);
}
buffer = g_cdc_ecm_tx_buffer;
for (q = p; q != NULL; q = q->next) {
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);
}
#endif
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep)
{
intf->class_interface_handler = cdc_ecm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = cdc_ecm_notify_handler;
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr = out_ep;
cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_cb = cdc_ecm_bulk_out;
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr = in_ep;
cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_cb = cdc_ecm_bulk_in;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr = int_ep;
cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_cb = cdc_ecm_int_in;
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
usbd_add_endpoint(0, &cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX]);
return intf;
}
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
{
memcpy(g_connect_speed_table, speed, 8);
}
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
}

42
class/cdc/usbd_cdc_ecm.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_CDC_ECM_H
#define USBD_CDC_ECM_H
#include "usb_cdc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Ethernet Maximum Segment size, typically 1514 bytes */
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
/* Init cdc ecm interface driver */
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
/* Setup request command callback api */
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
/* Api for eth only without any net stack */
uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
void usbd_cdc_ecm_send_done(void);
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
void usbd_cdc_ecm_start_read_next(void);
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct pbuf *usbd_cdc_ecm_eth_rx(void);
int usbd_cdc_ecm_eth_tx(struct pbuf *p);
#endif
#ifdef __cplusplus
}
#endif
#endif /* USBD_CDC_ECM_H */

View File

@@ -6,9 +6,13 @@
#include "usbh_core.h"
#include "usbh_cdc_acm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_acm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/ttyACM%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
@@ -45,12 +49,12 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
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 = cdc_acm_class->ctrl_intf;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding));
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
}
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
@@ -61,14 +65,14 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
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->ctrl_intf;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 7;
ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
if (ret < 0) {
return ret;
}
memcpy(line_coding, (uint8_t *)&g_cdc_line_coding, sizeof(struct cdc_line_coding));
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
return ret;
}
@@ -79,60 +83,40 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo
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 = cdc_acm_class->ctrl_intf;
setup->wIndex = cdc_acm_class->intf;
setup->wLength = 0;
cdc_acm_class->dtr = dtr;
cdc_acm_class->rts = rts;
return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL);
return usbh_control_transfer(cdc_acm_class->hport, setup, NULL);
}
static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
int ret = 0;
struct usbh_cdc_acm *cdc_acm_class = usbh_cdc_acm_class_alloc();
if (cdc_acm_class == NULL) {
USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
cdc_acm_class->hport = hport;
cdc_acm_class->ctrl_intf = intf;
cdc_acm_class->data_intf = intf + 1;
cdc_acm_class->intf = intf;
hport->config.intf[intf].priv = cdc_acm_class;
hport->config.intf[intf + 1].priv = NULL;
cdc_acm_class->linecoding.dwDTERate = 115200;
cdc_acm_class->linecoding.bDataBits = 8;
cdc_acm_class->linecoding.bParityType = 0;
cdc_acm_class->linecoding.bCharFormat = 0;
ret = usbh_cdc_acm_set_line_coding(cdc_acm_class, &cdc_acm_class->linecoding);
if (ret < 0) {
USB_LOG_ERR("Fail to set linecoding\r\n");
return ret;
}
ret = usbh_cdc_acm_set_line_state(cdc_acm_class, true, true);
if (ret < 0) {
USB_LOG_ERR("Fail to set line state\r\n");
return ret;
}
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
usbh_hport_activate_epx(&cdc_acm_class->intin, hport, ep_desc);
USBH_EP_INIT(cdc_acm_class->intin, ep_desc);
#endif
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_hport_activate_epx(&cdc_acm_class->bulkin, hport, ep_desc);
USBH_EP_INIT(cdc_acm_class->bulkin, ep_desc);
} else {
usbh_hport_activate_epx(&cdc_acm_class->bulkout, hport, ep_desc);
USBH_EP_INIT(cdc_acm_class->bulkout, ep_desc);
}
}
@@ -140,6 +124,34 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test cdc acm 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_cdc_acm_set_line_coding(cdc_acm_class, &linecoding);
usbh_cdc_acm_set_line_state(cdc_acm_class, true, false);
memset(g_cdc_acm_buf, 'a', sizeof(g_cdc_acm_buf));
ret = usbh_cdc_acm_bulk_out_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_cdc_acm_bulk_in_transfer(cdc_acm_class, g_cdc_acm_buf, sizeof(g_cdc_acm_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_cdc_acm_buf[i]);
}
}
USB_LOG_RAW("\r\n");
}
#endif
usbh_cdc_acm_run(cdc_acm_class);
return ret;
}
@@ -152,13 +164,19 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (cdc_acm_class) {
if (cdc_acm_class->bulkin) {
usbh_pipe_free(cdc_acm_class->bulkin);
usbh_kill_urb(&cdc_acm_class->bulkin_urb);
}
if (cdc_acm_class->bulkout) {
usbh_pipe_free(cdc_acm_class->bulkout);
usbh_kill_urb(&cdc_acm_class->bulkout_urb);
}
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
if (cdc_acm_class->intin) {
usbh_kill_urb(&cdc_acm_class->intin_urb);
}
#endif
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_acm_stop(cdc_acm_class);
@@ -170,6 +188,32 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
return ret;
}
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cdc_acm_class->bulkin_urb;
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cdc_acm_class->bulkout_urb;
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
{
return 0;
@@ -205,8 +249,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
};
@@ -215,7 +258,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

@@ -10,18 +10,23 @@
struct usbh_cdc_acm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint (optional) */
#endif
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
struct usbh_urb intin_urb;
#endif
struct cdc_line_coding linecoding;
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
bool dtr;
bool rts;
uint8_t intf;
uint8_t minor;
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
#endif
void *user_data;
};
#ifdef __cplusplus
@@ -32,6 +37,9 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts);
int usbh_cdc_acm_bulk_in_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class);
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class);

351
class/cdc/usbh_cdc_ecm.c Normal file
View File

@@ -0,0 +1,351 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_ecm.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_cdc_ecm"
#include "usb_log.h"
#define DEV_FORMAT "/dev/cdc_ether"
/* 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_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_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;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CDC_REQUEST_SET_ETHERNET_PACKET_FILTER;
setup->wValue = filter_value;
setup->wIndex = cdc_ecm_class->ctrl_intf;
setup->wLength = 0;
return usbh_control_transfer(cdc_ecm_class->hport, setup, NULL);
}
int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class)
{
int ret;
usbh_int_urb_fill(&cdc_ecm_class->intin_urb, cdc_ecm_class->hport, cdc_ecm_class->intin, g_cdc_ecm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&cdc_ecm_class->intin_urb);
if (ret < 0) {
return ret;
}
if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
if (g_cdc_ecm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
cdc_ecm_class->connect_status = true;
} else {
cdc_ecm_class->connect_status = false;
}
} else if (g_cdc_ecm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
memcpy(cdc_ecm_class->speed, &g_cdc_ecm_inttx_buffer[8], 8);
}
return 0;
}
static int usbh_cdc_ecm_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_ecm *cdc_ecm_class = &g_cdc_ecm_class;
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
cdc_ecm_class->hport = hport;
cdc_ecm_class->ctrl_intf = intf;
cdc_ecm_class->data_intf = intf + 1;
hport->config.intf[intf].priv = cdc_ecm_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_ecm_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_ecm_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 ecm mac string\r\n");
return -1;
}
memset(mac_buffer, 0, 12);
ret = usbh_get_string_desc(cdc_ecm_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_ecm_class->mac[j] = (unsigned char)byte;
}
USB_LOG_INFO("CDC ECM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
cdc_ecm_class->mac[0],
cdc_ecm_class->mac[1],
cdc_ecm_class->mac[2],
cdc_ecm_class->mac[3],
cdc_ecm_class->mac[4],
cdc_ecm_class->mac[5]);
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);
}
/* enable int ep */
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
USBH_EP_INIT(cdc_ecm_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_ecm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc);
}
}
USB_LOG_INFO("Select cdc ecm altsetting: %d\r\n", altsetting);
usbh_set_interface(cdc_ecm_class->hport, cdc_ecm_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_ecm_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cdc_ecm_class->bulkout, ep_desc);
}
}
}
/* bit0 Promiscuous
* bit1 ALL Multicast
* bit2 Directed
* bit3 Broadcast
* bit4 Multicast
*/
ret = usbh_cdc_ecm_set_eth_packet_filter(cdc_ecm_class, CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
if (ret < 0) {
return ret;
}
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);
USB_LOG_INFO("Register CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_run(cdc_ecm_class);
return ret;
}
static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)hport->config.intf[intf].priv;
if (cdc_ecm_class) {
if (cdc_ecm_class->bulkin) {
usbh_kill_urb(&cdc_ecm_class->bulkin_urb);
}
if (cdc_ecm_class->bulkout) {
usbh_kill_urb(&cdc_ecm_class->bulkout_urb);
}
if (cdc_ecm_class->intin) {
usbh_kill_urb(&cdc_ecm_class->intin_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_stop(cdc_ecm_class);
}
memset(cdc_ecm_class, 0, sizeof(struct usbh_cdc_ecm));
}
return ret;
}
void usbh_cdc_ecm_rx_thread(void *argument)
{
uint32_t g_cdc_ecm_rx_length;
int ret;
err_t err;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#else
pbuf_type type = PBUF_POOL;
#endif
struct netif *netif = (struct netif *)argument;
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
// clang-format off
find_class:
// clang-format on
g_cdc_ecm_class.connect_status = false;
if (usbh_find_class_instance("/dev/cdc_ether") == NULL) {
goto delete;
}
while (g_cdc_ecm_class.connect_status == false) {
ret = usbh_cdc_ecm_get_connect_status(&g_cdc_ecm_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
}
}
g_cdc_ecm_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
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;
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = g_cdc_ecm_rx_buffer;
#else
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
#endif
g_cdc_ecm_rx_length = 0;
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");
}
} else {
/* read continue util read short packet */
if (g_cdc_ecm_rx_length > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_cdc_ecm_rx_length = 0;
}
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete cdc ecm rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
{
int ret;
struct pbuf *q;
uint8_t *buffer = g_cdc_ecm_tx_buffer;
if (g_cdc_ecm_class.connect_status == false) {
return ERR_BUF;
}
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
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;
}
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
{
}
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
{
}
const struct usbh_class_driver cdc_ecm_class_driver = {
.driver_name = "cdc_ecm",
.connect = usbh_cdc_ecm_connect,
.disconnect = usbh_cdc_ecm_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_CDC,
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
.protocol = CDC_COMMON_PROTOCOL_NONE,
.id_table = NULL,
.class_driver = &cdc_ecm_class_driver
};

55
class/cdc/usbh_cdc_ecm.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_ECM_H
#define USBH_CDC_ECM_H
#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 */
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;
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
extern "C" {
#endif
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);
void usbh_cdc_ecm_rx_thread(void *argument);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CDC_ECM_H */

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

@@ -0,0 +1,419 @@
/*
* 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 = cdc_ncm_class->hport->setup;
int ret;
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);
}
}
}
memcpy(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;
err_t err;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#else
pbuf_type type = PBUF_POOL;
#endif
struct netif *netif = (struct netif *)argument;
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], (CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE > (16 * 1024)) ? (16 * 1024) : CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
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;
if (g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize)) {
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);
p = pbuf_alloc(PBUF_RAW, ndp16_datagram->wDatagramLength, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
#else
memcpy(p->payload, (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex], ndp16_datagram->wDatagramLength);
#endif
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
USB_LOG_ERR("No memory to alloc pbuf for cdc ncm rx\r\n");
}
}
}
g_cdc_ncm_rx_length = 0;
} else {
if (g_cdc_ncm_rx_length > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_cdc_ncm_rx_length = 0;
}
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete cdc ncm rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
{
int ret;
struct pbuf *q;
uint8_t *buffer;
struct cdc_ncm_ndp16_datagram *ndp16_datagram;
if (g_cdc_ncm_class.connect_status == false) {
return ERR_BUF;
}
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(p->tot_len, 4);
nth16->wNdpIndex = 16 + USB_ALIGN_UP(p->tot_len, 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 = p->tot_len;
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 1];
ndp16_datagram->wDatagramIndex = 0;
ndp16_datagram->wDatagramLength = 0;
buffer = &g_cdc_ncm_tx_buffer[16];
for (q = p; q != NULL; q = q->next) {
memcpy(buffer, q->payload, q->len);
buffer += q->len;
}
USB_LOG_DBG("txlen:%d\r\n", nth16->wBlockLength);
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkout_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkout, g_cdc_ncm_tx_buffer, nth16->wBlockLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
}
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
{
}
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *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
};

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

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CDC_NCM_H
#define USBH_CDC_NCM_H
#include "usb_cdc.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_cdc_ncm {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
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];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
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);
err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p);
void usbh_cdc_ncm_rx_thread(void *argument);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CDC_NCM_H */

View File

@@ -428,7 +428,7 @@ void dfu_request_abort(void)
}
}
static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("DFU Class request: "
"bRequest 0x%02x\r\n",
@@ -464,7 +464,7 @@ static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, u
return 0;
}
static void dfu_notify_handler(uint8_t event, void *arg)
static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:

View File

@@ -6,7 +6,7 @@
#include "usbd_core.h"
#include "usbd_hid.h"
static int hid_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("HID Class request: "
"bRequest 0x%02x\r\n",
@@ -17,27 +17,27 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
switch (setup->bRequest) {
case HID_REQUEST_GET_REPORT:
/* report id ,report type */
usbd_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
usbd_hid_get_report(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
break;
case HID_REQUEST_GET_IDLE:
(*data)[0] = usbd_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
(*data)[0] = usbd_hid_get_idle(busid, intf_num, LO_BYTE(setup->wValue));
*len = 1;
break;
case HID_REQUEST_GET_PROTOCOL:
(*data)[0] = usbd_hid_get_protocol(intf_num);
(*data)[0] = usbd_hid_get_protocol(busid, intf_num);
*len = 1;
break;
case HID_REQUEST_SET_REPORT:
/* report id ,report type, report, report len */
usbd_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
usbd_hid_set_report(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
break;
case HID_REQUEST_SET_IDLE:
/* report id, duration */
usbd_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
usbd_hid_set_idle(busid, intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
break;
case HID_REQUEST_SET_PROTOCOL:
/* protocol */
usbd_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
usbd_hid_set_protocol(busid, intf_num, LO_BYTE(setup->wValue));
break;
default:
@@ -48,7 +48,7 @@ static int hid_class_interface_request_handler(struct usb_setup_packet *setup, u
return 0;
}
struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
{
intf->class_interface_handler = hid_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
@@ -60,30 +60,30 @@ struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uin
return intf;
}
__WEAK void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
__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)
{
(*data[0]) = 0;
*len = 1;
}
__WEAK uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id)
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
{
return 0;
}
__WEAK uint8_t usbd_hid_get_protocol(uint8_t intf)
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
{
return 0;
}
__WEAK void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
__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)
{
}
__WEAK void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
{
}
__WEAK void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol)
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
{
}

View File

@@ -13,19 +13,19 @@ extern "C" {
#endif
/* Init hid interface driver */
struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
/* Register desc api */
void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
void usbd_hid_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc);
void usbd_hid_report_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
/* Setup request command callback api */
void usbd_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
uint8_t usbd_hid_get_idle(uint8_t intf, uint8_t report_id);
uint8_t usbd_hid_get_protocol(uint8_t intf);
void usbd_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len);
void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol);
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);
uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id);
uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf);
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 usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration);
void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol);
#ifdef __cplusplus
}

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_hid.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_hid"
#include "usb_log.h"
#define DEV_FORMAT "/dev/input%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
@@ -49,7 +53,7 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b
setup->wIndex = hid_class->intf;
setup->wLength = 128;
ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
if (ret < 0) {
return ret;
}
@@ -67,7 +71,7 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur
setup->wIndex = hid_class->intf;
setup->wLength = 0;
return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
return usbh_control_transfer(hid_class->hport, setup, NULL);
}
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
@@ -81,7 +85,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
setup->wIndex = hid_class->intf;
setup->wLength = 1;
ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
if (ret < 0) {
return ret;
}
@@ -99,7 +103,33 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
setup->wIndex = 0;
setup->wLength = 0;
return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
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 = 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 = 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;
return usbh_control_transfer(hid_class->hport, setup, buffer);
}
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
@@ -110,7 +140,7 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_hid *hid_class = usbh_hid_class_alloc();
if (hid_class == NULL) {
USB_LOG_ERR("Fail to alloc hid_class\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
hid_class->hport = hport;
@@ -137,9 +167,9 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
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_hport_activate_epx(&hid_class->intin, hport, ep_desc);
USBH_EP_INIT(hid_class->intin, ep_desc);
} else {
usbh_hport_activate_epx(&hid_class->intout, hport, ep_desc);
USBH_EP_INIT(hid_class->intout, ep_desc);
}
}
@@ -159,11 +189,11 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (hid_class) {
if (hid_class->intin) {
usbh_pipe_free(hid_class->intin);
usbh_kill_urb(&hid_class->intin_urb);
}
if (hid_class->intout) {
usbh_pipe_free(hid_class->intout);
usbh_kill_urb(&hid_class->intout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
@@ -196,7 +226,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

@@ -10,12 +10,16 @@
struct usbh_hid {
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 report_desc[128];
uint8_t report_desc[256];
uint8_t intf; /* interface number */
uint8_t minor;
usbh_pipe_t intin; /* INTR IN endpoint */
usbh_pipe_t intout; /* INTR OUT endpoint */
void *user_data;
};
#ifdef __cplusplus
@@ -24,6 +28,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

@@ -3,8 +3,13 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_hub"
#include "usb_log.h"
#define DEV_FORMAT "/dev/hub%d"
#define HUB_DEBOUNCE_TIMEOUT 1500
@@ -14,20 +19,11 @@
#define EXTHUB_FIRST_INDEX 2
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
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)];
usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
usb_osal_thread_t hub_thread;
usb_osal_mq_t hub_mq;
struct usbh_hub roothub;
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
extern int usbh_enumerate(struct usbh_hubport *hport);
static void usbh_hub_thread_wakeup(struct usbh_hub *hub);
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" };
@@ -68,17 +64,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
}
#endif
static void usbh_hub_register(struct usbh_hub *hub)
{
usb_slist_add_tail(&hub_class_head, &hub->list);
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static void usbh_hub_unregister(struct usbh_hub *hub)
{
usb_slist_remove(&hub_class_head, &hub->list);
}
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
@@ -101,14 +87,14 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_HUB_DESC;
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
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)
{
struct usb_setup_packet *setup;
@@ -122,14 +108,15 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
setup->wIndex = 0;
setup->wLength = 2;
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
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], 2);
return ret;
}
#endif
#endif
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -144,11 +131,11 @@ static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct h
setup->wIndex = port;
setup->wLength = 4;
ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
if (ret < 0) {
return ret;
}
memcpy(port_status, g_hub_buf, 4);
memcpy(port_status, g_hub_buf[hub->bus->busid], 4);
return ret;
}
@@ -164,7 +151,7 @@ static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t fea
setup->wIndex = port;
setup->wLength = 0;
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
return usbh_control_transfer(hub->parent, setup, NULL);
}
static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
@@ -179,7 +166,7 @@ static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t f
setup->wIndex = port;
setup->wLength = 0;
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
return usbh_control_transfer(hub->parent, setup, NULL);
}
static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
@@ -194,7 +181,7 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
setup->wIndex = 0;
setup->wLength = 0;
return usbh_control_transfer(hub->parent->ep0, setup, NULL);
return usbh_control_transfer(hub->parent, setup, NULL);
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
@@ -233,13 +220,13 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hu
setup->wValue = 0;
setup->wIndex = port;
setup->wLength = 4;
return usbh_roothub_control(&roothub_setup, (uint8_t *)port_status);
return usbh_roothub_control(hub->bus, &roothub_setup, (uint8_t *)port_status);
} else {
return _usbh_hub_get_portstatus(hub, port, port_status);
}
}
static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
{
struct usb_setup_packet roothub_setup;
struct usb_setup_packet *setup;
@@ -251,13 +238,13 @@ static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feat
setup->wValue = feature;
setup->wIndex = port;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
return usbh_roothub_control(hub->bus, setup, NULL);
} else {
return _usbh_hub_set_feature(hub, port, feature);
}
}
static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
{
struct usb_setup_packet roothub_setup;
struct usb_setup_packet *setup;
@@ -269,7 +256,7 @@ static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t fe
setup->wValue = feature;
setup->wIndex = port;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
return usbh_roothub_control(hub->bus, setup, NULL);
} else {
return _usbh_hub_clear_feature(hub, port, feature);
}
@@ -287,7 +274,7 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
setup->wValue = depth;
setup->wIndex = 0;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
return usbh_roothub_control(hub->bus, setup, NULL);
} else {
return _usbh_hub_set_depth(hub, depth);
}
@@ -300,9 +287,22 @@ static void hub_int_complete_callback(void *arg, int nbytes)
if (nbytes > 0) {
usbh_hub_thread_wakeup(hub);
} else if (nbytes == -USB_ERR_NAK) {
/* 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;
@@ -311,12 +311,13 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_hub *hub = usbh_hub_class_alloc();
if (hub == NULL) {
USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
return -ENOMEM;
USB_LOG_ERR("Fail to alloc hub_class\r\n");
return -USB_ERR_NOMEM;
}
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->bus = hport->bus;
hport->config.intf[intf].priv = hub;
@@ -330,11 +331,12 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hub->child[port].port = port + 1;
hub->child[port].parent = hub;
hub->child[port].bus = hport->bus;
}
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_hport_activate_epx(&hub->intin, hport, ep_desc);
USBH_EP_INIT(hub->intin, ep_desc);
} else {
return -1;
}
@@ -370,12 +372,19 @@ 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);
usbh_hub_register(hub);
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->index - 1];
usbh_int_urb_fill(&hub->intin_urb, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
usbh_submit_urb(&hub->intin_urb);
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
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;
}
@@ -388,25 +397,22 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (hub) {
if (hub->intin) {
usbh_pipe_free(hub->intin);
usbh_kill_urb(&hub->intin_urb);
}
if (hub->int_timer) {
usb_osal_timer_delete(hub->int_timer);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
child = &hub->child[port];
usbh_hport_deactivate_ep0(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_hubport_release(child);
child->parent = NULL;
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hub_unregister(hub);
usb_slist_remove(&hub->bus->hub_list, &hub->list);
}
usbh_hub_class_free(hub);
@@ -415,27 +421,10 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
#endif
static void usbh_hubport_release(struct usbh_hubport *child)
{
if (child->connected) {
child->connected = false;
usbh_hport_deactivate_ep0(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;
}
}
static void usbh_hubport_enumerate_thread(void *argument)
{
struct usbh_hubport *child = (struct usbh_hubport *)argument;
/* Configure EP0 with the default maximum packet size */
usbh_hport_activate_ep0(child);
if (usbh_enumerate(child) < 0) {
/** release child sources */
usbh_hubport_release(child);
@@ -460,9 +449,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
return;
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
portchange_index = hub->int_buffer[0];
portchange_index = hub->int_buffer[0];
hub->int_buffer[0] &= ~portchange_index;
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
if (!(portchange_index & (1 << (port + 1)))) {
@@ -601,11 +591,13 @@ static void usbh_hub_events(struct usbh_hub *hub)
child->connected = true;
child->port = port + 1;
child->speed = speed;
child->bus = hub->bus;
child->mutex = usb_osal_mutex_create();
USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
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 */
child->thread = usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
} else {
child = &hub->child[port];
/** release child sources */
@@ -620,15 +612,14 @@ static void usbh_hub_events(struct usbh_hub *hub)
child = &hub->child[port];
/** release child sources */
usbh_hubport_release(child);
USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hub->bus->busid, hub->index, port + 1);
}
}
}
hub->int_buffer[0] = 0;
/* Start next hub int transfer */
if (!hub->is_roothub && hub->connected) {
usbh_submit_urb(&hub->intin_urb);
usb_osal_timer_start(hub->int_timer);
}
}
@@ -637,9 +628,11 @@ static void usbh_hub_thread(void *argument)
struct usbh_hub *hub;
int ret = 0;
usb_hc_init();
struct usbh_bus *bus = (struct usbh_bus *)argument;
usb_hc_init(bus);
while (1) {
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, 0xffffffff);
ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
@@ -647,46 +640,59 @@ static void usbh_hub_thread(void *argument)
}
}
static void usbh_roothub_register(void)
void usbh_hub_thread_wakeup(struct usbh_hub *hub)
{
memset(&roothub, 0, sizeof(struct usbh_hub));
roothub.connected = true;
roothub.index = 1;
roothub.is_roothub = true;
roothub.parent = NULL;
roothub.hub_addr = 1;
roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
usbh_hub_register(&roothub);
usb_osal_mq_send(hub->bus->hub_mq, (uintptr_t)hub);
}
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
int usbh_hub_initialize(struct usbh_bus *bus)
{
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
}
char thread_name[32] = { 0 };
void usbh_roothub_thread_wakeup(uint8_t port)
{
roothub.int_buffer = g_hub_intbuf[roothub.index - 1];
roothub.int_buffer[0] |= (1 << port);
usbh_hub_thread_wakeup(&roothub);
}
int usbh_hub_initialize(void)
{
usbh_roothub_register();
hub_mq = usb_osal_mq_create(7);
if (hub_mq == NULL) {
bus->hub_mq = usb_osal_mq_create(7);
if (bus->hub_mq == NULL) {
USB_LOG_ERR("Failed to create hub mq\r\n");
return -1;
}
hub_thread = usb_osal_thread_create("usbh_hub", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, NULL);
if (hub_thread == NULL) {
snprintf(thread_name, 32, "usbh_hub%u", bus->busid);
bus->hub_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, bus);
if (bus->hub_thread == NULL) {
USB_LOG_ERR("Failed to create hub thread\r\n");
return -1;
}
return 0;
}
int usbh_hub_deinitialize(struct usbh_bus *bus)
{
usb_slist_t *hub_list;
struct usbh_hubport *hport;
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);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
usbh_hubport_release(hport);
}
}
usb_hc_deinit(bus);
usb_osal_leave_critical_section(flags);
usb_osal_mq_delete(bus->hub_mq);
usb_osal_thread_delete(bus->hub_thread);
return 0;
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
const struct usbh_class_driver hub_class_driver = {
.driver_name = "hub",
@@ -699,8 +705,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

@@ -6,20 +6,26 @@
#ifndef USBH_HUB_H
#define USBH_HUB_H
#include "usbh_core.h"
#include "usb_hub.h"
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)
extern usb_slist_t hub_class_head;
#ifdef __cplusplus
extern "C" {
#endif
void usbh_roothub_thread_wakeup(uint8_t port);
int usbh_hub_initialize(void);
int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature);
void usbh_hub_thread_wakeup(struct usbh_hub *hub);
int usbh_hub_initialize(struct usbh_bus *bus);
int usbh_hub_deinitialize(struct usbh_bus *bus);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2024, zhihong chen
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,16 +14,16 @@ extern "C" {
#endif
/* Init msc interface driver */
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep);
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size);
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
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(bool readonly);
bool usbd_msc_set_popup(void);
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
bool usbd_msc_set_popup(uint8_t busid);
#ifdef __cplusplus
}

View File

@@ -7,12 +7,17 @@
#include "usbh_msc.h"
#include "usb_scsi.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_msc"
#include "usb_log.h"
#define DEV_FORMAT "/dev/sd%c"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[64];
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
static struct usbh_msc *usbh_msc_class_alloc(void)
{
@@ -49,7 +54,7 @@ static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
setup->wIndex = msc_class->intf;
setup->wLength = 1;
return usbh_control_transfer(msc_class->hport->ep0, setup, buffer);
return usbh_control_transfer(msc_class->hport, setup, buffer);
}
static void usbh_msc_cbw_dump(struct CBW *cbw)
@@ -86,9 +91,8 @@ static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t
{
int ret;
struct usbh_urb *urb = &msc_class->bulkin_urb;
memset(urb, 0, sizeof(struct usbh_urb));
usbh_bulk_urb_fill(urb, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
@@ -100,9 +104,8 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
{
int ret;
struct usbh_urb *urb = &msc_class->bulkout_urb;
memset(urb, 0, sizeof(struct usbh_urb));
usbh_bulk_urb_fill(urb, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
usbh_bulk_urb_fill(urb, msc_class->hport, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
@@ -110,7 +113,7 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
return ret;
}
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)
{
int nbytes;
@@ -156,12 +159,12 @@ int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct C
/* check csw status */
if (csw->dSignature != MSC_CSW_Signature) {
USB_LOG_ERR("csw signature error\r\n");
return -EINVAL;
return -USB_ERR_INVAL;
}
if (csw->bStatus != 0) {
USB_LOG_ERR("csw bStatus %d\r\n", csw->bStatus);
return -EINVAL;
return -USB_ERR_INVAL;
}
__err_exit:
return nbytes < 0 ? (int)nbytes : 0;
@@ -235,6 +238,132 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
}
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
memcpy(g_msc_buf, message, 31);
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_msc_modeswitch_config *config;
struct usbh_msc *msc_class = usbh_msc_class_alloc();
if (msc_class == NULL) {
USB_LOG_ERR("Fail to alloc msc_class\r\n");
return -USB_ERR_NOMEM;
}
msc_class->hport = hport;
msc_class->intf = intf;
hport->config.intf[intf].priv = msc_class;
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[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;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(msc_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(msc_class->bulkout, ep_desc);
}
}
if (g_msc_modeswitch_config) {
uint8_t num = 0;
while (1) {
config = &g_msc_modeswitch_config[num];
if (config && config->name) {
if ((hport->device_desc.idVendor == config->vid) &&
(hport->device_desc.idProduct == config->pid)) {
USB_LOG_INFO("%s usb_modeswitch enable\r\n", config->name);
usbh_msc_modeswitch(msc_class, config->message_content);
return 0;
}
num++;
} else {
break;
}
}
}
ret = usbh_msc_scsi_testunitready(msc_class);
if (ret < 0) {
ret = usbh_msc_scsi_requestsense(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
return ret;
}
}
ret = usbh_msc_scsi_inquiry(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
return ret;
}
ret = usbh_msc_scsi_readcapacity10(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
return ret;
}
if (msc_class->blocksize > 0) {
USB_LOG_INFO("Capacity info:\r\n");
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
} else {
USB_LOG_ERR("Invalid block size\r\n");
return -USB_ERR_RANGE;
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_run(msc_class);
return ret;
}
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
if (msc_class) {
if (msc_class->bulkin) {
usbh_kill_urb(&msc_class->bulkin_urb);
}
if (msc_class->bulkout) {
usbh_kill_urb(&msc_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_stop(msc_class);
}
usbh_msc_class_free(msc_class);
}
return ret;
}
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
@@ -274,97 +403,13 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
}
static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_msc *msc_class = usbh_msc_class_alloc();
if (msc_class == NULL) {
USB_LOG_ERR("Fail to alloc msc_class\r\n");
return -ENOMEM;
}
msc_class->hport = hport;
msc_class->intf = intf;
hport->config.intf[intf].priv = msc_class;
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[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;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_hport_activate_epx(&msc_class->bulkin, hport, ep_desc);
} else {
usbh_hport_activate_epx(&msc_class->bulkout, hport, ep_desc);
}
}
ret = usbh_msc_scsi_testunitready(msc_class);
if (ret < 0) {
ret = usbh_msc_scsi_requestsense(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
return ret;
}
}
ret = usbh_msc_scsi_inquiry(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
return ret;
}
ret = usbh_msc_scsi_readcapacity10(msc_class);
if (ret < 0) {
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
return ret;
}
if (msc_class->blocksize > 0) {
USB_LOG_INFO("Capacity info:\r\n");
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
if (config) {
g_msc_modeswitch_config = config;
} else {
USB_LOG_ERR("Invalid block size\r\n");
return -ERANGE;
g_msc_modeswitch_config = NULL;
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_run(msc_class);
return ret;
}
static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
if (msc_class) {
if (msc_class->bulkin) {
usbh_pipe_free(msc_class->bulkin);
}
if (msc_class->bulkout) {
usbh_pipe_free(msc_class->bulkout);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_stop(msc_class);
}
usbh_msc_class_free(msc_class);
}
return ret;
}
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
@@ -386,7 +431,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

@@ -11,17 +11,27 @@
struct usbh_msc {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
uint8_t intf; /* Data interface number */
uint8_t sdchar;
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
uint16_t blocksize; /* Block size of USB mass storage device */
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 {
const char *name;
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
uint16_t pid; /* Product ID (for vendor/product specific devices) */
const uint8_t *message_content;
};
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);

View File

@@ -1,471 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_MTP_H
#define USB_MTP_H
#define USB_MTP_CLASS 0x06
#define USB_MTP_SUB_CLASS 0x01U
#define USB_MTP_PROTOCOL 0x01U
/* MTP class requests */
#define MTP_REQUEST_CANCEL 0x64U
#define MTP_REQUEST_GET_EXT_EVENT_DATA 0x65U
#define MTP_REQUEST_RESET 0x66U
#define MTP_REQUEST_GET_DEVICE_STATUS 0x67U
/* Container Types */
#define MTP_CONTAINER_TYPE_UNDEFINED 0U
#define MTP_CONTAINER_TYPE_COMMAND 1U
#define MTP_CONTAINER_TYPE_DATA 2U
#define MTP_CONTAINER_TYPE_RESPONSE 3U
#define MTP_CONTAINER_TYPE_EVENT 4U
/*
* MTP Class specification Revision 1.1
* Appendix D. Operations
*/
/* Operations code */
#define MTP_OP_GET_DEVICE_INFO 0x1001U
#define MTP_OP_OPEN_SESSION 0x1002U
#define MTP_OP_CLOSE_SESSION 0x1003U
#define MTP_OP_GET_STORAGE_IDS 0x1004U
#define MTP_OP_GET_STORAGE_INFO 0x1005U
#define MTP_OP_GET_NUM_OBJECTS 0x1006U
#define MTP_OP_GET_OBJECT_HANDLES 0x1007U
#define MTP_OP_GET_OBJECT_INFO 0x1008U
#define MTP_OP_GET_OBJECT 0x1009U
#define MTP_OP_GET_THUMB 0x100AU
#define MTP_OP_DELETE_OBJECT 0x100BU
#define MTP_OP_SEND_OBJECT_INFO 0x100CU
#define MTP_OP_SEND_OBJECT 0x100DU
#define MTP_OP_FORMAT_STORE 0x100FU
#define MTP_OP_RESET_DEVICE 0x1010U
#define MTP_OP_GET_DEVICE_PROP_DESC 0x1014U
#define MTP_OP_GET_DEVICE_PROP_VALUE 0x1015U
#define MTP_OP_SET_DEVICE_PROP_VALUE 0x1016U
#define MTP_OP_RESET_DEVICE_PROP_VALUE 0x1017U
#define MTP_OP_TERMINATE_OPEN_CAPTURE 0x1018U
#define MTP_OP_MOVE_OBJECT 0x1019U
#define MTP_OP_COPY_OBJECT 0x101AU
#define MTP_OP_GET_PARTIAL_OBJECT 0x101BU
#define MTP_OP_INITIATE_OPEN_CAPTURE 0x101CU
#define MTP_OP_GET_OBJECT_PROPS_SUPPORTED 0x9801U
#define MTP_OP_GET_OBJECT_PROP_DESC 0x9802U
#define MTP_OP_GET_OBJECT_PROP_VALUE 0x9803U
#define MTP_OP_SET_OBJECT_PROP_VALUE 0x9804U
#define MTP_OP_GET_OBJECT_PROPLIST 0x9805U
#define MTP_OP_GET_OBJECT_PROP_REFERENCES 0x9810U
#define MTP_OP_GETSERVICEIDS 0x9301U
#define MTP_OP_GETSERVICEINFO 0x9302U
#define MTP_OP_GETSERVICECAPABILITIES 0x9303U
#define MTP_OP_GETSERVICEPROPDESC 0x9304U
/* MTP response code */
#define MTP_RESPONSE_OK 0x2001U
#define MTP_RESPONSE_GENERAL_ERROR 0x2002U
#define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006U
#define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007U
#define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008U
#define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009U
#define MTP_RESPONSE_DEVICEPROP_NOT_SUPPORTED 0x200AU
#define MTP_RESPONSE_STORE_FULL 0x200CU
#define MTP_RESPONSE_ACCESS_DENIED 0x200FU
#define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013U
#define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_NOT_SUPPORTED 0x2014U
#define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015U
#define MTP_RESPONSE_DEVICE_BUSY 0x2019U
#define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201AU
#define MTP_RESPONSE_INVALID_PARAMETER 0x201DU
#define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201EU
#define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201FU
#define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801U
#define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807U
#define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80AU
/* MTP Object format codes */
#define MTP_OBJ_FORMAT_UNDEFINED 0x3000U
#define MTP_OBJ_FORMAT_ASSOCIATION 0x3001U
#define MTP_OBJ_FORMAT_SCRIPT 0x3002U
#define MTP_OBJ_FORMAT_EXECUTABLE 0x3003U
#define MTP_OBJ_FORMAT_TEXT 0x3004U
#define MTP_OBJ_FORMAT_HTML 0x3005U
#define MTP_OBJ_FORMAT_DPOF 0x3006U
#define MTP_OBJ_FORMAT_AIFF 0x3007U
#define MTP_OBJ_FORMAT_WAV 0x3008U
#define MTP_OBJ_FORMAT_MP3 0x3009U
#define MTP_OBJ_FORMAT_AVI 0x300AU
#define MTP_OBJ_FORMAT_MPEG 0x300BU
#define MTP_OBJ_FORMAT_ASF 0x300CU
#define MTP_OBJ_FORMAT_DEFINED 0x3800U
#define MTP_OBJ_FORMAT_EXIF_JPEG 0x3801U
#define MTP_OBJ_FORMAT_TIFF_EP 0x3802U
#define MTP_OBJ_FORMAT_FLASHPIX 0x3803U
#define MTP_OBJ_FORMAT_BMP 0x3804U
#define MTP_OBJ_FORMAT_CIFF 0x3805U
#define MTP_OBJ_FORMAT_UNDEFINED_RESERVED0 0x3806U
#define MTP_OBJ_FORMAT_GIF 0x3807U
#define MTP_OBJ_FORMAT_JFIF 0x3808U
#define MTP_OBJ_FORMAT_CD 0x3809U
#define MTP_OBJ_FORMAT_PICT 0x380AU
#define MTP_OBJ_FORMAT_PNG 0x380BU
#define MTP_OBJ_FORMAT_UNDEFINED_RESERVED1 0x380CU
#define MTP_OBJ_FORMAT_TIFF 0x380DU
#define MTP_OBJ_FORMAT_TIFF_IT 0x380EU
#define MTP_OBJ_FORMAT_JP2 0x380FU
#define MTP_OBJ_FORMAT_JPX 0x3810U
#define MTP_OBJ_FORMAT_UNDEFINED_FIRMWARE 0xB802U
#define MTP_OBJ_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881U
#define MTP_OBJ_FORMAT_UNDEFINED_AUDIO 0xB900U
#define MTP_OBJ_FORMAT_WMA 0xB901U
#define MTP_OBJ_FORMAT_OGG 0xB902U
#define MTP_OBJ_FORMAT_AAC 0xB903U
#define MTP_OBJ_FORMAT_AUDIBLE 0xB904U
#define MTP_OBJ_FORMAT_FLAC 0xB906U
#define MTP_OBJ_FORMAT_UNDEFINED_VIDEO 0xB980U
#define MTP_OBJ_FORMAT_WMV 0xB981U
#define MTP_OBJ_FORMAT_MP4_CONTAINER 0xB982U
#define MTP_OBJ_FORMAT_MP2 0xB983U
#define MTP_OBJ_FORMAT_3GP_CONTAINER 0xB984U
/* MTP event codes*/
#define MTP_EVENT_UNDEFINED 0x4000U
#define MTP_EVENT_CANCELTRANSACTION 0x4001U
#define MTP_EVENT_OBJECTADDED 0x4002U
#define MTP_EVENT_OBJECTREMOVED 0x4003U
#define MTP_EVENT_STOREADDED 0x4004U
#define MTP_EVENT_STOREREMOVED 0x4005U
#define MTP_EVENT_DEVICEPROPCHANGED 0x4006U
#define MTP_EVENT_OBJECTINFOCHANGED 0x4007U
#define MTP_EVENT_DEVICEINFOCHANGED 0x4008U
#define MTP_EVENT_REQUESTOBJECTTRANSFER 0x4009U
#define MTP_EVENT_STOREFULL 0x400AU
#define MTP_EVENT_DEVICERESET 0x400BU
#define MTP_EVENT_STORAGEINFOCHANGED 0x400CU
#define MTP_EVENT_CAPTURECOMPLETE 0x400DU
#define MTP_EVENT_UNREPORTEDSTATUS 0x400EU
#define MTP_EVENT_OBJECTPROPCHANGED 0xC801U
#define MTP_EVENT_OBJECTPROPDESCCHANGED 0xC802U
#define MTP_EVENT_OBJECTREFERENCESCHANGED 0xC803U
/* MTP device properties code*/
#define MTP_DEV_PROP_UNDEFINED 0x5000U
#define MTP_DEV_PROP_BATTERY_LEVEL 0x5001U
#define MTP_DEV_PROP_FUNCTIONAL_MODE 0x5002U
#define MTP_DEV_PROP_IMAGE_SIZE 0x5003U
#define MTP_DEV_PROP_COMPRESSION_SETTING 0x5004U
#define MTP_DEV_PROP_WHITE_BALANCE 0x5005U
#define MTP_DEV_PROP_RGB_GAIN 0x5006U
#define MTP_DEV_PROP_F_NUMBER 0x5007U
#define MTP_DEV_PROP_FOCAL_LENGTH 0x5008U
#define MTP_DEV_PROP_FOCUS_DISTANCE 0x5009U
#define MTP_DEV_PROP_FOCUS_MODE 0x500AU
#define MTP_DEV_PROP_EXPOSURE_METERING_MODE 0x500BU
#define MTP_DEV_PROP_FLASH_MODE 0x500CU
#define MTP_DEV_PROP_EXPOSURE_TIME 0x500DU
#define MTP_DEV_PROP_EXPOSURE_PROGRAM_MODE 0x500EU
#define MTP_DEV_PROP_EXPOSURE_INDEX 0x500FU
#define MTP_DEV_PROP_EXPOSURE_BIAS_COMPENSATION 0x5010U
#define MTP_DEV_PROP_DATETIME 0x5011U
#define MTP_DEV_PROP_CAPTURE_DELAY 0x5012U
#define MTP_DEV_PROP_STILL_CAPTURE_MODE 0x5013U
#define MTP_DEV_PROP_CONTRAST 0x5014U
#define MTP_DEV_PROP_SHARPNESS 0x5015U
#define MTP_DEV_PROP_DIGITAL_ZOOM 0x5016U
#define MTP_DEV_PROP_EFFECT_MODE 0x5017U
#define MTP_DEV_PROP_BURST_NUMBER 0x5018U
#define MTP_DEV_PROP_BURST_INTERVAL 0x5019U
#define MTP_DEV_PROP_TIMELAPSE_NUMBER 0x501AU
#define MTP_DEV_PROP_TIMELAPSE_INTERVAL 0x501BU
#define MTP_DEV_PROP_FOCUS_METERING_MODE 0x501CU
#define MTP_DEV_PROP_UPLOAD_URL 0x501DU
#define MTP_DEV_PROP_ARTIST 0x501EU
#define MTP_DEV_PROP_COPYRIGHT_INFO 0x501FU
#define MTP_DEV_PROP_SYNCHRONIZATION_PARTNER 0xD401U
#define MTP_DEV_PROP_DEVICE_FRIENDLY_NAME 0xD402U
#define MTP_DEV_PROP_VOLUME 0xD403U
#define MTP_DEV_PROP_SUPPORTEDFORMATSORDERED 0xD404U
#define MTP_DEV_PROP_DEVICEICON 0xD405U
#define MTP_DEV_PROP_PLAYBACK_RATE 0xD410U
#define MTP_DEV_PROP_PLAYBACK_OBJECT 0xD411U
#define MTP_DEV_PROP_PLAYBACK_CONTAINER 0xD412U
#define MTP_DEV_PROP_SESSION_INITIATOR_VERSION_INFO 0xD406U
#define MTP_DEV_PROP_PERCEIVED_DEVICE_TYPE 0xD407U
/*
* MTP Class specification Revision 1.1
* Appendix B. Object Properties
*/
/* MTP OBJECT PROPERTIES supported*/
#define MTP_OB_PROP_STORAGE_ID 0xDC01U
#define MTP_OB_PROP_OBJECT_FORMAT 0xDC02U
#define MTP_OB_PROP_PROTECTION_STATUS 0xDC03U
#define MTP_OB_PROP_OBJECT_SIZE 0xDC04U
#define MTP_OB_PROP_ASSOC_TYPE 0xDC05U
#define MTP_OB_PROP_ASSOC_DESC 0xDC06U
#define MTP_OB_PROP_OBJ_FILE_NAME 0xDC07U
#define MTP_OB_PROP_DATE_CREATED 0xDC08U
#define MTP_OB_PROP_DATE_MODIFIED 0xDC09U
#define MTP_OB_PROP_KEYWORDS 0xDC0AU
#define MTP_OB_PROP_PARENT_OBJECT 0xDC0BU
#define MTP_OB_PROP_ALLOWED_FOLD_CONTENTS 0xDC0CU
#define MTP_OB_PROP_HIDDEN 0xDC0DU
#define MTP_OB_PROP_SYSTEM_OBJECT 0xDC0EU
#define MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN 0xDC41U
#define MTP_OB_PROP_SYNCID 0xDC42U
#define MTP_OB_PROP_PROPERTY_BAG 0xDC43U
#define MTP_OB_PROP_NAME 0xDC44U
#define MTP_OB_PROP_CREATED_BY 0xDC45U
#define MTP_OB_PROP_ARTIST 0xDC46U
#define MTP_OB_PROP_DATE_AUTHORED 0xDC47U
#define MTP_OB_PROP_DESCRIPTION 0xDC48U
#define MTP_OB_PROP_URL_REFERENCE 0xDC49U
#define MTP_OB_PROP_LANGUAGELOCALE 0xDC4AU
#define MTP_OB_PROP_COPYRIGHT_INFORMATION 0xDC4BU
#define MTP_OB_PROP_SOURCE 0xDC4CU
#define MTP_OB_PROP_ORIGIN_LOCATION 0xDC4DU
#define MTP_OB_PROP_DATE_ADDED 0xDC4EU
#define MTP_OB_PROP_NON_CONSUMABLE 0xDC4FU
#define MTP_OB_PROP_CORRUPTUNPLAYABLE 0xDC50U
#define MTP_OB_PROP_PRODUCERSERIALNUMBER 0xDC51U
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81U
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_SIZE 0xDC82U
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83U
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84U
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DURATION 0xDC85U
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DATA 0xDC86U
#define MTP_OB_PROP_WIDTH 0xDC87U
#define MTP_OB_PROP_HEIGHT 0xDC88U
#define MTP_OB_PROP_DURATION 0xDC89U
#define MTP_OB_PROP_RATING 0xDC8AU
#define MTP_OB_PROP_TRACK 0xDC8BU
#define MTP_OB_PROP_GENRE 0xDC8CU
#define MTP_OB_PROP_CREDITS 0xDC8DU
#define MTP_OB_PROP_LYRICS 0xDC8EU
#define MTP_OB_PROP_SUBSCRIPTION_CONTENT_ID 0xDC8FU
#define MTP_OB_PROP_PRODUCED_BY 0xDC90U
#define MTP_OB_PROP_USE_COUNT 0xDC91U
#define MTP_OB_PROP_SKIP_COUNT 0xDC92U
#define MTP_OB_PROP_LAST_ACCESSED 0xDC93U
#define MTP_OB_PROP_PARENTAL_RATING 0xDC94U
#define MTP_OB_PROP_META_GENRE 0xDC95U
#define MTP_OB_PROP_COMPOSER 0xDC96U
#define MTP_OB_PROP_EFFECTIVE_RATING 0xDC97U
#define MTP_OB_PROP_SUBTITLE 0xDC98U
#define MTP_OB_PROP_ORIGINAL_RELEASE_DATE 0xDC99U
#define MTP_OB_PROP_ALBUM_NAME 0xDC9AU
#define MTP_OB_PROP_ALBUM_ARTIST 0xDC9BU
#define MTP_OB_PROP_MOOD 0xDC9CU
#define MTP_OB_PROP_DRM_STATUS 0xDC9DU
#define MTP_OB_PROP_SUB_DESCRIPTION 0xDC9EU
#define MTP_OB_PROP_IS_CROPPED 0xDCD1U
#define MTP_OB_PROP_IS_COLOUR_CORRECTED 0xDCD2U
#define MTP_OB_PROP_IMAGE_BIT_DEPTH 0xDCD3U
#define MTP_OB_PROP_FNUMBER 0xDCD4U
#define MTP_OB_PROP_EXPOSURE_TIME 0xDCD5U
#define MTP_OB_PROP_EXPOSURE_INDEX 0xDCD6U
#define MTP_OB_PROP_TOTAL_BITRATE 0xDE91U
#define MTP_OB_PROP_BITRATE_TYPE 0xDE92U
#define MTP_OB_PROP_SAMPLE_RATE 0xDE93U
#define MTP_OB_PROP_NUMBER_OF_CHANNELS 0xDE94U
#define MTP_OB_PROP_AUDIO_BITDEPTH 0xDE95U
#define MTP_OB_PROP_SCAN_TYPE 0xDE97U
#define MTP_OB_PROP_AUDIO_WAVE_CODEC 0xDE99U
#define MTP_OB_PROP_AUDIO_BITRATE 0xDE9AU
#define MTP_OB_PROP_VIDEO_FOURCC_CODEC 0xDE9BU
#define MTP_OB_PROP_VIDEO_BITRATE 0xDE9CU
#define MTP_OB_PROP_FRAMES_PER_THOUSAND_SECONDS 0xDE9DU
#define MTP_OB_PROP_KEYFRAME_DISTANCE 0xDE9EU
#define MTP_OB_PROP_BUFFER_SIZE 0xDE9FU
#define MTP_OB_PROP_ENCODING_QUALITY 0xDEA0U
#define MTP_OB_PROP_ENCODING_PROFILE 0xDEA1U
#define MTP_OB_PROP_DISPLAY_NAME 0xDCE0U
#define MTP_OB_PROP_BODY_TEXT 0xDCE1U
#define MTP_OB_PROP_SUBJECT 0xDCE2U
#define MTP_OB_PROP_PRIORITY 0xDCE3U
#define MTP_OB_PROP_GIVEN_NAME 0xDD00U
#define MTP_OB_PROP_MIDDLE_NAMES 0xDD01U
#define MTP_OB_PROP_FAMILY_NAME 0xDD02U
#define MTP_OB_PROP_PREFIX 0xDD03U
#define MTP_OB_PROP_SUFFIX 0xDD04U
#define MTP_OB_PROP_PHONETIC_GIVEN_NAME 0xDD05U
#define MTP_OB_PROP_PHONETIC_FAMILY_NAME 0xDD06U
#define MTP_OB_PROP_EMAIL_PRIMARY 0xDD07U
#define MTP_OB_PROP_EMAIL_PERSONAL_1 0xDD08U
#define MTP_OB_PROP_EMAIL_PERSONAL_2 0xDD09U
#define MTP_OB_PROP_EMAIL_BUSINESS_1 0xDD0AU
#define MTP_OB_PROP_EMAIL_BUSINESS_2 0xDD0BU
#define MTP_OB_PROP_EMAIL_OTHERS 0xDD0CU
#define MTP_OB_PROP_PHONE_NUMBER_PRIMARY 0xDD0DU
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL 0xDD0EU
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL_2 0xDD0FU
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS 0xDD10U
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS_2 0xDD11U
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE 0xDD12U
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE_2 0xDD13U
#define MTP_OB_PROP_FAX_NUMBER_PRIMARY 0xDD14U
#define MTP_OB_PROP_FAX_NUMBER_PERSONAL 0xDD15U
#define MTP_OB_PROP_FAX_NUMBER_BUSINESS 0xDD16U
#define MTP_OB_PROP_PAGER_NUMBER 0xDD17U
#define MTP_OB_PROP_PHONE_NUMBER_OTHERS 0xDD18U
#define MTP_OB_PROP_PRIMARY_WEB_ADDRESS 0xDD19U
#define MTP_OB_PROP_PERSONAL_WEB_ADDRESS 0xDD1AU
#define MTP_OB_PROP_BUSINESS_WEB_ADDRESS 0xDD1BU
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS 0xDD1CU
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_2 0xDD1DU
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_3 0xDD1EU
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1FU
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20U
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21U
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22U
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23U
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24U
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25U
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26U
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27U
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28U
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29U
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2AU
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2BU
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2CU
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_FULL 0xDD2DU
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2EU
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2FU
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_CITY 0xDD30U
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_REGION 0xDD31U
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32U
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33U
#define MTP_OB_PROP_ORGANIZATION_NAME 0xDD34U
#define MTP_OB_PROP_PHONETIC_ORGANIZATION_NAME 0xDD35U
#define MTP_OB_PROP_ROLE 0xDD36U
#define MTP_OB_PROP_BIRTHDATE 0xDD37U
#define MTP_OB_PROP_MESSAGE_TO 0xDD40U
#define MTP_OB_PROP_MESSAGE_CC 0xDD41U
#define MTP_OB_PROP_MESSAGE_BCC 0xDD42U
#define MTP_OB_PROP_MESSAGE_READ 0xDD43U
#define MTP_OB_PROP_MESSAGE_RECEIVED_TIME 0xDD44U
#define MTP_OB_PROP_MESSAGE_SENDER 0xDD45U
#define MTP_OB_PROP_ACT_BEGIN_TIME 0xDD50U
#define MTP_OB_PROP_ACT_END_TIME 0xDD51U
#define MTP_OB_PROP_ACT_LOCATION 0xDD52U
#define MTP_OB_PROP_ACT_REQUIRED_ATTENDEES 0xDD54U
#define MTP_OB_PROP_ACT_OPTIONAL_ATTENDEES 0xDD55U
#define MTP_OB_PROP_ACT_RESOURCES 0xDD56U
#define MTP_OB_PROP_ACT_ACCEPTED 0xDD57U
#define MTP_OB_PROP_OWNER 0xDD5DU
#define MTP_OB_PROP_EDITOR 0xDD5EU
#define MTP_OB_PROP_WEBMASTER 0xDD5FU
#define MTP_OB_PROP_URL_SOURCE 0xDD60U
#define MTP_OB_PROP_URL_DESTINATION 0xDD61U
#define MTP_OB_PROP_TIME_BOOKMARK 0xDD62U
#define MTP_OB_PROP_OBJECT_BOOKMARK 0xDD63U
#define MTP_OB_PROP_BYTE_BOOKMARK 0xDD64U
#define MTP_OB_PROP_LAST_BUILD_DATE 0xDD70U
#define MTP_OB_PROP_TIME_TO_LIVE 0xDD71U
#define MTP_OB_PROP_MEDIA_GUID 0xDD72U
/* MTP storage type */
#define MTP_STORAGE_UNDEFINED 0U
#define MTP_STORAGE_FIXED_ROM 0x0001U
#define MTP_STORAGE_REMOVABLE_ROM 0x0002U
#define MTP_STORAGE_FIXED_RAM 0x0003U
#define MTP_STORAGE_REMOVABLE_RAM 0x0004U
/* MTP file system type */
#define MTP_FILESYSTEM_UNDEFINED 0U
#define MTP_FILESYSTEM_GENERIC_FLAT 0x0001U
#define MTP_FILESYSTEM_GENERIC_HIERARCH 0x0002U
#define MTP_FILESYSTEM_DCF 0x0003U
/* MTP access capability */
#define MTP_ACCESS_CAP_RW 0U /* read write */
#define MTP_ACCESS_CAP_RO_WITHOUT_DEL 0x0001U
#define MTP_ACCESS_CAP_RO_WITH_DEL 0x0002U
/* MTP standard data types supported */
#define MTP_DATATYPE_INT8 0x0001U
#define MTP_DATATYPE_UINT8 0x0002U
#define MTP_DATATYPE_INT16 0x0003U
#define MTP_DATATYPE_UINT16 0x0004U
#define MTP_DATATYPE_INT32 0x0005U
#define MTP_DATATYPE_UINT32 0x0006U
#define MTP_DATATYPE_INT64 0x0007U
#define MTP_DATATYPE_UINT64 0x0008U
#define MTP_DATATYPE_UINT128 0x000AU
#define MTP_DATATYPE_STR 0xFFFFU
/* MTP reading only or reading/writing */
#define MTP_PROP_GET 0x00U
#define MTP_PROP_GET_SET 0x01U
#define MTP_SESSION_CLOSED 0x00
#define MTP_SESSION_OPENED 0x01
struct mtp_container_command {
uint32_t conlen;
uint16_t contype;
uint16_t code;
uint32_t trans_id;
uint32_t param1;
uint32_t param2;
uint32_t param3;
uint32_t param4;
uint32_t param5;
} __PACKED;
struct mtp_container_data {
uint32_t conlen;
uint16_t contype;
uint16_t code;
uint32_t trans_id;
uint8_t data[512];
} __PACKED;
struct mtp_container_response {
uint32_t conlen;
uint16_t contype;
uint16_t code;
uint32_t trans_id;
} __PACKED;
/*Length of template descriptor: 23 bytes*/
#define MTP_DESCRIPTOR_LEN (9 + 7 + 7 + 7)
// clang-format off
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, wMaxPacketSize, str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x03, /* bNumEndpoints */ \
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
USB_MTP_SUB_CLASS, /* bInterfaceSubClass */ \
USB_MTP_PROTOCOL, /* bInterfaceProtocol */ \
str_idx, /* 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 */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x1c, 0x00, /* wMaxPacketSize */ \
0x06 /* bInterval */
// clang-format on
#endif /* USB_MTP_H */

View File

@@ -1,566 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_mtp.h"
#include "usbd_mtp_config.h"
/* MTP Stage */
enum Stage {
MTP_READ_COMMAND = 0,
MTP_DATA_OUT = 1,
MTP_DATA_IN = 2,
MTP_SEND_RESPONSE = 3,
MTP_WAIT_RESPONSE = 4,
};
USB_NOCACHE_RAM_SECTION struct usbd_mtp_priv {
USB_MEM_ALIGNX struct mtp_container_command con_command;
USB_MEM_ALIGNX struct mtp_container_data con_data;
USB_MEM_ALIGNX struct mtp_container_response con_response;
enum Stage stage;
uint8_t session_state;
uint32_t response_code;
} g_usbd_mtp;
/* Max USB packet size */
#ifndef CONFIG_USB_HS
#define MTP_BULK_EP_MPS 64
#else
#define MTP_BULK_EP_MPS 512
#endif
#define MTP_OUT_EP_IDX 0
#define MTP_IN_EP_IDX 1
#define MTP_INT_EP_IDX 2
/* Describe EndPoints configuration */
static struct usbd_endpoint mtp_ep_data[3];
static int mtp_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("MTP Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
switch (setup->bRequest) {
case MTP_REQUEST_CANCEL:
break;
case MTP_REQUEST_GET_EXT_EVENT_DATA:
break;
case MTP_REQUEST_RESET:
break;
case MTP_REQUEST_GET_DEVICE_STATUS:
break;
default:
USB_LOG_WRN("Unhandled MTP Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
static void usbd_mtp_send_response(uint32_t code)
{
USB_LOG_DBG("Send response\r\n");
g_usbd_mtp.stage = MTP_WAIT_RESPONSE;
g_usbd_mtp.con_response.conlen = 12;
g_usbd_mtp.con_response.contype = MTP_CONTAINER_TYPE_RESPONSE;
g_usbd_mtp.con_response.code = code;
g_usbd_mtp.con_response.trans_id = g_usbd_mtp.con_command.trans_id;
usbd_ep_start_write(mtp_ep_data[MTP_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_response, 12);
}
static void usbd_mtp_send_info(uint8_t *data, uint32_t len)
{
USB_LOG_DBG("Send info\r\n");
g_usbd_mtp.stage = MTP_SEND_RESPONSE;
g_usbd_mtp.con_data.conlen = 12 + len;
g_usbd_mtp.con_data.contype = MTP_CONTAINER_TYPE_DATA;
g_usbd_mtp.con_data.code = MTP_RESPONSE_OK;
g_usbd_mtp.con_data.trans_id = g_usbd_mtp.con_command.trans_id;
memcpy(g_usbd_mtp.con_data.data, data, len);
usbd_ep_start_write(mtp_ep_data[MTP_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_data, 12 + len);
}
static void usbd_mtp_get_device_info(void)
{
struct mtp_device_info device_info;
uint16_t i;
device_info.StandardVersion = 100;
device_info.VendorExtensionID = 0x06;
device_info.VendorExtensionVersion = 100;
device_info.VendorExtensionDesc_len = (uint8_t)CONFIG_MTP_VEND_EXT_DESC_LEN;
for (i = 0; i < CONFIG_MTP_VEND_EXT_DESC_LEN; i++) {
device_info.VendorExtensionDesc[i] = VendExtDesc[i];
}
/* device supports one mode , standard mode */
device_info.FunctionalMode = 0x0000;
/* All supported operation */
device_info.OperationsSupported_len = CONFIG_MTP_SUPP_OP_LEN;
for (i = 0U; i < CONFIG_MTP_SUPP_OP_LEN; i++) {
device_info.OperationsSupported[i] = SuppOP[i];
}
/* event that are currently generated by the device*/
device_info.EventsSupported_len = CONFIG_MTP_SUPP_EVENTS_LEN;
for (i = 0U; i < CONFIG_MTP_SUPP_EVENTS_LEN; i++) {
device_info.EventsSupported[i] = SuppEvents[i];
}
device_info.DevicePropertiesSupported_len = CONFIG_MTP_SUPP_DEVICE_PROP_LEN;
for (i = 0U; i < CONFIG_MTP_SUPP_DEVICE_PROP_LEN; i++) {
device_info.DevicePropertiesSupported[i] = DevicePropSupp[i];
}
device_info.CaptureFormats_len = CONFIG_MTP_SUPP_CAPT_FORMAT_LEN;
for (i = 0U; i < CONFIG_MTP_SUPP_CAPT_FORMAT_LEN; i++) {
device_info.CaptureFormats[i] = SuppCaptFormat[i];
}
device_info.ImageFormats_len = CONFIG_MTP_SUPP_IMG_FORMAT_LEN; /* number of image formats that are supported by the device*/
for (i = 0U; i < CONFIG_MTP_SUPP_IMG_FORMAT_LEN; i++) {
device_info.ImageFormats[i] = SuppImgFormat[i];
}
device_info.Manufacturer_len = (uint8_t)CONFIG_MTP_MANUF_LEN;
for (i = 0U; i < CONFIG_MTP_MANUF_LEN; i++) {
device_info.Manufacturer[i] = Manuf[i];
}
device_info.Model_len = (uint8_t)CONFIG_MTP_MODEL_LEN;
for (i = 0U; i < CONFIG_MTP_MODEL_LEN; i++) {
device_info.Model[i] = Model[i];
}
device_info.DeviceVersion_len = (uint8_t)CONFIG_MTP_DEVICE_VERSION_LEN;
for (i = 0U; i < CONFIG_MTP_DEVICE_VERSION_LEN; i++) {
device_info.DeviceVersion[i] = DeviceVers[i];
}
device_info.SerialNumber_len = (uint8_t)CONFIG_MTP_SERIAL_NBR_LEN;
for (i = 0U; i < CONFIG_MTP_SERIAL_NBR_LEN; i++) {
device_info.SerialNumber[i] = SerialNbr[i];
}
usbd_mtp_send_info((uint8_t *)&device_info, sizeof(struct mtp_device_info));
}
static void usbd_mtp_open_session(void)
{
usbd_mtp_send_response(MTP_RESPONSE_OK);
}
static void usbd_mtp_get_storage_ids(void)
{
struct mtp_storage_id storage_id;
storage_id.StorageIDS_len = CONFIG_MTP_STORAGE_ID_LEN;
storage_id.StorageIDS[0] = MTP_STORAGE_ID;
usbd_mtp_send_info((uint8_t *)&storage_id, sizeof(struct mtp_storage_id));
}
static void usbd_mtp_get_storage_info(void)
{
struct mtp_storage_info storage_info;
storage_info.StorageType = MTP_STORAGE_REMOVABLE_RAM;
storage_info.FilesystemType = MTP_FILESYSTEM_GENERIC_FLAT;
storage_info.AccessCapability = MTP_ACCESS_CAP_RW;
storage_info.MaxCapability = 0x0080DFA81A000000; // todo
storage_info.FreeSpaceInBytes = 0x00007EEB0D000000; // todo
storage_info.FreeSpaceInObjects = 0xFFFFFFFFU; /* not used */
storage_info.StorageDescription = 0U;
storage_info.VolumeLabel = 0U;
usbd_mtp_send_info((uint8_t *)&storage_info, sizeof(struct mtp_storage_info));
}
static void usbd_mtp_get_object_handles(void)
{
struct mtp_object_handle object_handle;
// todo
usbd_mtp_send_info((uint8_t *)&object_handle, sizeof(struct mtp_object_handle));
}
static void usbd_mtp_get_object_info(void)
{
struct mtp_object_info object_info;
object_info.Storage_id = MTP_STORAGE_ID;
object_info.ObjectFormat = 0; // todo
object_info.ObjectCompressedSize = 0; //todo
object_info.ProtectionStatus = 0U;
object_info.ThumbFormat = MTP_OBJ_FORMAT_UNDEFINED;
object_info.ThumbCompressedSize = 0U;
object_info.ThumbPixWidth = 0U; /* not supported or not an image */
object_info.ThumbPixHeight = 0U;
object_info.ImagePixWidth = 0U;
object_info.ImagePixHeight = 0U;
object_info.ImageBitDepth = 0U;
object_info.ParentObject = 0; // todo
object_info.AssociationType = 0U;
object_info.AssociationDesc = 0U;
object_info.SequenceNumber = 0U;
/* we have to get this value before object_info.Filename */
object_info.Filename_len = sizeof(DefaultFileName);
memcpy(object_info.Filename, DefaultFileName, (uint32_t)object_info.Filename_len + 1U);
object_info.CaptureDate = 0U;
object_info.ModificationDate = 0U;
object_info.Keywords = 0U;
usbd_mtp_send_info((uint8_t *)&object_info, sizeof(struct mtp_object_info));
}
static void usbd_mtp_get_object_prop_desc(void)
{
struct mtp_object_prop_desc object_prop_desc;
uint16_t undef_format = MTP_OBJ_FORMAT_UNDEFINED;
uint32_t storageid = MTP_STORAGE_ID;
switch (g_usbd_mtp.con_command.param1) /* switch obj prop code */
{
case MTP_OB_PROP_OBJECT_FORMAT:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_UINT16;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = (uint8_t *)&undef_format;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_STORAGE_ID:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_UINT32;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = (uint8_t *)&storageid;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_OBJ_FILE_NAME:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_STR;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = 0U;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_PARENT_OBJECT:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_STR;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = 0U;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_OBJECT_SIZE:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_UINT64;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = 0U;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_NAME:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_STR;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = NULL;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_UINT128;
object_prop_desc.GetSet = MTP_PROP_GET;
object_prop_desc.DefValue = 0U;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
case MTP_OB_PROP_PROTECTION_STATUS:
object_prop_desc.ObjectPropertyCode = (uint16_t)(g_usbd_mtp.con_command.param1);
object_prop_desc.DataType = MTP_DATATYPE_UINT16;
object_prop_desc.GetSet = MTP_PROP_GET_SET;
object_prop_desc.DefValue = 0U;
object_prop_desc.GroupCode = 0U;
object_prop_desc.FormFlag = 0U;
break;
default:
break;
}
// todo
usbd_mtp_send_info((uint8_t *)&object_prop_desc, sizeof(struct mtp_object_prop_desc));
}
static void usbd_mtp_get_object_props_supported(void)
{
struct mtp_object_props_support object_props_support;
uint32_t i;
object_props_support.ObjectPropCode_len = CONFIG_MTP_SUPP_OBJ_PROP_LEN;
for (i = 0U; i < CONFIG_MTP_SUPP_OBJ_PROP_LEN; i++) {
object_props_support.ObjectPropCode[i] = ObjectPropCode[i];
}
usbd_mtp_send_info((uint8_t *)&object_props_support, sizeof(struct mtp_object_props_support));
}
static void usbd_mtp_get_object_prop_list(void)
{
struct mtp_object_prop_list object_prop_list;
uint16_t filename[255];
uint32_t storageid = MTP_STORAGE_ID;
uint32_t default_val = 0U;
uint32_t i;
uint16_t format;
uint64_t objsize;
uint32_t parent_proval;
object_prop_list.Properties_len = CONFIG_MTP_SUPP_OBJ_PROP_LEN;
for (i = 0U; i < CONFIG_MTP_SUPP_OBJ_PROP_LEN; i++) {
object_prop_list.Properties[i].ObjectHandle = g_usbd_mtp.con_command.param1;
switch (ObjectPropCode[i]) {
case MTP_OB_PROP_STORAGE_ID:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_STORAGE_ID;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT32;
object_prop_list.Properties[i].propval = (uint8_t *)&storageid;
break;
case MTP_OB_PROP_OBJECT_FORMAT:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_FORMAT;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT16;
object_prop_list.Properties[i].propval = (uint8_t *)&format;
break;
case MTP_OB_PROP_OBJ_FILE_NAME:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJ_FILE_NAME;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_STR;
object_prop_list.Properties[i].propval = NULL;
break;
case MTP_OB_PROP_PARENT_OBJECT:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PARENT_OBJECT;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT32;
object_prop_list.Properties[i].propval = (uint8_t *)&parent_proval;
break;
case MTP_OB_PROP_OBJECT_SIZE:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_OBJECT_SIZE;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT64;
object_prop_list.Properties[i].propval = (uint8_t *)&objsize;
break;
case MTP_OB_PROP_NAME:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_NAME;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_STR;
object_prop_list.Properties[i].propval = NULL;
break;
case MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT128;
object_prop_list.Properties[i].propval = (uint8_t *)&g_usbd_mtp.con_command.param1;
break;
case MTP_OB_PROP_PROTECTION_STATUS:
object_prop_list.Properties[i].PropertyCode = MTP_OB_PROP_PROTECTION_STATUS;
object_prop_list.Properties[i].Datatype = MTP_DATATYPE_UINT16;
object_prop_list.Properties[i].propval = (uint8_t *)&default_val;
break;
default:
break;
}
}
// todo
usbd_mtp_send_info((uint8_t *)&object_prop_list, sizeof(struct mtp_object_prop_list));
}
static void usbd_mtp_get_device_prop_desc(void)
{
struct mtp_device_prop_desc device_prop_desc;
uint32_t i;
device_prop_desc.DevicePropertyCode = MTP_DEV_PROP_DEVICE_FRIENDLY_NAME;
device_prop_desc.DataType = MTP_DATATYPE_STR;
device_prop_desc.GetSet = MTP_PROP_GET_SET;
device_prop_desc.DefaultValue_len = CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN;
for (i = 0U; i < (sizeof(DevicePropDefVal) / 2U); i++) {
device_prop_desc.DefaultValue[i] = DevicePropDefVal[i];
}
device_prop_desc.CurrentValue_len = CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN;
for (i = 0U; i < (sizeof(DevicePropCurDefVal) / 2U); i++) {
device_prop_desc.CurrentValue[i] = DevicePropCurDefVal[i];
}
device_prop_desc.FormFlag = 0U;
usbd_mtp_send_info((uint8_t *)&device_prop_desc, sizeof(struct mtp_device_prop_desc));
}
static int usbd_mtp_decode_command(struct mtp_container_command *command)
{
printf("code:%04x\r\n", command->code);
switch (command->code) {
case MTP_OP_GET_DEVICE_INFO:
usbd_mtp_get_device_info();
break;
case MTP_OP_OPEN_SESSION:
usbd_mtp_open_session();
break;
case MTP_OP_CLOSE_SESSION:
break;
case MTP_OP_GET_STORAGE_IDS:
usbd_mtp_get_storage_ids();
break;
case MTP_OP_GET_STORAGE_INFO:
usbd_mtp_get_storage_info();
break;
case MTP_OP_GET_OBJECT_HANDLES:
usbd_mtp_get_object_handles();
break;
case MTP_OP_GET_OBJECT_INFO:
usbd_mtp_get_object_info();
break;
case MTP_OP_GET_OBJECT_PROP_REFERENCES:
break;
case MTP_OP_GET_OBJECT_PROPS_SUPPORTED:
usbd_mtp_get_object_props_supported();
break;
case MTP_OP_GET_OBJECT_PROP_DESC:
usbd_mtp_get_object_prop_desc();
break;
case MTP_OP_GET_OBJECT_PROPLIST:
usbd_mtp_get_object_prop_list();
break;
case MTP_OP_GET_OBJECT_PROP_VALUE:
break;
case MTP_OP_GET_DEVICE_PROP_DESC:
usbd_mtp_get_device_prop_desc();
break;
case MTP_OP_GET_OBJECT:
break;
case MTP_OP_SEND_OBJECT_INFO:
break;
case MTP_OP_SEND_OBJECT:
break;
case MTP_OP_DELETE_OBJECT:
break;
default:
break;
}
return 0;
}
static void usbd_mtp_bulk_out(uint8_t ep, uint32_t nbytes)
{
switch (g_usbd_mtp.stage) {
case MTP_READ_COMMAND:
usbd_mtp_decode_command(&g_usbd_mtp.con_command);
break;
case MTP_DATA_OUT:
break;
default:
break;
}
}
static void usbd_mtp_bulk_in(uint8_t ep, uint32_t nbytes)
{
printf("send:%d\r\n", nbytes);
switch (g_usbd_mtp.stage) {
case MTP_DATA_IN:
break;
case MTP_SEND_RESPONSE:
usbd_mtp_send_response(MTP_RESPONSE_OK);
break;
case MTP_WAIT_RESPONSE:
USB_LOG_DBG("Start reading command\r\n");
g_usbd_mtp.stage = MTP_READ_COMMAND;
usbd_ep_start_read(mtp_ep_data[MTP_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_command, MTP_BULK_EP_MPS);
break;
default:
break;
}
}
static void mtp_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONFIGURED:
USB_LOG_DBG("Start reading command\r\n");
g_usbd_mtp.stage = MTP_READ_COMMAND;
usbd_ep_start_read(mtp_ep_data[MTP_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_mtp.con_command, MTP_BULK_EP_MPS);
break;
default:
break;
}
}
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep,
const uint8_t int_ep)
{
intf->class_interface_handler = mtp_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = mtp_notify_handler;
mtp_ep_data[MTP_OUT_EP_IDX].ep_addr = out_ep;
mtp_ep_data[MTP_OUT_EP_IDX].ep_cb = usbd_mtp_bulk_out;
mtp_ep_data[MTP_IN_EP_IDX].ep_addr = in_ep;
mtp_ep_data[MTP_IN_EP_IDX].ep_cb = usbd_mtp_bulk_in;
mtp_ep_data[MTP_INT_EP_IDX].ep_addr = int_ep;
mtp_ep_data[MTP_INT_EP_IDX].ep_cb = NULL;
usbd_add_endpoint(&mtp_ep_data[MTP_OUT_EP_IDX]);
usbd_add_endpoint(&mtp_ep_data[MTP_IN_EP_IDX]);
usbd_add_endpoint(&mtp_ep_data[MTP_INT_EP_IDX]);
return intf;
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_MTP_H
#define USBD_MTP_H
#include "usb_mtp.h"
#ifdef __cplusplus
extern "C" {
#endif
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep,
const uint8_t int_ep);
#ifdef __cplusplus
}
#endif
#endif /* USBD_MTP_H */

View File

@@ -1,179 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_MTP_CONFIG_H
#define USB_MTP_CONFIG_H
#include "usb_mtp.h"
static const uint16_t VendExtDesc[] = { 'm', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '.', 'c', 'o', 'm', ':', ' ', '1', '.', '0', ';', ' ', 0 }; /* last 2 bytes must be 0*/
static const uint16_t SuppOP[] = { MTP_OP_GET_DEVICE_INFO, MTP_OP_OPEN_SESSION, MTP_OP_CLOSE_SESSION,
MTP_OP_GET_STORAGE_IDS, MTP_OP_GET_STORAGE_INFO, MTP_OP_GET_NUM_OBJECTS,
MTP_OP_GET_OBJECT_HANDLES, MTP_OP_GET_OBJECT_INFO, MTP_OP_GET_OBJECT,
MTP_OP_DELETE_OBJECT, MTP_OP_SEND_OBJECT_INFO, MTP_OP_SEND_OBJECT,
MTP_OP_GET_DEVICE_PROP_DESC, MTP_OP_GET_DEVICE_PROP_VALUE,
MTP_OP_SET_OBJECT_PROP_VALUE, MTP_OP_GET_OBJECT_PROP_VALUE,
MTP_OP_GET_OBJECT_PROPS_SUPPORTED, MTP_OP_GET_OBJECT_PROPLIST,
MTP_OP_GET_OBJECT_PROP_DESC, MTP_OP_GET_OBJECT_PROP_REFERENCES };
static const uint16_t SuppEvents[] = { MTP_EVENT_OBJECTADDED };
static const uint16_t DevicePropSupp[] = { MTP_DEV_PROP_DEVICE_FRIENDLY_NAME, MTP_DEV_PROP_BATTERY_LEVEL };
static const uint16_t SuppCaptFormat[] = { MTP_OBJ_FORMAT_UNDEFINED, MTP_OBJ_FORMAT_ASSOCIATION, MTP_OBJ_FORMAT_TEXT };
static const uint16_t SuppImgFormat[] = { MTP_OBJ_FORMAT_UNDEFINED, MTP_OBJ_FORMAT_TEXT, MTP_OBJ_FORMAT_ASSOCIATION,
MTP_OBJ_FORMAT_EXECUTABLE, MTP_OBJ_FORMAT_WAV, MTP_OBJ_FORMAT_MP3,
MTP_OBJ_FORMAT_EXIF_JPEG, MTP_OBJ_FORMAT_MPEG, MTP_OBJ_FORMAT_MP4_CONTAINER,
MTP_OBJ_FORMAT_WINDOWS_IMAGE_FORMAT, MTP_OBJ_FORMAT_PNG, MTP_OBJ_FORMAT_WMA,
MTP_OBJ_FORMAT_WMV };
static const uint16_t Manuf[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
static const uint16_t Model[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
static const uint16_t DeviceVers[] = { 'V', '1', '.', '0', '0', 0 }; /* last 2 bytes must be 0*/
/*SerialNbr shall be 32 character hexadecimal string for legacy compatibility reasons */
static const uint16_t SerialNbr[] = { '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '0', '0', '0', '0',
'1', '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '0', '0', '0',
'0', '1', '0', '0', 0 }; /* last 2 bytes must be 0*/
static const uint16_t DefaultFileName[] = { 'N', 'e', 'w', ' ', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
static const uint16_t DevicePropDefVal[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 }; /* last 2 bytes must be 0*/
static const uint16_t DevicePropCurDefVal[] = { 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', 0 };
/* required for all object format : storageID, objectFormat, ObjectCompressedSize,
persistent unique object identifier, name*/
static const uint16_t ObjectPropCode[] = { MTP_OB_PROP_STORAGE_ID, MTP_OB_PROP_OBJECT_FORMAT, MTP_OB_PROP_OBJECT_SIZE,
MTP_OB_PROP_OBJ_FILE_NAME, MTP_OB_PROP_PARENT_OBJECT, MTP_OB_PROP_NAME,
MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN, MTP_OB_PROP_PROTECTION_STATUS };
#define MTP_STORAGE_ID 0x00010001U /* SD card is inserted*/
#define CONFIG_MTP_VEND_EXT_DESC_LEN (sizeof(VendExtDesc) / 2U)
#define CONFIG_MTP_SUPP_OP_LEN (sizeof(SuppOP) / 2U)
#define CONFIG_MTP_SUPP_EVENTS_LEN (sizeof(SuppEvents) / 2U)
#define CONFIG_MTP_SUPP_DEVICE_PROP_LEN (sizeof(DevicePropSupp) / 2U)
#define CONFIG_MTP_SUPP_CAPT_FORMAT_LEN (sizeof(SuppCaptFormat) / 2U)
#define CONFIG_MTP_SUPP_IMG_FORMAT_LEN (sizeof(SuppImgFormat) / 2U)
#define CONFIG_MTP_MANUF_LEN (sizeof(Manuf) / 2U)
#define CONFIG_MTP_MODEL_LEN (sizeof(Model) / 2U)
#define CONFIG_MTP_DEVICE_VERSION_LEN (sizeof(DeviceVers) / 2U)
#define CONFIG_MTP_SERIAL_NBR_LEN (sizeof(SerialNbr) / 2U)
#define CONFIG_MTP_SUPP_OBJ_PROP_LEN (sizeof(ObjectPropCode) / 2U)
#define CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN (sizeof(DevicePropDefVal) / 2U)
#define CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN (sizeof(DevicePropCurDefVal) / 2U)
#define CONFIG_MTP_STORAGE_ID_LEN 1
#define CONFIG_MTP_OBJECT_HANDLE_LEN 100
struct mtp_device_info {
uint16_t StandardVersion;
uint32_t VendorExtensionID;
uint16_t VendorExtensionVersion;
uint8_t VendorExtensionDesc_len;
uint16_t VendorExtensionDesc[CONFIG_MTP_VEND_EXT_DESC_LEN];
uint16_t FunctionalMode;
uint32_t OperationsSupported_len;
uint16_t OperationsSupported[CONFIG_MTP_SUPP_OP_LEN];
uint32_t EventsSupported_len;
uint16_t EventsSupported[CONFIG_MTP_SUPP_EVENTS_LEN];
uint32_t DevicePropertiesSupported_len;
uint16_t DevicePropertiesSupported[CONFIG_MTP_SUPP_DEVICE_PROP_LEN];
uint32_t CaptureFormats_len;
uint16_t CaptureFormats[CONFIG_MTP_SUPP_CAPT_FORMAT_LEN];
uint32_t ImageFormats_len;
uint16_t ImageFormats[CONFIG_MTP_SUPP_IMG_FORMAT_LEN];
uint8_t Manufacturer_len;
uint16_t Manufacturer[CONFIG_MTP_MANUF_LEN];
uint8_t Model_len;
uint16_t Model[CONFIG_MTP_MODEL_LEN];
uint8_t DeviceVersion_len;
uint16_t DeviceVersion[CONFIG_MTP_DEVICE_VERSION_LEN];
uint8_t SerialNumber_len;
uint16_t SerialNumber[CONFIG_MTP_SERIAL_NBR_LEN];
} __PACKED;
struct mtp_object_props_support {
uint32_t ObjectPropCode_len;
uint16_t ObjectPropCode[CONFIG_MTP_SUPP_OBJ_PROP_LEN];
} __PACKED;
struct mtp_device_prop_desc {
uint16_t DevicePropertyCode;
uint16_t DataType;
uint8_t GetSet;
uint8_t DefaultValue_len;
uint16_t DefaultValue[CONFIG_MTP_DEVICE_PROP_DESC_DEF_LEN];
uint8_t CurrentValue_len;
uint16_t CurrentValue[CONFIG_MTP_DEVICE_PROP_DESC_CUR_LEN];
uint8_t FormFlag;
} __PACKED;
struct mtp_storage_id {
uint32_t StorageIDS_len;
uint32_t StorageIDS[CONFIG_MTP_STORAGE_ID_LEN];
} __PACKED;
struct mtp_storage_info {
uint16_t StorageType;
uint16_t FilesystemType;
uint16_t AccessCapability;
uint64_t MaxCapability;
uint64_t FreeSpaceInBytes;
uint32_t FreeSpaceInObjects;
uint8_t StorageDescription;
uint8_t VolumeLabel;
} __PACKED;
struct mtp_object_handle {
uint32_t ObjectHandle_len;
uint32_t ObjectHandle[CONFIG_MTP_OBJECT_HANDLE_LEN];
} __PACKED;
struct mtp_object_info {
uint32_t Storage_id;
uint16_t ObjectFormat;
uint16_t ProtectionStatus;
uint32_t ObjectCompressedSize;
uint16_t ThumbFormat;
uint32_t ThumbCompressedSize;
uint32_t ThumbPixWidth;
uint32_t ThumbPixHeight;
uint32_t ImagePixWidth;
uint32_t ImagePixHeight;
uint32_t ImageBitDepth;
uint32_t ParentObject;
uint16_t AssociationType;
uint32_t AssociationDesc;
uint32_t SequenceNumber;
uint8_t Filename_len;
uint16_t Filename[255];
uint32_t CaptureDate;
uint32_t ModificationDate;
uint8_t Keywords;
} __PACKED;
struct mtp_object_prop_desc {
uint16_t ObjectPropertyCode;
uint16_t DataType;
uint8_t GetSet;
uint8_t *DefValue;
uint32_t GroupCode;
uint8_t FormFlag;
} __PACKED;
struct mtp_object_prop_element {
uint32_t ObjectHandle;
uint16_t PropertyCode;
uint16_t Datatype;
uint8_t *propval;
} __PACKED;
struct mtp_object_prop_list {
uint32_t Properties_len;
struct mtp_object_prop_element Properties[CONFIG_MTP_SUPP_OBJ_PROP_LEN];
} __PACKED;
#endif /* USB_MTP_CONFIG_H */

View File

@@ -1,90 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_mtp.h"
#define DEV_FORMAT "/dev/mtp"
static int usbh_mtp_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_mtp *mtp_class = usb_malloc(sizeof(struct usbh_mtp));
if (mtp_class == NULL) {
USB_LOG_ERR("Fail to alloc mtp_class\r\n");
return -ENOMEM;
}
memset(mtp_class, 0, sizeof(struct usbh_mtp));
mtp_class->hport = hport;
mtp_class->intf = intf;
hport->config.intf[intf].priv = mtp_class;
#ifdef CONFIG_USBHOST_MTP_NOTIFY
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
usbh_hport_activate_epx(&mtp_class->intin, hport, ep_desc);
#endif
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_hport_activate_epx(&mtp_class->bulkin, hport, ep_desc);
} else {
usbh_hport_activate_epx(&mtp_class->bulkout, hport, ep_desc);
}
}
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register MTP Class:%s\r\n", hport->config.intf[intf].devname);
return ret;
}
static int usbh_mtp_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_mtp *mtp_class = (struct usbh_mtp *)hport->config.intf[intf].priv;
if (mtp_class) {
if (mtp_class->bulkin) {
usbh_pipe_free(mtp_class->bulkin);
}
if (mtp_class->bulkout) {
usbh_pipe_free(mtp_class->bulkout);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister MTP Class:%s\r\n", hport->config.intf[intf].devname);
}
memset(mtp_class, 0, sizeof(struct usbh_mtp));
usb_free(mtp_class);
}
return ret;
}
static const struct usbh_class_driver mtp_class_driver = {
.driver_name = "mtp",
.connect = usbh_mtp_connect,
.disconnect = usbh_mtp_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info mtp_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_MTP_CLASS,
.subclass = USB_MTP_SUB_CLASS,
.protocol = USB_MTP_PROTOCOL,
.vid = 0x00,
.pid = 0x00,
.class_driver = &mtp_class_driver
};

View File

@@ -1,30 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_MTP_H
#define USBH_MTP_H
#include "usb_mtp.h"
struct usbh_mtp {
struct usbh_hubport *hport;
uint8_t intf; /* interface number */
usbh_pipe_t bulkin; /* BULK IN endpoint */
usbh_pipe_t bulkout; /* BULK OUT endpoint */
#ifdef CONFIG_USBHOST_MTP_NOTIFY
usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* USBH_MTP_H */

View File

@@ -1,19 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_PRINTER_H
#define USB_PRINTER_H
#define PRINTER_SUBCLASS 0x01U
#define PRINTER_REQUEST_GET_DEVICE_ID 0x00U
#define PRINTER_REQUEST_GET_PORT_SATTUS 0x01U
#define PRINTER_REQUEST_SOFT_RESET 0x02U
#define PRINTER_STATUS_NO_ERROR 0x00U
#define PRINTER_STATUS_SELECTED 0x08U
#define PRINTER_STATUS_PAPER_EMPTY 0x10U
#endif /* USB_PRINTER_H */

View File

@@ -1,61 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_printer.h"
struct usbd_printer_priv {
const uint8_t *device_id;
uint8_t device_id_len;
uint8_t port_status;
} g_usbd_printer;
static int printer_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("Printer Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
switch (setup->bRequest) {
case PRINTER_REQUEST_GET_DEVICE_ID:
memcpy(*data, g_usbd_printer.device_id, g_usbd_printer.device_id_len);
*len = g_usbd_printer.device_id_len;
break;
case PRINTER_REQUEST_GET_PORT_SATTUS:
break;
case PRINTER_REQUEST_SOFT_RESET:
break;
default:
USB_LOG_WRN("Unhandled Printer Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
static void printer_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
break;
default:
break;
}
}
struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const uint8_t *device_id, uint8_t device_id_len)
{
intf->class_interface_handler = printer_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = printer_notify_handler;
g_usbd_printer.device_id = device_id;
g_usbd_printer.device_id_len = device_id_len;
return intf;
}

View File

@@ -1,22 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_PRINTER_H
#define USBD_PRINTER_H
#include "usb_printer.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Init printer interface driver */
struct usbd_interface *usbd_printer_init_intf(struct usbd_interface *intf, const uint8_t *device_id, uint8_t device_id_len);
#ifdef __cplusplus
}
#endif
#endif /* USBD_PRINTER_H */

View File

@@ -1,156 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_printer.h"
#define DEV_FORMAT "/dev/printer"
static struct usbh_printer g_printer_class[CONFIG_USBHOST_MAX_PRINTER_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_printer *usbh_printer_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_PRINTER_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_printer_class[devno], 0, sizeof(struct usbh_printer));
g_printer_class[devno].minor = devno;
return &g_printer_class[devno];
}
}
return NULL;
}
static void usbh_printer_class_free(struct usbh_printer *printer_class)
{
int devno = printer_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(printer_class, 0, sizeof(struct usbh_printer));
}
static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer)
{
struct usb_setup_packet *setup = &printer_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = PRINTER_REQUEST_GET_DEVICE_ID;
setup->wValue = 0;
setup->wIndex = printer_class->intf;
setup->wLength = 256;
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
}
static int usbh_printer_get_port_status(struct usbh_printer *printer_class, uint8_t *buffer)
{
struct usb_setup_packet *setup = &printer_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = PRINTER_REQUEST_GET_PORT_SATTUS;
setup->wValue = 0;
setup->wIndex = printer_class->intf;
setup->wLength = 1;
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
}
static int usbh_printer_soft_reset(struct usbh_printer *printer_class)
{
struct usb_setup_packet *setup = &printer_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = PRINTER_REQUEST_SOFT_RESET;
setup->wValue = 0;
setup->wIndex = printer_class->intf;
setup->wLength = 0;
return usbh_control_transfer(printer_class->hport->ep0, setup, NULL);
}
static int usbh_printer_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_printer *printer_class = usbh_printer_class_alloc();
if (printer_class == NULL) {
USB_LOG_ERR("Fail to alloc printer_class\r\n");
return -ENOMEM;
}
printer_class->hport = hport;
printer_class->intf = intf;
hport->config.intf[intf].priv = printer_class;
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_hport_activate_epx(&printer_class->bulkin, hport, ep_desc);
} else {
usbh_hport_activate_epx(&printer_class->bulkout, hport, ep_desc);
}
}
// uint8_t *device_id = usb_iomalloc(256);
// ret = usbh_printer_get_device_id(printer_class, device_id);
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
USB_LOG_INFO("Register Printer Class:%s\r\n", hport->config.intf[intf].devname);
return 0;
}
static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_printer *printer_class = (struct usbh_printer *)hport->config.intf[intf].priv;
if (printer_class) {
if (printer_class->bulkin) {
usbh_pipe_free(printer_class->bulkin);
}
if (printer_class->bulkout) {
usbh_pipe_free(printer_class->bulkout);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister Printer Class:%s\r\n", hport->config.intf[intf].devname);
}
usbh_printer_class_free(printer_class);
}
return ret;
}
static const struct usbh_class_driver printer_class_driver = {
.driver_name = "printer",
.connect = usbh_printer_connect,
.disconnect = usbh_printer_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info printer_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_PRINTER,
.subclass = PRINTER_SUBCLASS,
.protocol = 0x00,
.vid = 0x00,
.pid = 0x00,
.class_driver = &printer_class_driver
};

View File

@@ -1,28 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_PRINTER_H
#define USBH_PRINTER_H
#include "usb_printer.h"
struct usbh_printer {
struct usbh_hubport *hport;
uint8_t intf; /* interface number */
uint8_t minor;
usbh_pipe_t bulkin; /* BULK IN endpoint */
usbh_pipe_t bulkout; /* BULK OUT endpoint */
};
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* USBH_PRINTER_H */

View File

@@ -1,7 +1,7 @@
#include "usbd_core.h"
#include "usbd_xxx.h"
static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int xxx_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_WRN("XXX Class request: "
"bRequest 0x%02x\r\n",
@@ -16,7 +16,7 @@ static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, u
return 0;
}
static void xxx_notify_handler(uint8_t event, void *arg)
static void xxx_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -28,12 +28,12 @@ static void xxx_notify_handler(uint8_t event, void *arg)
}
}
void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
struct usbd_interface *usbd_xxx_init_intf(uint8_t busid, struct usbd_interface *intf)
{
intf->class_interface_handler = xxx_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = xxx_notify_handler;
usbd_class_add_interface(devclass, intf);
return intf;
}

View File

@@ -7,7 +7,7 @@
extern "C" {
#endif
void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
struct usbd_interface *usbd_xxx_init_intf(uint8_t busid, struct usbd_interface *intf);
#ifdef __cplusplus
}

View File

@@ -3,6 +3,7 @@
#define DEV_FORMAT "/dev/xxx"
#define CONFIG_USBHOST_MAX_CUSTOM_CLASS 1
static struct usbh_xxx g_xxx_class[CONFIG_USBHOST_MAX_CUSTOM_CLASS];
static uint32_t g_devinuse = 0;
@@ -33,14 +34,13 @@ static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
if (xxx_class == NULL) {
USB_LOG_ERR("Fail to alloc xxx_class\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
return ret;
@@ -54,12 +54,12 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv;
if (xxx_class) {
if (xxx_class->bulkin) {
usbh_pipe_free(xxx_class->bulkin);
if (xxx_class->xxxin) {
usbh_kill_urb(&xxx_class->xxxin_urb);
}
if (xxx_class->bulkout) {
usbh_pipe_free(xxx_class->bulkout);
if (xxx_class->xxxout) {
usbh_kill_urb(&xxx_class->xxxout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
@@ -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

@@ -5,11 +5,18 @@
struct usbh_xxx {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *xxxin;
struct usb_endpoint_descriptor *xxxout;
struct usbh_urb xxxin_urb;
struct usbh_urb xxxout_urb;
uint8_t intf; /* interface number */
uint8_t minor;
usbh_pipe_t bulkin; /* bulk IN endpoint */
usbh_pipe_t bulkout; /* bulk OUT endpoint */
void *user_data;
};
void usbh_xxx_run(struct usbh_xxx *xxx_class);
void usbh_xxx_stop(struct usbh_xxx *xxx_class);
#endif

View File

@@ -1,107 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#define DEV_FORMAT "/dev/air724"
struct usbh_cdc_custom_air724 {
struct usbh_hubport *hport;
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
};
static inline int usbh_air724_bulk_out_transfer(struct usbh_cdc_custom_air724 *cdc_custom_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cdc_custom_class->bulkout_urb;
memset(urb, 0, sizeof(struct usbh_urb));
usbh_bulk_urb_fill(urb, cdc_custom_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
if (intf != 3) {
USB_LOG_WRN("ignore intf:%d\r\n", intf);
return 0;
}
struct usbh_cdc_custom_air724 *cdc_custom_class = usb_malloc(sizeof(struct usbh_cdc_custom_air724));
if (cdc_custom_class == NULL) {
USB_LOG_ERR("Fail to alloc cdc_custom_class\r\n");
return -ENOMEM;
}
memset(cdc_custom_class, 0, sizeof(struct usbh_cdc_custom_air724));
cdc_custom_class->hport = hport;
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
hport->config.intf[intf].priv = cdc_custom_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_hport_activate_epx(&cdc_custom_class->bulkin, hport, ep_desc);
} else {
usbh_hport_activate_epx(&cdc_custom_class->bulkout, hport, ep_desc);
}
}
USB_LOG_INFO("Register air724 Class:%s\r\n", hport->config.intf[intf].devname);
uint8_t cdc_buffer[32] = { 0x41, 0x54, 0x0d, 0x0a };
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkout, cdc_buffer, 4, 3000);
if (ret < 0) {
USB_LOG_ERR("bulk out error,ret:%d\r\n", ret);
} else {
USB_LOG_RAW("send over:%d\r\n", ret);
}
ret = usbh_air724_bulk_out_transfer(cdc_custom_class->bulkin, cdc_buffer, 10, 3000);
if (ret < 0) {
USB_LOG_ERR("bulk in error,ret:%d\r\n", ret);
} else {
USB_LOG_RAW("recv over:%d\r\n", ret);
for (size_t i = 0; i < ret; i++) {
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
}
}
return ret;
}
int usbh_air724_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
return 0;
}
const struct usbh_class_driver cdc_custom_class_driver = {
.driver_name = "cdc_acm",
.connect = usbh_air724_connect,
.disconnect = usbh_air724_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cdc_custom_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = 0xff,
.subclass = 0,
.protocol = 0,
.vid = 0x1782,
.pid = 0x4e00,
.class_driver = &cdc_custom_class_driver
};

View File

@@ -1,596 +0,0 @@
/*
* Change Logs
* Date Author Notes
* 2022-04-17 aozima the first version for CherryUSB.
*/
#ifndef __LINUX_USBNET_ASIX_H
#define __LINUX_USBNET_ASIX_H
// #define __BIG_ENDIAN_BITFIELD
#define __LITTLE_ENDIAN_BITFIELD
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#define KERNEL_VERSION(...) (0)
#define LINUX_VERSION_CODE (1)
/*
* Turn on this flag if the implementation of your USB host controller
* cannot handle non-double word aligned buffer.
* When turn on this flag, driver will fixup egress packet aligned on double
* word boundary before deliver to USB host controller. And will Disable the
* function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
* double word alignment for ingress packets.
*/
#define AX_FORCE_BUFF_ALIGN 0
//#define RX_SKB_COPY
#define AX_MONITOR_MODE 0x01
#define AX_MONITOR_LINK 0x02
#define AX_MONITOR_MAGIC 0x04
#define AX_MONITOR_HSFS 0x10
/* AX88172 Medium Status Register values */
#define AX_MEDIUM_FULL_DUPLEX 0x02
#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
#define AX_MCAST_FILTER_SIZE 8
#define AX_MAX_MCAST 64
#define AX_EEPROM_LEN 0x40
#define AX_SWRESET_CLEAR 0x00
#define AX_SWRESET_RR 0x01
#define AX_SWRESET_RT 0x02
#define AX_SWRESET_PRTE 0x04
#define AX_SWRESET_PRL 0x08
#define AX_SWRESET_BZ 0x10
#define AX_SWRESET_IPRL 0x20
#define AX_SWRESET_IPPD 0x40
#define AX_SWRESET_IPOSC 0x0080
#define AX_SWRESET_IPPSL_0 0x0100
#define AX_SWRESET_IPPSL_1 0x0200
#define AX_SWRESET_IPCOPS 0x0400
#define AX_SWRESET_IPCOPSC 0x0800
#define AX_SWRESET_AUTODETACH 0x1000
#define AX_SWRESET_WOLLP 0x8000
#define AX88772_IPG0_DEFAULT 0x15
#define AX88772_IPG1_DEFAULT 0x0c
#define AX88772_IPG2_DEFAULT 0x0E
#define AX88772A_IPG0_DEFAULT 0x15
#define AX88772A_IPG1_DEFAULT 0x16
#define AX88772A_IPG2_DEFAULT 0x1A
#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
#define AX88772_MEDIUM_RESERVED 0x0004
#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
#define AX88772_MEDIUM_RX_ENABLE 0x0100
#define AX88772_MEDIUM_100MB 0x0200
#define AX88772_MEDIUM_DEFAULT \
(AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE)
#define AX_CMD_SET_SW_MII 0x06
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_READ_STATMNGSTS_REG 0x09
#define AX_HOST_EN 0x01
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_WRITE_EEPROM 0x0c
#define AX_CMD_WRITE_EEPROM_EN 0x0d
#define AX_CMD_WRITE_EEPROM_DIS 0x0e
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
#define AX_CMD_WRITE_IPG1 0x13
#define AX_CMD_WRITE_IPG2 0x14
#define AX_CMD_WRITE_MULTI_FILTER 0x16
#define AX_CMD_READ_NODE_ID 0x17
#define AX_CMD_READ_PHY_ID 0x19
#define AX_CMD_READ_MEDIUM_MODE 0x1a
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
#define AX_CMD_READ_MONITOR_MODE 0x1c
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
#define AX_CMD_WRITE_GPIOS 0x1f
#define AX_CMD_SW_RESET 0x20
#define AX_CMD_SW_PHY_STATUS 0x21
#define AX_CMD_SW_PHY_SELECT 0x22
#define AX_PHYSEL_PSEL (1 << 0)
#define AX_PHYSEL_ASEL (1 << 1)
#define AX_PHYSEL_SSMII (0 << 2)
#define AX_PHYSEL_SSRMII (1 << 2)
#define AX_PHYSEL_SSRRMII (3 << 2)
#define AX_PHYSEL_SSEN (1 << 4)
#define AX88772_CMD_READ_NODE_ID 0x13
#define AX88772_CMD_WRITE_NODE_ID 0x14
#define AX_CMD_READ_WKFARY 0x23
#define AX_CMD_WRITE_WKFARY 0x24
#define AX_CMD_READ_RXCOE_CTL 0x2b
#define AX_CMD_WRITE_RXCOE_CTL 0x2c
#define AX_CMD_READ_TXCOE_CTL 0x2d
#define AX_CMD_WRITE_TXCOE_CTL 0x2e
#define REG_LENGTH 2
#define PHY_ID_MASK 0x1f
#define AX_RXCOE_IPCE 0x0001
#define AX_RXCOE_IPVE 0x0002
#define AX_RXCOE_V6VE 0x0004
#define AX_RXCOE_TCPE 0x0008
#define AX_RXCOE_UDPE 0x0010
#define AX_RXCOE_ICMP 0x0020
#define AX_RXCOE_IGMP 0x0040
#define AX_RXCOE_ICV6 0x0080
#define AX_RXCOE_TCPV6 0x0100
#define AX_RXCOE_UDPV6 0x0200
#define AX_RXCOE_ICMV6 0x0400
#define AX_RXCOE_IGMV6 0x0800
#define AX_RXCOE_ICV6V6 0x1000
#define AX_RXCOE_FOPC 0x8000
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
#else
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
AX_RXCOE_TCPE | AX_RXCOE_UDPE)
#endif
#define AX_RXCOE_64TE 0x0100
#define AX_RXCOE_PPPOE 0x0200
#define AX_RXCOE_RPCE 0x8000
#define AX_TXCOE_IP 0x0001
#define AX_TXCOE_TCP 0x0002
#define AX_TXCOE_UDP 0x0004
#define AX_TXCOE_ICMP 0x0008
#define AX_TXCOE_IGMP 0x0010
#define AX_TXCOE_ICV6 0x0020
#define AX_TXCOE_TCPV6 0x0100
#define AX_TXCOE_UDPV6 0x0200
#define AX_TXCOE_ICMV6 0x0400
#define AX_TXCOE_IGMV6 0x0800
#define AX_TXCOE_ICV6V6 0x1000
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
#else
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
#endif
#define AX_TXCOE_64TE 0x0001
#define AX_TXCOE_PPPE 0x0002
#define AX88772B_MAX_BULKIN_2K 0
#define AX88772B_MAX_BULKIN_4K 1
#define AX88772B_MAX_BULKIN_6K 2
#define AX88772B_MAX_BULKIN_8K 3
#define AX88772B_MAX_BULKIN_16K 4
#define AX88772B_MAX_BULKIN_20K 5
#define AX88772B_MAX_BULKIN_24K 6
#define AX88772B_MAX_BULKIN_32K 7
struct {unsigned short size, byte_cnt, threshold; } AX88772B_BULKIN_SIZE[] = {
/* 2k */
{2048, 0x8000, 0x8001},
/* 4k */
{4096, 0x8100, 0x8147},
/* 6k */
{6144, 0x8200, 0x81EB},
/* 8k */
{8192, 0x8300, 0x83D7},
/* 16 */
{16384, 0x8400, 0x851E},
/* 20k */
{20480, 0x8500, 0x8666},
/* 24k */
{24576, 0x8600, 0x87AE},
/* 32k */
{32768, 0x8700, 0x8A3D},
};
#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
#define AX_MONITOR_MODE 0x01
#define AX_MONITOR_LINK 0x02
#define AX_MONITOR_MAGIC 0x04
#define AX_MONITOR_HSFS 0x10
#define AX_MCAST_FILTER_SIZE 8
#define AX_MAX_MCAST 64
#define AX_INTERRUPT_BUFSIZE 8
#define AX_EEPROM_LEN 0x40
#define AX_EEPROM_MAGIC 0xdeadbeef
#define EEPROMMASK 0x7f
/* GPIO REGISTER */
#define AXGPIOS_GPO0EN 0X01 /* 1 << 0 */
#define AXGPIOS_GPO0 0X02 /* 1 << 1 */
#define AXGPIOS_GPO1EN 0X04 /* 1 << 2 */
#define AXGPIOS_GPO1 0X08 /* 1 << 3 */
#define AXGPIOS_GPO2EN 0X10 /* 1 << 4 */
#define AXGPIOS_GPO2 0X20 /* 1 << 5 */
#define AXGPIOS_RSE 0X80 /* 1 << 7 */
/* TX-header format */
#define AX_TX_HDR_CPHI 0x4000
#define AX_TX_HDR_DICF 0x8000
/* GMII register definitions */
#define GMII_PHY_CONTROL 0x00 /* control reg */
#define GMII_PHY_STATUS 0x01 /* status reg */
#define GMII_PHY_OUI 0x02 /* most of the OUI bits */
#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */
#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */
#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */
#define GMII_PHY_ANER 0x06 /* AN expansion reg */
#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */
#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */
/* Bit definitions: GMII Control */
#define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */
#define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */
#define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */
#define GMII_CONTROL_100MB 0x2000 /* 100Mbit */
#define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */
#define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */
#define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */
#define GMII_CONTROL_POWER_DOWN 0x0800
#define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */
#define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */
#define GMII_CONTROL_FULL_DUPLEX 0x0100
/* Bit definitions: GMII Status */
#define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */
#define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */
#define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */
#define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */
#define GMII_STATUS_LINK_UP 0x0004 /* link status bit */
#define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */
#define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */
#define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */
#define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */
#define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */
#define GMII_STATUS_10T 0x0800 /* capable of 10BT */
/* Bit definitions: Auto-Negotiation Advertisement */
#define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
#define GMII_ANAR_PAUSE 0x0400 /* support pause packets */
#define GMII_ANAR_100T4 0x0200 /* support 100BT4 */
#define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */
#define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */
#define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */
#define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */
#define GMII_SELECTOR_FIELD 0x001F /* selector field. */
/* Bit definitions: Auto-Negotiation Link Partner Ability */
#define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */
#define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */
#define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */
#define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */
#define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */
#define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */
#define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
#define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */
#define GMII_SELECTOR_8023 0x0001;
/* Bit definitions: 1000BaseT AUX Control */
#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */
#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */
/* Bit definitions: 1000BaseT AUX Status */
#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */
#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */
/* Cicada MII Registers */
#define GMII_AUX_CTRL_STATUS 0x1C
#define GMII_AUX_ANEG_CPLT 0x8000
#define GMII_AUX_FDX 0x0020
#define GMII_AUX_SPEED_1000 0x0010
#define GMII_AUX_SPEED_100 0x0008
#ifndef ADVERTISE_PAUSE_CAP
#define ADVERTISE_PAUSE_CAP 0x0400
#endif
#ifndef MII_STAT1000
#define MII_STAT1000 0x000A
#endif
#ifndef LPA_1000FULL
#define LPA_1000FULL 0x0800
#endif
/* medium mode register */
#define MEDIUM_GIGA_MODE 0x0001
#define MEDIUM_FULL_DUPLEX_MODE 0x0002
#define MEDIUM_TX_ABORT_MODE 0x0004
#define MEDIUM_ENABLE_125MHZ 0x0008
#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
#define MEDIUM_ENABLE_RECEIVE 0x0100
#define MEDIUM_MII_100M_MODE 0x0200
#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
/* PHY mode */
#define PHY_MODE_MARVELL 0
#define PHY_MODE_CICADA_FAMILY 1
#define PHY_MODE_CICADA_V1 1
#define PHY_MODE_AGERE_FAMILY 2
#define PHY_MODE_AGERE_V0 2
#define PHY_MODE_CICADA_V2 5
#define PHY_MODE_AGERE_V0_GMII 6
#define PHY_MODE_CICADA_V2_ASIX 9
#define PHY_MODE_VSC8601 10
#define PHY_MODE_RTL8211CL 12
#define PHY_MODE_RTL8211BN 13
#define PHY_MODE_RTL8251CL 14
#define PHY_MODE_ATTANSIC_V0 0x40
#define PHY_MODE_ATTANSIC_FAMILY 0x40
#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
/* */
#define LED_MODE_MARVELL 0
#define LED_MODE_CAMEO 1
#define MARVELL_LED_CTRL 0x18
#define MARVELL_MANUAL_LED 0x19
#define PHY_IDENTIFIER 0x0002
#define PHY_AGERE_IDENTIFIER 0x0282
#define PHY_CICADA_IDENTIFIER 0x000f
#define PHY_MARVELL_IDENTIFIER 0x0141
#define PHY_MARVELL_STATUS 0x001b
#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
#define PHY_MARVELL_CTRL 0x0014
#define MARVELL_CTRL_RXDELAY 0x0080
#define MARVELL_CTRL_TXDELAY 0x0002
#define PHY_CICADA_EXTPAGE 0x001f
#define CICADA_EXTPAGE_EN 0x0001
#define CICADA_EXTPAGE_DIS 0x0000
/* External ethernet phy */
#define EXTPHY_ID_MASK_OUI(phyid1, phyid2) ((phyid1 << 6) | ((phyid2 & 0xFC00) >> 10))
#define EXTPHY_ID_MASK_MODEL(phyid2) ((phyid2 & 0x3F0) >> 4)
#define EXTPHY_BROADCOM_OUI 0x2B8094
#define EXTPHY_BCM89811_MODEL 0x02
struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] = {
{0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
{0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
{0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
{0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
{0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
{0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
{0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
{0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
};
struct {unsigned short value, offset; } CICADA_V2_HWINIT[] = {
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
{0x0000, 0x001f},
};
struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] = {
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
{0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
{0x0000, 0x001f},
};
struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] = {
{0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
{0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
{0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
{0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
{0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
{0x0002, 0x0012},
};
struct ax88178_data {
u16 EepromData;
u16 MediaLink;
int UseGpio0;
int UseRgmii;
u8 PhyMode;
u8 LedMode;
u8 BuffaloOld;
};
enum watchdog_state {
AX_NOP = 0,
CHK_LINK, /* Routine A */
CHK_CABLE_EXIST, /* Called by A */
CHK_CABLE_EXIST_AGAIN, /* Routine B */
PHY_POWER_UP, /* Called by B */
PHY_POWER_UP_BH,
PHY_POWER_DOWN,
CHK_CABLE_STATUS, /* Routine C */
WAIT_AUTONEG_COMPLETE,
AX_SET_RX_CFG,
AX_CHK_AUTODETACH,
};
#if 0
struct ax88772b_data {
struct usbnet *dev;
struct workqueue_struct *ax_work;
struct work_struct check_link;
unsigned long time_to_chk;
u16 psc;
u8 pw_enabled;
u8 Event;
u8 checksum;
u8 PhySelect:1;
u8 OperationMode:1;
u16 presvd_phy_advertise;
u16 presvd_phy_bmcr;
u32 ext_phy_oui;
u8 ext_phy_model;
};
#endif
/* define for MAC or PHY mode */
#define OPERATION_MAC_MODE 0
#define OPERATION_PHY_MODE 1
#if 0
struct ax88772a_data {
struct usbnet *dev;
struct workqueue_struct *ax_work;
struct work_struct check_link;
unsigned long autoneg_start;
#define AX88772B_WATCHDOG (6 * HZ)
u8 Event;
u8 TickToExpire;
u8 DlyIndex;
u8 DlySel;
u16 EepromData;
u16 presvd_phy_advertise;
u16 presvd_phy_bmcr;
};
struct ax88772_data {
struct usbnet *dev;
struct workqueue_struct *ax_work;
struct work_struct check_link;
unsigned long autoneg_start;
u8 Event;
u8 TickToExpire;
u16 presvd_phy_advertise;
u16 presvd_phy_bmcr;
};
#endif
#define AX_RX_CHECKSUM 1
#define AX_TX_CHECKSUM 2
#if 0
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
struct ax8817x_data {
u8 multi_filter[AX_MCAST_FILTER_SIZE];
int (*resume) (struct usb_interface *intf);
int (*suspend) (struct usb_interface *intf,
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
pm_message_t message);
#else
u32 message);
#endif
};
#endif
struct ax88172_int_data {
u16 res1;
#define AX_INT_PPLS_LINK (1 << 0)
#define AX_INT_SPLS_LINK (1 << 1)
#define AX_INT_CABOFF_UNPLUG (1 << 7)
u8 link;
u16 res2;
u8 status;
u16 res3;
} __attribute__ ((packed));
#define AX_RXHDR_L4_ERR (1 << 8)
#define AX_RXHDR_L3_ERR (1 << 9)
#define AX_RXHDR_L4_TYPE_UDP 1
#define AX_RXHDR_L4_TYPE_ICMP 2
#define AX_RXHDR_L4_TYPE_IGMP 3
#define AX_RXHDR_L4_TYPE_TCP 4
#define AX_RXHDR_L4_TYPE_TCMPV6 5
#define AX_RXHDR_L4_TYPE_MASK 7
#define AX_RXHDR_L3_TYPE_IP 1
#define AX_RXHDR_L3_TYPE_IPV6 2
struct ax88772b_rx_header {
#if defined(__LITTLE_ENDIAN_BITFIELD)
u16 len:11,
res1:1,
crc:1,
mii:1,
runt:1,
mc_bc:1;
u16 len_bar:11,
res2:5;
u8 vlan_ind:3,
vlan_tag_striped:1,
pri:3,
res3:1;
u8 l4_csum_err:1,
l3_csum_err:1,
l4_type:3,
l3_type:2,
ce:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
u16 mc_bc:1,
runt:1,
mii:1,
crc:1,
res1:1,
len:11;
u16 res2:5,
len_bar:11;
u8 res3:1,
pri:3,
vlan_tag_striped:1,
vlan_ind:3;
u8 ce:1,
l3_type:2,
l4_type:3,
l3_csum_err:1,
l4_csum_err:1;
#else
#error "Please fix <asm/byteorder.h>"
#endif
} __attribute__ ((packed));
#endif /* __LINUX_USBNET_ASIX_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
/*
* Copyright (c) 2022, aozima
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Change Logs
* Date Author Notes
* 2022-04-17 aozima the first version for CherryUSB.
*/
#ifndef __USB_CLASHH_AXUSBNET_H__
#define __USB_CLASHH_AXUSBNET_H__
#include "usbh_core.h"
#include "asix.h"
struct usbh_axusbnet {
struct usbh_hubport *hport;
uint8_t intf; /* interface number */
usbh_pipe_t int_notify; /* Notify endpoint */
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
uint32_t bulkin_buf[2048/sizeof(uint32_t)];
};
#endif /* __USB_CLASHH_AXUSBNET_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,99 +0,0 @@
#ifndef USBH_CP210X_H
#define USBH_CP210X_H
#include <stdint.h>
#include "usbh_core.h"
typedef int32_t speed_t;
typedef int32_t tcflag_t;
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
struct usb_serial_port{
uint8_t partnum;
uint8_t ctrlpipe_rx;
uint8_t ctrlpipe_tx;
int32_t max_speed;
speed_t use_actual_rate;
uint8_t bInterfaceNumber;
int has_swapped_line_ctl;
};
typedef unsigned char cc_t;
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_cc[NCCS]; /* control characters */
cc_t c_line; /* line discipline (== c_cc[19]) */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* Alpha has identical termios and termios2 */
struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_cc[NCCS]; /* control characters */
cc_t c_line; /* line discipline (== c_cc[19]) */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* Alpha has matching termios and ktermios */
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_cc[NCCS]; /* control characters */
cc_t c_line; /* line discipline (== c_cc[19]) */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
struct tty_struct{
struct usb_serial_port driver_data;
struct termios termios;
};
int cp210x_attach(struct usb_serial_port *port);
int cp210x_port_probe(struct usb_serial_port *port);
void cp210x_break_ctl(struct tty_struct *tty, int break_state);
int cp210x_open(struct tty_struct *tty);
int cp210x_tiocmget(struct tty_struct *tty);
void cp210x_set_termios(struct tty_struct *tty);
void cp210x_change_speed(struct tty_struct *tty);
void cp210x_dtr_rts(struct usb_serial_port *port, int on);
struct usbh_cp210x
{
struct usbh_hubport *hport;
uint8_t intf;
usbh_pipe_t bulkin;
usbh_pipe_t bulkout;
struct usbh_urb bulkin_urb;
struct usbh_urb bulkout_urb;
struct tty_struct drv_data;
int index;
};
/* weak defined function */
void drv_usbh_cp210x_run(struct usbh_cp210x *p_device);
void drv_usbh_cp210x_stop(struct usbh_cp210x *p_device);
#endif

805
class/vendor/net/usbh_asix.c vendored Normal file
View File

@@ -0,0 +1,805 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_asix.h"
#include "usb_cdc.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "asix"
#include "usb_log.h"
#define DEV_FORMAT "/dev/asix"
static struct usbh_asix g_asix_class;
#define CONFIG_USBHOST_ASIX_ETH_MAX_SIZE (1514U + 8)
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[16];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[32];
#define ETH_ALEN 6
#define PHY_MODE_MARVELL 0x0000
#define MII_MARVELL_LED_CTRL 0x0018
#define MII_MARVELL_STATUS 0x001b
#define MII_MARVELL_CTRL 0x0014
#define MARVELL_LED_MANUAL 0x0019
#define MARVELL_STATUS_HWCFG 0x0004
#define MARVELL_CTRL_TXDELAY 0x0002
#define MARVELL_CTRL_RXDELAY 0x0080
#define PHY_MODE_RTL8211CL 0x000C
#define AX88772A_PHY14H 0x14
#define AX88772A_PHY14H_DEFAULT 0x442C
#define AX88772A_PHY15H 0x15
#define AX88772A_PHY15H_DEFAULT 0x03C8
#define AX88772A_PHY16H 0x16
#define AX88772A_PHY16H_DEFAULT 0x4044
#define SPEED_100 0
#define SPEED_10 1
static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
uint8_t cmd,
uint16_t value,
uint16_t index,
void *data,
uint16_t size)
{
struct usb_setup_packet *setup = asix_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = cmd;
setup->wValue = value;
setup->wIndex = index;
setup->wLength = size;
ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
if (ret < 0) {
return ret;
}
memcpy(data, g_asix_buf, ret - 8);
return ret;
}
static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
uint8_t cmd,
uint16_t value,
uint16_t index,
void *data,
uint16_t size)
{
struct usb_setup_packet *setup = asix_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = cmd;
setup->wValue = value;
setup->wIndex = index;
setup->wLength = size;
memcpy(g_asix_buf, data, size);
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
}
static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val)
{
uint8_t smsr;
uint16_t res = (uint16_t)val;
int ret;
for (uint8_t i = 0; i < 10; i++) {
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0);
if (ret < 0) {
return ret;
}
usb_osal_msleep(1);
ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1);
if (ret < 0) {
return ret;
}
if (smsr & AX_HOST_EN) {
break;
}
}
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MII_REG, phy_id, loc, &res, 2);
if (ret < 0) {
return ret;
}
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0);
if (ret < 0) {
return ret;
}
return 0;
}
static int usbh_asix_mdio_read(struct usbh_asix *asix_class, int phy_id, int loc)
{
uint8_t smsr;
uint16_t res;
int ret;
for (uint8_t i = 0; i < 10; i++) {
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_SW_MII, 0, 0, NULL, 0);
if (ret < 0) {
return ret;
}
usb_osal_msleep(1);
ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &smsr, 1);
if (ret < 0) {
return ret;
}
if (smsr & AX_HOST_EN) {
break;
}
}
ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MII_REG, phy_id, loc, &res, 2);
if (ret < 0) {
return ret;
}
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SET_HW_MII, 0, 0, NULL, 0);
if (ret < 0) {
return ret;
}
return res;
}
static int usbh_asix_read_phy_addr(struct usbh_asix *asix_class, bool internal)
{
int ret, offset;
uint8_t buf[2];
ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_PHY_ID, 0, 0, buf, 2);
if (ret < 0) {
return ret;
}
offset = (internal ? 1 : 0);
ret = buf[offset];
USB_LOG_INFO("%s PHY address 0x%x\r\n", internal ? "internal" : "external", ret);
return ret;
}
static int usbh_asix_sw_reset(struct usbh_asix *asix_class, uint8_t flags)
{
int ret;
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_RESET, flags, 0, NULL, 0);
if (ret < 0)
USB_LOG_ERR("Failed to send software reset: %d\r\n", ret);
return ret;
}
static uint16_t usbh_asix_read_rx_ctl(struct usbh_asix *asix_class)
{
uint16_t v;
int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_RX_CTL, 0, 0, &v, 2);
if (ret < 0) {
return ret;
}
return v;
}
static int usbh_asix_write_rx_ctl(struct usbh_asix *asix_class, uint16_t mode)
{
int ret;
USB_LOG_DBG("asix_write_rx_ctl() - mode = 0x%04x\r\n", mode);
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, mode, 0, NULL, 0);
if (ret < 0)
USB_LOG_ERR("Failed to write RX_CTL mode to 0x%04x: %02x\r\n",
mode, ret);
return ret;
}
static uint16_t usbh_asix_read_medium_status(struct usbh_asix *asix_class)
{
uint16_t v;
int ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_MEDIUM_STATUS, 0, 0, &v, 2);
if (ret < 0) {
USB_LOG_ERR("Error reading Medium Status register: %02x\r\n",
ret);
return ret; /* TODO: callers not checking for error ret */
}
return v;
}
static int usbh_asix_write_medium_mode(struct usbh_asix *asix_class, uint16_t mode)
{
int ret;
USB_LOG_DBG("asix_write_medium_mode() - mode = 0x%04x\r\n", mode);
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, NULL, 0);
if (ret < 0)
USB_LOG_ERR("Failed to write Medium Mode mode to 0x%04x: %02x\r\n",
mode, ret);
return ret;
}
static int usbh_asix_write_gpio(struct usbh_asix *asix_class, uint16_t value, int sleep)
{
int ret;
USB_LOG_DBG("asix_write_gpio() - value = 0x%04x\r\n", value);
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_GPIOS, value, 0, NULL, 0);
if (ret < 0)
USB_LOG_ERR("Failed to write GPIO value 0x%04x: %d\r\n",
value, ret);
if (sleep)
usb_osal_msleep(sleep);
return ret;
}
/*
* AX88772 & AX88178 have a 16-bit RX_CTL value
*/
static void usbh_asix_set_multicast(struct usbh_asix *asix_class)
{
uint16_t rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_AM;
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);
usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, NULL, 0);
}
static int usbh_ax88772_hw_reset(struct usbh_asix *asix_class)
{
uint16_t rx_ctl;
int ret;
ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5);
if (ret < 0)
goto out;
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy,
0, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret);
goto out;
}
if (asix_class->embd_phy) {
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD);
if (ret < 0)
goto out;
usb_osal_msleep(10);
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR);
if (ret < 0)
goto out;
usb_osal_msleep(60);
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL | AX_SWRESET_PRL);
if (ret < 0)
goto out;
} else {
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_PRL);
if (ret < 0)
goto out;
}
usb_osal_msleep(150);
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
if (ret < 0)
goto out;
ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT);
if (ret < 0)
goto out;
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret);
goto out;
}
/* Rewrite MAC address */
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN);
if (ret < 0)
goto out;
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
if (ret < 0)
goto out;
rx_ctl = usbh_asix_read_rx_ctl(asix_class);
USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n",
rx_ctl);
rx_ctl = usbh_asix_read_medium_status(asix_class);
USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n",
rx_ctl);
return 0;
out:
return ret;
}
static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class)
{
uint16_t rx_ctl, phy14h, phy15h, phy16h;
int ret;
ret = usbh_asix_write_gpio(asix_class, AX_GPIO_RSE, 5);
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, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret);
goto out;
}
usb_osal_msleep(10);
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPPD | AX_SWRESET_IPRL);
if (ret < 0)
goto out;
usb_osal_msleep(10);
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL);
if (ret < 0)
goto out;
usb_osal_msleep(160);
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_CLEAR);
if (ret < 0)
goto out;
ret = usbh_asix_sw_reset(asix_class, AX_SWRESET_IPRL);
if (ret < 0)
goto out;
usb_osal_msleep(200);
if (asix_class->chipcode == AX_AX88772B_CHIPCODE) {
ret = usbh_asix_write_cmd(asix_class, AX_QCTCTRL, 0x8000, 0x8001, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Write BQ setting failed: %d\r\n", ret);
goto out;
}
} else if (asix_class->chipcode == AX_AX88772A_CHIPCODE) {
/* Check if the PHY registers have default settings */
phy14h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr,
AX88772A_PHY14H);
phy15h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr,
AX88772A_PHY15H);
phy16h = usbh_asix_mdio_read(asix_class, asix_class->phy_addr,
AX88772A_PHY16H);
USB_LOG_DBG("772a_hw_reset: MR20=0x%x MR21=0x%x MR22=0x%x\r\n",
phy14h, phy15h, phy16h);
/* Restore PHY registers default setting if not */
if (phy14h != AX88772A_PHY14H_DEFAULT)
usbh_asix_mdio_write(asix_class, asix_class->phy_addr,
AX88772A_PHY14H,
AX88772A_PHY14H_DEFAULT);
if (phy15h != AX88772A_PHY15H_DEFAULT)
usbh_asix_mdio_write(asix_class, asix_class->phy_addr,
AX88772A_PHY15H,
AX88772A_PHY15H_DEFAULT);
if (phy16h != AX88772A_PHY16H_DEFAULT)
usbh_asix_mdio_write(asix_class, asix_class->phy_addr,
AX88772A_PHY16H,
AX88772A_PHY16H_DEFAULT);
}
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, NULL, 0);
if (ret < 0) {
USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret);
goto out;
}
/* Rewrite MAC address */
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_NODE_ID, 0, 0, asix_class->mac, ETH_ALEN);
if (ret < 0)
goto out;
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
if (ret < 0)
goto out;
ret = usbh_asix_write_medium_mode(asix_class, AX88772_MEDIUM_DEFAULT);
if (ret < 0)
return ret;
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = usbh_asix_write_rx_ctl(asix_class, AX_DEFAULT_RX_CTL);
if (ret < 0)
goto out;
rx_ctl = usbh_asix_read_rx_ctl(asix_class);
USB_LOG_INFO("RX_CTL is 0x%04x after all initializations\r\n", rx_ctl);
rx_ctl = usbh_asix_read_medium_status(asix_class);
USB_LOG_INFO("Medium Status is 0x%04x after all initializations\r\n", rx_ctl);
return 0;
out:
return ret;
}
static void usbh_ax88772_mac_link_down(struct usbh_asix *asix_class)
{
usbh_asix_write_medium_mode(asix_class, 0);
}
static void usbh_ax88772_mac_link_up(struct usbh_asix *asix_class, int speed, int duplex, bool tx_pause, bool rx_pause)
{
uint16_t m = AX_MEDIUM_AC | AX_MEDIUM_RE;
m |= duplex ? AX_MEDIUM_FD : 0;
switch (speed) {
case SPEED_100:
m |= AX_MEDIUM_PS;
break;
case SPEED_10:
break;
default:
return;
}
if (tx_pause)
m |= AX_MEDIUM_TFC;
if (rx_pause)
m |= AX_MEDIUM_RFC;
usbh_asix_write_medium_mode(asix_class, m);
}
static int usbh_asix_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_asix *asix_class = &g_asix_class;
memset(asix_class, 0, sizeof(struct usbh_asix));
asix_class->hport = hport;
asix_class->intf = intf;
hport->config.intf[intf].priv = asix_class;
if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x772b)) {
asix_class->name = "ASIX AX88772B";
} else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x7720)) {
asix_class->name = "ASIX AX88772";
} else if ((hport->device_desc.idVendor == 0x0b95) && (hport->device_desc.idProduct == 0x1780)) {
asix_class->name = "ASIX AX88178";
}
for (uint8_t i = 0; i < (ETH_ALEN >> 1); i++) {
ret = usbh_asix_read_cmd(asix_class, AX_CMD_READ_EEPROM,
0x04 + i, 0, &asix_class->mac[i * 2], 2);
if (ret < 0) {
return ret;
}
}
USB_LOG_INFO("asix MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
asix_class->mac[0],
asix_class->mac[1],
asix_class->mac[2],
asix_class->mac[3],
asix_class->mac[4],
asix_class->mac[5]);
ret = usbh_asix_read_phy_addr(asix_class, true);
if (ret < 0) {
USB_LOG_ERR("Failed to read phy addr: %d\r\n", ret);
return ret;
}
asix_class->phy_addr = ret;
asix_class->embd_phy = ((ret & 0x1f) == AX_EMBD_PHY_ADDR);
ret = usbh_asix_read_cmd(asix_class, AX_CMD_STATMNGSTS_REG, 0, 0, &asix_class->chipcode, 1);
if (ret < 0) {
USB_LOG_ERR("Failed to read STATMNGSTS_REG: %d\r\n", ret);
return ret;
}
asix_class->chipcode &= AX_CHIPCODE_MASK;
USB_LOG_INFO("asix chipcode 0x%x\r\n", asix_class->chipcode);
if (asix_class->chipcode == AX_AX88772_CHIPCODE) {
usbh_ax88772_hw_reset(asix_class);
} else {
usbh_ax88772a_hw_reset(asix_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 (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(asix_class->intin, ep_desc);
} else {
return -USB_ERR_NOTSUPP;
}
} else {
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(asix_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(asix_class->bulkout, ep_desc);
}
}
}
if (asix_class->chipcode == AX_AX88772B_CHIPCODE) {
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0);
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x8200);
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3900);
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3100);
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 4);
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 4, 0x01e1);
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 1);
usbh_asix_mdio_write(asix_class, asix_class->phy_addr, 0, 0x3300);
usbh_asix_mdio_read(asix_class, asix_class->phy_addr, 0);
}
USB_LOG_INFO("Init %s done\r\n", asix_class->name);
memcpy(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);
return ret;
}
static int usbh_asix_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_asix *asix_class = (struct usbh_asix *)hport->config.intf[intf].priv;
if (asix_class) {
if (asix_class->bulkin) {
usbh_kill_urb(&asix_class->bulkin_urb);
}
if (asix_class->bulkout) {
usbh_kill_urb(&asix_class->bulkout_urb);
}
if (asix_class->intin) {
usbh_kill_urb(&asix_class->intin_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister ASIX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_asix_stop(asix_class);
}
memset(asix_class, 0, sizeof(struct usbh_asix));
}
return ret;
}
int usbh_asix_get_connect_status(struct usbh_asix *asix_class)
{
int ret;
usbh_int_urb_fill(&asix_class->intin_urb, asix_class->hport, asix_class->intin, g_asix_inttx_buffer, 8, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&asix_class->intin_urb);
if (ret < 0) {
return ret;
}
if (g_asix_inttx_buffer[1] == 0x00) {
if (g_asix_inttx_buffer[2] & 0x01) {
asix_class->connect_status = true;
usbh_ax88772_mac_link_up(asix_class, SPEED_100, 1, 1, 1);
usbh_asix_set_multicast(asix_class);
} else {
asix_class->connect_status = false;
usbh_ax88772_mac_link_down(asix_class);
}
}
return 0;
}
void usbh_asix_rx_thread(void *argument)
{
uint32_t g_asix_rx_length;
int ret;
err_t err;
uint16_t len;
uint16_t len_crc;
struct pbuf *p;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#else
pbuf_type type = PBUF_POOL;
#endif
struct netif *netif = (struct netif *)argument;
USB_LOG_INFO("Create asix rx thread\r\n");
// clang-format off
find_class:
// clang-format on
g_asix_class.connect_status = false;
if (usbh_find_class_instance("/dev/asix") == NULL) {
goto delete;
}
while (g_asix_class.connect_status == false) {
ret = usbh_asix_get_connect_status(&g_asix_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
}
}
g_asix_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], CONFIG_USBHOST_ASIX_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_asix_class.bulkin_urb);
if (ret < 0) {
goto 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;
}
USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length);
p = pbuf_alloc(PBUF_RAW, len, type);
if (p != NULL) {
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = (uint8_t *)&g_asix_rx_buffer[4];
#else
memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len);
#endif
g_asix_rx_length = 0;
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
g_asix_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n");
}
} else {
if (g_asix_rx_length > CONFIG_USBHOST_ASIX_ETH_MAX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_asix_rx_length = 0;
}
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete asix rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p)
{
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;
}
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[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;
} else {
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4);
actual_len = p->tot_len + 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;
}
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
{
}
__WEAK void usbh_asix_stop(struct usbh_asix *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 asix_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = asix_id_table,
.class_driver = &asix_class_driver
};

182
class/vendor/net/usbh_asix.h vendored Normal file
View File

@@ -0,0 +1,182 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#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
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_STATMNGSTS_REG 0x09
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_WRITE_EEPROM 0x0c
#define AX_CMD_WRITE_ENABLE 0x0d
#define AX_CMD_WRITE_DISABLE 0x0e
#define AX_CMD_READ_RX_CTL 0x0f
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
#define AX_CMD_WRITE_IPG1 0x13
#define AX_CMD_READ_NODE_ID 0x13
#define AX_CMD_WRITE_NODE_ID 0x14
#define AX_CMD_WRITE_IPG2 0x14
#define AX_CMD_WRITE_MULTI_FILTER 0x16
#define AX88172_CMD_READ_NODE_ID 0x17
#define AX_CMD_READ_PHY_ID 0x19
#define AX_CMD_READ_MEDIUM_STATUS 0x1a
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
#define AX_CMD_READ_MONITOR_MODE 0x1c
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
#define AX_CMD_READ_GPIOS 0x1e
#define AX_CMD_WRITE_GPIOS 0x1f
#define AX_CMD_SW_RESET 0x20
#define AX_CMD_SW_PHY_STATUS 0x21
#define AX_CMD_SW_PHY_SELECT 0x22
#define AX_QCTCTRL 0x2A
#define AX_CHIPCODE_MASK 0x70
#define AX_AX88772_CHIPCODE 0x00
#define AX_AX88772A_CHIPCODE 0x10
#define AX_AX88772B_CHIPCODE 0x20
#define AX_HOST_EN 0x01
#define AX_PHYSEL_PSEL 0x01
#define AX_PHYSEL_SSMII 0
#define AX_PHYSEL_SSEN 0x10
#define AX_PHY_SELECT_MASK (BIT(3) | BIT(2))
#define AX_PHY_SELECT_INTERNAL 0
#define AX_PHY_SELECT_EXTERNAL BIT(2)
#define AX_MONITOR_MODE 0x01
#define AX_MONITOR_LINK 0x02
#define AX_MONITOR_MAGIC 0x04
#define AX_MONITOR_HSFS 0x10
/* AX88172 Medium Status Register values */
#define AX88172_MEDIUM_FD 0x02
#define AX88172_MEDIUM_TX 0x04
#define AX88172_MEDIUM_FC 0x10
#define AX88172_MEDIUM_DEFAULT \
(AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC)
#define AX_MCAST_FILTER_SIZE 8
#define AX_MAX_MCAST 64
#define AX_SWRESET_CLEAR 0x00
#define AX_SWRESET_RR 0x01
#define AX_SWRESET_RT 0x02
#define AX_SWRESET_PRTE 0x04
#define AX_SWRESET_PRL 0x08
#define AX_SWRESET_BZ 0x10
#define AX_SWRESET_IPRL 0x20
#define AX_SWRESET_IPPD 0x40
#define AX88772_IPG0_DEFAULT 0x15
#define AX88772_IPG1_DEFAULT 0x0c
#define AX88772_IPG2_DEFAULT 0x12
/* AX88772 & AX88178 Medium Mode Register */
#define AX_MEDIUM_PF 0x0080
#define AX_MEDIUM_JFE 0x0040
#define AX_MEDIUM_TFC 0x0020
#define AX_MEDIUM_RFC 0x0010
#define AX_MEDIUM_ENCK 0x0008
#define AX_MEDIUM_AC 0x0004
#define AX_MEDIUM_FD 0x0002
#define AX_MEDIUM_GM 0x0001
#define AX_MEDIUM_SM 0x1000
#define AX_MEDIUM_SBP 0x0800
#define AX_MEDIUM_PS 0x0200
#define AX_MEDIUM_RE 0x0100
#define AX88178_MEDIUM_DEFAULT \
(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
AX_MEDIUM_RE)
#define AX88772_MEDIUM_DEFAULT \
(AX_MEDIUM_FD | AX_MEDIUM_PS | \
AX_MEDIUM_AC | AX_MEDIUM_RE)
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB)
/* GPIO 0 .. 2 toggles */
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */
#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */
#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */
#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */
#define AX_GPIO_RESERVED 0x40 /* Reserved */
#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */
#define AX_EEPROM_MAGIC 0xdeadbeef
#define AX_EEPROM_LEN 0x200
#define AX_EMBD_PHY_ADDR 0x10
struct usbh_asix {
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;
char *name;
uint8_t phy_addr;
uint8_t embd_phy;
uint8_t chipcode;
uint16_t mac_capabilities;
bool connect_status;
uint8_t mac[6];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
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);
void usbh_asix_rx_thread(void *argument);
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p);
#ifdef __cplusplus
}
#endif
#endif /* USBH_ASIX_H */

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

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_RTL8152_H
#define USBH_RTL8152_H
#include "lwip/netif.h"
#include "lwip/pbuf.h"
struct usbh_rtl8152 {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
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];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
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);
void usbh_rtl8152_rx_thread(void *argument);
err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p);
#ifdef __cplusplus
}
#endif
#endif /* USBH_RTL8152_H */

356
class/vendor/serial/usbh_ch34x.c vendored Normal file
View File

@@ -0,0 +1,356 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_ch34x.h"
#define DEV_FORMAT "/dev/ttyUSB%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ch34x_buf[64];
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
static struct usbh_ch34x g_ch34x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x));
g_ch34x_class[devno].minor = devno;
return &g_ch34x_class[devno];
}
}
return NULL;
}
static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class)
{
int devno = ch34x_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(ch34x_class, 0, sizeof(struct usbh_ch34x));
}
static int usbh_ch34x_get_baudrate_div(uint32_t baudrate, uint8_t *factor, uint8_t *divisor)
{
uint8_t a;
uint8_t b;
uint32_t c;
switch (baudrate) {
case 921600:
a = 0xf3;
b = 7;
break;
case 307200:
a = 0xd9;
b = 7;
break;
default:
if (baudrate > 6000000 / 255) {
b = 3;
c = 6000000;
} else if (baudrate > 750000 / 255) {
b = 2;
c = 750000;
} else if (baudrate > 93750 / 255) {
b = 1;
c = 93750;
} else {
b = 0;
c = 11719;
}
a = (uint8_t)(c / baudrate);
if (a == 0 || a == 0xFF) {
return -USB_ERR_INVAL;
}
if ((c / a - baudrate) > (baudrate - c / (a + 1))) {
a++;
}
a = (uint8_t)(256 - a);
break;
}
*factor = a;
*divisor = b;
return 0;
}
static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_READ_VERSION;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = 2;
ret = usbh_control_transfer(ch34x_class->hport, setup, g_ch34x_buf);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Ch34x chip version %02x:%02x\r\n", g_ch34x_buf[0], g_ch34x_buf[1]);
return ret;
}
static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_WRITE_REG;
setup->wValue = 0x2727;
setup->wIndex = 0;
setup->wLength = 0;
return usbh_control_transfer(ch34x_class->hport, setup, NULL);
}
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;
uint16_t reg_value = 0;
uint16_t value = 0;
uint8_t factor = 0;
uint8_t divisor = 0;
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 */
switch (line_coding->bParityType) {
case 0:
break;
case 1:
reg_value |= CH341_L_PO;
break;
case 2:
reg_value |= CH341_L_PE;
break;
case 3:
reg_value |= CH341_L_PM;
break;
case 4:
reg_value |= CH341_L_PS;
break;
default:
return -USB_ERR_INVAL;
}
switch (line_coding->bDataBits) {
case 5:
reg_value |= CH341_L_D5;
break;
case 6:
reg_value |= CH341_L_D6;
break;
case 7:
reg_value |= CH341_L_D7;
break;
case 8:
reg_value |= CH341_L_D8;
break;
default:
return -USB_ERR_INVAL;
}
if (line_coding->bCharFormat == 2) {
reg_value |= CH341_L_SB;
}
reg_value |= 0xC0;
value |= 0x9c;
value |= reg_value << 8;
usbh_ch34x_get_baudrate_div(line_coding->dwDTERate, &factor, &divisor);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_SERIAL_INIT;
setup->wValue = value;
setup->wIndex = (factor << 8) | 0x80 | divisor;
setup->wLength = 0;
return usbh_control_transfer(ch34x_class->hport, setup, NULL);
}
int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding)
{
memcpy(line_coding, (uint8_t *)&ch34x_class->line_coding, sizeof(struct cdc_line_coding));
return 0;
}
int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts)
{
struct usb_setup_packet *setup = ch34x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CH34X_MODEM_CTRL;
setup->wValue = 0x0f | (dtr << 5) | (rts << 6);
setup->wIndex = 0;
setup->wLength = 0;
return usbh_control_transfer(ch34x_class->hport, setup, NULL);
}
static int usbh_ch34x_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_ch34x *ch34x_class = usbh_ch34x_class_alloc();
if (ch34x_class == NULL) {
USB_LOG_ERR("Fail to alloc ch34x_class\r\n");
return -USB_ERR_NOMEM;
}
ch34x_class->hport = hport;
ch34x_class->intf = intf;
hport->config.intf[intf].priv = ch34x_class;
usbh_ch34x_get_version(ch34x_class);
usbh_ch34x_flow_ctrl(ch34x_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 (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
continue;
} else {
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(ch34x_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(ch34x_class->bulkout, ep_desc);
}
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ch34x_class->minor);
USB_LOG_INFO("Register CH34X Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test ch34x 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_ch34x_set_line_coding(ch34x_class, &linecoding);
usbh_ch34x_set_line_state(ch34x_class, true, false);
memset(g_ch34x_buf, 'a', sizeof(g_ch34x_buf));
ret = usbh_ch34x_bulk_out_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_ch34x_bulk_in_transfer(ch34x_class, g_ch34x_buf, sizeof(g_ch34x_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_ch34x_buf[i]);
}
USB_LOG_RAW("\r\n");
}
}
#endif
usbh_ch34x_run(ch34x_class);
return ret;
}
static int usbh_ch34x_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_ch34x *ch34x_class = (struct usbh_ch34x *)hport->config.intf[intf].priv;
if (ch34x_class) {
if (ch34x_class->bulkin) {
usbh_kill_urb(&ch34x_class->bulkin_urb);
}
if (ch34x_class->bulkout) {
usbh_kill_urb(&ch34x_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CH34X Class:%s\r\n", hport->config.intf[intf].devname);
usbh_ch34x_stop(ch34x_class);
}
usbh_ch34x_class_free(ch34x_class);
}
return ret;
}
int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &ch34x_class->bulkin_urb;
usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &ch34x_class->bulkout_urb;
usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
{
}
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *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,
.disconnect = usbh_ch34x_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = ch34x_id_table,
.class_driver = &ch34x_class_driver
};

76
class/vendor/serial/usbh_ch34x.h vendored Normal file
View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CH34X_H
#define USBH_CH34X_H
#include "usb_cdc.h"
/* Requests */
#define CH34X_READ_VERSION 0x5F
#define CH34X_WRITE_REG 0x9A
#define CH34X_READ_REG 0x95
#define CH34X_SERIAL_INIT 0xA1
#define CH34X_MODEM_CTRL 0xA4
// modem control bits
#define CH34X_BIT_RTS (1 << 6)
#define CH34X_BIT_DTR (1 << 5)
#define CH341_CTO_O 0x10
#define CH341_CTO_D 0x20
#define CH341_CTO_R 0x40
#define CH341_CTI_C 0x01
#define CH341_CTI_DS 0x02
#define CH341_CTRL_RI 0x04
#define CH341_CTI_DC 0x08
#define CH341_CTI_ST 0x0f
#define CH341_L_ER 0x80
#define CH341_L_ET 0x40
#define CH341_L_PS 0x38
#define CH341_L_PM 0x28
#define CH341_L_PE 0x18
#define CH341_L_PO 0x08
#define CH341_L_SB 0x04
#define CH341_L_D8 0x03
#define CH341_L_D7 0x02
#define CH341_L_D6 0x01
#define CH341_L_D5 0x00
struct usbh_ch34x {
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 line_coding;
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding);
int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding);
int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts);
int usbh_ch34x_bulk_in_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
void usbh_ch34x_run(struct usbh_ch34x *ch34x_class);
void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CH34X_H */

295
class/vendor/serial/usbh_cp210x.c vendored Normal file
View File

@@ -0,0 +1,295 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cp210x.h"
#define DEV_FORMAT "/dev/ttyUSB%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
#define CONFIG_USBHOST_MAX_CP210X_CLASS 4
static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x));
g_cp210x_class[devno].minor = devno;
return &g_cp210x_class[devno];
}
}
return NULL;
}
static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class)
{
int devno = cp210x_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(cp210x_class, 0, sizeof(struct usbh_cp210x));
}
static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_IFC_ENABLE;
setup->wValue = 1;
setup->wIndex = cp210x_class->intf;
setup->wLength = 0;
return usbh_control_transfer(cp210x_class->hport, setup, NULL);
}
static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_FLOW;
setup->wValue = 0;
setup->wIndex = cp210x_class->intf;
setup->wLength = 16;
memset(g_cp210x_buf, 0, 16);
g_cp210x_buf[13] = 0x20;
return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf);
}
static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_CHARS;
setup->wValue = 0;
setup->wIndex = cp210x_class->intf;
setup->wLength = 6;
memset(g_cp210x_buf, 0, 6);
g_cp210x_buf[0] = 0x80;
g_cp210x_buf[4] = 0x88;
g_cp210x_buf[5] = 0x28;
return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf);
}
static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t baudrate)
{
struct usb_setup_packet *setup = cp210x_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_BAUDRATE;
setup->wValue = 0;
setup->wIndex = cp210x_class->intf;
setup->wLength = 4;
memcpy(g_cp210x_buf, (uint8_t *)&baudrate, 4);
return usbh_control_transfer(cp210x_class->hport, setup, g_cp210x_buf);
}
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;
uint16_t value;
value = ((databits & 0x0F) << 8) | ((parity & 0x0f) << 4) | ((stopbits & 0x03) << 0);
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = CP210X_SET_LINE_CTL;
setup->wValue = value;
setup->wIndex = cp210x_class->intf;
setup->wLength = 0;
return usbh_control_transfer(cp210x_class->hport, setup, NULL);
}
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;
uint16_t value;
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;
setup->bRequest = CP210X_SET_MHS;
setup->wValue = value;
setup->wIndex = cp210x_class->intf;
setup->wLength = 0;
return usbh_control_transfer(cp210x_class->hport, setup, NULL);
}
int usbh_cp210x_set_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding)
{
memcpy((uint8_t *)&cp210x_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
usbh_cp210x_set_baudrate(cp210x_class, line_coding->dwDTERate);
return usbh_cp210x_set_data_format(cp210x_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat);
}
int usbh_cp210x_get_line_coding(struct usbh_cp210x *cp210x_class, struct cdc_line_coding *line_coding)
{
memcpy(line_coding, (uint8_t *)&cp210x_class->line_coding, sizeof(struct cdc_line_coding));
return 0;
}
int usbh_cp210x_set_line_state(struct usbh_cp210x *cp210x_class, bool dtr, bool rts)
{
return usbh_cp210x_set_mhs(cp210x_class, dtr, rts, 1, 1);
}
static int usbh_cp210x_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_cp210x *cp210x_class = usbh_cp210x_class_alloc();
if (cp210x_class == NULL) {
USB_LOG_ERR("Fail to alloc cp210x_class\r\n");
return -USB_ERR_NOMEM;
}
cp210x_class->hport = hport;
cp210x_class->intf = intf;
hport->config.intf[intf].priv = cp210x_class;
usbh_cp210x_enable(cp210x_class);
usbh_cp210x_set_flow(cp210x_class);
usbh_cp210x_set_chars(cp210x_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(cp210x_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(cp210x_class->bulkout, ep_desc);
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cp210x_class->minor);
USB_LOG_INFO("Register CP210X Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test cp2102 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_cp210x_set_line_coding(cp210x_class, &linecoding);
usbh_cp210x_set_line_state(cp210x_class, true, false);
memset(g_cp210x_buf, 'a', sizeof(g_cp210x_buf));
ret = usbh_cp210x_bulk_out_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_cp210x_bulk_in_transfer(cp210x_class, g_cp210x_buf, sizeof(g_cp210x_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_cp210x_buf[i]);
}
USB_LOG_RAW("\r\n");
}
}
#endif
usbh_cp210x_run(cp210x_class);
return ret;
}
static int usbh_cp210x_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_cp210x *cp210x_class = (struct usbh_cp210x *)hport->config.intf[intf].priv;
if (cp210x_class) {
if (cp210x_class->bulkin) {
usbh_kill_urb(&cp210x_class->bulkin_urb);
}
if (cp210x_class->bulkout) {
usbh_kill_urb(&cp210x_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister CP210X Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cp210x_stop(cp210x_class);
}
usbh_cp210x_class_free(cp210x_class);
}
return ret;
}
int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cp210x_class->bulkin_urb;
usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &cp210x_class->bulkout_urb;
usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
{
}
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *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,
.disconnect = usbh_cp210x_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = cp210x_id_table,
.class_driver = &cp210x_class_driver
};

73
class/vendor/serial/usbh_cp210x.h vendored Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_CP210X_H
#define USBH_CP210X_H
#include "usb_cdc.h"
/* Requests */
#define CP210X_IFC_ENABLE 0x00
#define CP210X_SET_BAUDDIV 0x01
#define CP210X_GET_BAUDDIV 0x02
#define CP210X_SET_LINE_CTL 0x03 // Set parity, data bits, stop bits
#define CP210X_GET_LINE_CTL 0x04
#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_SET_XON 0x09
#define CP210X_SET_XOFF 0x0A
#define CP210X_SET_EVENTMASK 0x0B
#define CP210X_GET_EVENTMASK 0x0C
#define CP210X_SET_CHAR 0x0D
#define CP210X_GET_CHARS 0x0E
#define CP210X_GET_PROPS 0x0F
#define CP210X_GET_COMM_STATUS 0x10
#define CP210X_RESET 0x11
#define CP210X_PURGE 0x12
#define CP210X_SET_FLOW 0x13
#define CP210X_GET_FLOW 0x14
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
#define CP210X_GET_BAUDRATE 0x1D
#define CP210X_SET_BAUDRATE 0x1E // Set baudrate
#define CP210X_VENDOR_SPECIFIC 0xFF
struct usbh_cp210x {
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 line_coding;
uint8_t intf;
uint8_t minor;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_cp210x_set_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding);
int usbh_cp210x_get_line_coding(struct usbh_cp210x *ftdi_class, struct cdc_line_coding *line_coding);
int usbh_cp210x_set_line_state(struct usbh_cp210x *ftdi_class, bool dtr, bool rts);
int usbh_cp210x_bulk_in_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
void usbh_cp210x_run(struct usbh_cp210x *cp210x_class);
void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_CP210X_H */

363
class/vendor/serial/usbh_ftdi.c vendored Normal file
View File

@@ -0,0 +1,363 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_ftdi.h"
#define DEV_FORMAT "/dev/ttyUSB%d"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
#define CONFIG_USBHOST_MAX_FTDI_CLASS 4
static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi));
g_ftdi_class[devno].minor = devno;
return &g_ftdi_class[devno];
}
}
return NULL;
}
static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class)
{
int devno = ftdi_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(ftdi_class, 0, sizeof(struct usbh_ftdi));
}
static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_baudrate)
{
#define FTDI_USB_CLK 48000000
int baudrate;
uint8_t frac[] = { 0, 8, 4, 2, 6, 10, 12, 14 };
if (actual_baudrate == 2000000) {
*itdf_divisor = 0x01;
} else if (actual_baudrate == 3000000) {
*itdf_divisor = 0x00;
} else {
baudrate = actual_baudrate;
if (baudrate > 100000 && baudrate < 12000000) {
baudrate = (baudrate / 100000) + 100000;
}
int divisor = FTDI_USB_CLK / baudrate;
int frac_bits = 0;
for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
if ((divisor & 0xF) == frac[i]) {
frac_bits = i;
break;
}
}
divisor >>= 4;
divisor &= 0x3FFF;
*itdf_divisor = (divisor << 14) | (frac_bits << 8);
}
}
int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_RESET_REQUEST;
setup->wValue = 0;
setup->wIndex = ftdi_class->intf;
setup->wLength = 0;
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
}
static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value)
{
struct usb_setup_packet *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;
setup->wValue = value;
setup->wIndex = ftdi_class->intf;
setup->wLength = 0;
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
}
static int usbh_ftdi_set_baudrate(struct usbh_ftdi *ftdi_class, uint32_t baudrate)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
uint32_t itdf_divisor;
uint16_t value;
uint8_t baudrate_high;
usbh_ftdi_caculate_baudrate(&itdf_divisor, baudrate);
value = itdf_divisor & 0xFFFF;
baudrate_high = (itdf_divisor >> 16) & 0xff;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_SET_BAUDRATE_REQUEST;
setup->wValue = value;
setup->wIndex = (baudrate_high << 8) | ftdi_class->intf;
setup->wLength = 0;
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
}
static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t databits, uint8_t parity, uint8_t stopbits, uint8_t isbreak)
{
/**
* 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
* D14 BREAK_OFF=0, BREAK_ON=1
**/
uint16_t value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f);
struct usb_setup_packet *setup = ftdi_class->hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_SET_DATA_REQUEST;
setup->wValue = value;
setup->wIndex = ftdi_class->intf;
setup->wLength = 0;
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
}
static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t value)
{
struct usb_setup_packet *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;
setup->wValue = value;
setup->wIndex = ftdi_class->intf;
setup->wLength = 0;
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
}
static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value)
{
struct usb_setup_packet *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;
setup->wValue = value;
setup->wIndex = ftdi_class->intf;
setup->wLength = 0;
return usbh_control_transfer(ftdi_class->hport, setup, NULL);
}
static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class)
{
struct usb_setup_packet *setup = ftdi_class->hport->setup;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = SIO_POLL_MODEM_STATUS_REQUEST;
setup->wValue = 0x0000;
setup->wIndex = ftdi_class->intf;
setup->wLength = 2;
ret = usbh_control_transfer(ftdi_class->hport, setup, g_ftdi_buf);
if (ret < 0) {
return ret;
}
memcpy(ftdi_class->modem_status, g_ftdi_buf, 2);
return ret;
}
int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding)
{
memcpy((uint8_t *)&ftdi_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
usbh_ftdi_set_baudrate(ftdi_class, line_coding->dwDTERate);
return usbh_ftdi_set_data_format(ftdi_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat, 0);
}
int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding)
{
memcpy(line_coding, (uint8_t *)&ftdi_class->line_coding, sizeof(struct cdc_line_coding));
return 0;
}
int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts)
{
int ret;
if (dtr) {
usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_HIGH);
} else {
usbh_ftdi_set_modem(ftdi_class, SIO_SET_DTR_LOW);
}
if (rts) {
ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_HIGH);
} else {
ret = usbh_ftdi_set_modem(ftdi_class, SIO_SET_RTS_LOW);
}
return ret;
}
static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
struct usbh_ftdi *ftdi_class = usbh_ftdi_class_alloc();
if (ftdi_class == NULL) {
USB_LOG_ERR("Fail to alloc ftdi_class\r\n");
return -USB_ERR_NOMEM;
}
ftdi_class->hport = hport;
ftdi_class->intf = intf;
hport->config.intf[intf].priv = ftdi_class;
usbh_ftdi_reset(ftdi_class);
usbh_ftdi_set_flow_ctrl(ftdi_class, SIO_DISABLE_FLOW_CTRL);
usbh_ftdi_set_latency_timer(ftdi_class, 0x10);
usbh_ftdi_read_modem_status(ftdi_class);
USB_LOG_INFO("modem status:%02x:%02x\r\n", ftdi_class->modem_status[0], ftdi_class->modem_status[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;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(ftdi_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(ftdi_class->bulkout, ep_desc);
}
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, ftdi_class->minor);
USB_LOG_INFO("Register FTDI Class:%s\r\n", hport->config.intf[intf].devname);
#if 0
USB_LOG_INFO("Test ftdi 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_ftdi_set_line_coding(ftdi_class, &linecoding);
usbh_ftdi_set_line_state(ftdi_class, true, false);
memset(g_ftdi_buf, 'a', sizeof(g_ftdi_buf));
ret = usbh_ftdi_bulk_out_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_buf), 0xfffffff);
USB_LOG_RAW("out ret:%d\r\n", ret);
while (count--) {
ret = usbh_ftdi_bulk_in_transfer(ftdi_class, g_ftdi_buf, sizeof(g_ftdi_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_ftdi_buf[i]);
}
}
USB_LOG_RAW("\r\n");
}
#endif
usbh_ftdi_run(ftdi_class);
return ret;
}
static int usbh_ftdi_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_ftdi *ftdi_class = (struct usbh_ftdi *)hport->config.intf[intf].priv;
if (ftdi_class) {
if (ftdi_class->bulkin) {
usbh_kill_urb(&ftdi_class->bulkin_urb);
}
if (ftdi_class->bulkout) {
usbh_kill_urb(&ftdi_class->bulkout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister FTDI Class:%s\r\n", hport->config.intf[intf].devname);
usbh_ftdi_stop(ftdi_class);
}
usbh_ftdi_class_free(ftdi_class);
}
return ret;
}
int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &ftdi_class->bulkin_urb;
usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &ftdi_class->bulkout_urb;
usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
{
}
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *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 ftdi_class_info = {
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = ftdi_id_table,
.class_driver = &ftdi_class_driver
};

76
class/vendor/serial/usbh_ftdi.h vendored Normal file
View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_FTDI_H
#define USBH_FTDI_H
#include "usb_cdc.h"
/* Requests */
#define SIO_RESET_REQUEST 0x00 /* Reset the port */
#define SIO_SET_MODEM_CTRL_REQUEST 0x01 /* Set the modem control register */
#define SIO_SET_FLOW_CTRL_REQUEST 0x02 /* Set flow control register */
#define SIO_SET_BAUDRATE_REQUEST 0x03 /* Set baud rate */
#define SIO_SET_DATA_REQUEST 0x04 /* Set the data characteristics of the port */
#define SIO_POLL_MODEM_STATUS_REQUEST 0x05
#define SIO_SET_EVENT_CHAR_REQUEST 0x06
#define SIO_SET_ERROR_CHAR_REQUEST 0x07
#define SIO_SET_LATENCY_TIMER_REQUEST 0x09
#define SIO_GET_LATENCY_TIMER_REQUEST 0x0A
#define SIO_SET_BITMODE_REQUEST 0x0B
#define SIO_READ_PINS_REQUEST 0x0C
#define SIO_READ_EEPROM_REQUEST 0x90
#define SIO_WRITE_EEPROM_REQUEST 0x91
#define SIO_ERASE_EEPROM_REQUEST 0x92
#define SIO_DISABLE_FLOW_CTRL 0x0
#define SIO_RTS_CTS_HS (0x1 << 8)
#define SIO_DTR_DSR_HS (0x2 << 8)
#define SIO_XON_XOFF_HS (0x4 << 8)
#define SIO_SET_DTR_MASK 0x1
#define SIO_SET_DTR_HIGH (1 | (SIO_SET_DTR_MASK << 8))
#define SIO_SET_DTR_LOW (0 | (SIO_SET_DTR_MASK << 8))
#define SIO_SET_RTS_MASK 0x2
#define SIO_SET_RTS_HIGH (2 | (SIO_SET_RTS_MASK << 8))
#define SIO_SET_RTS_LOW (0 | (SIO_SET_RTS_MASK << 8))
#define SIO_RTS_CTS_HS (0x1 << 8)
struct usbh_ftdi {
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 line_coding;
uint8_t intf;
uint8_t minor;
uint8_t modem_status[2];
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding);
int usbh_ftdi_get_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding);
int usbh_ftdi_set_line_state(struct usbh_ftdi *ftdi_class, bool dtr, bool rts);
int usbh_ftdi_bulk_in_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
void usbh_ftdi_run(struct usbh_ftdi *ftdi_class);
void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_FTDI_H */

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

@@ -0,0 +1,426 @@
/*
* 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 4
#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 = 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 = 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 = pl2303_class->hport->setup;
int ret;
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 = 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)
{
}
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *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 */

View File

@@ -18,9 +18,9 @@ struct usbd_video_priv {
uint8_t power_mode;
uint8_t error_code;
struct video_entity_info info[3];
} g_usbd_video;
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
@@ -60,13 +60,13 @@ static int usbd_video_control_request_handler(struct usb_setup_packet *setup, ui
return 0;
}
static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
for (uint8_t i = 0; i < 3; i++) {
struct video_entity_info *entity_info = &g_usbd_video.info[i];
struct video_entity_info *entity_info = &g_usbd_video[busid].info[i];
if (entity_info->bEntityId == entity_id) {
switch (entity_info->bDescriptorSubtype) {
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
@@ -546,7 +546,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
}
break;
default:
g_usbd_video.error_code = 0x06;
g_usbd_video[busid].error_code = 0x06;
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
return -1;
}
@@ -564,7 +564,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
return 0;
}
static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
@@ -572,10 +572,10 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_PROBE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
//memcpy((uint8_t *)&g_usbd_video.probe, *data, setup->wLength);
//memcpy((uint8_t *)&g_usbd_video[busid].probe, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
@@ -583,7 +583,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_REQUEST_GET_MAX:
case VIDEO_REQUEST_GET_RES:
case VIDEO_REQUEST_GET_DEF:
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
case VIDEO_REQUEST_GET_LEN:
@@ -604,17 +604,17 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_COMMIT_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
//memcpy((uint8_t *)&g_usbd_video.commit, *data, setup->wLength);
//memcpy((uint8_t *)&g_usbd_video[busid].commit, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
case VIDEO_REQUEST_GET_MIN:
case VIDEO_REQUEST_GET_MAX:
case VIDEO_REQUEST_GET_RES:
case VIDEO_REQUEST_GET_DEF:
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
@@ -636,7 +636,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_GET_CUR:
(*data)[0] = g_usbd_video.error_code;
(*data)[0] = g_usbd_video[busid].error_code;
*len = 1;
break;
case VIDEO_REQUEST_GET_INFO:
@@ -655,7 +655,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
return 0;
}
static int video_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int video_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("Video Class request: "
"bRequest 0x%02x\r\n",
@@ -666,30 +666,30 @@ static int video_class_interface_request_handler(struct usb_setup_packet *setup,
if (intf_num == 0) { /* Video Control Interface */
if (entity_id == 0) {
return usbd_video_control_request_handler(setup, data, len); /* Interface Control Requests */
return usbd_video_control_request_handler(busid, setup, data, len); /* Interface Control Requests */
} else {
return usbd_video_control_unit_terminal_request_handler(setup, data, len); /* Unit and Terminal Requests */
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
}
} else if (intf_num == 1) { /* Video Stream Inteface */
return usbd_video_stream_request_handler(setup, data, len); /* Interface Stream Requests */
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
}
return -1;
}
static void video_notify_handler(uint8_t event, void *arg)
static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
g_usbd_video.error_code = 0;
g_usbd_video.power_mode = 0;
g_usbd_video[busid].error_code = 0;
g_usbd_video[busid].power_mode = 0;
break;
case USBD_EVENT_SET_INTERFACE: {
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
if (intf->bAlternateSetting == 1) {
usbd_video_open(intf->bInterfaceNumber);
usbd_video_open(busid, intf->bInterfaceNumber);
} else {
usbd_video_close(intf->bInterfaceNumber);
usbd_video_close(busid, intf->bInterfaceNumber);
}
}
@@ -699,46 +699,46 @@ static void video_notify_handler(uint8_t event, void *arg)
}
}
void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
{
g_usbd_video.probe.hintUnion.bmHint = 0x01;
g_usbd_video.probe.hintUnion1.bmHint = 0;
g_usbd_video.probe.bFormatIndex = 1;
g_usbd_video.probe.bFrameIndex = 1;
g_usbd_video.probe.dwFrameInterval = dwFrameInterval;
g_usbd_video.probe.wKeyFrameRate = 0;
g_usbd_video.probe.wPFrameRate = 0;
g_usbd_video.probe.wCompQuality = 0;
g_usbd_video.probe.wCompWindowSize = 0;
g_usbd_video.probe.wDelay = 0;
g_usbd_video.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video.probe.dwClockFrequency = 0;
g_usbd_video.probe.bmFramingInfo = 0;
g_usbd_video.probe.bPreferedVersion = 0;
g_usbd_video.probe.bMinVersion = 0;
g_usbd_video.probe.bMaxVersion = 0;
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
g_usbd_video[busid].probe.bFormatIndex = 1;
g_usbd_video[busid].probe.bFrameIndex = 1;
g_usbd_video[busid].probe.dwFrameInterval = dwFrameInterval;
g_usbd_video[busid].probe.wKeyFrameRate = 0;
g_usbd_video[busid].probe.wPFrameRate = 0;
g_usbd_video[busid].probe.wCompQuality = 0;
g_usbd_video[busid].probe.wCompWindowSize = 0;
g_usbd_video[busid].probe.wDelay = 0;
g_usbd_video[busid].probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video[busid].probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video[busid].probe.dwClockFrequency = 0;
g_usbd_video[busid].probe.bmFramingInfo = 0;
g_usbd_video[busid].probe.bPreferedVersion = 0;
g_usbd_video[busid].probe.bMinVersion = 0;
g_usbd_video[busid].probe.bMaxVersion = 0;
g_usbd_video.commit.hintUnion.bmHint = 0x01;
g_usbd_video.commit.hintUnion1.bmHint = 0;
g_usbd_video.commit.bFormatIndex = 1;
g_usbd_video.commit.bFrameIndex = 1;
g_usbd_video.commit.dwFrameInterval = dwFrameInterval;
g_usbd_video.commit.wKeyFrameRate = 0;
g_usbd_video.commit.wPFrameRate = 0;
g_usbd_video.commit.wCompQuality = 0;
g_usbd_video.commit.wCompWindowSize = 0;
g_usbd_video.commit.wDelay = 0;
g_usbd_video.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video.commit.dwClockFrequency = 0;
g_usbd_video.commit.bmFramingInfo = 0;
g_usbd_video.commit.bPreferedVersion = 0;
g_usbd_video.commit.bMinVersion = 0;
g_usbd_video.commit.bMaxVersion = 0;
g_usbd_video[busid].commit.hintUnion.bmHint = 0x01;
g_usbd_video[busid].commit.hintUnion1.bmHint = 0;
g_usbd_video[busid].commit.bFormatIndex = 1;
g_usbd_video[busid].commit.bFrameIndex = 1;
g_usbd_video[busid].commit.dwFrameInterval = dwFrameInterval;
g_usbd_video[busid].commit.wKeyFrameRate = 0;
g_usbd_video[busid].commit.wPFrameRate = 0;
g_usbd_video[busid].commit.wCompQuality = 0;
g_usbd_video[busid].commit.wCompWindowSize = 0;
g_usbd_video[busid].commit.wDelay = 0;
g_usbd_video[busid].commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
g_usbd_video[busid].commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
g_usbd_video[busid].commit.dwClockFrequency = 0;
g_usbd_video[busid].commit.bmFramingInfo = 0;
g_usbd_video[busid].commit.bPreferedVersion = 0;
g_usbd_video[busid].commit.bMinVersion = 0;
g_usbd_video[busid].commit.bMaxVersion = 0;
}
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
uint32_t dwFrameInterval,
uint32_t dwMaxVideoFrameSize,
uint32_t dwMaxPayloadTransferSize)
@@ -748,39 +748,39 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
intf->vendor_handler = NULL;
intf->notify_handler = video_notify_handler;
g_usbd_video.info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video.info[0].bEntityId = 0x01;
g_usbd_video.info[0].wTerminalType = VIDEO_ITT_CAMERA;
g_usbd_video.info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video.info[1].bEntityId = 0x03;
g_usbd_video.info[1].wTerminalType = 0x00;
g_usbd_video.info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
g_usbd_video.info[2].bEntityId = 0x02;
g_usbd_video.info[2].wTerminalType = 0x00;
g_usbd_video[busid].info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video[busid].info[0].bEntityId = 0x01;
g_usbd_video[busid].info[0].wTerminalType = VIDEO_ITT_CAMERA;
g_usbd_video[busid].info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
g_usbd_video[busid].info[1].bEntityId = 0x03;
g_usbd_video[busid].info[1].wTerminalType = 0x00;
g_usbd_video[busid].info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
g_usbd_video[busid].info[2].bEntityId = 0x02;
g_usbd_video[busid].info[2].wTerminalType = 0x00;
usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
usbd_video_probe_and_commit_controls_init(busid, dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
return intf;
}
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
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 packets;
uint32_t last_packet_size;
uint32_t picture_pos = 0;
static uint8_t uvc_header[2] = { 0x02, 0x80 };
packets = input_len / g_usbd_video.probe.dwMaxPayloadTransferSize + 1;
last_packet_size = input_len - ((packets - 1) * (g_usbd_video.probe.dwMaxPayloadTransferSize - 2)) + 2;
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
for (size_t i = 0; i < packets; i++) {
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
if (i == (packets - 1)) {
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
} else {
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
picture_pos += g_usbd_video.probe.dwMaxPayloadTransferSize - 2;
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
}
}
uvc_header[1] ^= 1;

View File

@@ -13,14 +13,14 @@ extern "C" {
#endif
/* Init video interface driver */
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
uint32_t dwFrameInterval,
uint32_t dwMaxVideoFrameSize,
uint32_t dwMaxPayloadTransferSize);
void usbd_video_open(uint8_t intf);
void usbd_video_close(uint8_t intf);
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
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);
#ifdef __cplusplus
}

View File

@@ -6,6 +6,10 @@
#include "usbh_core.h"
#include "usbh_video.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_video"
#include "usb_log.h"
#define DEV_FORMAT "/dev/video%d"
/* general descriptor field offsets */
@@ -53,46 +57,59 @@ static void usbh_video_class_free(struct usbh_video *video_class)
memset(video_class, 0, sizeof(struct usbh_video));
}
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
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;
int ret;
uint8_t retry;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = VIDEO_REQUEST_GET_CUR;
setup->bRequest = request;
setup->wValue = cs << 8;
setup->wIndex = (entity_id << 8) | intf;
setup->wLength = len;
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
if (ret < 0) {
return ret;
retry = 0;
while (1) {
ret = usbh_control_transfer(video_class->hport, setup, g_video_buf);
if (ret > 0) {
break;
}
retry++;
if (retry == 3) {
return ret;
}
}
memcpy(buf, g_video_buf, len);
if (buf) {
memcpy(buf, g_video_buf, len);
}
return ret;
}
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
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;
int ret;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = VIDEO_REQUEST_SET_CUR;
setup->bRequest = request;
setup->wValue = cs << 8;
setup->wIndex = (entity_id << 8) | intf;
setup->wLength = len;
memcpy(g_video_buf, buf, len);
ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
usb_osal_msleep(5);
ret = usbh_control_transfer(video_class->hport, setup, g_video_buf);
usb_osal_msleep(50);
return ret;
}
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
{
return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
return usbh_video_get(video_class, VIDEO_REQUEST_GET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
}
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
@@ -100,7 +117,8 @@ int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t fo
video_class->probe.bFormatIndex = formatindex;
video_class->probe.bFrameIndex = frameindex;
video_class->probe.dwMaxPayloadTransferSize = 0;
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
video_class->probe.dwFrameInterval = 333333;
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
}
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
@@ -108,7 +126,8 @@ int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t f
memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
video_class->commit.bFormatIndex = formatindex;
video_class->commit.bFrameIndex = frameindex;
return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
video_class->commit.dwFrameInterval = 333333;
return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
}
int usbh_video_open(struct usbh_video *video_class,
@@ -125,9 +144,10 @@ int usbh_video_open(struct usbh_video *video_class,
bool found = false;
uint8_t formatidx = 0;
uint8_t frameidx = 0;
uint8_t step;
if (video_class->is_opened) {
return -EMFILE;
return 0;
}
for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
@@ -145,47 +165,81 @@ int usbh_video_open(struct usbh_video *video_class,
}
if (found == false) {
return -ENODEV;
return -USB_ERR_NODEV;
}
if (altsetting > (video_class->num_of_intf_altsettings - 1)) {
return -EINVAL;
return -USB_ERR_INVAL;
}
/* Open video step:
* Get CUR request (probe)
* Set CUR request (probe)
* Get CUR request (probe)
* Get MAX request (probe)
* Get MIN request (probe)
* Get CUR request (probe)
* Set CUR request (commit)
*
*/
step = 0;
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
return ret;
goto errout;
}
step = 1;
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
if (ret < 0) {
return ret;
goto errout;
}
step = 2;
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
return ret;
goto errout;
}
step = 3;
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MAX, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
if (ret < 0) {
goto errout;
}
step = 4;
ret = usbh_video_get(video_class, VIDEO_REQUEST_GET_MIN, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, NULL, 26);
if (ret < 0) {
goto errout;
}
step = 5;
ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
if (ret < 0) {
return ret;
goto errout;
}
step = 6;
ret = usbh_videostreaming_get_cur_probe(video_class);
if (ret < 0) {
return ret;
goto errout;
}
step = 7;
ret = usbh_videostreaming_set_cur_commit(video_class, formatidx, frameidx);
if (ret < 0) {
return ret;
goto errout;
}
step = 8;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = altsetting;
setup->wIndex = video_class->data_intf;
setup->wLength = 0;
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
ret = usbh_control_transfer(video_class->hport, setup, NULL);
if (ret < 0) {
return ret;
goto errout;
}
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
@@ -193,16 +247,20 @@ int usbh_video_open(struct usbh_video *video_class,
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
if (ep_desc->bEndpointAddress & 0x80) {
video_class->isoin_mps = mps * (mult + 1);
usbh_hport_activate_epx(&video_class->isoin, video_class->hport, ep_desc);
USBH_EP_INIT(video_class->isoin, ep_desc);
} else {
video_class->isoout_mps = mps * (mult + 1);
usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc);
USBH_EP_INIT(video_class->isoout, ep_desc);
}
USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting);
video_class->is_opened = true;
video_class->current_format = format_type;
return ret;
errout:
USB_LOG_ERR("Fail to open video in step %u\r\n", step);
return ret;
}
int usbh_video_close(struct usbh_video *video_class)
@@ -215,12 +273,10 @@ int usbh_video_close(struct usbh_video *video_class)
video_class->is_opened = false;
if (video_class->isoin) {
usbh_pipe_free(video_class->isoin);
video_class->isoin = NULL;
}
if (video_class->isoout) {
usbh_pipe_free(video_class->isoout);
video_class->isoout = NULL;
}
@@ -230,7 +286,7 @@ int usbh_video_close(struct usbh_video *video_class)
setup->wIndex = video_class->data_intf;
setup->wLength = 0;
ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
ret = usbh_control_transfer(video_class->hport, setup, NULL);
if (ret < 0) {
return ret;
}
@@ -244,12 +300,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;
@@ -257,7 +313,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,
@@ -266,15 +322,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);
}
@@ -296,7 +352,7 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_video *video_class = usbh_video_class_alloc();
if (video_class == NULL) {
USB_LOG_ERR("Fail to alloc video_class\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
video_class->hport = hport;
@@ -401,11 +457,9 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (video_class) {
if (video_class->isoin) {
usbh_pipe_free(video_class->isoin);
}
if (video_class->isoout) {
usbh_pipe_free(video_class->isoout);
}
if (hport->config.intf[intf].devname[0] != '\0') {
@@ -454,8 +508,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
};
@@ -464,7 +517,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,20 +22,29 @@ 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;
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
uint16_t width;
uint16_t height;
};
struct usbh_video {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *isoin; /* ISO IN endpoint */
struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
uint8_t ctrl_intf; /* interface number */
uint8_t data_intf; /* interface number */
uint8_t minor;
usbh_pipe_t isoin; /* ISO IN endpoint */
usbh_pipe_t isoout; /* ISO OUT endpoint */
struct video_probe_and_commit_controls probe;
struct video_probe_and_commit_controls commit;
uint16_t isoin_mps;
@@ -46,17 +55,16 @@ 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
extern "C" {
#endif
int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class);
int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex);
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);
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);
int usbh_video_open(struct usbh_video *video_class,
uint8_t format_type,

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
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
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];
@@ -105,10 +97,10 @@ static void rndis_notify_rsp(void)
{
memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
usbd_ep_start_write(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
usbd_ep_start_write(0, rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
}
static int rndis_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
switch (setup->bRequest) {
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
@@ -169,8 +161,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;
@@ -225,7 +217,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);
infomation_len = 4;
break;
case OID_GEN_VENDOR_ID:
@@ -250,7 +242,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:
@@ -394,7 +391,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
{
rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
rndis_reset_cmplt_t *resp;
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
@@ -426,7 +423,7 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
return 0;
}
static void rndis_notify_handler(uint8_t event, void *arg)
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -436,7 +433,7 @@ static void rndis_notify_handler(uint8_t event, void *arg)
g_rndis_rx_data_length = 0;
g_rndis_tx_data_length = 0;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
break;
default:
@@ -444,14 +441,14 @@ static void rndis_notify_handler(uint8_t event, void *arg)
}
}
void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
rndis_data_packet_t *hdr;
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)) {
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
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;
}
@@ -462,17 +459,17 @@ void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
usbd_rndis_data_recv_done();
}
void rndis_bulk_in(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) {
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(ep, NULL, 0);
usbd_ep_start_write(0, ep, NULL, 0);
} else {
g_rndis_tx_data_length = 0;
}
}
void rndis_int_in(uint8_t ep, uint32_t nbytes)
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
//USB_LOG_DBG("len:%d\r\n", nbytes);
}
@@ -496,7 +493,7 @@ struct pbuf *usbd_rndis_eth_rx(void)
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
g_rndis_rx_data_length = 0;
usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return p;
}
@@ -508,11 +505,11 @@ 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) {
return -EBUSY;
return -USB_ERR_BUSY;
}
if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
@@ -536,7 +533,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
return usbd_ep_start_write(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
}
#endif
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
@@ -548,7 +545,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;
@@ -557,9 +553,9 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
usbd_add_endpoint(&rndis_ep_data[RNDIS_OUT_EP_IDX]);
usbd_add_endpoint(&rndis_ep_data[RNDIS_IN_EP_IDX]);
usbd_add_endpoint(&rndis_ep_data[RNDIS_INT_EP_IDX]);
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_OUT_EP_IDX]);
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_IN_EP_IDX]);
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_INT_EP_IDX]);
intf->class_interface_handler = rndis_class_interface_request_handler;
intf->class_endpoint_handler = NULL;

View File

@@ -0,0 +1,402 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_bluetooth.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_bluetooth"
#include "usb_log.h"
#define DEV_FORMAT "/dev/bluetooth"
static struct usbh_bluetooth g_bluetooth_class;
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
#else
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[1 + 256];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[1 + 256];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
#endif
static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
uint8_t mult;
uint16_t mps;
#endif
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
if (intf != 0) {
return 0;
}
#endif
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
bluetooth_class->hport = hport;
bluetooth_class->intf = intf;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
bluetooth_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
#endif
hport->config.intf[intf].priv = bluetooth_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;
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(bluetooth_class->intin, ep_desc);
} else {
return -USB_ERR_NOTSUPP;
}
} else {
#endif
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(bluetooth_class->bulkin, ep_desc);
} else {
USBH_EP_INIT(bluetooth_class->bulkout, ep_desc);
}
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
}
#endif
}
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
USB_LOG_INFO("Num of altsettings:%u\r\n", bluetooth_class->num_of_intf_altsettings);
for (uint8_t i = 0; i < bluetooth_class->num_of_intf_altsettings; i++) {
USB_LOG_INFO("Altsetting:%u\r\n", i);
for (uint8_t j = 0; j < hport->config.intf[intf + 1].altsetting[i].intf_desc.bNumEndpoints; j++) {
ep_desc = &bluetooth_class->hport->config.intf[intf + 1].altsetting[i].ep[j].ep_desc;
mult = USB_GET_MULT(ep_desc->wMaxPacketSize);
mps = USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize);
USB_LOG_INFO("\tEp=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
ep_desc->bEndpointAddress,
ep_desc->bmAttributes,
mps,
ep_desc->bInterval,
mult);
}
}
ret = usbh_set_interface(hport, intf, 0);
if (ret < 0) {
return ret;
}
USB_LOG_INFO("Bluetooth select altsetting 0\r\n");
#endif
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT);
USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bluetooth_run(bluetooth_class);
return ret;
}
static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_bluetooth *bluetooth_class = (struct usbh_bluetooth *)hport->config.intf[intf].priv;
if (hport->config.config_desc.bNumInterfaces == (intf + 1)) {
return 0;
}
if (bluetooth_class) {
if (bluetooth_class->bulkin) {
usbh_kill_urb(&bluetooth_class->bulkin_urb);
}
if (bluetooth_class->bulkout) {
usbh_kill_urb(&bluetooth_class->bulkout_urb);
}
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
if (bluetooth_class->intin) {
usbh_kill_urb(&bluetooth_class->intin_urb);
}
// if (bluetooth_class->isoin) {
// usbh_kill_urb(&bluetooth_class->isoin_urb);
// }
// if (bluetooth_class->isoin) {
// usbh_kill_urb(&bluetooth_class->isoinin_urb);
// }
#endif
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bluetooth_stop(bluetooth_class);
}
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
}
return ret;
}
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_LOG
static void usbh_bluetooth_hci_dump(uint8_t *data, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len; i++) {
if (i % 16 == 0) {
USB_LOG_RAW("\r\n");
}
USB_LOG_RAW("%02x ", data[i]);
}
USB_LOG_RAW("\r\n");
}
#else
#define usbh_bluetooth_hci_dump(data, len)
#endif
static int usbh_bluetooth_hci_bulk_out(uint8_t *buffer, uint32_t buflen)
{
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
struct usbh_urb *urb = &bluetooth_class->bulkout_urb;
int ret;
usbh_bulk_urb_fill(urb, bluetooth_class->hport, bluetooth_class->bulkout, buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
{
int ret;
g_bluetooth_tx_buf[0] = hci_type;
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
ret = usbh_bluetooth_hci_bulk_out(g_bluetooth_tx_buf, buflen + 1);
return ret;
}
void usbh_bluetooth_hci_rx_thread(void *argument)
{
int ret;
uint32_t ep_mps;
uint8_t retry = 0;
uint16_t actual_len = 0;
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
USB_LOG_INFO("Create hc rx thread\r\n");
while (1) {
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
if (ret < 0) {
if (ret == -USB_ERR_SHUTDOWN) {
goto delete;
} else {
retry++;
if (retry == 3) {
retry = 0;
goto delete;
}
continue;
}
}
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len);
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len);
actual_len = 0;
} else {
/* read continue util read short packet */
}
}
// clang-format off
delete :
USB_LOG_INFO("Delete hc acl rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
#else
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;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = 0x00;
setup->wValue = 0;
setup->wIndex = bluetooth_class->intf;
setup->wLength = buflen;
return usbh_control_transfer(bluetooth_class->hport, setup, buffer);
}
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
{
int ret;
if (hci_type == USB_BLUETOOTH_HCI_CMD) {
g_bluetooth_cmd_buf[0] = USB_BLUETOOTH_HCI_CMD;
memcpy(&g_bluetooth_cmd_buf[1], buffer, buflen);
usbh_bluetooth_hci_dump(g_bluetooth_cmd_buf, buflen + 1);
ret = usbh_bluetooth_hci_cmd(&g_bluetooth_cmd_buf[1], buflen);
} else if (hci_type == USB_BLUETOOTH_HCI_ACL) {
g_bluetooth_tx_buf[0] = USB_BLUETOOTH_HCI_ACL;
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
ret = usbh_bluetooth_hci_bulk_out(&g_bluetooth_tx_buf[1], buflen);
} else {
ret = -1;
}
return ret;
}
void usbh_bluetooth_hci_evt_rx_thread(void *argument)
{
int ret;
uint32_t ep_mps;
uint32_t interval;
uint8_t retry = 0;
uint16_t actual_len = 0;
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.intin->wMaxPacketSize);
interval = g_bluetooth_class.intin->bInterval;
USB_LOG_INFO("Create hc event rx thread\r\n");
while (1) {
usbh_int_urb_fill(&g_bluetooth_class.intin_urb, g_bluetooth_class.hport, g_bluetooth_class.intin, &g_bluetooth_evt_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_bluetooth_class.intin_urb);
if (ret < 0) {
if (ret == -USB_ERR_SHUTDOWN) {
goto delete;
} else if (ret == -USB_ERR_NAK) {
usb_osal_msleep(interval);
continue;
} else {
retry++;
if (retry == 3) {
retry = 0;
goto delete;
}
usb_osal_msleep(interval);
continue;
}
}
actual_len += g_bluetooth_class.intin_urb.actual_length;
if (g_bluetooth_class.intin_urb.actual_length != ep_mps) {
g_bluetooth_evt_buf[0] = USB_BLUETOOTH_HCI_EVT;
usbh_bluetooth_hci_dump(g_bluetooth_evt_buf, actual_len + 1);
usbh_bluetooth_hci_read_callback(g_bluetooth_evt_buf, actual_len + 1);
actual_len = 0;
} else {
/* read continue util read short packet */
}
usb_osal_msleep(interval);
}
// clang-format off
delete :
USB_LOG_INFO("Delete hc event rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
void usbh_bluetooth_hci_acl_rx_thread(void *argument)
{
int ret;
uint32_t ep_mps;
uint8_t retry = 0;
uint16_t actual_len = 0;
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
USB_LOG_INFO("Create hc acl rx thread\r\n");
while (1) {
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
if (ret < 0) {
if (ret == -USB_ERR_SHUTDOWN) {
goto delete;
} else {
retry++;
if (retry == 3) {
retry = 0;
goto delete;
}
continue;
}
}
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
g_bluetooth_rx_buf[0] = USB_BLUETOOTH_HCI_ACL;
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len + 1);
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len + 1);
actual_len = 0;
} else {
/* read continue util read short packet */
}
}
// clang-format off
delete :
USB_LOG_INFO("Delete hc acl rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
#endif
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
{
}
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
{
}
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
{
}
static const struct usbh_class_driver bluetooth_class_driver = {
.driver_name = "bluetooth",
.connect = usbh_bluetooth_connect,
.disconnect = usbh_bluetooth_disconnect
};
#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_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
.class = 0xff,
.subclass = 0x00,
.protocol = 0x00,
.id_table = bluetooth_id_table,
.class_driver = &bluetooth_class_driver
};
#else
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.class = USB_DEVICE_CLASS_WIRELESS,
.subclass = 0x01,
.protocol = 0x01,
.id_table = NULL,
.class_driver = &bluetooth_class_driver
};
#endif

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_BLUETOOTH_H
#define USBH_BLUETOOTH_H
#define USB_BLUETOOTH_HCI_NONE 0x00
#define USB_BLUETOOTH_HCI_CMD 0x01
#define USB_BLUETOOTH_HCI_ACL 0x02
#define USB_BLUETOOTH_HCI_SCO 0x03
#define USB_BLUETOOTH_HCI_EVT 0x04
#define USB_BLUETOOTH_HCI_ISO 0x05
struct usbh_bluetooth {
struct usbh_hubport *hport;
uint8_t intf;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
struct usb_endpoint_descriptor *isoin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *isoout; /* Bulk OUT endpoint */
struct usbh_urb intin_urb; /* INTR IN urb */
struct usbh_urb *isoin_urb; /* Bulk IN urb */
struct usbh_urb *isoout_urb; /* Bulk OUT urb */
uint8_t num_of_intf_altsettings;
#endif
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
void usbh_bluetooth_hci_rx_thread(void *argument);
#else
void usbh_bluetooth_hci_evt_rx_thread(void *argument);
void usbh_bluetooth_hci_acl_rx_thread(void *argument);
#endif
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);
void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class);
#ifdef __cplusplus
}
#endif
#endif /* USBH_BLUETOOTH_H */

View File

@@ -7,36 +7,35 @@
#include "usbh_rndis.h"
#include "rndis_protocol.h"
#define DEV_FORMAT "/dev/rndis%d"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_rndis"
#include "usb_log.h"
#define DEV_FORMAT "/dev/rndis"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
static struct usbh_rndis g_rndis_class[CONFIG_USBHOST_MAX_RNDIS_CLASS];
static uint32_t g_devinuse = 0;
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
static struct usbh_rndis *usbh_rndis_class_alloc(void)
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];
static struct usbh_rndis g_rndis_class;
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
{
int devno;
// int ret;
// struct usbh_urb *urb = &rndis_class->intin_urb;
for (devno = 0; devno < CONFIG_USBHOST_MAX_RNDIS_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_rndis_class[devno], 0, sizeof(struct usbh_rndis));
g_rndis_class[devno].minor = devno;
return &g_rndis_class[devno];
}
}
return NULL;
}
static void usbh_rndis_class_free(struct usbh_rndis *rndis_class)
{
int devno = rndis_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(rndis_class, 0, sizeof(struct usbh_rndis));
// usbh_int_urb_fill(urb, rndis_class->hport, rndis_class->intin, g_rndis_inttx_buffer, rndis_class->intin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, NULL, NULL);
// ret = usbh_submit_urb(urb);
// if (ret == 0) {
// ret = urb->actual_length;
// }
// return ret;
return 0;
}
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
@@ -61,13 +60,13 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
setup->wIndex = 0;
setup->wLength = sizeof(rndis_initialize_msg_t);
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
if (ret < 0) {
USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret);
return ret;
}
//ret = usbh_ep_intr_transfer()
usbh_rndis_get_notification(rndis_class);
resp = (rndis_initialize_cmplt_t *)g_rndis_buf;
@@ -77,7 +76,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
setup->wIndex = 0;
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret);
return ret;
@@ -107,15 +106,15 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(rndis_query_msg_t);
setup->wLength = query_len + sizeof(rndis_query_msg_t);
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
if (ret < 0) {
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
return ret;
}
//ret = usbh_ep_intr_transfer()
usbh_rndis_get_notification(rndis_class);
resp = (rndis_query_cmplt_t *)g_rndis_buf;
@@ -125,7 +124,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
setup->wIndex = 0;
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
return ret;
@@ -159,15 +158,15 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
setup->wValue = 0;
setup->wIndex = 0;
setup->wLength = sizeof(rndis_set_msg_t);
setup->wLength = info_len + sizeof(rndis_set_msg_t);
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
if (ret < 0) {
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
return ret;
}
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
usbh_rndis_get_notification(rndis_class);
resp = (rndis_set_cmplt_t *)g_rndis_buf;
@@ -177,7 +176,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
setup->wIndex = 0;
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
return ret;
@@ -186,32 +185,22 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
return ret;
}
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
{
int ret;
struct usbh_urb *urb = &rndis_class->bulkout_urb;
memset(urb, 0, sizeof(struct usbh_urb));
uint8_t data[32];
uint32_t data_len;
usbh_bulk_urb_fill(urb, rndis_class->bulkout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
if (ret < 0) {
return ret;
}
return ret;
}
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &rndis_class->bulkin_urb;
memset(urb, 0, sizeof(struct usbh_urb));
usbh_bulk_urb_fill(urb, rndis_class->bulkin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
rndis_class->connect_status = true;
} else {
rndis_class->connect_status = false;
}
return ret;
return 0;
}
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
@@ -233,13 +222,13 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
setup->wIndex = 0;
setup->wLength = sizeof(rndis_keepalive_msg_t);
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
if (ret < 0) {
USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
return ret;
}
//ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
usbh_rndis_get_notification(rndis_class);
resp = (rndis_keepalive_cmplt_t *)g_rndis_buf;
@@ -249,7 +238,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
setup->wIndex = 0;
setup->wLength = 4096;
ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
if (ret < 0) {
USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
return ret;
@@ -260,7 +249,6 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
struct usb_endpoint_descriptor *ep_desc;
int ret;
uint32_t *oid_support_list;
@@ -270,11 +258,9 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
uint8_t tmp_buffer[512];
uint8_t data[32];
struct usbh_rndis *rndis_class = usbh_rndis_class_alloc();
if (rndis_class == NULL) {
USB_LOG_ERR("Fail to alloc rndis_class\r\n");
return -ENOMEM;
}
struct usbh_rndis *rndis_class = &g_rndis_class;
memset(rndis_class, 0, sizeof(struct usbh_rndis));
rndis_class->hport = hport;
rndis_class->ctrl_intf = intf;
@@ -283,17 +269,16 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
hport->config.intf[intf].priv = rndis_class;
hport->config.intf[intf + 1].priv = NULL;
#ifdef CONFIG_USBHOST_RNDIS_NOTIFY
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
usbh_hport_activate_epx(&rndis_class->intin, hport, ep_desc);
#endif
// ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
// USBH_EP_INIT(rndis_class->intin, ep_desc);
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_hport_activate_epx(&rndis_class->bulkin, hport, ep_desc);
USBH_EP_INIT(rndis_class->bulkin, ep_desc);
} else {
usbh_hport_activate_epx(&rndis_class->bulkout, hport, ep_desc);
USBH_EP_INIT(rndis_class->bulkout, ep_desc);
}
}
@@ -341,9 +326,9 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
goto query_errorout;
}
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
rndis_class->link_status = true;
rndis_class->connect_status = true;
} else {
rndis_class->link_status = false;
rndis_class->connect_status = false;
}
break;
case OID_802_3_MAXIMUM_LIST_SIZE:
@@ -389,7 +374,15 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
}
USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, rndis_class->minor);
USB_LOG_INFO("rndis MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
rndis_class->mac[0],
rndis_class->mac[1],
rndis_class->mac[2],
rndis_class->mac[3],
rndis_class->mac[4],
rndis_class->mac[5]);
memcpy(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);
@@ -407,24 +400,174 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (rndis_class) {
if (rndis_class->bulkin) {
usbh_pipe_free(rndis_class->bulkin);
usbh_kill_urb(&rndis_class->bulkin_urb);
}
if (rndis_class->bulkout) {
usbh_pipe_free(rndis_class->bulkout);
usbh_kill_urb(&rndis_class->bulkout_urb);
}
// if (rndis_class->intin) {
// usbh_kill_urb(&rndis_class->intin_urb);
// }
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
usbh_rndis_stop(rndis_class);
}
usbh_rndis_class_free(rndis_class);
memset(rndis_class, 0, sizeof(struct usbh_rndis));
}
return ret;
}
void usbh_rndis_rx_thread(void *argument)
{
uint32_t g_rndis_rx_length;
uint32_t pmg_offset;
int ret;
err_t err;
struct pbuf *p;
rndis_data_packet_t *pmsg;
rndis_data_packet_t temp;
#if LWIP_TCPIP_CORE_LOCKING_INPUT
pbuf_type type = PBUF_ROM;
#else
pbuf_type type = PBUF_POOL;
#endif
struct netif *netif = (struct netif *)argument;
USB_LOG_INFO("Create rndis rx thread\r\n");
// clang-format off
find_class:
// clang-format on
g_rndis_class.connect_status = false;
if (usbh_find_class_instance("/dev/rndis") == NULL) {
goto delete;
}
while (g_rndis_class.connect_status == false) {
ret = usbh_rndis_get_connect_status(&g_rndis_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
}
}
g_rndis_rx_length = 0;
while (1) {
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, (CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE > (16 * 1024)) ? (16 * 1024) : CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
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;
if (g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize)) {
pmg_offset = 0;
uint32_t total_len = g_rndis_rx_length;
while (g_rndis_rx_length > 0) {
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
/* Not word-aligned case */
if (pmg_offset & 0x3) {
memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
pmsg = &temp;
}
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, type);
if (p != NULL) {
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
#if LWIP_TCPIP_CORE_LOCKING_INPUT
p->payload = src;
#else
memcpy(p->payload, src, pmsg->DataLength);
#endif
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
pmg_offset += pmsg->MessageLength;
g_rndis_rx_length -= pmsg->MessageLength;
/* 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 {
g_rndis_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
}
} else {
USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
g_rndis_rx_length = 0;
USB_LOG_ERR("Error rndis packet message\r\n");
}
}
} else {
if (g_rndis_rx_length > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
USB_LOG_ERR("Rx packet is overflow\r\n");
g_rndis_rx_length = 0;
}
}
}
// clang-format off
delete:
USB_LOG_INFO("Delete rndis rx thread\r\n");
usb_osal_thread_delete(NULL);
// clang-format on
}
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
{
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;
}
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->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;
}
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)) {
len += 1;
}
USB_LOG_DBG("txlen:%d\r\n", len);
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
}
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
{
}
@@ -444,7 +587,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,36 +8,48 @@
#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 */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
struct usbh_urb intin_urb; /* INTR IN urb */
uint8_t ctrl_intf; /* Control interface number */
uint8_t data_intf; /* Data interface number */
uint8_t minor;
usbh_pipe_t bulkin; /* Bulk IN endpoint */
usbh_pipe_t bulkout; /* Bulk OUT endpoint */
usbh_pipe_t intin; /* Notify endpoint */
struct usbh_urb bulkin_urb; /* Bulk IN urb */
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
uint32_t request_id;
uint32_t link_speed;
bool link_status;
bool connect_status;
uint8_t mac[6];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
void *user_data;
};
#ifdef __cplusplus
extern "C" {
#endif
int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class);
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);
void usbh_rndis_rx_thread(void *argument);
#ifdef __cplusplus
}
#endif

View File

@@ -12,29 +12,17 @@
extern "C" {
#endif
/**
* @brief USB Endpoint Configuration.
*
* Structure containing the USB endpoint configuration.
*/
struct usbd_endpoint_cfg {
uint8_t ep_addr; /* Endpoint addr with direction */
uint8_t ep_type; /* Endpoint type */
uint16_t ep_mps; /* Endpoint max packet size */
uint8_t ep_mult; /* Endpoint additional transcations in micro frame */
};
/**
* @brief init device controller registers.
* @return On success will return 0, and others indicate fail.
*/
int usb_dc_init(void);
int usb_dc_init(uint8_t busid);
/**
* @brief deinit device controller registers.
* @return On success will return 0, and others indicate fail.
*/
int usb_dc_deinit(void);
int usb_dc_deinit(uint8_t busid);
/**
* @brief Set USB device address
@@ -43,16 +31,16 @@ int usb_dc_deinit(void);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_set_address(const uint8_t addr);
int usbd_set_address(uint8_t busid, const uint8_t addr);
/**
* @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(const uint8_t port);
uint8_t usbd_get_port_speed(uint8_t busid);
/**
* @brief configure and enable endpoint.
@@ -61,7 +49,7 @@ uint8_t usbd_get_port_speed(const uint8_t port);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep);
/**
* @brief Disable the selected endpoint
@@ -70,7 +58,7 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_close(const uint8_t ep);
int usbd_ep_close(uint8_t busid, const uint8_t ep);
/**
* @brief Set stall condition for the selected endpoint
@@ -80,7 +68,7 @@ int usbd_ep_close(const uint8_t ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_set_stall(const uint8_t ep);
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep);
/**
* @brief Clear stall condition for the selected endpoint
@@ -90,7 +78,7 @@ int usbd_ep_set_stall(const uint8_t ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_clear_stall(const uint8_t ep);
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep);
/**
* @brief Check if the selected endpoint is stalled
@@ -101,7 +89,7 @@ int usbd_ep_clear_stall(const uint8_t ep);
*
* @return On success will return 0, and others indicate fail.
*/
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled);
/**
* @brief Setup in ep transfer setting and start transfer.
@@ -120,7 +108,7 @@ int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
* be zero for a zero length status packet.
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len);
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len);
/**
* @brief Setup out ep transfer setting and start transfer.
@@ -139,40 +127,40 @@ int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len
*
* @return 0 on success, negative errno code on fail.
*/
int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len);
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len);
/* usb dcd irq callback */
/**
* @brief Usb connect irq callback.
*/
void usbd_event_connect_handler(void);
void usbd_event_connect_handler(uint8_t busid);
/**
* @brief Usb disconnect irq callback.
*/
void usbd_event_disconnect_handler(void);
void usbd_event_disconnect_handler(uint8_t busid);
/**
* @brief Usb resume irq callback.
*/
void usbd_event_resume_handler(void);
void usbd_event_resume_handler(uint8_t busid);
/**
* @brief Usb suspend irq callback.
*/
void usbd_event_suspend_handler(void);
void usbd_event_suspend_handler(uint8_t busid);
/**
* @brief Usb reset irq callback.
*/
void usbd_event_reset_handler(void);
void usbd_event_reset_handler(uint8_t busid);
/**
* @brief Usb setup packet recv irq callback.
* @param[in] psetup setup packet.
*/
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup);
/**
* @brief In ep transfer complete irq callback.
@@ -180,7 +168,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
* listed in the device configuration table
* @param[in] nbytes How many nbytes have transferred.
*/
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
void usbd_event_ep_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
/**
* @brief Out ep transfer complete irq callback.
@@ -188,7 +176,16 @@ void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
* listed in the device configuration table
* @param[in] nbytes How many nbytes have transferred.
*/
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes);
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
}

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)
@@ -221,6 +225,7 @@
#define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_GET_ENDPOINT_TYPE(x) ((x & USB_ENDPOINT_TYPE_MASK) >> USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_SYNC_SHIFT 2
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
@@ -245,6 +250,8 @@
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_GET_MAXPACKETSIZE(x) ((x & USB_MAXPACKETSIZE_MASK) >> USB_MAXPACKETSIZE_SHIFT)
#define USB_GET_MULT(x) ((x & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
/* bDevCapabilityType in Device Capability Descriptor */
#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1
@@ -535,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;
};
@@ -609,12 +616,12 @@ struct usb_webusb_url_descriptor {
struct usb_webusb_url_ex_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;
};
@@ -657,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

@@ -1,320 +1,24 @@
/*
* Apache NuttX
* Copyright 2020 The Apache Software Foundation
* Copyright (c) 2023, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __INCLUDE_ERRNO_H
#define __INCLUDE_ERRNO_H
#ifndef USB_ERRNO_H
#define USB_ERRNO_H
/****************************************************************************
* Included Files
****************************************************************************/
#define USB_ERR_NOMEM 1
#define USB_ERR_INVAL 2
#define USB_ERR_NODEV 3
#define USB_ERR_NOTCONN 4
#define USB_ERR_NOTSUPP 5
#define USB_ERR_BUSY 6
#define USB_ERR_RANGE 7
#define USB_ERR_STALL 8
#define USB_ERR_BABBLE 9
#define USB_ERR_NAK 10
#define USB_ERR_DT 11
#define USB_ERR_IO 12
#define USB_ERR_SHUTDOWN 13
#define USB_ERR_TIMEOUT 14
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Convenience/compatibility definition. If the errno is accessed from the
* internal OS code, then the OS code should use the set_errno() and
* get_errno(). Currently, those are just placeholders but would be needed
* in the KERNEL mode build in order to instantiate the process address
* environment as necessary to access the TLS-based errno variable.
*/
/* Definitions of error numbers and the string that would be
* returned by strerror().
*/
#ifndef CONFIG_USB_ERROR_USE_SYSTEM
#define EPERM 1
#define EPERM_STR "Operation not permitted"
#define ENOENT 2
#define ENOENT_STR "No such file or directory"
#define ESRCH 3
#define ESRCH_STR "No such process"
#define EINTR 4
#define EINTR_STR "Interrupted system call"
#define EIO 5
#define EIO_STR "I/O error"
#define ENXIO 6
#define ENXIO_STR "No such device or address"
#define E2BIG 7
#define E2BIG_STR "Arg list too long"
#define ENOEXEC 8
#define ENOEXEC_STR "Exec format error"
#define EBADF 9
#define EBADF_STR "Bad file number"
#define ECHILD 10
#define ECHILD_STR "No child processes"
#define EAGAIN 11
#define EWOULDBLOCK EAGAIN
#define EAGAIN_STR "Try again"
#define ENOMEM 12
#define ENOMEM_STR "Out of memory"
#define EACCES 13
#define EACCES_STR "Permission denied"
#define EFAULT 14 /* Linux errno extension */
#define EFAULT_STR "Bad address"
#define ENOTBLK 15
#define ENOTBLK_STR "Block device required"
#define EBUSY 16
#define EBUSY_STR "Device or resource busy"
#define EEXIST 17
#define EEXIST_STR "File exists"
#define EXDEV 18
#define EXDEV_STR "Cross-device link"
#define ENODEV 19
#define ENODEV_STR "No such device"
#define ENOTDIR 20
#define ENOTDIR_STR "Not a directory"
#define EISDIR 21
#define EISDIR_STR "Is a directory"
#define EINVAL 22
#define EINVAL_STR "Invalid argument"
#define ENFILE 23
#define ENFILE_STR "File table overflow"
#define EMFILE 24
#define EMFILE_STR "Too many open files"
#define ENOTTY 25
#define ENOTTY_STR "Not a typewriter"
#define ETXTBSY 26
#define ETXTBSY_STR "Text file busy"
#define EFBIG 27
#define EFBIG_STR "File too large"
#define ENOSPC 28
#define ENOSPC_STR "No space left on device"
#define ESPIPE 29
#define ESPIPE_STR "Illegal seek"
#define EROFS 30
#define EROFS_STR "Read-only file system"
#define EMLINK 31
#define EMLINK_STR "Too many links"
#define EPIPE 32
#define EPIPE_STR "Broken pipe"
#define EDOM 33
#define EDOM_STR "Math argument out of domain of func"
#define ERANGE 34
#define ERANGE_STR "Math result not representable"
#define ENOMSG 35
#define ENOMSG_STR "No message of desired type"
#define EIDRM 36
#define EIDRM_STR "Identifier removed"
#define ECHRNG 37 /* Linux errno extension */
#define ECHRNG_STR "Channel number out of range"
#define EL2NSYNC 38 /* Linux errno extension */
#define EL2NSYNC_STR "Level 2 not synchronized"
#define EL3HLT 39 /* Linux errno extension */
#define EL3HLT_STR "Level 3 halted"
#define EL3RST 40 /* Linux errno extension */
#define EL3RST_STR "Level 3 reset"
#define ELNRNG 41 /* Linux errno extension */
#define ELNRNG_STR "Link number out of range"
#define EUNATCH 42 /* Linux errno extension */
#define EUNATCH_STR "Protocol driver not attached"
#define ENOCSI 43 /* Linux errno extension */
#define ENOCSI_STR "No CSI structure available"
#define EL2HLT 44 /* Linux errno extension */
#define EL2HLT_STR "Level 2 halted"
#define EDEADLK 45
#define EDEADLK_STR "Resource deadlock would occur"
#define ENOLCK 46
#define ENOLCK_STR "No record locks available"
#define EBADE 50 /* Linux errno extension */
#define EBADE_STR "Invalid exchange"
#define EBADR 51 /* Linux errno extension */
#define EBADR_STR "Invalid request descriptor"
#define EXFULL 52 /* Linux errno extension */
#define EXFULL_STR "Exchange full"
#define ENOANO 53 /* Linux errno extension */
#define ENOANO_STR "No anode"
#define EBADRQC 54 /* Linux errno extension */
#define EBADRQC_STR "Invalid request code"
#define EBADSLT 55 /* Linux errno extension */
#define EBADSLT_STR "Invalid slot"
#define EDEADLOCK 56 /* Linux errno extension */
#define EDEADLOCK_STR "File locking deadlock error"
#define EBFONT 57 /* Linux errno extension */
#define EBFONT_STR "Bad font file format"
#define ENOSTR 60
#define ENOSTR_STR "Device not a stream"
#define ENODATA 61
#define ENODATA_STR "No data available"
#define ETIME 62
#define ETIME_STR "Timer expired"
#define ENOSR 63
#define ENOSR_STR "Out of streams resources"
#define ENONET 64 /* Linux errno extension */
#define ENONET_STR "Machine is not on the network"
#define ENOPKG 65 /* Linux errno extension */
#define ENOPKG_STR "Package not installed"
#define EREMOTE 66 /* Linux errno extension */
#define EREMOTE_STR "Object is remote"
#define ENOLINK 67
#define ENOLINK_STR "Link has been severed"
#define EADV 68 /* Linux errno extension */
#define EADV_STR "Advertise error"
#define ESRMNT 69 /* Linux errno extension */
#define ESRMNT_STR "Srmount error"
#define ECOMM 70 /* Linux errno extension */
#define ECOMM_STR "Communication error on send"
#define EPROTO 71
#define EPROTO_STR "Protocol error"
#define EMULTIHOP 74
#define EMULTIHOP_STR "Multihop attempted"
#define ELBIN 75 /* Linux errno extension */
#define ELBIN_STR "Inode is remote"
#define EDOTDOT 76 /* Linux errno extension */
#define EDOTDOT_STR "RFS specific error"
#define EBADMSG 77
#define EBADMSG_STR "Not a data message"
#define EFTYPE 79
#define EFTYPE_STR "Inappropriate file type or format"
#define ENOTUNIQ 80 /* Linux errno extension */
#define ENOTUNIQ_STR "Name not unique on network"
#define EBADFD 81 /* Linux errno extension */
#define EBADFD_STR "File descriptor in bad state"
#define EREMCHG 82 /* Linux errno extension */
#define EREMCHG_STR "Remote address changed"
#define ELIBACC 83 /* Linux errno extension */
#define ELIBACC_STR "Can not access a needed shared library"
#define ELIBBAD 84 /* Linux errno extension */
#define ELIBBAD_STR "Accessing a corrupted shared library"
#define ELIBSCN 85 /* Linux errno extension */
#define ELIBSCN_STR ".lib section in a.out corrupted"
#define ELIBMAX 86 /* Linux errno extension */
#define ELIBMAX_STR "Attempting to link in too many shared libraries"
#define ELIBEXEC 87 /* Linux errno extension */
#define ELIBEXEC_STR "Cannot exec a shared library directly"
#define ENOSYS 88
#define ENOSYS_STR "Function not implemented"
#define ENMFILE 89 /* Cygwin */
#define ENMFILE_STR "No more files"
#define ENOTEMPTY 90
#define ENOTEMPTY_STR "Directory not empty"
#define ENAMETOOLONG 91
#define ENAMETOOLONG_STR "File name too long"
#define ELOOP 92
#define ELOOP_STR "Too many symbolic links encountered"
#define EOPNOTSUPP 95
#define EOPNOTSUPP_STR "Operation not supported on transport endpoint"
#define EPFNOSUPPORT 96
#define EPFNOSUPPORT_STR "Protocol family not supported"
#define ECONNRESET 104
#define ECONNRESET_STR "Connection reset by peer"
#define ENOBUFS 105
#define ENOBUFS_STR "No buffer space available"
#define EAFNOSUPPORT 106
#define EAFNOSUPPORT_STR "Address family not supported by protocol"
#define EPROTOTYPE 107
#define EPROTOTYPE_STR "Protocol wrong type for socket"
#define ENOTSOCK 108
#define ENOTSOCK_STR "Socket operation on non-socket"
#define ENOPROTOOPT 109
#define ENOPROTOOPT_STR "Protocol not available"
#define ESHUTDOWN 110 /* Linux errno extension */
#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown"
#define ECONNREFUSED 111
#define ECONNREFUSED_STR "Connection refused"
#define EADDRINUSE 112
#define EADDRINUSE_STR "Address already in use"
#define ECONNABORTED 113
#define ECONNABORTED_STR "Software caused connection abort"
#define ENETUNREACH 114
#define ENETUNREACH_STR "Network is unreachable"
#define ENETDOWN 115
#define ENETDOWN_STR "Network is down"
#define ETIMEDOUT 116
#define ETIMEDOUT_STR "Connection timed out"
#define EHOSTDOWN 117
#define EHOSTDOWN_STR "Host is down"
#define EHOSTUNREACH 118
#define EHOSTUNREACH_STR "No route to host"
#define EINPROGRESS 119
#define EINPROGRESS_STR "Operation now in progress"
#define EALREADY 120
#define EALREADY_STR "Socket already connected"
#define EDESTADDRREQ 121
#define EDESTADDRREQ_STR "Destination address required"
#define EMSGSIZE 122
#define EMSGSIZE_STR "Message too long"
#define EPROTONOSUPPORT 123
#define EPROTONOSUPPORT_STR "Protocol not supported"
#define ESOCKTNOSUPPORT 124 /* Linux errno extension */
#define ESOCKTNOSUPPORT_STR "Socket type not supported"
#define EADDRNOTAVAIL 125
#define EADDRNOTAVAIL_STR "Cannot assign requested address"
#define ENETRESET 126
#define ENETRESET_STR "Network dropped connection because of reset"
#define EISCONN 127
#define EISCONN_STR "Transport endpoint is already connected"
#define ENOTCONN 128
#define ENOTCONN_STR "Transport endpoint is not connected"
#define ETOOMANYREFS 129
#define ETOOMANYREFS_STR "Too many references: cannot splice"
#define EPROCLIM 130
#define EPROCLIM_STR "Limit would be exceeded by attempted fork"
#define EUSERS 131
#define EUSERS_STR "Too many users"
#define EDQUOT 132
#define EDQUOT_STR "Quota exceeded"
#define ESTALE 133
#define ESTALE_STR "Stale NFS file handle"
#define ENOTSUP 134
#define ENOTSUP_STR "Not supported"
#define ENOMEDIUM 135 /* Linux errno extension */
#define ENOMEDIUM_STR "No medium found"
#define ENOSHARE 136 /* Cygwin */
#define ENOSHARE_STR "No such host or network path"
#define ECASECLASH 137 /* Cygwin */
#define ECASECLASH_STR "Filename exists with different case"
#define EILSEQ 138
#define EILSEQ_STR "Illegal byte sequence"
#define EOVERFLOW 139
#define EOVERFLOW_STR "Value too large for defined data type"
#define ECANCELED 140
#define ECANCELED_STR "Operation cancelled"
#define ENOTRECOVERABLE 141
#define ENOTRECOVERABLE_STR "State not recoverable"
#define EOWNERDEAD 142
#define EOWNERDEAD_STR "Previous owner died"
#define ESTRPIPE 143 /* Linux errno extension */
#define ESTRPIPE_STR "Streams pipe error"
#define __ELASTERROR 2000 /* Users can add values starting here */
#else
#include <errno.h>
#endif
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/* Return a pointer to the thread specific errno. */
int *__errno(void);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_ERRNO_H */
#endif /* USB_ERRNO_H */

View File

@@ -13,21 +13,8 @@ extern "C" {
#endif
typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
typedef void *usbh_pipe_t;
/**
* @brief USB Endpoint Configuration.
*
* Structure containing the USB endpoint configuration.
*/
struct usbh_endpoint_cfg {
struct usbh_hubport *hport;
uint8_t ep_addr; /* Endpoint addr with direction */
uint8_t ep_type; /* Endpoint type */
uint16_t ep_mps; /* Endpoint max packet size */
uint8_t ep_interval; /* Endpoint interval */
uint8_t mult; /* Endpoint additional transcation */
};
struct usbh_bus;
/**
* @brief USB Iso Configuration.
@@ -47,7 +34,11 @@ struct usbh_iso_frame_packet {
* Structure containing the USB Urb configuration.
*/
struct usbh_urb {
usbh_pipe_t pipe;
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;
@@ -59,7 +50,11 @@ struct usbh_urb {
uint32_t start_frame;
usbh_complete_callback_t complete;
void *arg;
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
struct usbh_iso_frame_packet *iso_packet;
#else
struct usbh_iso_frame_packet iso_packet[0];
#endif
};
/**
@@ -67,14 +62,21 @@ struct usbh_urb {
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_init(void);
int usb_hc_init(struct usbh_bus *bus);
/**
* @brief usb host controller hardware deinit.
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_deinit(struct usbh_bus *bus);
/**
* @brief Get frame number.
*
* @return frame number.
*/
uint16_t usbh_get_frame_number(void);
uint16_t usbh_get_frame_number(struct usbh_bus *bus);
/**
* @brief control roothub.
*
@@ -82,35 +84,7 @@ uint16_t usbh_get_frame_number(void);
* @param buf buf for reading response or write data.
* @return On success will return 0, and others indicate fail.
*/
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
/**
* @brief reconfig endpoint pipe.
*
* @param pipe A memory allocated for pipe.
* @param dev_addr device address.
* @param ep_mps endpoint max packet size.
* @param mult endpoint additional transcation
* @return On success will return 0, and others indicate fail.
*/
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult);
/**
* @brief Allocate pipe for endpoint
*
* @param pipe A memory location provided by the caller in which to save the allocated pipe.
* @param ep_cfg Describes the endpoint info to be allocated.
* @return On success will return 0, and others indicate fail.
*/
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
/**
* @brief Free a pipe in which saves endpoint info.
*
* @param pipe A memory location provided by the caller in which to free the allocated endpoint info.
* @return On success will return 0, and others indicate fail.
*/
int usbh_pipe_free(usbh_pipe_t pipe);
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf);
/**
* @brief Submit a usb transfer request to an endpoint.
@@ -126,7 +100,7 @@ int usbh_submit_urb(struct usbh_urb *urb);
/**
* @brief Cancel a transfer request.
*
* This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN.
* This function will call When calls usbh_submit_urb and return -USB_ERR_TIMEOUT or -USB_ERR_SHUTDOWN.
*
* @param urb Usb request block.
* @return On success will return 0, and others indicate fail.

View File

@@ -1,60 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_MEM_H
#define USB_MEM_H
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
#if (CONFIG_USB_ALIGN_SIZE > 4)
static inline void *usb_iomalloc(size_t size)
{
void *ptr;
void *align_ptr;
int uintptr_size;
size_t align_size;
uint32_t align = CONFIG_USB_ALIGN_SIZE;
/* sizeof pointer */
uintptr_size = sizeof(void *);
uintptr_size -= 1;
/* align the alignment size to uintptr size byte */
align = ((align + uintptr_size) & ~uintptr_size);
/* get total aligned size */
align_size = ((size + uintptr_size) & ~uintptr_size) + align;
/* allocate memory block from heap */
ptr = usb_malloc(align_size);
if (ptr != NULL) {
/* the allocated memory block is aligned */
if (((unsigned long)ptr & (align - 1)) == 0) {
align_ptr = (void *)((unsigned long)ptr + align);
} else {
align_ptr = (void *)(((unsigned long)ptr + (align - 1)) & ~(align - 1));
}
/* set the pointer before alignment pointer to the real pointer */
*((unsigned long *)((unsigned long)align_ptr - sizeof(void *))) = (unsigned long)ptr;
ptr = align_ptr;
}
return ptr;
}
static inline void usb_iofree(void *ptr)
{
void *real_ptr;
real_ptr = (void *)*(unsigned long *)((unsigned long)ptr - sizeof(void *));
usb_free(real_ptr);
}
#else
#define usb_iomalloc(size) usb_malloc(size)
#define usb_iofree(ptr) usb_free(ptr)
#endif
#endif /* USB_MEM_H */

View File

@@ -8,12 +8,23 @@
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
typedef void *usb_osal_thread_t;
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
@@ -25,6 +36,7 @@ usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
void usb_osal_sem_delete(usb_osal_sem_t sem);
int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
int usb_osal_sem_give(usb_osal_sem_t sem);
void usb_osal_sem_reset(usb_osal_sem_t sem);
usb_osal_mutex_t usb_osal_mutex_create(void);
void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
@@ -32,9 +44,15 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex);
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs);
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);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, sakumisu
* Copyright (c) 2022-2023, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -44,9 +44,9 @@
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#elif defined(__ICCARM__) || defined(__ICCRX__)
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
#ifndef __USED
#if __ICCARM_V8
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __USED __attribute__((used))
#else
#define __USED __root
@@ -54,7 +54,7 @@
#endif
#ifndef __WEAK
#if __ICCARM_V8
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __WEAK __attribute__((weak))
#else
#define __WEAK _Pragma("__weak")
@@ -62,7 +62,7 @@
#endif
#ifndef __PACKED
#if __ICCARM_V8
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __PACKED __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
@@ -71,7 +71,7 @@
#endif
#ifndef __PACKED_STRUCT
#if __ICCARM_V8
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
@@ -80,7 +80,7 @@
#endif
#ifndef __PACKED_UNION
#if __ICCARM_V8
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
@@ -89,7 +89,7 @@
#endif
#ifndef __ALIGNED
#if __ICCARM_V8
#if defined(__ICCARM_V8) || defined(__ICCRISCV__)
#define __ALIGNED(x) __attribute__((aligned(x)))
#elif (__VER__ >= 7080000)
/* Needs IAR language extensions */
@@ -203,4 +203,8 @@
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
#define USB_ALIGN_UP(size, align) (((size) + (align)-1) & ~((align)-1))
#endif /* USB_UTIL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,6 @@ extern "C" {
#include "usb_errno.h"
#include "usb_def.h"
#include "usb_list.h"
#include "usb_mem.h"
#include "usb_log.h"
#include "usb_dc.h"
@@ -39,12 +38,14 @@ enum usbd_event_type {
USBD_EVENT_SET_INTERFACE, /** USB interface selected */
USBD_EVENT_SET_REMOTE_WAKEUP, /** USB set remote wakeup */
USBD_EVENT_CLR_REMOTE_WAKEUP, /** USB clear remote wakeup */
USBD_EVENT_INIT, /** USB init done when call usbd_initialize */
USBD_EVENT_DEINIT, /** USB deinit done when call usbd_deinitialize */
USBD_EVENT_UNKNOWN
};
typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
typedef int (*usbd_request_handler)(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
typedef void (*usbd_endpoint_callback)(uint8_t busid, uint8_t ep, uint32_t nbytes);
typedef void (*usbd_notify_handler)(uint8_t busid, uint8_t event, void *arg);
struct usbd_endpoint {
uint8_t ep_addr;
@@ -62,36 +63,46 @@ struct usbd_interface {
};
struct usb_descriptor {
const uint8_t *device_descriptor;
const uint8_t *fs_config_descriptor;
const uint8_t *hs_config_descriptor;
const uint8_t *device_quality_descriptor;
const uint8_t *fs_other_speed_descriptor;
const uint8_t *hs_other_speed_descriptor;
const char **string_descriptor;
struct usb_msosv1_descriptor *msosv1_descriptor;
struct usb_msosv2_descriptor *msosv2_descriptor;
struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
struct usb_bos_descriptor *bos_descriptor;
const uint8_t *(*device_descriptor_callback)(uint8_t speed);
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 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_bos_descriptor *bos_descriptor;
};
#ifdef CONFIG_USBDEV_ADVANCE_DESC
void usbd_desc_register(struct usb_descriptor *desc);
#else
void usbd_desc_register(const uint8_t *desc);
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc);
void usbd_bos_desc_register(struct usb_bos_descriptor *desc);
struct usbd_bus {
uint8_t busid;
uint32_t reg_base;
};
extern struct usbd_bus g_usbdev_bus[];
#ifdef USBD_IRQHandler
#error USBD_IRQHandler is obsolete, please call USBD_IRQHandler(xxx) in your irq
#endif
void usbd_add_interface(struct usbd_interface *intf);
void usbd_add_endpoint(struct usbd_endpoint *ep);
#ifdef CONFIG_USBDEV_ADVANCE_DESC
void usbd_desc_register(uint8_t busid, const struct usb_descriptor *desc);
#else
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);
#endif
bool usb_device_is_configured(void);
int usbd_initialize(void);
int usbd_deinitialize(void);
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
void usbd_event_handler(uint8_t event);
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));
int usbd_deinitialize(uint8_t busid);
#ifdef __cplusplus
}

View File

@@ -4,13 +4,20 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
#undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_core"
#include "usb_log.h"
struct usbh_class_info *usbh_class_info_table_begin = NULL;
struct usbh_class_info *usbh_class_info_table_end = NULL;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
usb_slist_t g_bus_head = USB_SLIST_OBJECT_INIT(g_bus_head);
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(CONFIG_USBHOST_REQUEST_BUFFER_LEN, CONFIG_USB_ALIGN_SIZE)];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup_buffer[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
@@ -20,22 +27,6 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_US
#define USB_DEV_ADDR_MARK_OFFSET 5
#define USB_DEV_ADDR_MARK_MASK 0x1f
struct usbh_devaddr_map {
/**
* alloctab[0]:addr from 0~31
* alloctab[1]:addr from 32~63
* alloctab[2]:addr from 64~95
* alloctab[3]:addr from 96~127
*
*/
uint8_t next; /* Next device address */
uint32_t alloctab[4]; /* Bit allocation table */
};
struct usbh_bus {
struct usbh_devaddr_map devgen;
} g_usbh_bus;
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
{
uint8_t startaddr = devgen->next;
@@ -59,12 +50,12 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
}
if (startaddr == devaddr) {
return -ENOMEM;
return -USB_ERR_NOMEM;
}
}
}
static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
{
int index;
int bitno;
@@ -88,37 +79,44 @@ static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
return 0;
}
static int usbh_free_devaddr(struct usbh_hubport *hport)
{
#ifndef CONFIG_USBHOST_XHCI
if (hport->dev_addr > 0) {
__usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
}
#endif
hport->dev_addr = 0;
return 0;
}
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;
}
@@ -127,10 +125,10 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device
{
if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -EINVAL;
return -USB_ERR_INVAL;
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) {
USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
return -EINVAL;
return -USB_ERR_INVAL;
} else {
if (length <= 8) {
return 0;
@@ -183,10 +181,10 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
return -EINVAL;
return -USB_ERR_INVAL;
} else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
return -EINVAL;
return -USB_ERR_INVAL;
} else {
if (length <= USB_SIZEOF_CONFIG_DESC) {
return 0;
@@ -228,15 +226,18 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
cur_ep = 0;
if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
USB_LOG_ERR("Interface num overflow\r\n");
return -ENOMEM;
while (1) {
}
}
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
USB_LOG_ERR("Interface altsetting num overflow\r\n");
return -ENOMEM;
while (1) {
}
}
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
USB_LOG_ERR("Endpoint num overflow\r\n");
return -ENOMEM;
while (1) {
}
}
#if 0
USB_LOG_DBG("Interface Descriptor:\r\n");
@@ -270,23 +271,6 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
return 0;
}
#ifdef CONFIG_USBHOST_GET_STRING_DESC
void usbh_print_string(char *lead, uint8_t *str)
{
uint8_t string[64 + 1] = { 0 };
int len, i = 2, j = 0;
len = str[0];
while (i < len) {
string[j] = str[i];
i += 2;
j++;
}
USB_LOG_RAW("%s%s\r\n", lead, string);
}
#endif
static void usbh_print_hubport_info(struct usbh_hubport *hport)
{
USB_LOG_RAW("Device Descriptor:\r\n");
@@ -317,25 +301,25 @@ static void usbh_print_hubport_info(struct usbh_hubport *hport)
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
USB_LOG_RAW("Interface Descriptor:\r\n");
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
USB_LOG_RAW("bInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
USB_LOG_RAW("bAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
USB_LOG_RAW("bNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
USB_LOG_RAW("bInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
USB_LOG_RAW("bInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
USB_LOG_RAW("bInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
USB_LOG_RAW("iInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
USB_LOG_RAW("\tInterface Descriptor:\r\n");
USB_LOG_RAW("\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
USB_LOG_RAW("\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
USB_LOG_RAW("\tbInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
USB_LOG_RAW("\tbAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
USB_LOG_RAW("\tbNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
USB_LOG_RAW("\tbInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
USB_LOG_RAW("\tiInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
USB_LOG_RAW("Endpoint Descriptor:\r\n");
USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
USB_LOG_RAW("bEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
USB_LOG_RAW("wMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
USB_LOG_RAW("bInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
USB_LOG_RAW("\t\tbLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
USB_LOG_RAW("\t\tbDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
USB_LOG_RAW("\t\tbmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
USB_LOG_RAW("\t\tbInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
}
}
}
@@ -357,68 +341,32 @@ static int usbh_get_default_mps(int speed)
}
}
int usbh_hport_activate_ep0(struct usbh_hubport *hport)
{
struct usbh_endpoint_cfg ep0_cfg = { 0 };
ep0_cfg.ep_addr = 0x00;
ep0_cfg.ep_interval = 0x00;
ep0_cfg.ep_mps = usbh_get_default_mps(hport->speed);
ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL;
ep0_cfg.hport = hport;
usbh_pipe_alloc(&hport->ep0, &ep0_cfg);
return 0;
}
int usbh_hport_deactivate_ep0(struct usbh_hubport *hport)
{
#ifndef CONFIG_USBHOST_XHCI
if (hport->dev_addr > 0) {
usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
}
#endif
if (hport->ep0) {
usbh_pipe_free(hport->ep0);
}
hport->ep0 = NULL;
hport->dev_addr = 0;
return 0;
}
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
ep_cfg.ep_addr = ep_desc->bEndpointAddress;
ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
ep_cfg.ep_interval = ep_desc->bInterval;
ep_cfg.mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
ep_cfg.hport = hport;
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
ep_cfg.ep_addr,
ep_desc->bmAttributes,
ep_cfg.ep_mps,
ep_cfg.ep_interval,
ep_cfg.mult);
return usbh_pipe_alloc(pipe, &ep_cfg);
}
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;
uint8_t config_value;
uint8_t config_index;
int ret;
hport->setup = &g_setup[hport->parent->index - 1][hport->port - 1];
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;
@@ -427,16 +375,16 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = 8;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
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, 8);
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;
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 {
@@ -448,7 +396,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
dev_desc->bDeviceProtocol, ep_mps);
/* Reconfigure EP0 with the correct maximum packet size */
usbh_ep_pipe_reconfigure(hport->ep0, 0, ep_mps, 0);
ep->wMaxPacketSize = ep_mps;
#ifdef CONFIG_USBHOST_XHCI
extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe);
@@ -461,7 +409,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
}
#else
/* Assign a function address to the device connected to this port */
dev_addr = usbh_allocate_devaddr(&g_usbh_bus.devgen);
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;
@@ -475,7 +423,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport->ep0, setup, NULL);
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
goto errout;
@@ -484,12 +432,9 @@ int usbh_enumerate(struct usbh_hubport *hport)
/* Wait device set address completely */
usb_osal_msleep(2);
/* Assign the function address to the port */
/*Reconfigure EP0 with the correct address */
hport->dev_addr = dev_addr;
/* And reconfigure EP0 with the correct address */
usbh_ep_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, 0);
/* Read the full device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
@@ -497,120 +442,133 @@ int usbh_enumerate(struct usbh_hubport *hport)
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_DEVICE_DESC;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
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, USB_SIZEOF_DEVICE_DESC);
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)->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer)->idProduct,
((struct usb_device_descriptor *)ep0_request_buffer)->bcdDevice);
((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) | 0);
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->ep0, setup, ep0_request_buffer);
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);
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)->wTotalLength;
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) | 0);
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
setup->wIndex = 0;
setup->wLength = wTotalLength;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
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, wTotalLength);
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)->bNumInterfaces);
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 = -ENOMEM;
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
/* Get Manufacturer string */
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_STRING << 8) | USB_STRING_MFC_INDEX);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
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;
}
usbh_print_string("Manufacturer: ", ep0_request_buffer);
USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
/* Get Product string */
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_STRING << 8) | USB_STRING_PRODUCT_INDEX);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
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;
}
usbh_print_string("Product: ", ep0_request_buffer);
USB_LOG_INFO("Product: %s\r\n", string_buffer);
/* Get SerialNumber string */
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_STRING << 8) | USB_STRING_SERIAL_INDEX);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
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;
}
usbh_print_string("SerialNumber: ", ep0_request_buffer);
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->wValue = config_value;
setup->wIndex = 0;
setup->wLength = 0;
ret = usbh_control_transfer(hport->ep0, setup, NULL);
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 != -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++) {
@@ -639,49 +597,66 @@ errout:
return ret;
}
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr)
void usbh_hubport_release(struct usbh_hubport *hport)
{
struct usbh_hubport *hport;
usb_slist_t *hub_list;
usb_slist_for_each(hub_list, &hub_class_head)
{
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) {
if (hport->dev_addr == dev_addr) {
return &hub->child[port];
}
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);
}
}
}
return NULL;
}
void *usbh_find_class_instance(const char *devname)
{
struct usbh_hubport *hport;
usb_slist_t *hub_list;
usb_slist_for_each(hub_list, &hub_class_head)
{
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;
}
}
hport->config.config_desc.bNumInterfaces = 0;
usbh_kill_urb(&hport->ep0_urb);
if (hport->mutex) {
usb_osal_mutex_delete(hport->mutex);
}
}
return NULL;
}
int usbh_initialize(void)
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
{
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
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;
@@ -693,39 +668,125 @@ int usbh_initialize(void)
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__)
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");
#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
/* devaddr 1 is for roothub */
g_usbh_bus.devgen.next = 2;
usbh_hub_initialize();
usbh_hub_initialize(bus);
return 0;
}
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer)
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 = usb_malloc(sizeof(struct usbh_urb));
memset(urb, 0, sizeof(struct usbh_urb));
urb = &hport->ep0_urb;
usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
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_free(urb);
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;
int ret;
uint8_t *src;
uint8_t *dst;
uint16_t len;
uint16_t i = 2;
uint16_t j = 0;
/* Get Manufacturer string */
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_STRING << 8) | index);
setup->wIndex = 0x0409;
setup->wLength = 255;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
return ret;
}
src = ep0_request_buffer[hport->bus->busid];
dst = output;
len = src[0];
while (i < len) {
dst[j] = src[i];
i += 2;
j++;
}
return 0;
}
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting)
{
struct usb_setup_packet *setup = hport->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = USB_REQUEST_SET_INTERFACE;
setup->wValue = altsetting;
setup->wIndex = intf;
setup->wLength = 0;
return usbh_control_transfer(hport, setup, NULL);
}
void *usbh_find_class_instance(const char *devname)
{
struct usbh_hubport *hport;
usb_slist_t *hub_list;
usb_slist_t *bus_list;
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;
}
}
}
}
}
return NULL;
}
int lsusb(int argc, char **argv)
{
usb_slist_t *i;
usb_slist_t *hub_list;
usb_slist_t *bus_list;
struct usbh_hubport *hport;
if (argc < 2) {
@@ -750,30 +811,38 @@ int lsusb(int argc, char **argv)
}
if (strcmp(argv[1], "-t") == 0) {
usb_slist_for_each(i, &hub_class_head)
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
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);
if (hub->is_roothub) {
USB_LOG_RAW("/: Hub %02u, ports=%u, is roothub\r\n", hub->index, hub->hub_desc.bNbrPorts);
} else {
USB_LOG_RAW("/: Hub %02u, ports=%u, mounted on Hub %02u:Port %u\r\n",
hub->index,
hub->hub_desc.bNbrPorts,
hub->parent->parent->index,
hub->parent->port);
}
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(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
i,
hport->config.intf[i].class_driver->driver_name);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->driver_name) {
USB_LOG_RAW("\t|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
i,
hport->config.intf[i].class_driver->driver_name);
}
}
}
}
@@ -782,19 +851,24 @@ int lsusb(int argc, char **argv)
}
if (strcmp(argv[1], "-v") == 0) {
usb_slist_for_each(i, &hub_class_head)
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_hub *hub = usb_slist_entry(i, 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("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n",
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
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);
}
}
}
}

View File

@@ -16,11 +16,10 @@
#include "usb_errno.h"
#include "usb_def.h"
#include "usb_list.h"
#include "usb_mem.h"
#include "usb_log.h"
#include "usb_hc.h"
#include "usb_osal.h"
#include "usb_hub.h"
#include "usbh_hub.h"
#ifdef __cplusplus
extern "C" {
@@ -31,6 +30,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,70 +39,30 @@ extern "C" {
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__GNUC__)
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#elif defined(__ICCARM__) || defined(__ICCRX__)
#pragma section = "usbh_class_info"
#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)
#endif
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
usbh_pipe_t pipe,
struct usb_setup_packet *setup,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->pipe = pipe;
urb->setup = setup;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? interval : (1 << (interval - 1)))
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
usbh_pipe_t pipe,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->pipe = pipe;
urb->setup = NULL;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
usbh_pipe_t pipe,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->pipe = pipe;
urb->setup = NULL;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
#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), \
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \
ep_desc->bInterval, \
USB_GET_MULT(ep_desc->bmAttributes)); \
} 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;
};
@@ -140,7 +100,6 @@ struct usbh_hubport {
uint8_t port; /* Hub port index */
uint8_t dev_addr; /* device address */
uint8_t speed; /* device speed */
usbh_pipe_t ep0; /* control ep pipe info */
struct usb_device_descriptor device_desc;
struct usbh_configuration config;
const char *iManufacturer;
@@ -149,10 +108,13 @@ struct usbh_hubport {
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
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
usb_osal_thread_t thread;
struct usb_endpoint_descriptor ep0;
struct usbh_urb ep0_urb;
usb_osal_mutex_t mutex;
};
struct usbh_hub {
@@ -161,15 +123,107 @@ struct usbh_hub {
bool is_roothub;
uint8_t index;
uint8_t hub_addr;
usbh_pipe_t intin;
uint8_t *int_buffer;
struct usbh_urb intin_urb;
struct usb_hub_descriptor hub_desc;
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;
};
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
struct usbh_devaddr_map {
/**
* alloctab[0]:addr from 0~31
* alloctab[1]:addr from 32~63
* alloctab[2]:addr from 64~95
* alloctab[3]:addr from 96~127
*
*/
uint8_t next; /* Next device address */
uint32_t alloctab[4]; /* Bit allocation table */
};
struct usbh_hcd {
uint32_t reg_base;
uint8_t hcd_id;
uint8_t roothub_intbuf[1];
struct usbh_hub roothub;
};
struct usbh_bus {
usb_slist_t list;
uint8_t busid;
struct usbh_hcd hcd;
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,
struct usbh_hubport *hport,
struct usb_setup_packet *setup,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->hport = hport;
urb->ep = &hport->ep0;
urb->setup = setup;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
struct usbh_hubport *hport,
struct usb_endpoint_descriptor *ep,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->hport = hport;
urb->ep = ep;
urb->setup = NULL;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
urb->timeout = timeout;
urb->complete = complete;
urb->arg = arg;
}
static inline void usbh_int_urb_fill(struct usbh_urb *urb,
struct usbh_hubport *hport,
struct usb_endpoint_descriptor *ep,
uint8_t *transfer_buffer,
uint32_t transfer_buffer_length,
uint32_t timeout,
usbh_complete_callback_t complete,
void *arg)
{
urb->hport = hport;
urb->ep = ep;
urb->setup = NULL;
urb->transfer_buffer = transfer_buffer;
urb->transfer_buffer_length = transfer_buffer_length;
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[];
#ifdef USBH_IRQHandler
#error USBH_IRQHandler is obsolete, please call USBH_IRQHandler(xxx) in your irq
#endif
/**
* @brief Submit an control transfer to an endpoint.
@@ -181,10 +235,38 @@ int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struc
* @param buffer buffer used for sending the request and for returning any responses.
* @return On success will return 0, and others indicate fail.
*/
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer);
int usbh_initialize(void);
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
/**
* @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.
* @return On success will return 0, and others indicate fail.
*/
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output);
/**
* @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.
* @return On success will return 0, and others indicate fail.
*/
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_deinitialize(uint8_t busid);
void *usbh_find_class_instance(const char *devname);
int lsusb(int argc, char **argv);

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -148,7 +153,7 @@ const uint8_t audio_v1_descriptor[] = {
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -173,19 +178,21 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
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 intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
ep_tx_busy_flag = false;
tx_flag = 0;
}
void usbd_audio_iso_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
ep_tx_busy_flag = false;
@@ -205,25 +212,25 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v1_init(uint8_t busid)
void audio_v1_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v1_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(&audio_in_ep);
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
void audio_test()
void audio_test(uint8_t busid)
{
while (1) {
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -147,7 +152,7 @@ volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -172,23 +177,25 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
printf("OPEN1\r\n");
} else {
tx_flag = 1;
ep_tx_busy_flag = false;
printf("OPEN2\r\n");
}
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
ep_tx_busy_flag = false;
printf("CLOSE1\r\n");
} else {
tx_flag = 0;
@@ -196,13 +203,13 @@ void usbd_audio_close(uint8_t intf)
}
}
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
ep_tx_busy_flag = false;
@@ -231,24 +238,24 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_OUT_EP },
};
void audio_v1_init(void)
void audio_v1_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v1_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0100, audio_entity_table, 2));
usbd_add_endpoint(&audio_in_ep);
usbd_add_endpoint(&audio_out_ep);
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_add_endpoint(busid, &audio_out_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v1_test(void)
void audio_v1_test(uint8_t busid)
{
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -159,7 +164,7 @@ static const uint8_t mic_default_sampling_freq_table[] = {
volatile bool tx_flag = 0;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -184,26 +189,26 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
tx_flag = 1;
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
tx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_IN_EP) {
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
}
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
@@ -224,17 +229,17 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v2_init(void)
void audio_v2_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(&audio_in_ep);
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v2_test(void)
void audio_v2_test(uint8_t busid)
{
if (tx_flag) {
}

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -229,7 +234,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -254,12 +259,12 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN1\r\n");
} else {
tx_flag = 1;
@@ -267,7 +272,7 @@ void usbd_audio_open(uint8_t intf)
}
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
@@ -278,7 +283,7 @@ void usbd_audio_close(uint8_t intf)
}
}
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
@@ -288,7 +293,7 @@ void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_tabl
}
}
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
uint16_t packet_size = 0;
if (ep == AUDIO_OUT_EP) {
@@ -302,13 +307,13 @@ void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
}
}
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
@@ -341,19 +346,19 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_IN_EP },
};
void audio_v2_init(void)
void audio_v2_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 4));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 4));
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0200, audio_entity_table, 4));
usbd_add_endpoint(&audio_in_ep);
usbd_add_endpoint(&audio_out_ep);
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 4));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0200, audio_entity_table, 4));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_add_endpoint(busid, &audio_out_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v2_test(void)
void audio_v2_test(uint8_t busid)
{
if (tx_flag) {
}

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_audio.h"
@@ -173,7 +178,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
volatile bool rx_flag = 0;
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -198,31 +203,31 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_audio_open(uint8_t intf)
void usbd_audio_open(uint8_t busid, uint8_t intf)
{
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
void usbd_audio_close(uint8_t busid, uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
rx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
}
}
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
static struct usbd_endpoint audio_out_ep = {
@@ -242,17 +247,17 @@ struct audio_entity_info audio_entity_table[] = {
.ep = AUDIO_OUT_EP },
};
void audio_v2_init(void)
void audio_v2_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(&audio_out_ep);
usbd_desc_register(busid, audio_v2_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(busid, &audio_out_ep);
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void audio_v2_test(void)
void audio_v2_test(uint8_t busid)
{
if (rx_flag) {
}

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_msc.h"
#include "usbd_cdc.h"
@@ -216,7 +221,7 @@ static struct hid_mouse mouse_cfg;
static volatile uint8_t hid_state = HID_STATE_IDLE;
/* function ------------------------------------------------------------------*/
static void usbd_hid_int_callback(uint8_t ep, uint32_t nbytes)
static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
hid_state = HID_STATE_IDLE;
}
@@ -228,17 +233,11 @@ 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
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -252,8 +251,10 @@ void usbd_event_handler(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(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -265,20 +266,20 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
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(CDC_IN_EP, NULL, 0);
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -300,19 +301,19 @@ struct usbd_interface intf1;
struct usbd_interface intf2;
struct usbd_interface intf3;
void cdc_acm_hid_msc_descriptor_init(void)
void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(cdc_acm_hid_msc_descriptor);
usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_add_interface(usbd_hid_init_intf(&intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(&hid_in_ep);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &hid_in_ep);
/*!< init mouse report data */
mouse_cfg.buttons = 0;
@@ -320,7 +321,7 @@ void cdc_acm_hid_msc_descriptor_init(void)
mouse_cfg.x = 0;
mouse_cfg.y = 0;
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
/**
@@ -329,12 +330,12 @@ void cdc_acm_hid_msc_descriptor_init(void)
* @param[in] none
* @retval none
*/
void hid_mouse_test(void)
void hid_mouse_test(uint8_t busid)
{
/*!< move mouse pointer */
mouse_cfg.x += 10;
mouse_cfg.y = 0;
int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
if (ret < 0) {
return;
}
@@ -345,7 +346,7 @@ void hid_mouse_test(void)
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
@@ -354,12 +355,12 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
}
}
void cdc_acm_data_send_with_dtr_test(void)
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
memset(&write_buffer[10], 'a', 2038);
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
@@ -375,19 +376,19 @@ typedef struct
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_msc.h"
@@ -30,6 +35,70 @@
#define MSC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x40,
0x01,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC MSC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_msc_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_msc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
@@ -109,19 +178,14 @@ static const uint8_t cdc_msc_descriptor[] = {
#endif
0x00
};
#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
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -135,8 +199,9 @@ void usbd_event_handler(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(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -148,20 +213,20 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
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(CDC_IN_EP, NULL, 0);
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -182,21 +247,25 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void cdc_acm_msc_init(void)
void cdc_acm_msc_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(cdc_msc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_msc_descriptor);
#else
usbd_desc_register(busid, cdc_msc_descriptor);
#endif
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize();
usbd_initialize(busid, reg_base, usbd_event_handler);
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
@@ -205,12 +274,12 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
}
}
void cdc_acm_data_send_with_dtr_test(void)
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
memset(&write_buffer[10], 'a', 2038);
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
@@ -226,19 +295,19 @@ typedef struct
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc.h"
@@ -115,17 +120,11 @@ 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
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -139,11 +138,12 @@ void usbd_event_handler(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(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(CDC_OUT_EP2, read_buffer, 2048);
usbd_ep_start_read(CDC_OUT_EP3, read_buffer, 2048);
usbd_ep_start_read(CDC_OUT_EP4, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP2, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP3, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP4, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -155,14 +155,14 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
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);
@@ -223,29 +223,29 @@ struct usbd_interface intf5;
struct usbd_interface intf6;
struct usbd_interface intf7;
void cdc_acm_multi_init(void)
void cdc_acm_multi_init(uint8_t busid, uint32_t reg_base)
{
usbd_desc_register(cdc_descriptor);
usbd_desc_register(busid, cdc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep1);
usbd_add_endpoint(&cdc_in_ep1);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep1);
usbd_add_endpoint(busid, &cdc_in_ep1);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf3));
usbd_add_endpoint(&cdc_out_ep2);
usbd_add_endpoint(&cdc_in_ep2);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf3));
usbd_add_endpoint(busid, &cdc_out_ep2);
usbd_add_endpoint(busid, &cdc_in_ep2);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf4));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf5));
usbd_add_endpoint(&cdc_out_ep3);
usbd_add_endpoint(&cdc_in_ep3);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf4));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf5));
usbd_add_endpoint(busid, &cdc_out_ep3);
usbd_add_endpoint(busid, &cdc_in_ep3);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf6));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf7));
usbd_add_endpoint(&cdc_out_ep4);
usbd_add_endpoint(&cdc_in_ep4);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf6));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf7));
usbd_add_endpoint(busid, &cdc_out_ep4);
usbd_add_endpoint(busid, &cdc_in_ep4);
usbd_initialize();
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_cdc.h"
@@ -99,18 +104,12 @@ 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
void usbd_event_handler(uint8_t event)
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
@@ -124,8 +123,9 @@ void usbd_event_handler(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(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -137,7 +137,7 @@ void usbd_event_handler(uint8_t event)
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
// for (int i = 0; i < 100; i++) {
@@ -145,16 +145,16 @@ void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
// }
// printf("\r\n");
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
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(CDC_IN_EP, NULL, 0);
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
@@ -171,27 +171,27 @@ struct usbd_endpoint cdc_in_ep = {
.ep_cb = usbd_cdc_acm_bulk_in
};
struct usbd_interface intf0;
struct usbd_interface intf1;
static struct usbd_interface intf0;
static struct usbd_interface intf1;
void cdc_acm_init(void)
void cdc_acm_init(uint8_t busid, uint32_t reg_base)
{
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
memcpy(&write_buffer[0], data, 10);
memset(&write_buffer[10], 'a', 2038);
usbd_desc_register(cdc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_initialize();
usbd_desc_register(busid, cdc_descriptor);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
@@ -200,11 +200,11 @@ void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
}
}
void cdc_acm_data_send_with_dtr_test(void)
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
{
if (dtr_enable) {
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}

279
demo/cdc_ecm_template.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_ecm.h"
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
#define CDC_INT_EP 0x83
#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 + CDC_ECM_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#define CDC_ECM_ETH_STATISTICS_BITMAP 0x00000000
/* str idx = 4 is for mac address: aa:bb:cc:dd:ee:ff*/
#define CDC_ECM_MAC_STRING_INDEX 4
/*!< global descriptor */
static const uint8_t cdc_ecm_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ECM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, CDC_ECM_ETH_STATISTICS_BITMAP, CONFIG_CDC_ECM_ETH_MAX_SEGSZE, 0, 0, CDC_ECM_MAC_STRING_INDEX),
///////////////////////////////////////
/// 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
///////////////////////////////////////
0x2E, /* 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 */
'D', 0x00, /* wcChar11 */
'C', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'E', 0x00, /* wcChar14 */
'C', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
' ', 0x00, /* wcChar17 */
'D', 0x00, /* wcChar18 */
'E', 0x00, /* wcChar19 */
'M', 0x00, /* wcChar20 */
'O', 0x00, /* wcChar21 */
///////////////////////////////////////
/// 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 */
///////////////////////////////////////
/// string4 descriptor
///////////////////////////////////////
0x1A, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'a', 0x00, /* wcChar0 */
'a', 0x00, /* wcChar1 */
'b', 0x00, /* wcChar2 */
'b', 0x00, /* wcChar3 */
'c', 0x00, /* wcChar4 */
'c', 0x00, /* wcChar5 */
'd', 0x00, /* wcChar6 */
'd', 0x00, /* wcChar7 */
'e', 0x00, /* wcChar8 */
'e', 0x00, /* wcChar9 */
'f', 0x00, /* wcChar10 */
'f', 0x00, /* wcChar11 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x40,
0x01,
0x00,
#endif
0x00
};
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
#define IP_ADDR0 (uint8_t)192
#define IP_ADDR1 (uint8_t)168
#define IP_ADDR2 (uint8_t)123
#define IP_ADDR3 (uint8_t)100
/*NETMASK*/
#define NETMASK_ADDR0 (uint8_t)255
#define NETMASK_ADDR1 (uint8_t)255
#define NETMASK_ADDR2 (uint8_t)255
#define NETMASK_ADDR3 (uint8_t)0
/*Gateway Address*/
#define GW_ADDR0 (uint8_t)192
#define GW_ADDR1 (uint8_t)168
#define GW_ADDR2 (uint8_t)123
#define GW_ADDR3 (uint8_t)1
#include "netif/etharp.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
static struct netif cdc_ecm_netif; //network interface
/* Network interface name */
#define IFNAME0 'E'
#define IFNAME1 'X'
static err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
{
static int ret;
ret = usbd_cdc_ecm_eth_tx(p);
if (ret == 0)
return ERR_OK;
else
return ERR_BUF;
}
err_t cdc_ecm_if_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
netif->state = NULL;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = etharp_output;
netif->linkoutput = linkoutput_fn;
return ERR_OK;
}
err_t cdc_ecm_if_input(struct netif *netif)
{
static err_t err;
static struct pbuf *p;
p = usbd_cdc_ecm_eth_rx();
if (p != NULL) {
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
return ERR_BUF;
}
return err;
}
void cdc_ecm_lwip_init(void)
{
struct netif *netif = &cdc_ecm_netif;
lwip_init();
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, mac, 6);
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, cdc_ecm_if_init, netif_input);
netif_set_default(netif);
while (!netif_is_up(netif)) {
}
// while (dhserv_init(&dhcp_config)) {}
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
}
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
{
}
void cdc_ecm_input_poll(void)
{
cdc_ecm_if_input(&cdc_ecm_netif);
}
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;
}
}
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)
{
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));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

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