212 Commits

Author SHA1 Message Date
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
sakimisu
94505f9e41 change rndis_encapsulated_resp_buffer size to 156 2023-08-05 11:11:03 +08:00
sakimisu
c8b832e1a0 fix function name 2023-08-05 11:08:24 +08:00
Zhihong Chen
d3aa9449e1 class: rndis: host: fix function name
- fix function name

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-05 11:05:44 +08:00
Zhihong Chen
4d7938e349 update for midi
- add MidiCodeIndexNumber enum
- update midi descriptor. Audio v1.0's endpoint has 9 bytes instead of 7.

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-05 11:05:44 +08:00
Zhihong Chen
4777a65f54 ehci: update hardcode for hpmicro
- should define CONFIG_USB_EHCI_HPMICRO and CONFIG_HPM_USB_BASE in usb_config.h

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-08-01 20:10:02 +08:00
sakimisu
96c0b655fd update version 0.10.0 2023-07-29 17:05:21 +08:00
sakimisu
61da3794cf update device api 2023-07-29 16:09:23 +08:00
Chen Leeren
45ea9928bc Fix the callback api in usbd_hid.c 2023-07-21 12:38:23 +08:00
sakimisu
64e2b8d480 update hid inout demo 2023-07-20 22:03:45 +08:00
sakumisu
fed6f26ebd fix log 2023-07-14 17:58:39 +08:00
sakimisu
513772a534 update doc 2023-07-13 20:34:11 +08:00
sakumisu
e45a2857df fix missing function 2023-07-13 20:14:28 +08:00
sakumisu
c8ecf31c99 remove ununsed code 2023-07-13 20:13:51 +08:00
sakimisu
4395c7f039 update device & host usage 2023-07-13 19:36:31 +08:00
sakimisu
3057f41020 use static memory to malloc & free class 2023-07-12 22:48:18 +08:00
sakimisu
47c0255cdc fix rt-thread once thread delete 2023-07-12 21:48:18 +08:00
sakumisu
d53e8a2adf add msc popup function 2023-07-11 22:17:03 +08:00
sakimisu
3bdb3bbf84 clasify vendor driver 2023-07-09 17:57:35 +08:00
sakimisu
3c1168d58c update cmakelist for common 2023-07-09 14:44:44 +08:00
lenovo
f672591d58 Silicon Laboratories CP210x USB to RS232 serial adaptor driver is suppported 2023-07-09 00:52:30 +08:00
sakumisu
84598eed7c fix rndis build error 2023-07-08 21:44:20 +08:00
sakimisu
7574063e94 enum device with disposable thread, do not block hub thread 2023-07-05 22:53:13 +08:00
sakimisu
0d916af297 check if urb is null 2023-07-02 22:29:07 +08:00
sakimisu
b90d6a727e update double winusb demo 2023-06-30 23:53:23 +08:00
sakimisu
d0d6f99c90 use DxEPCTL to check if ep is busy 2023-06-30 22:19:23 +08:00
sakumisu
9673b2cf67 update outline pic 2023-06-30 18:08:30 +08:00
sakimisu
7061367484 support multi winusb 2023-06-28 22:59:22 +08:00
sakimisu
faf90663a9 format code 2023-06-28 21:45:06 +08:00
sakimisu
bb58348510 check if current context is in irq when gives sem 2023-06-28 21:44:28 +08:00
sakimisu
8253f074ce implment musb usbh_kill_urb 2023-06-28 21:11:38 +08:00
sakimisu
8a93ca4bce remove dap 2023-06-25 22:38:18 +08:00
sakimisu
8968b7b3c9 update dwc2 iso transfer 2023-06-22 13:40:07 +08:00
sakimisu
2ca22deaad remove unused code 2023-06-21 23:30:44 +08:00
sakimisu
340fa4e024 use usbd_event_handler instead of usbd_configure_done_callback 2023-06-21 21:26:25 +08:00
sakimisu
822cd9d679 add dwc2 param log 2023-06-21 20:51:10 +08:00
sakimisu
e061b8e784 fix winusb demo 2023-06-21 20:46:59 +08:00
sakimisu
8856361be0 remove unused code 2023-06-21 20:44:32 +08:00
sakimisu
1c7110bd86 refactor audio device class 2023-06-21 20:43:35 +08:00
sakimisu
48efbfe521 update demo, move hid buffer into nocache ram 2023-06-21 20:43:25 +08:00
sakimisu
c540080c96 format class struct and global variable name 2023-06-21 20:43:06 +08:00
sakimisu
d970f88f06 add cdc send break request 2023-06-21 19:39:48 +08:00
sakimisu
2d1b4b8b82 export cdc/msc/rndis/mtp mps, configured by user 2023-06-21 19:39:22 +08:00
sakumisu
9bac9537db remove ununsed code 2023-06-19 22:25:32 +08:00
Runcheng Lu
f35b345680 third_party: rtthread: fix rndis_host some issue
- fix some issue

Signed-off-by: Runcheng Lu <runcheng.lu@hpmicro.com>
2023-06-16 10:43:49 +08:00
Runcheng Lu
56868b513a third_party: freertos: add adapt rndis_host APIs
- add adapt rndis_host APIs

Signed-off-by: Runcheng Lu <runcheng.lu@hpmicro.com>
2023-06-16 10:43:49 +08:00
sakimisu
85a494326a check intf num when arg is valid 2023-06-06 22:22:46 +08:00
sakimisu
ccf97b35e3 move capture files into tools 2023-06-04 14:51:19 +08:00
sakimisu
4dff5aac24 update readme 2023-06-03 16:29:35 +08:00
sakumisu
66e95c9d81 remove ununsed code 2023-06-02 19:06:48 +08:00
Zhihong Chen
16180bfc8e audio: fix descriptor endpoint attribute error and add audiov2 feedback descriptor
- fix descriptor endpoint attribute error and add audiov2 feedback descriptor

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-06-02 15:26:32 +08:00
sakimisu
9d24ae4725 update to v0.9.0 2023-05-27 14:21:27 +08:00
sakimisu
8162a156d4 move out es32/stm32/phytium demo 2023-05-26 21:19:59 +08:00
sakimisu
b59c1c6613 check if dwc2 supports dma 2023-05-26 20:37:23 +08:00
sakimisu
1c6f062bc9 add yoc port 2023-05-26 19:47:42 +08:00
sakimisu
c1fbb4ae56 copy desc into nocache ram 2023-05-26 19:33:30 +08:00
sakimisu
e77657e723 extend report length 2023-05-26 19:31:38 +08:00
sakimisu
00546b64b7 update demo repo url 2023-05-24 20:58:12 +08:00
sakimisu
a26d8b602c use usbh_hport_activate_epx to alloc rndis intin pipe 2023-05-24 20:22:34 +08:00
Zhihong Chen
0c36483b40 class: rndis host: fix buffer size and pointer error
- fix buffer size and pointer error

Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
2023-05-24 19:47:53 +08:00
sakumisu
bfb8146699 fix hid get report len 2023-05-24 16:40:13 +08:00
sakumisu
77c3f17b7d check with last to reduce set line coding repeatly 2023-05-24 16:40:13 +08:00
heyuanjie87
01c6d60076 修复requestsense设定数据长度错误的问题 2023-05-19 19:57:43 +08:00
sakimisu
841cf83c22 update esp32 repo version 2023-05-19 15:34:42 +08:00
sakimisu
dcbad9eebe comment musb reg struct 2023-05-19 15:32:07 +08:00
sakimisu
3861728751 add remote wakeup event 2023-05-17 20:59:38 +08:00
sakimisu
9172223fe6 call usbh_xxx_stop when class enumerates completely 2023-05-17 20:43:23 +08:00
sakumisu
0c21844166 prevent variables being optimised 2023-05-08 20:22:04 +08:00
sakumisu
f446a7e95b move g_dwc2_udc into no cache ram 2023-05-08 20:05:32 +08:00
sakumisu
b439be2475 fix typo 2023-05-04 17:15:31 +08:00
sakimisu
3aeadb3046 fix build error 2023-04-29 15:17:59 +08:00
sakimisu
0bfa749333 fix typo 2023-04-23 22:50:23 +08:00
sakimisu
b39c9b779a update readme 2023-04-22 14:28:16 +08:00
sakimisu
773cad823f align hub intbuf 2023-04-22 14:23:26 +08:00
sakimisu
8f56dbdff4 update audio test 2023-04-22 14:06:12 +08:00
sakimisu
31a86ac578 fix typo 2023-04-22 00:11:49 +08:00
sakimisu
ca5d2902f3 do not check intf when calls endpoint handler 2023-04-22 00:00:33 +08:00
sakimisu
d35d5bc12f update phytium sdk url 2023-04-21 23:44:48 +08:00
sakimisu
5657b2a028 update hub process for usb3.0, update xhci driver 2023-04-21 23:43:59 +08:00
sakimisu
dc4887aef1 fix pointer in 64bit cpu, use uintptr_t instead 2023-04-21 23:24:13 +08:00
zhugengyu
4b59a1330e update xhci demo 2023-04-21 22:57:41 +08:00
zhugengyu
ef126eafa6 update xhci driver 2023-04-21 22:56:46 +08:00
sakumisu
53fe0f2cd5 update ehci iso struct and api 2023-04-20 15:12:38 +08:00
Chen Leeren
2bac932648 Fix enum of low-speed and high-speed devices 2023-04-11 17:57:15 +08:00
Chen Leeren
a51edd9231 Update wch driver 2023-04-08 19:32:27 +08:00
sakumisu
5a06a85484 fix dap response len limit 2023-03-31 19:00:27 +08:00
sakumisu
cc4c7727df add const for printer device_id 2023-03-30 19:09:46 +08:00
sakumisu
bbdf098dfe Fix printer usbd_add_interface 2023-03-30 14:16:10 +08:00
sakumisu
c47b8dd3e1 enable dwc2 nak irq for bulk if someday uses 2023-03-25 00:36:44 +08:00
sakimisu
25d14f3f89 copy desc into align buf 2023-03-25 00:02:30 +08:00
sakumisu
d7c0add7ef add usbd_event_handler for users 2023-03-22 15:00:34 +08:00
sakumisu
e9ad3bdc21 add volume and mute control 2023-03-22 14:58:07 +08:00
sakumisu
9c5af19cb1 remove unused functions 2023-03-22 14:57:47 +08:00
sakumisu
0322934cf4 fix warning when use no ext hub 2023-03-17 10:23:18 +08:00
sakumisu
2241098561 disconnect sources in usbh_hport_release 2023-03-17 10:21:43 +08:00
sakumisu
70a22c24c7 fix print log 2023-03-16 15:12:41 +08:00
sakimisu
419622f4e4 fix vbusen in gd32 2023-03-15 21:47:28 +08:00
GrAgiu
19d509052a fix STM32L4 dwc2 Deactivate VBUS Sensing 2023-03-15 21:42:34 +08:00
sakimisu
bb8cfe23de fix ep0 data receive 2023-03-15 21:38:41 +08:00
sakimisu
4cd9031d31 replace speed reconfig with mult 2023-03-12 15:05:35 +08:00
sakimisu
cda6e48fc1 check if urb is null in sunxi 2023-03-12 14:56:29 +08:00
sakimisu
854e633808 move variables into no cache 2023-03-12 14:53:04 +08:00
sakimisu
80f19f738c format code 2023-03-12 14:49:24 +08:00
sakumisu
66c46a3eb2 update printer driver and demo 2023-03-11 19:06:13 +08:00
zhouji
79f0a1989e [update] Improve the compatibility of USB flash drive enumeration。 2023-03-11 18:52:25 +08:00
sakimisu
cbba334678 fix typo 2023-03-08 22:31:19 +08:00
419 changed files with 15665 additions and 144023 deletions

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,56 +1,57 @@
## Script for hpmicro ##
sdk_inc(common)
sdk_inc(osal)
sdk_inc(core)
sdk_inc(class/cdc)
sdk_inc(class/hid)
sdk_inc(class/msc)
sdk_inc(class/audio)
sdk_inc(class/video)
sdk_inc(class/hub)
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)
sdk_src(core/usbd_core.c)
sdk_src(port/hpm/usb_dc_hpm.c)
sdk_compile_definitions(-DCONFIG_USB_HS)
if(CONFIG_CHERRYUSB_DEVICE_CDC)
sdk_src(class/cdc/usbd_cdc.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_HID)
sdk_src(class/hid/usbd_hid.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_MSC)
sdk_src(class/msc/usbd_msc.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
sdk_src(class/audio/usbd_audio.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
sdk_src(class/video/usbd_video.c)
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_DEVICE_DEMO_CDC)
sdk_src(demo/cdc_acm_template.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_DEMO_CDC_MSC)
sdk_src(demo/cdc_acm_msc_template.c)
endif()
elseif(CONFIG_CHERRYUSB_HOST)
sdk_src(core/usbh_core.c)
sdk_src(class/hub/usbh_hub.c)
sdk_src(port/ehci/usb_hc_ehci.c)
sdk_src(port/ehci/usb_glue_hpm.c)
sdk_src(osal/usb_osal_freertos.c)
sdk_src(class/cdc/usbh_cdc_acm.c)
sdk_src(class/msc/usbh_msc.c)
sdk_src(class/hid/usbh_hid.c)
sdk_src(class/wireless/usbh_rndis.c)
if(CONFIG_CHERRYUSB_HOST_DEMO)
sdk_src(demo/usb_host.c)
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()

135
README.md
View File

@@ -2,19 +2,37 @@
[中文版](./README_zh.md)
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB ip.
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
![CherryUSB](./docs/assets/usb_outline.png)
![CherryUSB](./docs/assets/CherryUSB.svg)
## Why choose
- Streamlined code with small memory usage which also can be further trimmed
- Comprehensive class drivers and all master and slave class drivers are templated,making it easy for users to add new class drivers and find patterns when learning
- The APIs available to the users are very few and clearly categorised. Device: initialisation + registration apis, command callback apis, data sending and receiving apis; Host: initialisation + lookup apis, data sending and receiving apis
- Tree-based programming with a hierarchy of code that makes it easy for the user to sort out function call relationships, enumerations and class-driven loading processes
- Standardised porting interface, no need to rewrite the driver for the same ip, and porting drivers are templated to make it easier for users to add new ports
- The use of the device or host transceiver apis are equivalent to the use of the uart tx/rx dma, and there is no limit to the length
- Capable of achieving theoretical USB hardware bandwidth
### Easy to study USB
In order to make it easier for users to learn USB basics, enumeration, driver loading and IP drivers, the code has been written with the following advantages:
- Lean code, simple logic, no complex C syntax
- Tree-based programming with cascading code
- Class-drivers and porting-drivers are templating and simplification
- Clear API classification (slave: initialisation, registration api, command callback api, data sending and receiving api; host: initialisation, lookup api, data sending and receiving api)
### Easy to use USB
In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
- Equivalent to using uart tx dma/uart rx dma
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does the packetization process)
### Easy to bring out USB performance
Taking into account USB performance issues and trying to achieve the theoretical bandwidth of the USB hardware, the design of the data transceiver class interface has the following advantages:
- Porting drivers directly to registers, no abstraction layer encapsulation
- Memory zero copy
- If IP has DMA then uses DMA mode (DMA with hardware packetization)
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
- Subcontracting function is handled in interrupt
## Directoy Structure
@@ -36,13 +54,12 @@ CherryUSB is a tiny, beautiful and portable USB host and device stack for embedd
|:-------------:|:---------------------------:|
|class | usb class driver |
|common | usb spec macros and utils |
|core | usb core implementation |
|demo | different chips demo |
|osal | os wrapper |
|docs | doc for guiding |
|packet capture | packet capture file |
|port | usb dcd and hcd porting |
|tools | tool used url |
|core | usb core implementation |
|demo | different chips demo |
|osal | os wrapper |
|docs | doc for guiding |
|port | usb dcd and hcd porting |
|tools | tool url |
## Device Stack Overview
@@ -50,10 +67,10 @@ CherryUSB Device Stack provides a unified framework of functions for standard de
CherryUSB Device Stack has the following functions
- Support USB2.0 full and high speed
- 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)
@@ -68,12 +85,13 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3263 | 384 | 17 | 0 |
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 501 | 0 | 0 | 0 |
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|usbd_video.c | 2272 | 0 | 82 | 0 |
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
## Host Stack Overview
@@ -85,38 +103,51 @@ CherryUSB Host Stack has the following functions
- Support blocking transfers and asynchronous transfers
- Support Composite Device
- Multi-level HUB support, expandable up to 7 levels
- 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
- Support USB Audio CLASS
- Support Remote NDIS (RNDIS)
- Support Vendor class
- Support USB modeswitch
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 | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 4895 | 32 + 1* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
| 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 |
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
```
x is affected by the following macros
```
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
```
## Documentation Tutorial
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
@@ -131,25 +162,19 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr
## Demo Repo
Note: After version 0.4.1, the dcd drivers have been refactored and some repositories are not maintained for a long time, so if you use a higher version, you need to update it yourself.
| Manufacturer | CHIP or Series | USB IP| Repo Url |Corresponds to master version|
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bl_mcu_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|latest |
|ST | STM32F4 | dwc2 |[stm32f429_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f429igt6) [stm32f429_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32f429igt6)|latest |
|ST | STM32H7 | dwc2 |[stm32h743_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32h743vbt6) [stm32h743_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32h743xih6)|latest |
|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.6.0 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/es32)|latest |
|AllwinnerTech | F1C100S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|Phytium | e2000 | xhci |[phytium _repo](https://gitee.com/phytium_embedded/phytium-standalone-sdk)|latest |
|Raspberry pi | rp2040 | rp2040 |[rp2040_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/rp2040)|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 |
|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 |
|Espressif | esp32 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|v0.4.1 |
|Mindmotion | MM32L3xx | mm32 |[mm32_repo](https://github.com/CherryUSB/cherryusb_mm32)|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 |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Contact

View File

@@ -2,19 +2,37 @@
[English](./README.md)
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB ip)的 USB 主从协议栈。
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
![CherryUSB](./docs/assets/usb_outline.png)
![CherryUSB](./docs/assets/CherryUSB.svg)
## 为什么选择
- 代码精简,并且内存占用极小,详细参考下面表格,而且还可进一步的裁剪
- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律
- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册类、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类
- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程
- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。
- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制
- 能够达到 USB 硬件理论带宽
### 易于学习 USB
为了方便用户学习 USB 基本知识、枚举、驱动加载、IP 驱动,因此,编写的代码具备以下优点:
- 代码精简,逻辑简单,无复杂 C 语言语法
- 树状化编程,代码层层递进
- Class 驱动和 porting 驱动模板化、精简化
- API 分类清晰(从机:初始化、注册类、命令回调类、数据收发类;主机:初始化、查找类、数据收发类)
### 易于使用 USB
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma因此设计的数据收发类接口具备以下优点
- 等价于使用 uart tx dma/uart rx dma
- 收发长度没有限制,用户不需要关心 USB 分包过程porting 驱动做分包过程)
### 易于发挥 USB 性能
考虑到 USB 性能问题,尽量达到 USB 硬件理论带宽,因此,设计的数据收发类接口具备以下优点:
- Porting 驱动直接对接寄存器,无抽象层封装
- Memory zero copy
- IP 如果带 DMA 则使用 DMA 模式DMA 带硬件分包功能)
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
- 分包功能在中断中处理
## 目录结构
@@ -26,22 +44,20 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
├── demo
├── docs
├── osal
├── packet capture
└── port
└── tools
```
| 目录名 | 描述 |
|:-------------:|:------------------------------:|
|:-------------:|:-------------------------------:|
|class | usb class 类主从驱动 |
|common | usb spec 定义、常用宏、标准接口定义 |
|core | usb 主从协议栈核心实现 |
|demo | 示例 |
|docs | 文档 |
|core | usb 主从协议栈核心实现 |
|demo | 示例 |
|docs | 文档 |
|osal | os 封装层 |
|packet capture | 抓包文件(需要使用力科软件打开)|
|port | usb 主从需要实现的 porting 接口 |
|tools | 工具链接 |
|tools | 工具链接 |
## Device 协议栈简介
@@ -49,10 +65,10 @@ CherryUSB Device 协议栈对标准设备请求、CLASS 请求、VENDOR 请求
CherryUSB Device 协议栈当前实现以下功能:
- 支持 USB2.0 全速和高速设备
- 支持 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)
@@ -67,12 +83,13 @@ CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | 3263 | 384 | 17 | 0 |
|usbd_cdc.c | 490 | 0 | 0 | 0 |
|usbd_msc.c | 2772 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 501 | 0 | 0 | 0 |
|usbd_audio.c | 1208 | 0 | 4 | 0 |
|usbd_video.c | 2272 | 0 | 82 | 0 |
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|usbd_hid.c | 364 | 0 | 0 | 0 |
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|usbd_video.c | 2494 | 0 | 84 | 0 |
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
## Host 协议栈简介
@@ -84,38 +101,51 @@ CherryUSB Host 协议栈当前实现以下功能:
- 支持阻塞式传输和异步传输
- 支持复合设备
- 支持多级 HUB,最高可拓展到 7 级
- 支持 Communication Device Class (CDC)
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
- 支持 Human Interface Device (HID)
- 支持 Mass Storage Class (MSC)
- Support USB Video CLASS
- Support USB Audio CLASS
- 支持 Remote NDIS (RNDIS)
- 支持 Vendor 类 class
- 支持 USB modeswitch
同时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 | 4417 | 512 | 28 | sizeof(struct usbh_urb) |
|usbh_hub.c | 4895 | 32 + 1* (1+n) | 16 + sizeof(struct usbh_hub) * (1+n) | 0 |
|usbh_cdc_acm.c | 1064 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
|usbh_hid.c | 922 | 128 | 4 | sizeof(struct usbh_hid) * x |
|usbh_video.c | 3592 | 128 | 4 | sizeof(struct usbh_video) * x |
|usbh_audio.c | 3230 | 128 | 4 | sizeof(struct usbh_audio) * x |
| 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 |
其中,`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
```
x 受以下宏影响:
```
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
```
## 文档教程
CherryUSB 快速入门、USB 基本概念API 手册Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
@@ -130,25 +160,19 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch
## 示例仓库
注意0.4.1 版本以后 dcd 驱动进行了重构,部分仓库不做长期维护,所以如果使用高版本需要自行更新
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bl_mcu_sdk](https://github.com/CherryUSB/cherryusb_bouffalolab)| latest |
|ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|latest |
|ST | STM32F4 | dwc2 |[stm32f429_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f429igt6) [stm32f429_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32f429igt6)|latest |
|ST | STM32H7 | dwc2 |[stm32h743_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32h743vbt6) [stm32h743_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32h743xih6)|latest |
|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.6.0 |
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/es32)|latest |
|AllwinnerTech | F1C100S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
|Phytium | e2000 | xhci |[phytium _repo](https://gitee.com/phytium_embedded/phytium-standalone-sdk)|latest |
|Raspberry pi | rp2040 | rp2040 |[rp2040_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/rp2040)|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 |
|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 |
|Espressif | esp32 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|v0.4.1 |
|Mindmotion | MM32L3xx | mm32 |[mm32_repo](https://github.com/CherryUSB/cherryusb_mm32)|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 |
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
## Contact

View File

@@ -16,7 +16,9 @@ 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']
@@ -44,6 +46,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('demo/hid_keyboard_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
src += Glob('demo/msc_ram_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_STORAGE_TEMPLATE']):
src += Glob('demo/msc_storage_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
@@ -58,14 +62,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
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_DWC2_STM32']):
src += Glob('port/dwc2/usb_glue_st.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
src += Glob('port/musb/usb_dc_musb.c')
@@ -81,6 +79,12 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
else:
src += Glob('port/ch32/usb_dc_usbfs.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
path += [cwd + '/port/pusb2/common']
path += [cwd + '/port/pusb2/fpusb2']
src += Glob('port/pusb2/fpusb2' + '/*.c')
src += Glob('port/pusb2/usb_dc_pusb2.c')
# USB HOST
if GetDepend(['PKG_CHERRYUSB_HOST']):
path += [cwd + '/osal']
@@ -97,9 +101,13 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
src += Glob('class/msc/usbh_msc.c')
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
src += Glob('class/wireless/usbh_rndis.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
src += Glob('class/cdc/usbh_cdc_ecm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
src += Glob('port/dwc2/usb_hc_dwc2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_STM32']):
src += Glob('port/dwc2/usb_glue_st.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']):
src += Glob('port/musb/usb_hc_musb.c')
@@ -111,8 +119,24 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
src += Glob('port/ehci/usb_glue_hpm.c')
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
src += Glob('port/xhci/usb_hc_xhci.c')
src += Glob('port/xhci/xhci_dbg.c')
src += Glob('port/xhci/xhci.c')
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
path += [cwd + '/port/pusb2/common']
path += [cwd + '/port/pusb2/fpusb2']
src += Glob('port/pusb2/fpusb2' + '/*.c')
src += Glob('port/pusb2/usb_hc_pusb2.c')
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
src += Glob('demo/usb_host.c')
if GetDepend('RT_USING_DFS'):
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
src += Glob('third_party/rt-thread-5.0/msh_cmd.c')
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 = 0
PATCHLEVEL = 99
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

@@ -6,7 +6,8 @@
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x000800
#define CHERRYUSB_VERSION 0x010000
#define CHERRYUSB_VERSION_STR "v1.0.0"
/* ================ USB common Configuration ================ */
@@ -44,27 +45,6 @@
/* 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
#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
#endif
@@ -81,16 +61,18 @@
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
#ifndef CONFIG_USBDEV_AUDIO_VERSION
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
// #define CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_PRIO
#define CONFIG_USBDEV_MSC_PRIO 4
#endif
#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
#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 128
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
@@ -112,14 +94,20 @@
#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
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_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
@@ -127,6 +115,9 @@
//#define CONFIG_USBHOST_GET_STRING_DESC
// #define CONFIG_USBHOST_MSOS_ENABLE
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
/* Ep0 max transfer buffer */
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
@@ -140,13 +131,15 @@
/* ================ USB Device Port Configuration ================*/
//#define USBD_IRQHandler USBD_IRQHandler
//#define USB_BASE (0x40080000UL)
//#define USB_NUM_BIDIR_ENDPOINTS 4
#define USBD_IRQHandler USBD_IRQHandler
#define USBD_BASE (0)
#define CONFIG_USBDEV_EP_NUM 4
/* ================ USB Host Port Configuration ==================*/
#define CONFIG_USBHOST_PIPE_NUM 10
// #define USBH_IRQHandler USBH_IRQHandler
// #define USBH_BASE (0)
// #define CONFIG_USBHOST_PIPE_NUM 10
/* ================ EHCI Configuration ================ */
@@ -154,7 +147,7 @@
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
#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_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_CONFIGFLAG
// #define CONFIG_USB_EHCI_PORT_POWER

View File

@@ -760,7 +760,7 @@ struct audio_cs_ep_ep_general_descriptor {
__VA_ARGS__, /* bmaControls(0) Mute */ \
0x00 /* iTerminal */
#define AUDIO_AS_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, ...) \
#define AUDIO_AS_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval, ...) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
@@ -797,7 +797,7 @@ struct audio_cs_ep_ep_general_descriptor {
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
0x01, /* bmAttributes */ \
bmAttributes, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
bInterval, /* bInterval : one packet per frame */ \
0x00, /* bRefresh */ \
@@ -812,6 +812,19 @@ struct audio_cs_ep_ep_general_descriptor {
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT(bInterfaceNumber, bNumEndpoints) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
bNumEndpoints, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_MIDISTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
0x00 /* iInterface */
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT_LEN 0x09
struct audio_v2_channel_cluster_descriptor {
uint8_t bNrChannels;
uint32_t bmChannelConfig;
@@ -1033,7 +1046,7 @@ struct audio_v2_control_range3_param_block {
__VA_ARGS__, /* bmaControls(0) Mute */ \
0x00 /* iTerminal */
#define AUDIO_V2_AS_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval) \
#define AUDIO_V2_AS_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
@@ -1071,8 +1084,8 @@ struct audio_v2_control_range3_param_block {
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
0x01, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
bmAttributes, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
bInterval, /* bInterval */ \
0x08, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
@@ -1083,9 +1096,66 @@ struct audio_v2_control_range3_param_block {
0x00, /* wLockDelay */ \
0x00
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, bFeedbackEndpointAddress) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bInterfaceNumber, /* bInterfaceNumber */ \
0x01, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
0x00, /* iInterface */ \
0x10, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
bTerminalLink, /* bTerminalLink : Unit ID of the Output or Input Terminal*/ \
0x00, /* bmControls */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType : AUDIO_FORMAT_TYPE_I */ \
DBVAL(AUDIO_V2_FORMAT_PCM), /* bmFormats PCM */ \
bNrChannels, /* bNrChannels */ \
DBVAL(bmChannelConfig), /* bmChannelConfig */ \
0x00, /* iChannelNames */ \
0x06, /* bLength */ \
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
bSubslotSize, /* bSubslotSize */ \
bBitResolution, /* bBitResolution */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
0x05, /* bmAttributes: TransferType=Isochronous SyncType=Asynchronous EndpointType=Data*/ \
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
bInterval, /* bInterval */ \
0x08, /* bLength */ \
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
0x00, /* bmAttributes */ \
0x00, /* bmControls */ \
0x00, /* bLockDelayUnits */ \
0x00, /* wLockDelay */ \
0x00, \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bFeedbackEndpointAddress, /* bFeedbackEndpointAddress Revise Dir to bEndpointAddress */ \
0x11, /* bmAttributes: TransferType=Isochronous SyncType=None EndpointType=Feedback */ \
WBVAL(4), /* XXXX wMaxPacketSize in Bytes */ \
bInterval /* bInterval */ \
// clang-format on
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
#define AUDIO_SAMPLE_FREQ_NUM(num) (uint8_t)(num), (uint8_t)((num >> 8))
#define AUDIO_SAMPLE_FREQ_3B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))

View File

@@ -6,109 +6,71 @@
#include "usbd_core.h"
#include "usbd_audio.h"
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
struct usbd_audio_volume_info {
uint16_t vol_min;
uint16_t vol_max;
uint16_t vol_res;
uint16_t vol_current;
struct audio_entity_param {
uint32_t wCur;
uint32_t wMin;
uint32_t wMax;
uint32_t wRes;
};
struct usbd_audio_attribute_control {
struct usbd_audio_volume_info volume[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
uint8_t automatic_gain[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
};
#else
struct audio_v2_control_range2_param_block_default {
uint16_t wNumSubRanges;
struct
{
uint16_t wMin;
uint16_t wMax;
uint16_t wRes;
} subrange[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
} __PACKED;
struct usbd_audio_priv {
struct audio_entity_info *table;
uint8_t num;
uint16_t uac_version;
} g_usbd_audio;
struct usbd_audio_attribute_control {
uint32_t volume_bCUR;
uint32_t mute_bCUR;
struct audio_v2_control_range2_param_block_default volume;
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
};
#endif
struct audio_entity_info {
usb_slist_t list;
uint8_t bDescriptorSubtype;
uint8_t bEntityId;
void *priv[2];
};
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector;
uint32_t sampling_freq = 0;
uint8_t pitch_enable;
uint8_t ep;
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
control_selector = HI_BYTE(setup->wValue);
ep = LO_BYTE(setup->wIndex);
control_selector = HI_BYTE(setup->wValue);
ep = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
switch (control_selector) {
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
memcpy((uint8_t *)&sampling_freq, *data, *len);
USB_LOG_DBG("Set ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(0, ep, sampling_freq);
break;
case AUDIO_EP_CONTROL_PITCH:
pitch_enable = (*data)[0];
usbd_audio_set_pitch(ep, pitch_enable);
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
case AUDIO_REQUEST_GET_CUR:
sampling_freq = 16000;
memcpy(*data, &sampling_freq, 4);
*len = 4;
USB_LOG_DBG("Get ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
} else {
return -1;
switch (control_selector) {
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
switch (setup->bRequest) {
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);
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);
memcpy(*data, &sampling_freq, 3);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 3;
break;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
return 0;
}
#endif
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("AUDIO Class request: "
USB_LOG_DBG("Audio Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
struct audio_entity_info *current_entity_info = NULL;
struct usbd_audio_attribute_control *current_feature_control = NULL;
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
uint32_t *sampling_freq;
#endif
usb_slist_t *i;
uint8_t entity_id;
uint8_t ep;
uint8_t subtype = 0x01;
uint8_t control_selector;
uint8_t ch;
uint8_t mute;
uint16_t volume;
int volume_db = 0;
uint32_t sampling_freq = 0;
const char *mute_string[2] = { "off", "on" };
entity_id = HI_BYTE(setup->wIndex);
@@ -116,211 +78,189 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
ch = LO_BYTE(setup->wValue);
ARG_UNUSED(mute_string);
if (ch > (CONFIG_USBDEV_AUDIO_MAX_CHANNEL - 1)) {
return -2;
}
usb_slist_for_each(i, &usbd_audio_entity_info_head)
{
struct audio_entity_info *tmp_entity_info = usb_slist_entry(i, struct audio_entity_info, list);
if (tmp_entity_info->bEntityId == entity_id) {
current_entity_info = tmp_entity_info;
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;
break;
}
}
if (current_entity_info == NULL) {
return -2;
}
current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
sampling_freq = (uint32_t *)current_entity_info->priv[1];
#endif
if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
float volume2db = 0.0;
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
current_feature_control->mute[ch] = mute;
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
usbd_audio_set_mute(entity_id, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = current_feature_control->mute[ch];
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
break;
case AUDIO_FU_CONTROL_VOLUME:
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
current_feature_control->volume[ch].vol_current = volume;
if (volume < 0x8000) {
volume2db = 0.00390625 * volume;
} else if (volume > 0x8000) {
volume2db = -0.00390625 * (0xffff - volume + 1);
}
USB_LOG_DBG("Set UnitId:%d ch[%d] %0.4f dB\r\n", entity_id, ch, volume2db);
usbd_audio_set_volume(entity_id, ch, volume2db);
break;
case AUDIO_REQUEST_GET_CUR:
memcpy(*data, &current_feature_control->volume[ch].vol_current, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
memcpy(*data, &current_feature_control->volume[ch].vol_min, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
memcpy(*data, &current_feature_control->volume[ch].vol_max, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
memcpy(*data, &current_feature_control->volume[ch].vol_res, 2);
*len = 2;
break;
case AUDIO_REQUEST_SET_RES:
memcpy(&current_feature_control->volume[ch].vol_res, *data, 2);
*len = 2;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
#else
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = current_feature_control->mute_bCUR;
*len = 1;
} else {
mute = (*data)[0];
current_feature_control->mute_bCUR = mute;
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
usbd_audio_set_mute(entity_id, ch, mute);
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = current_feature_control->volume_bCUR & 0XFF;
(*data)[1] = (current_feature_control->volume_bCUR >> 8) & 0xff;
*len = 2;
} else {
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
current_feature_control->volume_bCUR = volume;
USB_LOG_DBG("Set UnitId:%d ch[%d] %d dB\r\n", entity_id, ch, volume);
usbd_audio_set_volume(entity_id, ch, volume);
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
case AUDIO_REQUEST_RANGE:
switch (control_selector) {
case AUDIO_FU_CONTROL_VOLUME:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = current_feature_control->volume.wNumSubRanges;
*((uint16_t *)(*data + 2)) = current_feature_control->volume.subrange[ch].wMin;
*((uint16_t *)(*data + 4)) = current_feature_control->volume.subrange[ch].wMax;
*((uint16_t *)(*data + 6)) = current_feature_control->volume.subrange[ch].wRes;
*len = 8;
} else {
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
#endif
}
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
else if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
memcpy(*data, &sampling_freq[ch], sizeof(uint32_t));
USB_LOG_DBG("Get ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
*len = 4;
} else {
memcpy(&sampling_freq[ch], *data, setup->wLength);
USB_LOG_DBG("Set ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
usbd_audio_set_sampling_freq(entity_id, ch, sampling_freq[ch]);
}
break;
case AUDIO_CS_CONTROL_CLOCK_VALID:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = 1;
*len = 1;
} else {
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
case AUDIO_REQUEST_RANGE:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(entity_id, &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);
USB_LOG_DBG("Get sampling_freq_table entity_id:%d ch[%d] addr:%x\r\n", entity_id, ch, (uint32_t)sampling_freq_table);
} else {
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
}
#endif
else {
if (subtype == 0x01) {
USB_LOG_ERR("Do not find subtype for 0x%02x\r\n", entity_id);
return -1;
}
USB_LOG_DBG("Audio entity_id:%02x, subtype:%02x, cs:%02x\r\n", entity_id, subtype, control_selector);
switch (subtype) {
case AUDIO_CONTROL_FEATURE_UNIT:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (g_usbd_audio.uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = usbd_audio_get_mute(ep, ch);
*len = 1;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
} else {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = usbd_audio_get_mute(ep, ch);
*len = 1;
} else {
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (g_usbd_audio.uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy(&volume, *data, *len);
if (volume < 0x8000) {
volume_db = volume / 256;
} else if (volume > 0x8000) {
volume_db = (0xffff - volume + 1) / -256;
}
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);
break;
case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(ep, ch);
volume_db -= 128;
if (volume_db >= 0) {
volume = volume_db * 256;
} else {
volume = volume_db * 256 + 0xffff + 1;
}
memcpy(*data, &volume, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
(*data)[0] = 0x00; /* -2560/256 dB */
(*data)[1] = 0xdb;
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
(*data)[0] = 0x00; /* 0 dB */
(*data)[1] = 0x00;
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
(*data)[0] = 0x00; /* -256/256 dB */
(*data)[1] = 0x01;
*len = 2;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
} else {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(ep, ch);
volume = volume_db;
memcpy(*data, &volume, 2);
*len = 2;
} else {
memcpy(&volume, *data, *len);
volume_db = volume;
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = 1;
*((uint16_t *)(*data + 2)) = 0;
*((uint16_t *)(*data + 4)) = 100;
*((uint16_t *)(*data + 6)) = 1;
*len = 8;
} else {
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1;
}
break;
case AUDIO_CONTROL_CLOCK_SOURCE:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
sampling_freq = usbd_audio_get_sampling_freq(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);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(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);
} else {
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
break;
case AUDIO_CS_CONTROL_CLOCK_VALID:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = 1;
*len = 1;
} else {
return -1;
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1;
}
break;
default:
break;
}
return 0;
}
@@ -333,7 +273,7 @@ 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 == 1) {
if (intf->bAlternateSetting) {
usbd_audio_open(intf->bInterfaceNumber);
} else {
usbd_audio_close(intf->bInterfaceNumber);
@@ -347,86 +287,57 @@ 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(struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num)
{
intf->class_interface_handler = audio_class_interface_request_handler;
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
#else
intf->class_endpoint_handler = NULL;
#endif
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
if (uac_version < 0x0200) {
intf->class_interface_handler = audio_class_interface_request_handler;
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
} else {
intf->class_interface_handler = audio_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
}
g_usbd_audio.uac_version = uac_version;
g_usbd_audio.table = table;
g_usbd_audio.num = num;
return intf;
}
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype)
{
struct audio_entity_info *entity_info = usb_malloc(sizeof(struct audio_entity_info));
memset(entity_info, 0, sizeof(struct audio_entity_info));
entity_info->bEntityId = entity_id;
entity_info->bDescriptorSubtype = bDescriptorSubtype;
if (bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
control->volume[ch].vol_min = 0xdb00;
control->volume[ch].vol_max = 0x0000;
control->volume[ch].vol_res = 0x0100;
control->volume[ch].vol_current = 0xf600;
control->mute[ch] = 0;
control->automatic_gain[ch] = 0;
}
#else
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
control->volume.wNumSubRanges = 1;
control->volume.subrange[ch].wMin = 0;
control->volume.subrange[ch].wMax = 100;
control->volume.subrange[ch].wRes = 1;
control->mute[ch] = 0;
control->volume_bCUR = 0;
control->mute_bCUR = 0;
}
#endif
entity_info->priv[0] = control;
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
sampling_freq[ch] = 16000;
}
entity_info->priv[1] = sampling_freq;
#else
entity_info->priv[1] = NULL;
#endif
}
usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
}
__WEAK void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB)
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
{
}
__WEAK void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable)
__WEAK int usbd_audio_get_volume(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_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
{
}
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
{
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
}
#endif
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
{
}

View File

@@ -12,17 +12,29 @@
extern "C" {
#endif
struct audio_entity_info {
uint8_t bDescriptorSubtype;
uint8_t bEntityId;
uint8_t ep;
};
/* Init audio interface driver */
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf);
struct usbd_interface *usbd_audio_init_intf(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_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype);
void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB);
void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable);
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq);
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table);
void usbd_audio_set_pitch(uint8_t ep, bool enable);
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_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
#ifdef __cplusplus
}

View File

@@ -17,33 +17,38 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
static uint32_t g_devinuse = 0;
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
static int usbh_audio_devno_alloc(struct usbh_audio *audio_class)
static struct usbh_audio g_audio_class[CONFIG_USBHOST_MAX_AUDIO_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_audio *usbh_audio_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
audio_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
g_audio_class[devno].minor = devno;
return &g_audio_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_audio_devno_free(struct usbh_audio *audio_class)
static void usbh_audio_class_free(struct usbh_audio *audio_class)
{
int devno = audio_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(audio_class, 0, sizeof(struct usbh_audio));
}
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
@@ -57,7 +62,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++) {
@@ -74,7 +79,7 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
}
}
return -ENODEV;
return -USB_ERR_NODEV;
freq_found:
@@ -84,7 +89,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;
}
@@ -98,7 +103,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;
}
@@ -107,10 +112,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);
@@ -133,7 +138,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);
@@ -142,12 +147,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;
}
}
@@ -158,11 +161,71 @@ 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);
if (ret < 0) {
return ret;
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume)
{
struct usb_setup_packet *setup = audio_class->hport->setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
uint16_t volume_hex;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
}
}
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
setup->wIndex = (feature_id << 8) | intf;
setup->wLength = 2;
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
memcpy(g_audio_buf, &volume_hex, 2);
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
return ret;
}
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute)
{
struct usb_setup_packet *setup = audio_class->hport->setup;
int ret;
uint8_t intf = 0xff;
uint8_t feature_id = 0xff;
for (size_t i = 0; i < audio_class->module_num; i++) {
if (strcmp(name, audio_class->module[i].name) == 0) {
intf = audio_class->ctrl_intf;
feature_id = audio_class->module[i].feature_unit_id;
}
}
if (intf == 0xff) {
return -USB_ERR_NODEV;
}
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
setup->bRequest = AUDIO_REQUEST_SET_CUR;
setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch;
setup->wIndex = (feature_id << 8) | intf;
setup->wLength = 1;
memcpy(g_audio_buf, &mute, 1);
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
return ret;
}
@@ -209,14 +272,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
uint8_t format_offset = 0;
uint8_t *p;
struct usbh_audio *audio_class = usb_malloc(sizeof(struct usbh_audio));
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;
}
memset(audio_class, 0, sizeof(struct usbh_audio));
usbh_audio_devno_alloc(audio_class);
audio_class->hport = hport;
audio_class->ctrl_intf = intf;
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
@@ -323,7 +384,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;
@@ -352,22 +413,18 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_audio *audio_class = (struct usbh_audio *)hport->config.intf[intf].priv;
if (audio_class) {
usbh_audio_devno_free(audio_class);
if (audio_class->isoin) {
usbh_pipe_free(audio_class->isoin);
}
if (audio_class->isoout) {
usbh_pipe_free(audio_class->isoout);
}
usbh_audio_stop(audio_class);
memset(audio_class, 0, sizeof(struct usbh_audio));
usb_free(audio_class);
if (hport->config.intf[intf].devname[0] != '\0')
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister Audio Class:%s\r\n", hport->config.intf[intf].devname);
usbh_audio_stop(audio_class);
}
usbh_audio_class_free(audio_class);
}
return ret;

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;
@@ -61,6 +61,8 @@ extern "C" {
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq);
int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume);
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
void usbh_audio_run(struct usbh_audio *audio_class);
void usbh_audio_stop(struct usbh_audio *audio_class);

View File

@@ -212,6 +212,57 @@
#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
/*------------------------------------------------------------------------------
* Structures based on usbcdc11.pdf (www.usb.org)
*----------------------------------------------------------------------------*/
@@ -299,11 +350,19 @@ struct cdc_ecm_descriptor {
uint8_t bNumberPowerFilters;
} __PACKED;
struct cdc_ecm_notification {
uint8_t bmRequestType;
uint8_t bNotificationType;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint8_t data[8];
} __PACKED;
/*Length of template descriptor: 66 bytes*/
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
#ifndef CONFIG_USB_HS
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
@@ -359,24 +418,100 @@ struct cdc_ecm_descriptor {
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
#else
#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
// clang-format on
/*Length of template descriptor: 66 bytes*/
#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
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_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
0x04, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x08, 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
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
/*Length of template descriptor: 66 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_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -384,8 +519,8 @@ struct cdc_ecm_descriptor {
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
CDC_ETHERNET_NETWORKING_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
@@ -393,23 +528,23 @@ struct cdc_ecm_descriptor {
WBVAL(CDC_V1_10), /* bcdCDC */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
0x04, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
0x02, /* bmCapabilities */ \
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 */ \
0x08, 0x00, /* wMaxPacketSize */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x10, /* bInterval */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -424,151 +559,14 @@ struct cdc_ecm_descriptor {
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
#endif
// clang-format on
/*Length of template descriptor: 66 bytes*/
#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
// clang-format off
#ifndef CONFIG_USB_HS
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
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_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
0x04, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x08, 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 */ \
0x40, 0x00, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
0x00 /* bInterval */
#else
#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
/* Interface Associate */ \
0x08, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
bFirstInterface, /* bFirstInterface */ \
0x02, /* bInterfaceCount */ \
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
0x00, /* iFunction */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints */ \
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
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_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
(uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
0x04, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
0x00, /* bmCapabilities */ \
0x05, /* bLength */ \
CDC_CS_INTERFACE, /* bDescriptorType */ \
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
bFirstInterface, /* bMasterInterface */ \
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x08, 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 */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00 /* bInterval */
#endif
// clang-format on
#endif /* USB_CDC_H */

View File

@@ -46,10 +46,11 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
line_coding.bDataBits,
parity_name[line_coding.bParityType],
stop_name[line_coding.bCharFormat]);
usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
break;
case CDC_REQUEST_SET_CONTROL_LINE_STATE: {
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
dtr = (setup->wValue & 0x0001);
rts = (setup->wValue & 0x0002);
USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
@@ -58,7 +59,7 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
rts);
usbd_cdc_acm_set_dtr(intf_num, dtr);
usbd_cdc_acm_set_rts(intf_num, rts);
} break;
break;
case CDC_REQUEST_GET_LINE_CODING:
usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
@@ -71,7 +72,9 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
line_coding.bParityType,
line_coding.bDataBits);
break;
case CDC_REQUEST_SEND_BREAK:
usbd_cdc_acm_send_break(intf_num);
break;
default:
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
@@ -80,22 +83,12 @@ static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setu
return 0;
}
static void cdc_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
break;
default:
break;
}
}
struct usbd_interface *usbd_cdc_acm_init_intf(struct usbd_interface *intf)
{
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = cdc_notify_handler;
intf->notify_handler = NULL;
return intf;
}
@@ -118,4 +111,8 @@ __WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
{
}
}
__WEAK void usbd_cdc_acm_send_break(uint8_t intf)
{
}

View File

@@ -20,6 +20,7 @@ void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_cod
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);
#ifdef __cplusplus
}

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

@@ -0,0 +1,237 @@
/*
* 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];
#ifdef CONFIG_USB_HS
#define CDC_ECM_MAX_PACKET_SIZE 512
#else
#define CDC_ECM_MAX_PACKET_SIZE 64
#endif
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16];
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_ecm_notification *notify = (struct cdc_ecm_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(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(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 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(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
break;
default:
break;
}
}
void cdc_ecm_bulk_out(uint8_t ep, uint32_t nbytes)
{
g_cdc_ecm_rx_data_length += nbytes;
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
usbd_cdc_ecm_data_recv_done();
} else {
usbd_ep_start_read(ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
}
}
void cdc_ecm_bulk_in(uint8_t ep, uint32_t nbytes)
{
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(ep, NULL, 0);
} else {
g_cdc_ecm_tx_data_length = 0;
}
}
void cdc_ecm_int_in(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);
}
}
#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) {
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);
g_cdc_ecm_rx_data_length = 0;
g_cdc_ecm_rx_data_buffer = NULL;
usbd_ep_start_read(cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
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;
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
return usbd_ep_start_write(cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, 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(&cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX]);
usbd_add_endpoint(&cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX]);
usbd_add_endpoint(&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(void)
{
}

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

@@ -0,0 +1,36 @@
/*
* 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
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
/* Init cdc ecm interface driver */
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
/* Setup request command callback api */
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
void usbd_cdc_ecm_data_recv_done(void);
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
#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

@@ -8,32 +8,34 @@
#define DEV_FORMAT "/dev/ttyACM%d"
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
static int usbh_cdc_acm_devno_alloc(struct usbh_cdc_acm *cdc_acm_class)
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
cdc_acm_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_cdc_acm_class[devno], 0, sizeof(struct usbh_cdc_acm));
g_cdc_acm_class[devno].minor = devno;
return &g_cdc_acm_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_cdc_acm_devno_free(struct usbh_cdc_acm *cdc_acm_class)
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
{
int devno = cdc_acm_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
}
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
@@ -48,7 +50,7 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
memcpy((uint8_t *)&g_cdc_line_coding, 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, (uint8_t *)&g_cdc_line_coding);
}
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
@@ -62,7 +64,7 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
setup->wIndex = cdc_acm_class->ctrl_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, (uint8_t *)&g_cdc_line_coding);
if (ret < 0) {
return ret;
}
@@ -83,7 +85,7 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo
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)
@@ -91,14 +93,12 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_cdc_acm *cdc_acm_class = usb_malloc(sizeof(struct usbh_cdc_acm));
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;
}
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
usbh_cdc_acm_devno_alloc(cdc_acm_class);
cdc_acm_class->hport = hport;
cdc_acm_class->ctrl_intf = intf;
cdc_acm_class->data_intf = intf + 1;
@@ -124,21 +124,15 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
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;
ep_cfg.ep_interval = ep_desc->bInterval;
ep_cfg.hport = hport;
usbh_pipe_alloc(&cdc_acm_class->intin, &ep_cfg);
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);
}
}
@@ -157,27 +151,57 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv;
if (cdc_acm_class) {
usbh_cdc_acm_devno_free(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);
}
usbh_cdc_acm_stop(cdc_acm_class);
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
usb_free(cdc_acm_class);
#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')
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);
}
usbh_cdc_acm_class_free(cdc_acm_class);
}
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;
@@ -190,12 +214,10 @@ static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
}
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
{
}
const struct usbh_class_driver cdc_acm_class_driver = {

View File

@@ -10,6 +10,12 @@
struct usbh_cdc_acm {
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 (optional) */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
struct usbh_urb intin_urb;
struct cdc_line_coding linecoding;
uint8_t ctrl_intf; /* Control interface number */
@@ -17,11 +23,6 @@ struct usbh_cdc_acm {
bool dtr;
bool rts;
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
};
#ifdef __cplusplus
@@ -32,6 +33,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);

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

@@ -0,0 +1,334 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_cdc_ecm.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_SEGSZE 1514U
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_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_notification(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_ecm_descriptor *desc = (struct cdc_ecm_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_SEGSZE) {
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE, cdc_ecm_class->max_segment_size);
} 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;
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_notification(&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], USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize), 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, PBUF_POOL);
if (p != NULL) {
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
g_cdc_ecm_rx_length = 0;
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 {
}
}
// 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,
.vid = 0x00,
.pid = 0x00,
.class_driver = &cdc_ecm_class_driver
};

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

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2022, 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;
};
#ifdef __cplusplus
extern "C" {
#endif
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_ACM_H */

View File

@@ -23,7 +23,7 @@
#define FLASH_ERASE_TIME 50
#endif
struct dfu_cfg_priv {
struct usbd_dfu_priv {
struct dfu_info info;
union {
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
@@ -40,26 +40,26 @@ struct dfu_cfg_priv {
uint8_t dev_state;
uint8_t manif_state;
uint8_t firmwar_flag;
} usbd_dfu_cfg;
} g_usbd_dfu;
static void dfu_reset(void)
{
memset(&usbd_dfu_cfg, 0, sizeof(usbd_dfu_cfg));
memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu));
usbd_dfu_cfg.alt_setting = 0U;
usbd_dfu_cfg.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
usbd_dfu_cfg.wblock_num = 0U;
usbd_dfu_cfg.wlength = 0U;
g_usbd_dfu.alt_setting = 0U;
g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[5] = 0U;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[5] = 0U;
}
static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
@@ -84,21 +84,21 @@ static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
static void dfu_request_detach(void)
{
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the state machine */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
usbd_dfu_cfg.dev_status[5] = 0U; /*iString*/
usbd_dfu_cfg.wblock_num = 0U;
usbd_dfu_cfg.wlength = 0U;
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
g_usbd_dfu.dev_status[5] = 0U; /*iString*/
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
}
}
@@ -109,62 +109,62 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
uint8_t *phaddr;
/* Data setup request */
if (req->wLength > 0U) {
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the global length and block number */
usbd_dfu_cfg.wblock_num = req->wValue;
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
g_usbd_dfu.wblock_num = req->wValue;
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
/* DFU Get Command */
if (usbd_dfu_cfg.wblock_num == 0U) {
if (g_usbd_dfu.wblock_num == 0U) {
/* Update the state machine */
usbd_dfu_cfg.dev_state = (usbd_dfu_cfg.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Store the values of all supported commands */
usbd_dfu_cfg.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
usbd_dfu_cfg.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
usbd_dfu_cfg.buffer.d8[2] = DFU_CMD_ERASE;
g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
/* Send the status data over EP0 */
memcpy(*data, usbd_dfu_cfg.buffer.d8, 3);
memcpy(*data, g_usbd_dfu.buffer.d8, 3);
*len = 3;
} else if (usbd_dfu_cfg.wblock_num > 1U) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
} else if (g_usbd_dfu.wblock_num > 1U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
/* Return the physical address where data are stored */
phaddr = dfu_read_flash((uint8_t *)addr, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
phaddr = dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
/* Send the status data over EP0 */
memcpy(*data, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
*len = usbd_dfu_cfg.wlength;
} else /* unsupported usbd_dfu_cfg.wblock_num */
memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
*len = g_usbd_dfu.wlength;
} else /* unsupported g_usbd_dfu.wblock_num */
{
usbd_dfu_cfg.dev_state = DFU_STATUS_ERR_STALLEDPKT;
g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_upload unsupported usbd_dfu_cfg.wblock_num\r\n");
USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
}
}
/* Unsupported state */
else {
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
@@ -172,12 +172,12 @@ static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, u
}
/* No Data setup request */
else {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
}
@@ -186,19 +186,19 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
/* Data setup request */
struct usb_setup_packet *req = setup;
if (req->wLength > 0U) {
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
/* Update the global length and block number */
usbd_dfu_cfg.wblock_num = req->wValue;
usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
g_usbd_dfu.wblock_num = req->wValue;
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
/* Update the state machine */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/*!< Data has received complete */
memcpy((uint8_t *)usbd_dfu_cfg.buffer.d8, (uint8_t *)*data, usbd_dfu_cfg.wlength);
memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
/*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
usbd_dfu_cfg.firmwar_flag = 1;
g_usbd_dfu.firmwar_flag = 1;
}
/* Unsupported state */
else {
@@ -208,16 +208,16 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
/* 0 Data DNLOAD request */
else {
/* End of DNLOAD operation*/
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE)) {
usbd_dfu_cfg.manif_state = DFU_MANIFEST_IN_PROGRESS;
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
} else {
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", usbd_dfu_cfg.dev_state);
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
}
}
}
@@ -225,63 +225,63 @@ static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, u
static int8_t dfu_getstatus_special_handler(void)
{
uint32_t addr;
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
/* Decode the Special Command */
if (usbd_dfu_cfg.wblock_num == 0U) {
if (usbd_dfu_cfg.wlength == 1U) {
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
if (g_usbd_dfu.wblock_num == 0U) {
if (g_usbd_dfu.wlength == 1U) {
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
/* Nothing to do */
}
} else if (usbd_dfu_cfg.wlength == 5U) {
if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
} else if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE) {
usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
} else if (g_usbd_dfu.wlength == 5U) {
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
} else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
USB_LOG_DBG("Erase start add %08x \r\n", usbd_dfu_cfg.data_ptr);
USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
/*!< Erase */
dfu_erase_flash(usbd_dfu_cfg.data_ptr);
dfu_erase_flash(g_usbd_dfu.data_ptr);
} else {
return -1;
}
} else {
/* Reset the global length and block number */
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Call the error management function (command will be NAKed) */
USB_LOG_ERR("Reset the global length and block number\r\n");
}
}
/* Regular Download Command */
else {
if (usbd_dfu_cfg.wblock_num > 1U) {
if (g_usbd_dfu.wblock_num > 1U) {
/* Decode the required address */
addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
/* Perform the write operation */
/* Write flash */
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, usbd_dfu_cfg.wlength);
dfu_write_flash(usbd_dfu_cfg.buffer.d8, (uint8_t *)addr, usbd_dfu_cfg.wlength);
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
}
}
/* Reset the global length and block number */
usbd_dfu_cfg.wlength = 0U;
usbd_dfu_cfg.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Update the state machine */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
return 0;
}
@@ -289,77 +289,77 @@ static int8_t dfu_getstatus_special_handler(void)
static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/*!< Determine whether to leave DFU mode */
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS &&
usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
usbd_dfu_cfg.dev_status[1] == 0U &&
usbd_dfu_cfg.dev_status[2] == 0U &&
usbd_dfu_cfg.dev_status[3] == 0U &&
usbd_dfu_cfg.dev_status[4] == usbd_dfu_cfg.dev_state) {
usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
g_usbd_dfu.dev_status[1] == 0U &&
g_usbd_dfu.dev_status[2] == 0U &&
g_usbd_dfu.dev_status[3] == 0U &&
g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
return;
} else {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Generate system reset to allow jumping to the user code */
dfu_leave();
}
}
switch (usbd_dfu_cfg.dev_state) {
switch (g_usbd_dfu.dev_state) {
case DFU_STATE_DFU_DNLOAD_SYNC:
if (usbd_dfu_cfg.wlength != 0U) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
if (g_usbd_dfu.wlength != 0U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
if ((usbd_dfu_cfg.wblock_num == 0U) && (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE)) {
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_ERASE, usbd_dfu_cfg.dev_status);
if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
} else {
dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_PROGRAM, usbd_dfu_cfg.dev_status);
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
}
} else /* (usbd_dfu_cfg.wlength==0)*/
} else /* (g_usbd_dfu.wlength==0)*/
{
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
break;
case DFU_STATE_DFU_MANIFEST_SYNC:
if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST;
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
usbd_dfu_cfg.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
} else {
if ((usbd_dfu_cfg.manif_state == DFU_MANIFEST_COMPLETE) &&
if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
((0x0B & DFU_MANIFEST_MASK) != 0U)) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U;
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
}
break;
@@ -369,62 +369,62 @@ static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data
}
/* Send the status data over EP0 */
memcpy(*data, usbd_dfu_cfg.dev_status, 6);
memcpy(*data, g_usbd_dfu.dev_status, 6);
*len = 6;
if (usbd_dfu_cfg.firmwar_flag == 1) {
if (g_usbd_dfu.firmwar_flag == 1) {
if (dfu_getstatus_special_handler() != 0) {
USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
}
usbd_dfu_cfg.firmwar_flag = 0;
g_usbd_dfu.firmwar_flag = 0;
}
}
static void dfu_request_clrstatus(void)
{
if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_ERROR) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK; /* bStatus */
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
g_usbd_dfu.dev_status[5] = 0U; /* iString */
} else {
/* State Error */
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_ERROR;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
g_usbd_dfu.dev_status[5] = 0U; /* iString */
}
}
static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Return the current state of the DFU interface */
(*data)[0] = usbd_dfu_cfg.dev_state;
(*data)[0] = g_usbd_dfu.dev_state;
*len = 1;
}
void dfu_request_abort(void)
{
if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
usbd_dfu_cfg.dev_status[1] = 0U;
usbd_dfu_cfg.dev_status[2] = 0U;
usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
usbd_dfu_cfg.wblock_num = 0U;
usbd_dfu_cfg.wlength = 0U;
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
g_usbd_dfu.dev_status[5] = 0U; /* iString */
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
}
}

View File

@@ -387,7 +387,7 @@
#define HID_KBD_USAGE_PAGEDOWN 0x4e /* Keyboard PageDown */
#define HID_KBD_USAGE_RIGHT 0x4f /* eyboard RightArrow */
#define HID_KBD_USAGE_LEFT 0x50 /* Keyboard LeftArrow */
#define HID_KBD_USAGE_DOWN 0x5a /* Keyboard DownArrow */
#define HID_KBD_USAGE_DOWN 0x51 /* Keyboard DownArrow */
#define HID_KBD_USAGE_UP 0x52 /* Keyboard UpArrow */
#define HID_KBD_USAGE_KPDNUMLOCK 0x53 /* Keypad Num Lock and Clear */
#define HID_KBD_USAGE_KPDNUMLOCKCLEAR 0x53 /* Keypad Num Lock and Clear */

View File

@@ -17,28 +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 */
(*data)[0] = usbh_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
*len = 1;
usbd_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), data, len);
break;
case HID_REQUEST_GET_IDLE:
(*data)[0] = usbh_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
(*data)[0] = usbd_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
*len = 1;
break;
case HID_REQUEST_GET_PROTOCOL:
(*data)[0] = usbh_hid_get_protocol(intf_num);
(*data)[0] = usbd_hid_get_protocol(intf_num);
*len = 1;
break;
case HID_REQUEST_SET_REPORT:
/* report id ,report type, report, report len */
usbh_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
usbd_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
break;
case HID_REQUEST_SET_IDLE:
/* report id, duration */
usbh_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
usbd_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
break;
case HID_REQUEST_SET_PROTOCOL:
/* protocol */
usbh_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
usbd_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
break;
default:
@@ -61,29 +60,30 @@ struct usbd_interface *usbd_hid_init_intf(struct usbd_interface *intf, const uin
return intf;
}
__WEAK uint8_t usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type)
__WEAK void usbd_hid_get_report(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)
{
return 0;
}
__WEAK uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id)
__WEAK uint8_t usbd_hid_get_protocol(uint8_t intf)
{
return 0;
}
__WEAK uint8_t usbh_hid_get_protocol(uint8_t intf)
{
return 0;
}
__WEAK void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len)
__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 usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
__WEAK void usbd_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
{
}
__WEAK void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol)
__WEAK void usbd_hid_set_protocol(uint8_t intf, uint8_t protocol)
{
}

View File

@@ -20,12 +20,12 @@ 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);
/* Setup request command callback api */
uint8_t usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type);
uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id);
uint8_t usbh_hid_get_protocol(uint8_t intf);
void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len);
void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol);
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);
#ifdef __cplusplus
}

View File

@@ -8,33 +8,34 @@
#define DEV_FORMAT "/dev/input%d"
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
static int usbh_hid_devno_alloc(struct usbh_hid *hid_class)
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
static uint32_t g_devinuse = 0;
static struct usbh_hid *usbh_hid_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
hid_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
g_hid_class[devno].minor = devno;
return &g_hid_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_hid_devno_free(struct usbh_hid *hid_class)
static void usbh_hid_class_free(struct usbh_hid *hid_class)
{
int devno = hid_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hid_class, 0, sizeof(struct usbh_hid));
}
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
@@ -48,7 +49,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;
}
@@ -66,7 +67,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)
@@ -80,7 +81,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;
}
@@ -98,7 +99,7 @@ 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_connect(struct usbh_hubport *hport, uint8_t intf)
@@ -106,14 +107,12 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_hid *hid_class = usb_malloc(sizeof(struct usbh_hid));
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;
}
memset(hid_class, 0, sizeof(struct usbh_hid));
usbh_hid_devno_alloc(hid_class);
hid_class->hport = hport;
hid_class->intf = intf;
@@ -138,9 +137,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,22 +158,20 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv;
if (hid_class) {
usbh_hid_devno_free(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);
}
usbh_hid_stop(hid_class);
memset(hid_class, 0, sizeof(struct usbh_hid));
usb_free(hid_class);
if (hport->config.intf[intf].devname[0] != '\0')
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HID Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hid_stop(hid_class);
}
usbh_hid_class_free(hid_class);
}
return ret;
@@ -182,12 +179,10 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
{
}
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
{
}
const struct usbh_class_driver hid_class_driver = {

View File

@@ -10,12 +10,14 @@
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 intf; /* interface number */
uint8_t minor;
usbh_pipe_t intin; /* INTR IN endpoint */
usbh_pipe_t intout; /* INTR OUT endpoint */
};
#ifdef __cplusplus

View File

@@ -7,7 +7,8 @@
#define USB_HUB_H
/* HUB Class Descriptor Types */
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
/* Hub class requests */
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
@@ -19,6 +20,7 @@
#define HUB_REQUEST_RESET_TT (0x09)
#define HUB_REQUEST_GET_TT_STATE (0x0a)
#define HUB_REQUEST_STOP_TT (0x0b)
#define HUB_REQUEST_SET_HUB_DEPTH (0x0C)
/* Hub class features */
#define HUB_FEATURE_HUB_C_LOCALPOWER (0x0)

View File

@@ -3,21 +3,20 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
#define DEV_FORMAT "/dev/hub%d"
#define DEV_FORMAT "/dev/hub%d"
#define HUB_DEBOUNCE_TIMEOUT 1500
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
#define DELAY_TIME_AFTER_RESET 200
#define EXTHUB_FIRST_INDEX 2
static uint32_t g_devinuse = 0;
#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][1];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USB_ALIGN_SIZE];
usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
@@ -26,37 +25,45 @@ usb_osal_mq_t hub_mq;
struct usbh_hub roothub;
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
#endif
extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
extern int usbh_free_devaddr(struct usbh_hubport *hport);
extern int usbh_enumerate(struct usbh_hubport *hport);
static void usbh_hub_thread_wakeup(struct usbh_hub *hub);
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
#ifdef CONFIG_USBHOST_XHCI
struct usbh_hubport *usbh_get_roothub_port(unsigned int port)
{
return &roothub.child[port - 1];
}
#endif
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int usbh_hub_devno_alloc(void)
static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
static uint32_t g_devinuse = 0;
static struct usbh_hub *usbh_hub_class_alloc(void)
{
int devno;
for (devno = EXTHUB_FIRST_INDEX; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
return devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
return &g_hub_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_hub_devno_free(uint8_t devno)
static void usbh_hub_class_free(struct usbh_hub *hub_class)
{
if (devno >= EXTHUB_FIRST_INDEX && devno < 32) {
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(hub_class, 0, sizeof(struct usbh_hub));
}
#endif
@@ -65,6 +72,7 @@ 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);
@@ -79,18 +87,27 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
/* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
and we havn't handle the difference here */
if ((hub->parent->speed == USB_SPEED_SUPER) ||
(hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
} else {
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
}
setup->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);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hub_buf, 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;
@@ -104,13 +121,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);
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hub_buf, 2);
return ret;
}
#endif
#endif
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -125,7 +144,7 @@ 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);
if (ret < 0) {
return ret;
}
@@ -145,7 +164,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)
@@ -160,9 +179,25 @@ 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)
{
struct usb_setup_packet *setup;
setup = hub->parent->setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
setup->wValue = depth;
setup->wIndex = 0;
setup->wLength = 0;
return usbh_control_transfer(hub->parent, setup, NULL);
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
{
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
@@ -184,6 +219,7 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
}
return 0;
}
#endif
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -203,7 +239,7 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hu
}
}
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;
@@ -221,7 +257,7 @@ static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feat
}
}
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;
@@ -239,6 +275,45 @@ static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t fe
}
}
static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
{
struct usb_setup_packet roothub_setup;
struct usb_setup_packet *setup;
if (hub->is_roothub) {
setup = &roothub_setup;
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
setup->wValue = depth;
setup->wIndex = 0;
setup->wLength = 0;
return usbh_roothub_control(setup, NULL);
} else {
return _usbh_hub_set_depth(hub, depth);
}
}
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
{
usb_osal_mq_send(hub_mq, (uintptr_t)hub);
}
static void usbh_hubport_release(struct usbh_hubport *child)
{
if (child->connected) {
child->connected = false;
usbh_free_devaddr(child);
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(child, i);
}
}
child->config.config_desc.bNumInterfaces = 0;
usbh_kill_urb(&child->ep0_urb);
usb_osal_mutex_delete(child->mutex);
}
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static void hub_int_complete_callback(void *arg, int nbytes)
{
@@ -254,21 +329,15 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
struct usb_endpoint_descriptor *ep_desc;
struct hub_port_status port_status;
int ret;
int index;
index = usbh_hub_devno_alloc();
if (index > (CONFIG_USBHOST_MAX_EXTHUBS + EXTHUB_FIRST_INDEX - 1)) {
USB_LOG_ERR("No memory to alloc hub class\r\n");
usbh_hub_devno_free(index);
return -ENOMEM;
struct usbh_hub *hub = usbh_hub_class_alloc();
if (hub == NULL) {
USB_LOG_ERR("Fail to alloc hub_class\r\n");
return -USB_ERR_NOMEM;
}
struct usbh_hub *hub = &exthub[index - EXTHUB_FIRST_INDEX];
memset(hub, 0, sizeof(struct usbh_hub));
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->index = index;
hport->config.intf[intf].priv = hub;
@@ -286,11 +355,25 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
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;
}
if (hport->speed == USB_SPEED_SUPER) {
uint16_t depth = 0;
struct usbh_hubport *parent = hport->parent->parent;
while (parent) {
depth++;
parent = parent->parent->parent;
}
ret = usbh_hub_set_depth(hub, depth);
if (ret < 0) {
return ret;
}
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
if (ret < 0) {
@@ -312,7 +395,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
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_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);
return 0;
}
@@ -325,47 +408,37 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
if (hub) {
usbh_hub_devno_free(hub->index);
if (hub->intin) {
usbh_pipe_free(hub->intin);
usbh_kill_urb(&hub->intin_urb);
}
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;
}
usbh_hub_unregister(hub);
memset(hub, 0, sizeof(struct usbh_hub));
if (hport->config.intf[intf].devname[0] != '\0')
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);
}
usbh_hub_class_free(hub);
}
return ret;
}
#endif
static void usbh_hubport_release(struct usbh_hubport *child)
static void usbh_hubport_enumerate_thread(void *argument)
{
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;
struct usbh_hubport *child = (struct usbh_hubport *)argument;
if (usbh_enumerate(child) < 0) {
/** release child sources */
usbh_hubport_release(child);
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
}
usb_osal_thread_delete(NULL);
}
static void usbh_hub_events(struct usbh_hub *hub)
@@ -384,9 +457,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] = 0;
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)))) {
@@ -496,9 +570,25 @@ static void usbh_hub_events(struct usbh_hub *hub)
speed = USB_SPEED_HIGH;
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
speed = USB_SPEED_LOW;
} else {
}
#ifdef CONFIG_USBHOST_XHCI
else {
extern uint8_t usbh_get_port_speed(struct usbh_hub * hub, const uint8_t port);
/* USB3.0 speed cannot get from portstatus, checkout port speed instead */
uint8_t super_speed = usbh_get_port_speed(hub, port + 1);
if (super_speed > USB_SPEED_HIGH) {
/* assert that when using USB 3.0 ports, attached device must also be USB 3.0 speed */
speed = super_speed;
} else {
speed = USB_SPEED_FULL;
}
}
#else
else {
speed = USB_SPEED_FULL;
}
#endif
child = &hub->child[port];
/** release child sources first */
@@ -509,22 +599,19 @@ static void usbh_hub_events(struct usbh_hub *hub)
child->connected = true;
child->port = port + 1;
child->speed = speed;
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);
/* 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);
USB_LOG_ERR("Port %u enumerate fail\r\n", port + 1);
}
/* create disposable thread to enumerate device on current hport, do not block hub thread */
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
} else {
child = &hub->child[port];
/** release child sources */
usbh_hubport_release(child);
USB_LOG_ERR("Failed to enable port %u\r\n", port + 1);
/** some USB 3.0 ip may failed to enable USB 2.0 port for USB 3.0 device */
USB_LOG_WRN("Failed to enable port %u\r\n", port + 1);
continue;
}
@@ -537,7 +624,6 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
}
hub->int_buffer[0] = 0;
/* Start next hub int transfer */
if (!hub->is_roothub && hub->connected) {
usbh_submit_urb(&hub->intin_urb);
@@ -551,7 +637,7 @@ static void usbh_hub_thread(void *argument)
usb_hc_init();
while (1) {
ret = usb_osal_mq_recv(hub_mq, (uint32_t *)&hub, 0xffffffff);
ret = usb_osal_mq_recv(hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
@@ -561,6 +647,8 @@ static void usbh_hub_thread(void *argument)
static void usbh_roothub_register(void)
{
usb_slist_init(&hub_class_head);
memset(&roothub, 0, sizeof(struct usbh_hub));
roothub.connected = true;
@@ -572,11 +660,6 @@ static void usbh_roothub_register(void)
usbh_hub_register(&roothub);
}
static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
{
usb_osal_mq_send(hub_mq, (uint32_t)hub);
}
void usbh_roothub_thread_wakeup(uint8_t port)
{
roothub.int_buffer = g_hub_intbuf[roothub.index - 1];
@@ -599,6 +682,36 @@ int usbh_hub_initialize(void)
}
return 0;
}
int usbh_hub_deinitialize(void)
{
usb_slist_t *i;
struct usbh_hubport *hport;
size_t flags;
flags = usb_osal_enter_critical_section();
usb_slist_for_each(i, &hub_class_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];
usbh_hubport_release(hport);
}
}
usb_hc_deinit();
usb_osal_leave_critical_section(flags);
usb_osal_mq_delete(hub_mq);
usb_osal_thread_delete(hub_thread);
return 0;
}
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
const struct usbh_class_driver hub_class_driver = {
.driver_name = "hub",

View File

@@ -6,7 +6,6 @@
#ifndef USBH_HUB_H
#define USBH_HUB_H
#include "usbh_core.h"
#include "usb_hub.h"
#define USBH_HUB_MAX_PORTS 4
@@ -14,12 +13,20 @@
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
extern usb_slist_t hub_class_head;
extern struct usbh_hub roothub;
#ifdef __cplusplus
extern "C" {
#endif
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_roothub_thread_wakeup(uint8_t port);
int usbh_hub_initialize(void);
int usbh_hub_deinitialize(void);
#ifdef __cplusplus
}
#endif

View File

@@ -23,6 +23,26 @@
#define MIDI_PITCHBEND_MIN -8192
#define MIDI_PITCHBEND_MAX 8191
/*! Enumeration of MIDI code index number */
enum MidiCodeIndexNumber {
MIDI_CIN_MISC = 0,
MIDI_CIN_CABLE_EVENT = 1,
MIDI_CIN_SYSCOM_2BYTE = 2, ///< 2 byte system common message e.g MTC, SongSelect
MIDI_CIN_SYSCOM_3BYTE = 3, ///< 3 byte system common message e.g SPP
MIDI_CIN_SYSEX_START = 4, ///< SysEx starts or continue
MIDI_CIN_SYSEX_END_1BYTE = 5, ///< SysEx ends with 1 data, or 1 byte system common message
MIDI_CIN_SYSEX_END_2BYTE = 6, ///< SysEx ends with 2 data
MIDI_CIN_SYSEX_END_3BYTE = 7, ///< SysEx ends with 3 data
MIDI_CIN_NOTE_OFF = 8,
MIDI_CIN_NOTE_ON = 9,
MIDI_CIN_POLY_KEYPRESS = 10,
MIDI_CIN_CONTROL_CHANGE = 11,
MIDI_CIN_PROGRAM_CHANGE = 12,
MIDI_CIN_CHANNEL_PRESSURE = 13,
MIDI_CIN_PITCH_BEND_CHANGE = 14,
MIDI_CIN_1BYTE_DATA = 15
};
/*! Enumeration of MIDI types */
enum MidiType {
InvalidType = 0x00, ///< For notifying errors
@@ -181,6 +201,13 @@ struct midi_cs_ep_ms_general_descriptor {
#define MIDI_SIZEOF_MS_GENERAL_DESC(n) (4 + n)
// clang-format off
#define MIDI_CS_HEADER_DESCRIPTOR_INIT(wTotalLength) \
0x07, /* bLength */ \
USB_CS_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
MIDI_MS_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubtype */ \
WBVAL(0x0100), /* bcdMSC */ \
WBVAL(wTotalLength) /* wTotalLength */
#define MIDI_IN_JACK_DESCRIPTOR_INIT(bJackType, bJackID) \
0x06, \
0x24, \

View File

@@ -61,8 +61,7 @@ struct CSW {
/*Length of template descriptor: 23 bytes*/
#define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
// clang-format off
#ifndef CONFIG_USB_HS
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, wMaxPacketSize, str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
@@ -77,39 +76,14 @@ struct CSW {
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00 /* bInterval */
#else
#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x02, /* bNumEndpoints */ \
USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \
MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00 /* bInterval */
#endif
// clang-format on
#endif /* USB_MSC_H */

View File

@@ -6,6 +6,9 @@
#include "usbd_core.h"
#include "usbd_msc.h"
#include "usb_scsi.h"
#if defined(CONFIG_USBDEV_MSC_THREAD)
#include "usb_osal.h"
#endif
#define MSD_OUT_EP_IDX 0
#define MSD_IN_EP_IDX 1
@@ -23,13 +26,14 @@ enum Stage {
};
/* Device data structure */
USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
/* state of the bulk-only state machine */
enum Stage stage;
USB_MEM_ALIGNX struct CBW cbw;
USB_MEM_ALIGNX struct CSW csw;
bool readonly;
bool popup;
uint8_t sKey; /* Sense key */
uint8_t ASC; /* Additional Sense Code */
uint8_t ASQ; /* Additional Sense Qualifier */
@@ -39,13 +43,19 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
uint16_t scsi_blk_size;
uint32_t scsi_blk_nbr;
uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
} usbd_msc_cfg;
USB_MEM_ALIGNX uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
#if defined(CONFIG_USBDEV_MSC_THREAD)
usb_osal_mq_t usbd_msc_mq;
usb_osal_thread_t usbd_msc_thread;
uint32_t nbytes;
#endif
} g_usbd_msc;
static void usbd_msc_reset(void)
{
usbd_msc_cfg.stage = MSC_READ_CBW;
usbd_msc_cfg.readonly = false;
g_usbd_msc.stage = MSC_READ_CBW;
g_usbd_msc.readonly = false;
}
static int msc_storage_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
@@ -60,7 +70,7 @@ static int msc_storage_class_interface_request_handler(struct usb_setup_packet *
break;
case MSC_REQUEST_GET_MAX_LUN:
(*data)[0] = usbd_msc_cfg.max_lun;
(*data)[0] = g_usbd_msc.max_lun;
*len = 1;
break;
@@ -80,7 +90,7 @@ void msc_storage_notify_handler(uint8_t event, void *arg)
break;
case USBD_EVENT_CONFIGURED:
USB_LOG_DBG("Start reading cbw\r\n");
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
break;
default:
@@ -90,40 +100,40 @@ void msc_storage_notify_handler(uint8_t event, void *arg)
static void usbd_msc_bot_abort(void)
{
if ((usbd_msc_cfg.cbw.bmFlags == 0) && (usbd_msc_cfg.cbw.dDataLength != 0)) {
if ((g_usbd_msc.cbw.bmFlags == 0) && (g_usbd_msc.cbw.dDataLength != 0)) {
usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr);
}
usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr);
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
}
static void usbd_msc_send_csw(uint8_t CSW_Status)
{
usbd_msc_cfg.csw.dSignature = MSC_CSW_Signature;
usbd_msc_cfg.csw.bStatus = CSW_Status;
g_usbd_msc.csw.dSignature = MSC_CSW_Signature;
g_usbd_msc.csw.bStatus = CSW_Status;
/* updating the State Machine , so that we wait CSW when this
* transfer is complete, ie when we get a bulk in callback
*/
usbd_msc_cfg.stage = MSC_WAIT_CSW;
g_usbd_msc.stage = MSC_WAIT_CSW;
USB_LOG_DBG("Send csw\r\n");
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw, sizeof(struct CSW));
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.csw, sizeof(struct CSW));
}
static void usbd_msc_send_info(uint8_t *buffer, uint8_t size)
{
size = MIN(size, usbd_msc_cfg.cbw.dDataLength);
size = MIN(size, g_usbd_msc.cbw.dDataLength);
/* updating the State Machine , so that we send CSW when this
* transfer is complete, ie when we get a bulk in callback
*/
usbd_msc_cfg.stage = MSC_SEND_CSW;
g_usbd_msc.stage = MSC_SEND_CSW;
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size);
usbd_msc_cfg.csw.dDataResidue -= size;
usbd_msc_cfg.csw.bStatus = CSW_STATUS_CMD_PASSED;
g_usbd_msc.csw.dDataResidue -= size;
g_usbd_msc.csw.bStatus = CSW_STATUS_CMD_PASSED;
}
static bool SCSI_processWrite(uint32_t nbytes);
@@ -139,9 +149,9 @@ static bool SCSI_processRead(void);
*/
static void SCSI_SetSenseData(uint32_t KCQ)
{
usbd_msc_cfg.sKey = (uint8_t)(KCQ >> 16);
usbd_msc_cfg.ASC = (uint8_t)(KCQ >> 8);
usbd_msc_cfg.ASQ = (uint8_t)(KCQ);
g_usbd_msc.sKey = (uint8_t)(KCQ >> 16);
g_usbd_msc.ASC = (uint8_t)(KCQ >> 8);
g_usbd_msc.ASQ = (uint8_t)(KCQ);
}
/**
@@ -151,7 +161,7 @@ static void SCSI_SetSenseData(uint32_t KCQ)
static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
{
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
if (g_usbd_msc.cbw.dDataLength != 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
@@ -163,13 +173,13 @@ static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
{
uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
if (g_usbd_msc.cbw.dDataLength == 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
data_len = usbd_msc_cfg.cbw.CB[4];
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
data_len = g_usbd_msc.cbw.CB[4];
}
uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = {
@@ -193,9 +203,9 @@ static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
0x00,
};
request_sense[2] = usbd_msc_cfg.sKey;
request_sense[12] = usbd_msc_cfg.ASC;
request_sense[13] = usbd_msc_cfg.ASQ;
request_sense[2] = g_usbd_msc.sKey;
request_sense[12] = g_usbd_msc.ASC;
request_sense[13] = g_usbd_msc.ASQ;
#if 0
request_sense[ 2] = 0x06; /* UNIT ATTENTION */
request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */
@@ -269,16 +279,16 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
memcpy(&inquiry[16], CONFIG_USBDEV_MSC_PRODUCT_STRING, strlen(CONFIG_USBDEV_MSC_PRODUCT_STRING));
memcpy(&inquiry[32], CONFIG_USBDEV_MSC_VERSION_STRING, strlen(CONFIG_USBDEV_MSC_VERSION_STRING));
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
if (g_usbd_msc.cbw.dDataLength == 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if ((usbd_msc_cfg.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
if (usbd_msc_cfg.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
if ((g_usbd_msc.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
if (g_usbd_msc.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
data_len = 0x06;
memcpy(*data, (uint8_t *)inquiry00, data_len);
} else if (usbd_msc_cfg.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
} else if (g_usbd_msc.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
data_len = 0x08;
memcpy(*data, (uint8_t *)inquiry80, data_len);
} else { /* Request Not supported */
@@ -286,8 +296,8 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
return false;
}
} else {
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
data_len = usbd_msc_cfg.cbw.CB[4];
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
data_len = g_usbd_msc.cbw.CB[4];
}
memcpy(*data, (uint8_t *)inquiry, data_len);
}
@@ -298,18 +308,19 @@ static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
{
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
if (g_usbd_msc.cbw.dDataLength != 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
{
//SCSI_MEDIUM_UNLOCKED;
} else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
{
//SCSI_MEDIUM_EJECTED;
} else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
g_usbd_msc.popup = true;
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
{
//SCSI_MEDIUM_UNLOCKED;
} else {
@@ -322,11 +333,11 @@ static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
{
if (usbd_msc_cfg.cbw.dDataLength != 0U) {
if (g_usbd_msc.cbw.dDataLength != 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (usbd_msc_cfg.cbw.CB[4] == 0U) {
if (g_usbd_msc.cbw.CB[4] == 0U) {
//SCSI_MEDIUM_UNLOCKED;
} else {
//SCSI_MEDIUM_LOCKED;
@@ -339,17 +350,17 @@ static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
{
uint8_t data_len = 4;
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
if (g_usbd_msc.cbw.dDataLength == 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
data_len = usbd_msc_cfg.cbw.CB[4];
if (g_usbd_msc.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
data_len = g_usbd_msc.cbw.CB[4];
}
uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 };
if (usbd_msc_cfg.readonly) {
if (g_usbd_msc.readonly) {
sense6[2] = 0x80;
}
memcpy(*data, (uint8_t *)sense6, data_len);
@@ -360,13 +371,13 @@ static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
{
uint8_t data_len = 27;
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
if (g_usbd_msc.cbw.dDataLength == 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if (usbd_msc_cfg.cbw.CB[8] < 27) {
data_len = usbd_msc_cfg.cbw.CB[8];
if (g_usbd_msc.cbw.CB[8] < 27) {
data_len = g_usbd_msc.cbw.CB[8];
}
uint8_t sense10[27] = {
@@ -406,7 +417,7 @@ static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
{
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
if (g_usbd_msc.cbw.dDataLength == 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
@@ -415,15 +426,15 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
0x00,
0x00,
0x08, /* Capacity List Length */
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 24) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 16) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 8) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 0) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 24) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 16) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 8) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_nbr >> 0) & 0xff),
0x02, /* Descriptor Code: Formatted Media */
0x00,
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
};
memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
@@ -433,21 +444,21 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
{
if (usbd_msc_cfg.cbw.dDataLength == 0U) {
if (g_usbd_msc.cbw.dDataLength == 0U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 24) & 0xff),
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 16) & 0xff),
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 8) & 0xff),
(uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 0) & 0xff),
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 24) & 0xff),
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 16) & 0xff),
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 8) & 0xff),
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 0) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 24) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 16) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
(uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_size >> 24) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_size >> 16) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
};
memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
@@ -457,113 +468,123 @@ static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
static bool SCSI_read10(uint8_t **data, uint32_t *len)
{
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
return false;
}
usbd_msc_cfg.stage = MSC_DATA_IN;
g_usbd_msc.stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
return true;
#else
return SCSI_processRead();
#endif
}
static bool SCSI_read12(uint8_t **data, uint32_t *len)
{
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
return false;
}
usbd_msc_cfg.stage = MSC_DATA_IN;
g_usbd_msc.stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
return true;
#else
return SCSI_processRead();
#endif
}
static bool SCSI_write10(uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (usbd_msc_cfg.cbw.dDataLength != data_len) {
if (g_usbd_msc.cbw.dDataLength != data_len) {
return false;
}
usbd_msc_cfg.stage = MSC_DATA_OUT;
g_usbd_msc.stage = MSC_DATA_OUT;
data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
return true;
}
static bool SCSI_write12(uint8_t **data, uint32_t *len)
{
uint32_t data_len = 0;
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
g_usbd_msc.start_sector = GET_BE32(&g_usbd_msc.cbw.CB[2]); /* Logical Block Address of First Block */
USB_LOG_DBG("lba: 0x%04x\r\n", g_usbd_msc.start_sector);
usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (usbd_msc_cfg.cbw.dDataLength != data_len) {
if (g_usbd_msc.cbw.dDataLength != data_len) {
return false;
}
usbd_msc_cfg.stage = MSC_DATA_OUT;
g_usbd_msc.stage = MSC_DATA_OUT;
data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
return true;
}
/* do not use verify to reduce code size */
@@ -574,41 +595,41 @@ static bool SCSI_verify10(uint8_t **data, uint32_t *len)
uint32_t lba = 0;
uint32_t blk_num = 0;
if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x00U) {
if ((g_usbd_msc.cbw.CB[1] & 0x02U) == 0x00U) {
return true;
}
if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
if (((g_usbd_msc.cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc.cbw.dDataLength == 0U)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x02U) {
if ((g_usbd_msc.cbw.CB[1] & 0x02U) == 0x02U) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA);
return false; /* Error, Verify Mode Not supported*/
}
lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]);
lba = GET_BE32(&g_usbd_msc.cbw.CB[2]);
USB_LOG_DBG("lba: 0x%x\r\n", lba);
usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size;
g_usbd_msc.scsi_blk_addr = lba * g_usbd_msc.scsi_blk_size;
/* Number of Blocks to transfer */
blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]);
blk_num = GET_BE16(&g_usbd_msc.cbw.CB[7]);
USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num);
usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size;
g_usbd_msc.scsi_blk_len = blk_num * g_usbd_msc.scsi_blk_size;
if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) {
if ((lba + blk_num) > g_usbd_msc.scsi_blk_nbr) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) {
if (g_usbd_msc.cbw.dDataLength != g_usbd_msc.scsi_blk_len) {
return false;
}
usbd_msc_cfg.stage = MSC_DATA_OUT;
g_usbd_msc.stage = MSC_DATA_OUT;
return true;
}
#endif
@@ -617,23 +638,23 @@ static bool SCSI_processRead(void)
{
uint32_t transfer_len;
USB_LOG_DBG("read lba:%d\r\n", usbd_msc_cfg.start_sector);
USB_LOG_DBG("read lba:%d\r\n", g_usbd_msc.start_sector);
transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
transfer_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, transfer_len) != 0) {
if (usbd_msc_sector_read(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, transfer_len) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
return false;
}
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, transfer_len);
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, g_usbd_msc.block_buffer, transfer_len);
usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size);
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
g_usbd_msc.start_sector += (transfer_len / g_usbd_msc.scsi_blk_size);
g_usbd_msc.nsectors -= (transfer_len / g_usbd_msc.scsi_blk_size);
g_usbd_msc.csw.dDataResidue -= transfer_len;
if (usbd_msc_cfg.nsectors == 0) {
usbd_msc_cfg.stage = MSC_SEND_CSW;
if (g_usbd_msc.nsectors == 0) {
g_usbd_msc.stage = MSC_SEND_CSW;
}
return true;
@@ -642,22 +663,22 @@ static bool SCSI_processRead(void)
static bool SCSI_processWrite(uint32_t nbytes)
{
uint32_t data_len = 0;
USB_LOG_DBG("write lba:%d\r\n", usbd_msc_cfg.start_sector);
USB_LOG_DBG("write lba:%d\r\n", g_usbd_msc.start_sector);
if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, nbytes) != 0) {
if (usbd_msc_sector_write(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, nbytes) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
return false;
}
usbd_msc_cfg.start_sector += (nbytes / usbd_msc_cfg.scsi_blk_size);
usbd_msc_cfg.nsectors -= (nbytes / usbd_msc_cfg.scsi_blk_size);
usbd_msc_cfg.csw.dDataResidue -= nbytes;
g_usbd_msc.start_sector += (nbytes / g_usbd_msc.scsi_blk_size);
g_usbd_msc.nsectors -= (nbytes / g_usbd_msc.scsi_blk_size);
g_usbd_msc.csw.dDataResidue -= nbytes;
if (usbd_msc_cfg.nsectors == 0) {
if (g_usbd_msc.nsectors == 0) {
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
} else {
data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
data_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
}
return true;
@@ -665,7 +686,7 @@ static bool SCSI_processWrite(uint32_t nbytes)
static bool SCSI_CBWDecode(uint32_t nbytes)
{
uint8_t *buf2send = usbd_msc_cfg.block_buffer;
uint8_t *buf2send = g_usbd_msc.block_buffer;
uint32_t len2send = 0;
bool ret = false;
@@ -675,15 +696,15 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
return false;
}
usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag;
usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength;
g_usbd_msc.csw.dTag = g_usbd_msc.cbw.dTag;
g_usbd_msc.csw.dDataResidue = g_usbd_msc.cbw.dDataLength;
if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) {
if ((g_usbd_msc.cbw.bLUN > 1) || (g_usbd_msc.cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc.cbw.bCBLength < 1) || (g_usbd_msc.cbw.bCBLength > 16)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
} else {
USB_LOG_DBG("Decode CB:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
switch (usbd_msc_cfg.cbw.CB[0]) {
USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc.cbw.CB[0]);
switch (g_usbd_msc.cbw.CB[0]) {
case SCSI_CMD_TESTUNITREADY:
ret = SCSI_testUnitReady(&buf2send, &len2send);
break;
@@ -730,13 +751,13 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
default:
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", g_usbd_msc.cbw.CB[0]);
ret = false;
break;
}
}
if (ret) {
if (usbd_msc_cfg.stage == MSC_READ_CBW) {
if (g_usbd_msc.stage == MSC_READ_CBW) {
if (len2send) {
USB_LOG_DBG("Send info len:%d\r\n", len2send);
usbd_msc_send_info(buf2send, len2send);
@@ -750,21 +771,26 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
{
switch (usbd_msc_cfg.stage) {
switch (g_usbd_msc.stage) {
case MSC_READ_CBW:
if (SCSI_CBWDecode(nbytes) == false) {
USB_LOG_ERR("Command:0x%02x decode err\r\n", usbd_msc_cfg.cbw.CB[0]);
USB_LOG_ERR("Command:0x%02x decode err\r\n", g_usbd_msc.cbw.CB[0]);
usbd_msc_bot_abort();
return;
}
break;
case MSC_DATA_OUT:
switch (usbd_msc_cfg.cbw.CB[0]) {
switch (g_usbd_msc.cbw.CB[0]) {
case SCSI_CMD_WRITE10:
case SCSI_CMD_WRITE12:
#ifdef CONFIG_USBDEV_MSC_THREAD
g_usbd_msc.nbytes = nbytes;
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_OUT);
#else
if (SCSI_processWrite(nbytes) == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
#endif
break;
default:
break;
@@ -777,15 +803,19 @@ void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
{
switch (usbd_msc_cfg.stage) {
switch (g_usbd_msc.stage) {
case MSC_DATA_IN:
switch (usbd_msc_cfg.cbw.CB[0]) {
switch (g_usbd_msc.cbw.CB[0]) {
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
#ifdef CONFIG_USBDEV_MSC_THREAD
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
#else
if (SCSI_processRead() == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
return;
}
#endif
break;
default:
break;
@@ -798,9 +828,9 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
/*the host has received the CSW*/
case MSC_WAIT_CSW:
usbd_msc_cfg.stage = MSC_READ_CBW;
g_usbd_msc.stage = MSC_READ_CBW;
USB_LOG_DBG("Start reading cbw\r\n");
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
break;
default:
@@ -808,6 +838,32 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
}
}
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbdev_msc_thread(void *argument)
{
uintptr_t event;
int ret;
while (1) {
ret = usb_osal_mq_recv(g_usbd_msc.usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
if (ret < 0) {
continue;
}
USB_LOG_DBG("%d\r\n", event);
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(g_usbd_msc.nbytes) == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else if (event == MSC_DATA_IN) {
if (SCSI_processRead() == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
} else {
}
}
}
#endif
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep)
{
intf->class_interface_handler = msc_storage_class_interface_request_handler;
@@ -823,19 +879,34 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin
usbd_add_endpoint(&mass_ep_data[MSD_OUT_EP_IDX]);
usbd_add_endpoint(&mass_ep_data[MSD_IN_EP_IDX]);
memset((uint8_t *)&usbd_msc_cfg, 0, sizeof(struct usbd_msc_cfg_priv));
memset((uint8_t *)&g_usbd_msc, 0, sizeof(struct usbd_msc_priv));
usbd_msc_get_cap(0, &usbd_msc_cfg.scsi_blk_nbr, &usbd_msc_cfg.scsi_blk_size);
usbd_msc_get_cap(0, &g_usbd_msc.scsi_blk_nbr, &g_usbd_msc.scsi_blk_size);
if (usbd_msc_cfg.scsi_blk_size > CONFIG_USBDEV_MSC_BLOCK_SIZE) {
if (g_usbd_msc.scsi_blk_size > CONFIG_USBDEV_MSC_BLOCK_SIZE) {
USB_LOG_ERR("msc block buffer overflow\r\n");
return NULL;
}
#ifdef CONFIG_USBDEV_MSC_THREAD
g_usbd_msc.usbd_msc_mq = usb_osal_mq_create(1);
if (g_usbd_msc.usbd_msc_mq == NULL) {
return NULL;
}
g_usbd_msc.usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, NULL);
if (g_usbd_msc.usbd_msc_thread == NULL) {
return NULL;
}
#endif
return intf;
}
void usbd_msc_set_readonly(bool readonly)
{
usbd_msc_cfg.readonly = readonly;
}
g_usbd_msc.readonly = readonly;
}
bool usbd_msc_set_popup(void)
{
return g_usbd_msc.popup;
}

View File

@@ -22,6 +22,7 @@ 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_set_readonly(bool readonly);
bool usbd_msc_set_popup(void);
#ifdef __cplusplus
}

View File

@@ -9,33 +9,35 @@
#define DEV_FORMAT "/dev/sd%c"
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
static int usbh_msc_devno_alloc(struct usbh_msc *msc_class)
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)
{
int devno;
for (devno = 0; devno < 26; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
msc_class->sdchar = 'a' + devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_msc_class[devno], 0, sizeof(struct usbh_msc));
g_msc_class[devno].sdchar = 'a' + devno;
return &g_msc_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_msc_devno_free(struct usbh_msc *msc_class)
static void usbh_msc_class_free(struct usbh_msc *msc_class)
{
int devno = msc_class->sdchar - 'a';
if (devno >= 0 && devno < 26) {
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(msc_class, 0, sizeof(struct usbh_msc));
}
static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
@@ -48,50 +50,45 @@ 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)
{
#if 0
int i;
USB_LOG_INFO("CBW:\r\n");
USB_LOG_INFO(" signature: 0x%08x\r\n", (unsigned int)cbw->dSignature);
USB_LOG_INFO(" tag: 0x%08x\r\n", (unsigned int)cbw->dTag);
USB_LOG_INFO(" datlen: 0x%08x\r\n", (unsigned int)cbw->dDataLength);
USB_LOG_INFO(" flags: 0x%02x\r\n", cbw->bmFlags);
USB_LOG_INFO(" lun: 0x%02x\r\n", cbw->bLUN);
USB_LOG_INFO(" cblen: 0x%02x\r\n", cbw->bCBLength);
USB_LOG_DBG("CBW:\r\n");
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)cbw->dSignature);
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)cbw->dTag);
USB_LOG_DBG(" datlen: 0x%08x\r\n", (unsigned int)cbw->dDataLength);
USB_LOG_DBG(" flags: 0x%02x\r\n", cbw->bmFlags);
USB_LOG_DBG(" lun: 0x%02x\r\n", cbw->bLUN);
USB_LOG_DBG(" cblen: 0x%02x\r\n", cbw->bCBLength);
USB_LOG_INFO("CB:\r\n");
USB_LOG_DBG("CB:\r\n");
for (i = 0; i < cbw->bCBLength; i += 8) {
USB_LOG_INFO(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\r\n",
cbw->CB[i], cbw->CB[i + 1], cbw->CB[i + 2],
cbw->CB[i + 3], cbw->CB[i + 4], cbw->CB[i + 5],
cbw->CB[i + 6], cbw->CB[i + 7]);
USB_LOG_DBG(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\r\n",
cbw->CB[i], cbw->CB[i + 1], cbw->CB[i + 2],
cbw->CB[i + 3], cbw->CB[i + 4], cbw->CB[i + 5],
cbw->CB[i + 6], cbw->CB[i + 7]);
}
#endif
}
static void usbh_msc_csw_dump(struct CSW *csw)
{
#if 0
USB_LOG_INFO("CSW:\r\n");
USB_LOG_INFO(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
USB_LOG_INFO(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
USB_LOG_INFO(" residue: 0x%08x\r\n", (unsigned int)csw->dDataResidue);
USB_LOG_INFO(" status: 0x%02x\r\n", csw->bStatus);
#endif
USB_LOG_DBG("CSW:\r\n");
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
USB_LOG_DBG(" residue: 0x%08x\r\n", (unsigned int)csw->dDataResidue);
USB_LOG_DBG(" status: 0x%02x\r\n", csw->bStatus);
}
static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
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;
@@ -103,9 +100,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;
@@ -113,9 +109,65 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
return ret;
}
static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
{
int nbytes;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes < 0) {
USB_LOG_ERR("cbw transfer error\r\n");
goto __err_exit;
}
if (cbw->dDataLength != 0) {
if (cbw->CB[0] == SCSI_CMD_WRITE10) {
nbytes = usbh_msc_bulk_out_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
} else if (cbw->CB[0] == SCSI_CMD_READCAPACITY10) {
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Save the capacity information */
msc_class->blocknum = GET_BE32(&buffer[0]) + 1;
msc_class->blocksize = GET_BE32(&buffer[4]);
}
} else {
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
}
if (nbytes < 0) {
USB_LOG_ERR("msc data transfer error\r\n");
goto __err_exit;
}
}
/* Receive the CSW */
memset(csw, 0, USB_SIZEOF_MSC_CSW);
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes < 0) {
USB_LOG_ERR("csw transfer error\r\n");
goto __err_exit;
}
usbh_msc_csw_dump(csw);
/* check csw status */
if (csw->dSignature != MSC_CSW_Signature) {
USB_LOG_ERR("csw signature error\r\n");
return -USB_ERR_INVAL;
}
if (csw->bStatus != 0) {
USB_LOG_ERR("csw bStatus %d\r\n", csw->bStatus);
return -USB_ERR_INVAL;
}
__err_exit:
return nbytes < 0 ? (int)nbytes : 0;
}
static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
{
struct CBW *cbw;
/* Construct the CBW */
@@ -126,22 +178,11 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the CSW */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)g_msc_buf);
}
}
return nbytes < 0 ? (int)nbytes : 0;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
}
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
{
int nbytes;
struct CBW *cbw;
/* Construct the CBW */
@@ -150,31 +191,16 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
cbw->dSignature = MSC_CBW_Signature;
cbw->bmFlags = 0x80;
cbw->bCBLength = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
cbw->dDataLength = SCSICMD_REQUESTSENSE_SIZEOF;
cbw->dDataLength = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
cbw->bCBLength = SCSICMD_REQUESTSENSE_SIZEOF;
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the sense data response */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, SCSIRESP_FIXEDSENSEDATA_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the CSW */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)g_msc_buf);
}
}
}
return nbytes < 0 ? (int)nbytes : 0;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
}
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
{
int nbytes;
struct CBW *cbw;
/* Construct the CBW */
@@ -188,26 +214,11 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
cbw->CB[0] = SCSI_CMD_INQUIRY;
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the sense data response */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, SCSIRESP_INQUIRY_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the CSW */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)g_msc_buf);
}
}
}
return nbytes < 0 ? (int)nbytes : 0;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
}
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
{
int nbytes;
struct CBW *cbw;
/* Construct the CBW */
@@ -220,108 +231,33 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the sense data response */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, SCSIRESP_READCAPACITY10_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Save the capacity information */
msc_class->blocknum = GET_BE32(&g_msc_buf[0]) + 1;
msc_class->blocksize = GET_BE32(&g_msc_buf[4]);
/* Receive the CSW */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)g_msc_buf);
}
}
}
return nbytes < 0 ? (int)nbytes : 0;
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
}
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
{
int nbytes;
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = (msc_class->blocksize * nsectors);
cbw->bCBLength = SCSICMD_WRITE10_SIZEOF;
cbw->CB[0] = SCSI_CMD_WRITE10;
memcpy(g_msc_buf, message, 31);
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Send the user data */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the CSW */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)g_msc_buf);
}
}
}
return nbytes < 0 ? (int)nbytes : 0;
}
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
int nbytes;
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = (msc_class->blocksize * nsectors);
cbw->bmFlags = 0x80;
cbw->bCBLength = SCSICMD_READ10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READ10;
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
usbh_msc_cbw_dump(cbw);
/* Send the CBW */
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the user data */
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
/* Receive the CSW */
nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)g_msc_buf);
}
}
}
return nbytes < 0 ? (int)nbytes : 0;
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 = usb_malloc(sizeof(struct usbh_msc));
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;
return -USB_ERR_NOMEM;
}
memset(msc_class, 0, sizeof(struct usbh_msc));
usbh_msc_devno_alloc(msc_class);
msc_class->hport = hport;
msc_class->intf = intf;
@@ -337,17 +273,39 @@ static int usbh_msc_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(&msc_class->bulkin, hport, ep_desc);
USBH_EP_INIT(msc_class->bulkin, ep_desc);
} else {
usbh_hport_activate_epx(&msc_class->bulkout, hport, ep_desc);
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) {
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
return ret;
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");
@@ -364,7 +322,7 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
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 -ERANGE;
return -USB_ERR_RANGE;
}
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
@@ -382,35 +340,80 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
if (msc_class) {
usbh_msc_devno_free(msc_class);
if (msc_class->bulkin) {
usbh_pipe_free(msc_class->bulkin);
usbh_kill_urb(&msc_class->bulkin_urb);
}
if (msc_class->bulkout) {
usbh_pipe_free(msc_class->bulkout);
usbh_kill_urb(&msc_class->bulkout_urb);
}
usbh_msc_stop(msc_class);
memset(msc_class, 0, sizeof(struct usbh_msc));
usb_free(msc_class);
if (hport->config.intf[intf].devname[0] != '\0')
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;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = (msc_class->blocksize * nsectors);
cbw->bCBLength = SCSICMD_WRITE10_SIZEOF;
cbw->CB[0] = SCSI_CMD_WRITE10;
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
}
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
{
struct CBW *cbw;
/* Construct the CBW */
cbw = (struct CBW *)g_msc_buf;
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
cbw->dSignature = MSC_CBW_Signature;
cbw->dDataLength = (msc_class->blocksize * nsectors);
cbw->bmFlags = 0x80;
cbw->bCBLength = SCSICMD_READ10_SIZEOF;
cbw->CB[0] = SCSI_CMD_READ10;
SET_BE32(&cbw->CB[2], start_sector);
SET_BE16(&cbw->CB[7], nsectors);
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
}
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
{
if (config) {
g_msc_modeswitch_config = config;
} else {
g_msc_modeswitch_config = NULL;
}
}
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
{
}
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
{
}
const struct usbh_class_driver msc_class_driver = {

View File

@@ -11,17 +11,25 @@
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 */
};
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,503 +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
#ifndef CONFIG_USB_HS
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, 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 */ \
0x40, 0x00, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x40, 0x00, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x1c, 0x00, /* wMaxPacketSize */ \
0x06 /* bInterval */
#else
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, 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 */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
0x00, 0x02, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x1c, 0x00, /* wMaxPacketSize */ \
0x06 /* bInterval */
#endif
// 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 {
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,107 +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->ctrl_intf = intf;
mtp_class->data_intf = intf + 1;
hport->config.intf[intf].priv = mtp_class;
hport->config.intf[intf + 1].priv = NULL;
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
#ifdef CONFIG_USBHOST_MTP_NOTIFY
ep_desc = &hport->config.intf[intf].ep[0].ep_desc;
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;
ep_cfg.ep_interval = ep_desc->bInterval;
ep_cfg.hport = hport;
usbh_pipe_alloc(&mtp_class->intin, &ep_cfg);
#endif
for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
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.hport = hport;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_pipe_alloc(&mtp_class->bulkin, &ep_cfg);
} else {
usbh_pipe_alloc(&mtp_class->bulkout, &ep_cfg);
}
}
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);
}
usb_free(mtp_class);
if (hport->config.intf[intf].devname[0] != '\0')
USB_LOG_INFO("Unregister MTP Class:%s\r\n", hport->config.intf[intf].devname);
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
hport->config.intf[intf].priv = NULL;
hport->config.intf[intf + 1].priv = NULL;
}
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,63 +0,0 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_printer.h"
struct printer_cfg_priv {
uint8_t *device_id;
uint8_t port_status;
} usbd_printer_cfg;
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:
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_alloc_intf(void)
{
struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
if (intf == NULL) {
USB_LOG_ERR("no mem to alloc intf\r\n");
return NULL;
}
intf->class_interface_handler = printer_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = printer_notify_handler;
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
/* Alloc printer interface driver */
struct usbd_interface *usbd_printer_alloc_intf(void);
#ifdef __cplusplus
}
#endif
#endif /* USBD_PRINTER_H */

View File

@@ -1,137 +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 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 = usb_malloc(sizeof(struct usbh_printer));
if (printer_class == NULL) {
USB_LOG_ERR("Fail to alloc printer_class\r\n");
return -ENOMEM;
}
memset(printer_class, 0, sizeof(struct usbh_printer));
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].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
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.hport = hport;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_pipe_alloc(&printer_class->bulkin, &ep_cfg);
} else {
usbh_pipe_alloc(&printer_class->bulkout, &ep_cfg);
}
}
// 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 ret;
}
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);
}
usb_free(printer_class);
if (hport->config.intf[intf].devname[0] != '\0')
USB_LOG_INFO("Unregister Printer Class:%s\r\n", hport->config.intf[intf].devname);
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
hport->config.intf[intf].priv = NULL;
}
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,27 +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 */
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

@@ -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(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(struct usbd_interface *intf);
#ifdef __cplusplus
}

View File

@@ -3,43 +3,47 @@
#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;
static struct usbh_xxx *usbh_xxx_class_alloc(void)
{
int devno;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_xxx_class[devno], 0, sizeof(struct usbh_xxx));
g_xxx_class[devno].minor = devno;
return &g_xxx_class[devno];
}
}
return NULL;
}
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
{
int devno = xxx_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
memset(xxx_class, 0, sizeof(struct usbh_xxx));
}
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 = usb_malloc(sizeof(struct usbh_xxx));
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;
}
memset(xxx_class, 0, sizeof(struct usbh_xxx));
xxx_class->hport = hport;
xxx_class->intf = intf;
hport->config.intf[intf].priv = xxx_class;
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
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;
ep_cfg.ep_interval = ep_desc->bInterval;
ep_cfg.hport = hport;
if (ep_desc->bEndpointAddress & 0x80) {
usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg);
} else {
usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg);
}
return -USB_ERR_NOMEM;
}
return ret;
}
@@ -50,25 +54,32 @@ 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);
}
usb_free(xxx_class);
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xxx_stop(xxx_class);
}
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
hport->config.intf[intf].priv = NULL;
usbh_xxx_class_free(xxx_class);
}
return ret;
}
__WEAK void usbh_xxx_run(struct usbh_xxx *xxx_class)
{
}
__WEAK void usbh_xxx_stop(struct usbh_xxx *xxx_class)
{
}
static const struct usbh_class_driver xxx_class_driver = {
.driver_name = "xxx",

View File

@@ -5,10 +5,16 @@
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 */
usbh_pipe_t intin; /* INTR IN endpoint */
usbh_pipe_t intout; /* INTR OUT endpoint */
uint8_t minor;
};
void usbh_xxx_run(struct usbh_xxx *xxx_class);
void usbh_xxx_stop(struct usbh_xxx *xxx_class);
#endif

596
class/vendor/asix.h vendored
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 */

1208
class/vendor/axusbnet.c vendored

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

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

@@ -12,17 +12,13 @@ struct video_entity_info {
uint16_t wTerminalType;
};
struct usbd_video_cfg_priv {
struct usbd_video_priv {
struct video_probe_and_commit_controls probe;
struct video_probe_and_commit_controls commit;
uint8_t power_mode;
uint8_t error_code;
struct video_entity_info info[3];
} usbd_video_cfg = {
.info[0] = { .bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x01, .wTerminalType = VIDEO_ITT_CAMERA },
.info[1] = { .bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x03, .wTerminalType = 0x00 },
.info[2] = { .bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, .bEntityId = 0x02, .wTerminalType = 0x00 },
};
} g_usbd_video;
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
@@ -70,7 +66,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
for (uint8_t i = 0; i < 3; i++) {
struct video_entity_info *entity_info = &usbd_video_cfg.info[i];
struct video_entity_info *entity_info = &g_usbd_video.info[i];
if (entity_info->bEntityId == entity_id) {
switch (entity_info->bDescriptorSubtype) {
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
@@ -550,7 +546,7 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
}
break;
default:
usbd_video_cfg.error_code = 0x06;
g_usbd_video.error_code = 0x06;
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
return -1;
}
@@ -576,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 *)usbd_video_cfg.probe, *data, setup->wLength);
//memcpy((uint8_t *)&g_usbd_video.probe, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
*data = (uint8_t *)&usbd_video_cfg.probe;
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
@@ -587,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:
*data = (uint8_t *)&usbd_video_cfg.probe;
memcpy(*data, (uint8_t *)&g_usbd_video.probe, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
case VIDEO_REQUEST_GET_LEN:
@@ -608,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 *)usbd_video_cfg.commit, *data, setup->wLength);
//memcpy((uint8_t *)&g_usbd_video.commit, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
*data = (uint8_t *)&usbd_video_cfg.commit;
memcpy(*data, (uint8_t *)&g_usbd_video.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:
*data = (uint8_t *)&usbd_video_cfg.commit;
memcpy(*data, (uint8_t *)&g_usbd_video.commit, setup->wLength);
*len = sizeof(struct video_probe_and_commit_controls);
break;
@@ -640,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 = &usbd_video_cfg.error_code;
(*data)[0] = g_usbd_video.error_code;
*len = 1;
break;
case VIDEO_REQUEST_GET_INFO:
@@ -684,8 +680,8 @@ static void video_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
usbd_video_cfg.error_code = 0;
usbd_video_cfg.power_mode = 0;
g_usbd_video.error_code = 0;
g_usbd_video.power_mode = 0;
break;
case USBD_EVENT_SET_INTERFACE: {
@@ -705,41 +701,41 @@ 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)
{
usbd_video_cfg.probe.hintUnion.bmHint = 0x01;
usbd_video_cfg.probe.hintUnion1.bmHint = 0;
usbd_video_cfg.probe.bFormatIndex = 1;
usbd_video_cfg.probe.bFrameIndex = 1;
usbd_video_cfg.probe.dwFrameInterval = dwFrameInterval;
usbd_video_cfg.probe.wKeyFrameRate = 0;
usbd_video_cfg.probe.wPFrameRate = 0;
usbd_video_cfg.probe.wCompQuality = 0;
usbd_video_cfg.probe.wCompWindowSize = 0;
usbd_video_cfg.probe.wDelay = 0;
usbd_video_cfg.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
usbd_video_cfg.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
usbd_video_cfg.probe.dwClockFrequency = 0;
usbd_video_cfg.probe.bmFramingInfo = 0;
usbd_video_cfg.probe.bPreferedVersion = 0;
usbd_video_cfg.probe.bMinVersion = 0;
usbd_video_cfg.probe.bMaxVersion = 0;
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;
usbd_video_cfg.commit.hintUnion.bmHint = 0x01;
usbd_video_cfg.commit.hintUnion1.bmHint = 0;
usbd_video_cfg.commit.bFormatIndex = 1;
usbd_video_cfg.commit.bFrameIndex = 1;
usbd_video_cfg.commit.dwFrameInterval = dwFrameInterval;
usbd_video_cfg.commit.wKeyFrameRate = 0;
usbd_video_cfg.commit.wPFrameRate = 0;
usbd_video_cfg.commit.wCompQuality = 0;
usbd_video_cfg.commit.wCompWindowSize = 0;
usbd_video_cfg.commit.wDelay = 0;
usbd_video_cfg.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
usbd_video_cfg.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
usbd_video_cfg.commit.dwClockFrequency = 0;
usbd_video_cfg.commit.bmFramingInfo = 0;
usbd_video_cfg.commit.bPreferedVersion = 0;
usbd_video_cfg.commit.bMinVersion = 0;
usbd_video_cfg.commit.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;
}
struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
@@ -752,6 +748,16 @@ 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;
usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
return intf;
}
@@ -763,18 +769,18 @@ uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8
uint32_t picture_pos = 0;
static uint8_t uvc_header[2] = { 0x02, 0x80 };
packets = input_len / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1;
last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2;
packets = (input_len + (g_usbd_video.probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video.probe.dwMaxPayloadTransferSize - 2);
last_packet_size = input_len - ((packets - 1) * (g_usbd_video.probe.dwMaxPayloadTransferSize - 2));
for (size_t i = 0; i < packets; i++) {
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
if (i == (packets - 1)) {
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
memcpy(&output[2 + g_usbd_video.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
output[g_usbd_video.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
} else {
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2);
picture_pos += usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2;
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;
}
}
uvc_header[1] ^= 1;

View File

@@ -21,117 +21,91 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
static uint32_t g_devinuse = 0;
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[128];
static const char *format_type[] = { "uncompressed", "mjpeg" };
static int __s_r_1370705v[256] = { 0 };
static int __s_b_1732446u[256] = { 0 };
static int __s_g_337633u[256] = { 0 };
static int __s_g_698001v[256] = { 0 };
static struct usbh_video g_video_class[CONFIG_USBHOST_MAX_VIDEO_CLASS];
static uint32_t g_devinuse = 0;
void usbh_video_inityuyv2rgb_table(void)
{
for (int i = 0; i < 256; i++) {
__s_r_1370705v[i] = (1.370705 * (i - 128));
__s_b_1732446u[i] = (1.732446 * (i - 128));
__s_g_337633u[i] = (0.337633 * (i - 128));
__s_g_698001v[i] = (0.698001 * (i - 128));
}
}
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len)
{
int y0, u, y1, v;
uint8_t r, g, b;
int val;
for (uint32_t i = 0; i < len / 4; i++) {
y0 = (int)(((uint8_t *)input)[i * 4 + 0]);
u = (int)(((uint8_t *)input)[i * 4 + 1]);
y1 = (int)(((uint8_t *)input)[i * 4 + 2]);
v = (int)(((uint8_t *)input)[i * 4 + 3]);
val = y0 + __s_r_1370705v[v];
r = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
val = y0 - __s_g_337633u[u] - __s_g_698001v[v];
g = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
val = y0 + __s_b_1732446u[u];
b = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
((uint16_t *)output)[i * 2] = (uint16_t)(b >> 3) | ((uint16_t)(g >> 2) << 5) | ((uint16_t)(r >> 3) << 11);
val = y1 + __s_r_1370705v[v];
r = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
val = y1 - __s_g_337633u[u] - __s_g_698001v[v];
g = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
val = y1 + __s_b_1732446u[u];
b = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
((uint16_t *)output)[i * 2 + 1] = (uint16_t)(b >> 3) | ((uint16_t)(g >> 2) << 5) | ((uint16_t)(r >> 3) << 11);
}
}
static int usbh_video_devno_alloc(struct usbh_video *video_class)
static struct usbh_video *usbh_video_class_alloc(void)
{
int devno;
for (devno = 0; devno < 32; devno++) {
uint32_t bitno = 1 << devno;
if ((g_devinuse & bitno) == 0) {
g_devinuse |= bitno;
video_class->minor = devno;
return 0;
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
if ((g_devinuse & (1 << devno)) == 0) {
g_devinuse |= (1 << devno);
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
g_video_class[devno].minor = devno;
return &g_video_class[devno];
}
}
return -EMFILE;
return NULL;
}
static void usbh_video_devno_free(struct usbh_video *video_class)
static void usbh_video_class_free(struct usbh_video *video_class)
{
int devno = video_class->minor;
if (devno >= 0 && devno < 32) {
g_devinuse &= ~(1 << devno);
}
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);
return usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
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)
@@ -139,7 +113,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)
@@ -147,7 +122,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,
@@ -164,9 +140,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++) {
@@ -184,47 +161,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;
@@ -232,16 +243,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)
@@ -254,12 +269,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;
}
@@ -269,7 +282,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;
}
@@ -332,14 +345,12 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
uint8_t num_of_frames = 0xff;
uint8_t *p;
struct usbh_video *video_class = usb_malloc(sizeof(struct usbh_video));
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;
}
memset(video_class, 0, sizeof(struct usbh_video));
usbh_video_devno_alloc(video_class);
video_class->hport = hport;
video_class->ctrl_intf = intf;
video_class->data_intf = intf + 1;
@@ -427,9 +438,7 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
usbh_video_list_info(video_class);
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, video_class->minor);
#ifdef CONFIG_USBHOST_UVC_YUV2RGB
inityuyv2rgb_table();
#endif
USB_LOG_INFO("Register Video Class:%s\r\n", hport->config.intf[intf].devname);
usbh_video_run(video_class);
@@ -443,22 +452,18 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
if (video_class) {
usbh_video_devno_free(video_class);
if (video_class->isoin) {
usbh_pipe_free(video_class->isoin);
}
if (video_class->isoout) {
usbh_pipe_free(video_class->isoout);
}
usbh_video_stop(video_class);
memset(video_class, 0, sizeof(struct usbh_video));
usb_free(video_class);
if (hport->config.intf[intf].devname[0] != '\0')
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister Video Class:%s\r\n", hport->config.intf[intf].devname);
usbh_video_stop(video_class);
}
usbh_video_class_free(video_class);
}
return ret;
@@ -474,121 +479,6 @@ static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t i
return 0;
}
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
{
struct usbh_iso_frame_packet *iso_packet;
uint32_t num_of_iso_packets;
uint8_t data_offset;
uint32_t data_len;
uint8_t header_len = 0;
num_of_iso_packets = urb->num_of_iso_packets;
iso_packet = urb->iso_packet;
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
/*
uint8_t frameIdentifier : 1U;
uint8_t endOfFrame : 1U;
uint8_t presentationTimeStamp : 1U;
uint8_t sourceClockReference : 1U;
uint8_t reserved : 1U;
uint8_t stillImage : 1U;
uint8_t errorBit : 1U;
uint8_t endOfHeader : 1U;
*/
if (iso_packet[i].actual_length == 0) { /* skip no data */
continue;
}
header_len = iso_packet[i].transfer_buffer[0];
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
while (1) {
}
}
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
stream->bufoffset = 0;
continue;
}
if ((stream->bufoffset == 0) && (iso_packet[i].transfer_buffer[header_len] != 0xff) && (iso_packet[i].transfer_buffer[header_len + 1] != 0xd8)) {
stream->bufoffset = 0;
continue;
}
data_offset = iso_packet[i].transfer_buffer[0];
data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
usbh_videostreaming_output(&iso_packet[i].transfer_buffer[data_offset], data_len);
stream->bufoffset += data_len;
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
if ((iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 2] != 0xff) && (iso_packet[i].transfer_buffer[iso_packet[i].actual_length - 1] != 0xd9)) {
stream->bufoffset = 0;
continue;
}
if (stream->video_one_frame_callback) {
stream->video_one_frame_callback(stream);
}
stream->bufoffset = 0;
}
}
}
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream)
{
struct usbh_iso_frame_packet *iso_packet;
uint32_t num_of_iso_packets;
uint8_t data_offset;
uint32_t data_len;
uint8_t header_len = 0;
num_of_iso_packets = urb->num_of_iso_packets;
iso_packet = urb->iso_packet;
for (uint32_t i = 0; i < num_of_iso_packets; i++) {
/*
uint8_t frameIdentifier : 1U;
uint8_t endOfFrame : 1U;
uint8_t presentationTimeStamp : 1U;
uint8_t sourceClockReference : 1U;
uint8_t reserved : 1U;
uint8_t stillImage : 1U;
uint8_t errorBit : 1U;
uint8_t endOfHeader : 1U;
*/
if (iso_packet[i].actual_length == 0) { /* skip no data */
continue;
}
header_len = iso_packet[i].transfer_buffer[0];
if ((header_len > 12) || (header_len == 0)) { /* do not be illegal */
while (1) {
}
}
if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
stream->bufoffset = 0;
continue;
}
data_offset = iso_packet[i].transfer_buffer[0];
data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
usbh_videostreaming_output(&iso_packet[i].transfer_buffer[data_offset], data_len);
stream->bufoffset += data_len;
if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
if (stream->video_one_frame_callback) {
stream->video_one_frame_callback(stream);
}
stream->bufoffset = 0;
}
}
}
__WEAK void usbh_video_run(struct usbh_video *video_class)
{
}
@@ -597,10 +487,6 @@ __WEAK void usbh_video_stop(struct usbh_video *video_class)
{
}
__WEAK void usbh_videostreaming_output(uint8_t *input, uint32_t input_len)
{
}
const struct usbh_class_driver video_ctrl_class_driver = {
.driver_name = "video_ctrl",
.connect = usbh_video_ctrl_connect,

View File

@@ -17,25 +17,27 @@ struct usbh_video_resolution {
};
struct usbh_video_format {
struct usbh_video_resolution frame[8];
struct usbh_video_resolution frame[12];
uint8_t format_type;
uint8_t num_of_frames;
};
struct usbh_videostreaming {
uint8_t *bufbase;
uint32_t bufoffset;
uint32_t buflen;
uint16_t width;
uint16_t heigth;
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
};
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;
@@ -52,14 +54,8 @@ struct usbh_video {
extern "C" {
#endif
void usbh_video_inityuyv2rgb_table(void);
void usbh_video_yuyv2rgb565(void *input, void *output, uint32_t len);
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,
@@ -70,10 +66,6 @@ int usbh_video_close(struct usbh_video *video_class);
void usbh_video_list_info(struct usbh_video *video_class);
void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream);
void usbh_videostreaming_parse_yuyv2(struct usbh_urb *urb, struct usbh_videostreaming *stream);
void usbh_videostreaming_output(uint8_t *input, uint32_t input_len);
void usbh_video_run(struct usbh_video *video_class);
void usbh_video_stop(struct usbh_video *video_class);

View File

@@ -30,7 +30,7 @@ static struct usbd_endpoint rndis_ep_data[3];
#endif
/* Device data structure */
struct usbd_rndis_cfg_priv {
struct usbd_rndis_priv {
uint32_t drv_version;
uint32_t link_status;
uint32_t speed;
@@ -38,14 +38,15 @@ struct usbd_rndis_cfg_priv {
usb_eth_stat_t eth_state;
rndis_state_t init_state;
uint8_t mac[6];
} usbd_rndis_cfg = { .drv_version = 0x0001,
.link_status = NDIS_MEDIA_STATE_DISCONNECTED,
.speed = RNDIS_LINK_SPEED,
.init_state = rndis_uninitialized,
.mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 } };
} g_usbd_rndis;
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_RESP_BUFFER_SIZE < 140
#undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
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];
@@ -174,7 +175,7 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
resp->AfListOffset = 0;
resp->AfListSize = 0;
usbd_rndis_cfg.init_state = rndis_initialized;
g_usbd_rndis.init_state = rndis_initialized;
rndis_notify_rsp();
return 0;
@@ -187,7 +188,7 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
resp->MessageLength = 0;
usbd_rndis_cfg.init_state = rndis_uninitialized;
g_usbd_rndis.init_state = rndis_uninitialized;
return 0;
}
@@ -241,7 +242,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
break;
case OID_802_3_CURRENT_ADDRESS:
case OID_802_3_PERMANENT_ADDRESS:
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
infomation_len = 6;
break;
case OID_GEN_PHYSICAL_MEDIUM:
@@ -253,7 +254,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_CURRENT_PACKET_FILTER:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.net_filter);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
infomation_len = 4;
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
@@ -261,7 +262,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.link_status);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
infomation_len = 4;
break;
case OID_GEN_RNDIS_CONFIG_PARAMETER:
@@ -301,19 +302,19 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
infomation_len = 4;
break;
case OID_GEN_XMIT_OK:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txok);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
infomation_len = 4;
break;
case OID_GEN_RCV_OK:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxok);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
infomation_len = 4;
break;
case OID_GEN_RCV_ERROR:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxbad);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
infomation_len = 4;
break;
case OID_GEN_XMIT_ERROR:
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txbad);
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
infomation_len = 4;
break;
case OID_GEN_RCV_NO_BUFFER:
@@ -354,7 +355,7 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
param->ParameterValueOffset, param->ParameterValueLength);
break;
case OID_GEN_CURRENT_PACKET_FILTER:
if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
USB_LOG_WRN("PACKET_FILTER!\r\n");
resp->Status = RNDIS_STATUS_INVALID_DATA;
} else {
@@ -362,12 +363,12 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
/* Parameter starts at offset buf_offset of the req_id field */
filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
//usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
usbd_rndis_cfg.net_filter = *(uint32_t *)filter;
if (usbd_rndis_cfg.net_filter) {
usbd_rndis_cfg.init_state = rndis_data_initialized;
//g_usbd_rndis.net_filter = param->ParameterNameOffset;
g_usbd_rndis.net_filter = *(uint32_t *)filter;
if (g_usbd_rndis.net_filter) {
g_usbd_rndis.init_state = rndis_data_initialized;
} else {
usbd_rndis_cfg.init_state = rndis_initialized;
g_usbd_rndis.init_state = rndis_initialized;
}
}
break;
@@ -393,7 +394,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);
@@ -402,7 +403,7 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
resp->Status = RNDIS_STATUS_SUCCESS;
resp->AddressingReset = 1;
usbd_rndis_cfg.init_state = rndis_uninitialized;
g_usbd_rndis.init_state = rndis_uninitialized;
rndis_notify_rsp();
@@ -429,12 +430,12 @@ static void rndis_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
break;
case USBD_EVENT_CONFIGURED:
g_rndis_rx_data_length = 0;
g_rndis_tx_data_length = 0;
usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_CONNECTED;
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));
break;
@@ -458,7 +459,7 @@ void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
g_rndis_rx_data_length = hdr->DataLength;
usbd_rndis_data_recv((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
usbd_rndis_data_recv_done();
}
void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
@@ -506,12 +507,12 @@ int usbd_rndis_eth_tx(struct pbuf *p)
uint8_t *buffer;
rndis_data_packet_t *hdr;
if (usbd_rndis_cfg.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
return 0;
}
if (g_rndis_tx_data_length > 0) {
return -EBUSY;
return -USB_ERR_BUSY;
}
if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
@@ -543,7 +544,11 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
const uint8_t in_ep,
const uint8_t int_ep, uint8_t mac[6])
{
memcpy(usbd_rndis_cfg.mac, mac, 6);
memcpy(g_usbd_rndis.mac, mac, 6);
g_usbd_rndis.drv_version = 0x0001;
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
g_usbd_rndis.speed = RNDIS_LINK_SPEED;
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;

View File

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

View File

@@ -9,7 +9,34 @@
#define DEV_FORMAT "/dev/rndis"
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[1024];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
/* eth rx size must be a multiple of 512 or 64 */
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE];
// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[16];
static struct usbh_rndis g_rndis_class;
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
{
// int ret;
// struct usbh_urb *urb = &rndis_class->intin_urb;
// 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)
{
@@ -33,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;
@@ -49,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;
@@ -79,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;
@@ -97,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;
@@ -131,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;
@@ -149,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;
@@ -158,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)
static 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->link_status = true;
} else {
rndis_class->link_status = false;
}
return ret;
return 0;
}
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
@@ -205,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;
@@ -221,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;
@@ -232,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;
@@ -242,11 +258,7 @@ 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 = usb_malloc(sizeof(struct usbh_rndis));
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));
@@ -257,24 +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;
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_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
// USBH_EP_INIT(rndis_class->intin, ep_desc);
ep_cfg.ep_interval = ep_desc->bInterval;
ep_cfg.hport = hport;
usbh_pipe_alloc(&rndis_class->intin, &ep_cfg);
#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(&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);
}
}
@@ -370,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");
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
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);
@@ -388,24 +400,153 @@ 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);
}
usbh_rndis_stop(rndis_class);
memset(rndis_class, 0, sizeof(struct usbh_rndis));
usb_free(rndis_class);
// if (rndis_class->intin) {
// usbh_kill_urb(&rndis_class->intin_urb);
// }
if (hport->config.intf[intf].devname[0] != '\0')
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);
}
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;
uint32_t payload_offset;
int ret;
err_t err;
struct pbuf *p, *q;
rndis_data_packet_t *pmsg;
rndis_data_packet_t temp;
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.link_status = false;
if (usbh_find_class_instance("/dev/rndis") == NULL) {
goto delete;
}
while (g_rndis_class.link_status == false) {
ret = usbh_rndis_get_connect_status(&g_rndis_class);
if (ret < 0) {
usb_osal_msleep(100);
goto find_class;
}
}
while (1) {
g_rndis_rx_length = 0;
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
if (ret < 0) {
goto find_class;
}
g_rndis_rx_length = g_rndis_class.bulkin_urb.actual_length;
pmg_offset = 0;
while (g_rndis_rx_length > 0) {
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
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, PBUF_POOL);
if (p != NULL) {
payload_offset = 0;
for (q = p; q != NULL; q = q->next) {
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset + payload_offset);
memcpy(q->payload, src, q->len);
payload_offset += q->len;
}
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
pmg_offset += pmsg->MessageLength;
g_rndis_rx_length -= pmsg->MessageLength;
} else {
g_rndis_rx_length = 0;
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
}
} else {
g_rndis_rx_length = 0;
USB_LOG_ERR("Error rndis packet message\r\n");
}
}
}
// 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;
if (g_rndis_class.link_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;
}
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
if (!(hdr->MessageLength % g_rndis_class.bulkout->wMaxPacketSize)) {
hdr->MessageLength += 1;
}
USB_LOG_DBG("txlen:%d\r\n", hdr->MessageLength);
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, hdr->MessageLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
if (ret < 0) {
return ERR_BUF;
}
return ERR_OK;
}
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
{
}

View File

@@ -8,36 +8,45 @@
#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;
uint8_t mac[6];
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
};
#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_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,18 +12,6 @@
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.
@@ -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(const struct usb_endpoint_descriptor *ep);
/**
* @brief Disable the selected endpoint
@@ -143,15 +131,37 @@ int usbd_ep_start_read(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);
/**
* @brief Usb disconnect irq callback.
*/
void usbd_event_disconnect_handler(void);
/**
* @brief Usb resume irq callback.
*/
void usbd_event_resume_handler(void);
/**
* @brief Usb suspend irq callback.
*/
void usbd_event_suspend_handler(void);
/**
* @brief Usb reset irq callback.
*/
void usbd_event_reset_handler(void);
/**
* @brief Usb setup packet recv irq callback.
* @param[in] psetup setup packet.
*/
void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
/**
* @brief In ep transfer complete irq callback.
* @param[in] ep Endpoint address corresponding to the one
@@ -159,6 +169,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
* @param[in] nbytes How many nbytes have transferred.
*/
void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
/**
* @brief Out ep transfer complete irq callback.
* @param[in] ep Endpoint address corresponding to the one
@@ -167,10 +178,6 @@ void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
*/
void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes);
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@@ -11,6 +11,9 @@
#define USB_2_0 0x0200
/* Set USB version to 2.1 so that the host will request the BOS descriptor */
#define USB_2_1 0x0210
#define USB_3_0 0x0300
#define USB_3_1 0x0310
#define USB_3_2 0x0320
/* Device speeds */
#define USB_SPEED_UNKNOWN 0 /* Transfer rate not yet set */
@@ -218,6 +221,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)
@@ -242,6 +246,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
@@ -481,13 +487,10 @@ struct usb_msosv1_comp_id_function_descriptor {
};
struct usb_msosv1_descriptor {
uint8_t *string;
uint8_t string_len;
const uint8_t *string;
uint8_t vendor_code;
uint8_t *compat_id;
uint16_t compat_id_len;
uint8_t *comp_id_property;
uint16_t comp_id_property_len;
const uint8_t *compat_id;
const uint8_t **comp_id_property;
};
/* MS OS 2.0 Header descriptor */

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,6 @@ 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 */
};
/**
* @brief USB Iso Configuration.
@@ -47,7 +32,10 @@ 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;
struct usb_setup_packet *setup;
uint8_t *transfer_buffer;
uint32_t transfer_buffer_length;
@@ -59,7 +47,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
};
/**
@@ -69,6 +61,13 @@ struct usbh_urb {
*/
int usb_hc_init(void);
/**
* @brief usb host controller hardware deinit.
*
* @return On success will return 0, and others indicate fail.
*/
int usb_hc_deinit(void);
/**
* @brief Get frame number.
*
@@ -84,34 +83,6 @@ uint16_t usbh_get_frame_number(void);
*/
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
/**
* @brief reconfig control endpoint pipe.
*
* @param pipe A memory allocated for pipe.
* @param dev_addr device address.
* @param ep_mps control endpoint max packet size.
* @param speed port speed
* @return On success will return 0, and others indicate fail.
*/
int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed);
/**
* @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);
/**
* @brief Submit a usb transfer request to an endpoint.
*
@@ -126,7 +97,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

@@ -52,25 +52,25 @@
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG)
#define USB_LOG_DBG(fmt, ...) usb_dbg_log_line("D", 0, fmt, ##__VA_ARGS__)
#else
#define USB_LOG_DBG(...)
#define USB_LOG_DBG(...) {}
#endif
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_INFO)
#define USB_LOG_INFO(fmt, ...) usb_dbg_log_line("I", 32, fmt, ##__VA_ARGS__)
#else
#define USB_LOG_INFO(...)
#define USB_LOG_INFO(...) {}
#endif
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_WARNING)
#define USB_LOG_WRN(fmt, ...) usb_dbg_log_line("W", 33, fmt, ##__VA_ARGS__)
#else
#define USB_LOG_WRN(...)
#define USB_LOG_WRN(...) {}
#endif
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_ERROR)
#define USB_LOG_ERR(fmt, ...) usb_dbg_log_line("E", 31, fmt, ##__VA_ARGS__)
#else
#define USB_LOG_ERR(...)
#define USB_LOG_ERR(...) {}
#endif
#define USB_LOG_RAW(...) CONFIG_USB_PRINTF(__VA_ARGS__)
@@ -82,4 +82,4 @@ void usb_assert(const char *filename, int linenum);
usb_assert(__FILE__, __LINE__); \
} while (0)
#endif /* USB_LOG_H */
#endif /* USB_LOG_H */

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

@@ -9,18 +9,25 @@
#include <stdint.h>
#include <string.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);
/*
* Task with smaller priority value indicates higher task priority
*/
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
void usb_osal_thread_delete(usb_osal_thread_t thread);
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);
@@ -28,8 +35,9 @@ 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);
int usb_osal_mq_send(usb_osal_mq_t mq, uint32_t addr);
int usb_osal_mq_recv(usb_osal_mq_t mq, uint32_t *addr, uint32_t timeout);
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);
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,6 @@
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)))
#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"
@@ -35,8 +34,10 @@ enum usbd_event_type {
USBD_EVENT_RESUME, /** USB connection resumed by the HOST */
/* USB DEVICE STATUS */
USBD_EVENT_CONFIGURED, /** USB configuration done */
USBD_EVENT_SET_INTERFACE, /** USB interface selected */
USBD_EVENT_CONFIGURED, /** USB configuration done */
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_UNKNOWN
};
@@ -44,15 +45,12 @@ typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **da
typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
extern usb_slist_t usbd_intf_head;
struct usbd_endpoint {
uint8_t ep_addr;
usbd_endpoint_callback ep_cb;
};
struct usbd_interface {
usb_slist_t list;
usbd_request_handler class_interface_handler;
usbd_request_handler class_endpoint_handler;
usbd_request_handler vendor_handler;
@@ -63,21 +61,19 @@ 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 uint8_t *(*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);
void usbd_desc_register(const struct usb_descriptor *desc);
#else
void usbd_desc_register(const uint8_t *desc);
void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
@@ -89,10 +85,11 @@ void usbd_add_interface(struct usbd_interface *intf);
void usbd_add_endpoint(struct usbd_endpoint *ep);
bool usb_device_is_configured(void);
void usbd_configure_done_callback(void);
int usbd_initialize(void);
int usbd_deinitialize(void);
void usbd_event_handler(uint8_t event);
#ifdef __cplusplus
}
#endif

View File

@@ -4,7 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
struct usbh_class_info *usbh_class_info_table_begin = NULL;
struct usbh_class_info *usbh_class_info_table_end = NULL;
@@ -13,8 +12,8 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct usb_setup_packet g_setup[CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
/* general descriptor field offsets */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
#define USB_DEV_ADDR_MAX 0x7f
#define USB_DEV_ADDR_MARK_OFFSET 5
@@ -59,12 +58,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;
@@ -127,10 +126,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 +182,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 +227,15 @@ 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;
return -USB_ERR_NOMEM;
}
if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
USB_LOG_ERR("Interface altsetting num overflow\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
USB_LOG_ERR("Endpoint num overflow\r\n");
return -ENOMEM;
return -USB_ERR_NOMEM;
}
#if 0
USB_LOG_DBG("Interface Descriptor:\r\n");
@@ -270,23 +269,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 +299,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,67 +339,90 @@ 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)
int usbh_free_devaddr(struct usbh_hubport *hport)
{
#ifndef CONFIG_USBHOST_XHCI
if (hport->dev_addr > 0) {
usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
__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)
int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output)
{
struct usbh_endpoint_cfg ep_cfg = { 0 };
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;
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;
/* 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;
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);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
if (ret < 0) {
return ret;
}
return usbh_pipe_alloc(pipe, &ep_cfg);
src = ep0_request_buffer;
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);
}
int usbh_enumerate(struct usbh_hubport *hport)
{
struct usb_interface_descriptor *intf_desc;
struct usb_setup_packet *setup;
struct usb_device_descriptor *dev_desc;
struct usb_endpoint_descriptor *ep;
int dev_addr;
uint16_t ep_mps;
int ret;
hport->setup = &g_setup[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;
@@ -426,7 +431,7 @@ 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);
if (ret < 0) {
USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
goto errout;
@@ -435,10 +440,19 @@ int usbh_enumerate(struct usbh_hubport *hport)
parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, 8);
/* Extract the correct max packetsize from the device descriptor */
ep_mps = ((struct usb_device_descriptor *)ep0_request_buffer)->bMaxPacketSize0;
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer;
if (dev_desc->bcdUSB >= USB_3_0) {
ep_mps = 1 << dev_desc->bMaxPacketSize0;
} else {
ep_mps = dev_desc->bMaxPacketSize0;
}
USB_LOG_DBG("Device rev=%04x cls=%02x sub=%02x proto=%02x size=%d\r\n",
dev_desc->bcdUSB, dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
dev_desc->bDeviceProtocol, ep_mps);
/* Reconfigure EP0 with the correct maximum packet size */
usbh_ep0_pipe_reconfigure(hport->ep0, 0, ep_mps, hport->speed);
ep->wMaxPacketSize = ep_mps;
#ifdef CONFIG_USBHOST_XHCI
extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe);
@@ -465,7 +479,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;
@@ -474,12 +488,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_ep0_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, hport->speed);
/* Read the full device descriptor */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
@@ -487,7 +498,7 @@ 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);
if (ret < 0) {
USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
goto errout;
@@ -506,7 +517,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
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);
if (ret < 0) {
USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
goto errout;
@@ -523,7 +534,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
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);
if (ret < 0) {
USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
goto errout;
@@ -537,56 +548,43 @@ int usbh_enumerate(struct usbh_hubport *hport)
USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->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;
uint8_t string_buffer[128];
ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
/* 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;
@@ -595,12 +593,25 @@ 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 configuration,errorcode:%d\r\n", ret);
goto errout;
}
#ifdef CONFIG_USBHOST_MSOS_ENABLE
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
setup->wValue = 0;
setup->wIndex = 0x0004;
setup->wLength = 16;
ret = usbh_control_transfer(hport, setup, ep0_request_buffer);
if (ret < 0 && (ret != -EPERM)) {
USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
goto errout;
}
#endif
USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
/*search supported class driver*/
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
@@ -619,10 +630,6 @@ int usbh_enumerate(struct usbh_hubport *hport)
hport->config.intf[i].class_driver = class_driver;
USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
ret = CLASS_CONNECT(hport, i);
if (ret < 0) {
CLASS_DISCONNECT(hport, i);
goto errout;
}
}
errout:
@@ -633,46 +640,6 @@ errout:
return ret;
}
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr)
{
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];
}
}
}
}
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;
}
}
}
}
return NULL;
}
int usbh_initialize(void)
{
memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
@@ -699,24 +666,52 @@ int usbh_initialize(void)
return 0;
}
int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer)
int usbh_deinitialize(void)
{
return usbh_hub_deinitialize();
}
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));
urb = &hport->ep0_urb;
usb_osal_mutex_take(hport->mutex);
memset(urb, 0, sizeof(struct usbh_urb));
usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
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;
}
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;
}
}
}
}
return NULL;
}
int lsusb(int argc, char **argv)
{
usb_slist_t *i;
@@ -795,4 +790,4 @@ int lsusb(int argc, char **argv)
}
return 0;
}
}

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" {
@@ -32,8 +31,8 @@ extern "C" {
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
#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))
#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))
#ifdef __ARMCC_VERSION /* ARM C Compiler */
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
@@ -44,57 +43,16 @@ extern "C" {
#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;
}
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 */
@@ -140,7 +98,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,6 +106,12 @@ struct usbh_hubport {
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
#ifdef CONFIG_USBHOST_XHCI
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
#endif
struct usb_endpoint_descriptor ep0;
struct usbh_urb ep0_urb;
usb_osal_mutex_t mutex;
};
struct usbh_hub {
@@ -157,15 +120,70 @@ 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 usb_endpoint_descriptor *intin;
struct usbh_urb intin_urb;
uint8_t *int_buffer;
};
int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
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;
}
/**
* @brief Submit an control transfer to an endpoint.
@@ -177,10 +195,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);
/**
* @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(void);
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
int usbh_deinitialize(void);
void *usbh_find_class_instance(const char *devname);
int lsusb(int argc, char **argv);

View File

@@ -14,6 +14,8 @@
#define AUDIO_IN_EP 0x81
#define AUDIO_IN_FU_ID 0x02
/* AUDIO Class Config */
#define AUDIO_FREQ 16000U
@@ -61,14 +63,14 @@
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v1_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, 0x00, 0x01),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, INPUT_CTRL),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_IN_FU_ID, 0x01, 0x01, INPUT_CTRL),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, AUDIO_IN_FU_ID),
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -143,19 +145,40 @@ const uint8_t audio_descriptor[] = {
0x00
};
void usbd_configure_done_callback(void)
{
/* no out ep, do nothing */
}
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(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;
}
}
void usbd_audio_open(uint8_t intf)
{
tx_flag = 1;
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
@@ -176,28 +199,35 @@ static struct usbd_endpoint audio_in_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void audio_init()
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_endpoint(&audio_in_ep);
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
};
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
void audio_v1_init(void)
{
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_initialize();
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
void audio_test()
{
while (1) {
if (tx_flag) {
memset(write_buffer, 'a', 2048);
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, 2048);
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;
}
}
}
}

View File

@@ -15,6 +15,9 @@
#define AUDIO_IN_EP 0x81
#define AUDIO_OUT_EP 0x02
#define AUDIO_IN_FU_ID 0x02
#define AUDIO_OUT_FU_ID 0x05
/* AUDIO Class Config */
#define AUDIO_SPEAKER_FREQ 16000U
#define AUDIO_SPEAKER_FRAME_SIZE_BYTE 2u
@@ -49,7 +52,7 @@
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v1_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
@@ -59,9 +62,9 @@ const uint8_t audio_descriptor[] = {
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, AUDIO_OUT_PACKET,\
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, AUDIO_IN_PACKET,\
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
///////////////////////////////////////
/// string0 descriptor
@@ -137,24 +140,51 @@ const uint8_t audio_descriptor[] = {
0x00
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
volatile bool ep_tx_busy_flag = false;
void usbd_event_handler(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;
}
}
void usbd_audio_open(uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
printf("OPEN1\r\n");
} else {
tx_flag = 1;
printf("OPEN2\r\n");
}
}
void usbd_audio_close(uint8_t intf)
{
if (intf == 1) {
@@ -166,22 +196,10 @@ void usbd_audio_close(uint8_t intf)
}
}
#ifdef CONFIG_USB_HS
#define AUDIO_OUT_EP_MPS 512
#else
#define AUDIO_OUT_EP_MPS 64
#endif
volatile bool ep_tx_busy_flag = false;
void usbd_configure_done_callback(void)
{
}
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
@@ -204,30 +222,37 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void audio_init()
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
{ .bEntityId = AUDIO_OUT_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_OUT_EP },
};
void audio_v1_init(void)
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_interface(usbd_audio_init_intf(&intf2));
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_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
usbd_audio_add_entity(0x05, AUDIO_CONTROL_FEATURE_UNIT);
usbd_initialize();
}
void audio_test()
void audio_v1_test(void)
{
while (1) {
if (tx_flag) {
// memset(write_buffer, 'a', 2048);
// ep_tx_busy_flag = true;
// usbd_ep_start_write(AUDIO_IN_EP, write_buffer, 2048);
// while (ep_tx_busy_flag) {
// }
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);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;
}
}
}
}

View File

@@ -14,12 +14,16 @@
#define AUDIO_IN_EP 0x81
#define AUDIO_IN_CLOCK_ID 0x01
#define AUDIO_IN_FU_ID 0x03
#define AUDIO_FREQ 48000
#define HALF_WORD_BYTES 2 //2 half word (one channel)
#define SAMPLE_BITS 16 //16 bit per channel
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
#define IN_CHANNEL_NUM 2
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
#if IN_CHANNEL_NUM == 1
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
@@ -49,7 +53,6 @@
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
@@ -64,7 +67,7 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
@@ -72,7 +75,7 @@ const uint8_t audio_descriptor[] = {
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_INTERM_MIC, 0x01, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, INPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x03, 0x01, 0x0000),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x04, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, (AUDIO_IN_PACKET + 4), EP_INTERVAL),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x04, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -156,29 +159,50 @@ static const uint8_t mic_default_sampling_freq_table[] = {
volatile bool tx_flag = 0;
void usbd_event_handler(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;
}
}
void usbd_audio_open(uint8_t intf)
{
tx_flag = 1;
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
tx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
if (entity_id == 0x01) {
if (ep == AUDIO_IN_EP) {
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
}
}
void usbd_configure_done_callback(void)
{
/* no out ep, do nothing */
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
{
}
@@ -191,23 +215,27 @@ static struct usbd_endpoint audio_in_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void audio_init()
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_endpoint(&audio_in_ep);
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_IN_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_IN_EP },
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
};
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
void audio_v2_init(void)
{
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_initialize();
}
void audio_test()
void audio_v2_test(void)
{
while (1) {
if (tx_flag) {
}
if (tx_flag) {
}
}

View File

@@ -15,10 +15,17 @@
#define AUDIO_OUT_EP 0x02
#define AUDIO_IN_EP 0x81
#define AUDIO_OUT_CLOCK_ID 0x01
#define AUDIO_OUT_FU_ID 0x03
#define AUDIO_IN_CLOCK_ID 0x05
#define AUDIO_IN_FU_ID 0x07
#define AUDIO_FREQ 48000
#define HALF_WORD_BYTES 2 //2 half word (one channel)
#define SAMPLE_BITS 16 //16 bit per channel
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
#define IN_CHANNEL_NUM 2
#if IN_CHANNEL_NUM == 1
@@ -47,42 +54,38 @@
#define INPUT_CH_ENABLE 0x000000ff
#endif
#define OUT_CHANNEL_NUM 2
#if OUT_CHANNEL_NUM == 1
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000000
#elif OUT_CHANNEL_NUM == 2
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000003
#elif OUT_CHANNEL_NUM == 3
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000007
#elif OUT_CHANNEL_NUM == 4
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000000f
#elif OUT_CHANNEL_NUM == 5
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000001f
#elif OUT_CHANNEL_NUM == 6
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000003F
#elif OUT_CHANNEL_NUM == 7
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000007f
#elif OUT_CHANNEL_NUM == 8
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x000000ff
#endif
/* AudioFreq * DataSize (2 bytes) * NumChannels */
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
@@ -106,7 +109,7 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
uint8_t audio_descriptor[] = {
uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
@@ -118,8 +121,8 @@ uint8_t audio_descriptor[] = {
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_INTERM_MIC, 0x05, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x07, 0x06, INPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x08, AUDIO_TERMINAL_STREAMING, 0x07, 0x05, 0x0000),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, (AUDIO_IN_PACKET + 4), EP_INTERVAL),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -220,23 +223,50 @@ static const uint8_t mic_default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_4B(0x00)
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
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)
{
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;
}
}
void usbd_audio_open(uint8_t intf)
{
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN1\r\n");
} else {
tx_flag = 1;
USB_LOG_RAW("OPEN2\r\n");
}
}
void usbd_audio_close(uint8_t intf)
{
if (intf == 1) {
@@ -248,36 +278,34 @@ void usbd_audio_close(uint8_t intf)
}
}
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
if (entity_id == 0x01) {
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
} else if (entity_id == 0x05) {
} else if (ep == AUDIO_IN_EP) {
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
} else {
}
}
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
{
uint16_t packet_size = 0;
if (entity_id == 1) {
if (ep == AUDIO_OUT_EP) {
packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
} else if (entity_id == 5) {
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
} else if (ep == AUDIO_IN_EP) {
packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
}
}
void usbd_configure_done_callback(void)
{
}
void usbd_audio_iso_out_callback(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);
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
@@ -298,27 +326,37 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void audio_init()
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_OUT_EP },
{ .bEntityId = AUDIO_OUT_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_OUT_EP },
{ .bEntityId = AUDIO_IN_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_IN_EP },
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
};
void audio_v2_init(void)
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_interface(usbd_audio_init_intf(&intf2));
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_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
usbd_audio_add_entity(0x05, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x07, AUDIO_CONTROL_FEATURE_UNIT);
usbd_initialize();
}
void audio_test()
void audio_v2_test(void)
{
while (1) {
if (tx_flag) {
}
if (tx_flag) {
}
if (rx_flag) {
}
}

View File

@@ -14,42 +14,45 @@
#define AUDIO_OUT_EP 0x01
#define AUDIO_OUT_CLOCK_ID 0x01
#define AUDIO_OUT_FU_ID 0x03
#define AUDIO_FREQ 48000
#define HALF_WORD_BYTES 2 //2 half word (one channel)
#define SAMPLE_BITS 16 //16 bit per channel
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
#define OUT_CHANNEL_NUM 2
#if OUT_CHANNEL_NUM == 1
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000000
#elif OUT_CHANNEL_NUM == 2
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000003
#elif OUT_CHANNEL_NUM == 3
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000007
#elif OUT_CHANNEL_NUM == 4
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000000f
#elif OUT_CHANNEL_NUM == 5
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000001f
#elif OUT_CHANNEL_NUM == 6
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000003F
#elif OUT_CHANNEL_NUM == 7
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000007f
#elif OUT_CHANNEL_NUM == 8
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x000000ff
#endif
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
@@ -64,15 +67,15 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(AUDIO_OUT_CLOCK_ID, 0x03, 0x03),
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -166,36 +169,60 @@ static const uint8_t default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_4B(0x00),
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
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)
{
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;
}
}
void usbd_audio_open(uint8_t intf)
{
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
{
USB_LOG_RAW("CLOSE\r\n");
rx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
if (entity_id == 0x01) {
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
}
}
void usbd_configure_done_callback(void)
{
}
void usbd_audio_iso_out_callback(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);
}
static struct usbd_endpoint audio_out_ep = {
@@ -206,23 +233,27 @@ static struct usbd_endpoint audio_out_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void audio_init()
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_endpoint(&audio_out_ep);
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_OUT_EP },
{ .bEntityId = AUDIO_OUT_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_OUT_EP },
};
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
void audio_v2_init(void)
{
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_initialize();
}
void audio_test()
void audio_v2_test(void)
{
while (1) {
if (rx_flag) {
}
if (rx_flag) {
}
}

View File

@@ -26,11 +26,23 @@
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN + 25)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USB_HS
#define MSC_MAX_MPS 512
#else
#define MSC_MAX_MPS 64
#endif
const uint8_t cdc_acm_hid_msc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x02),
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, 0x02),
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
@@ -136,35 +148,6 @@ const uint8_t cdc_acm_hid_msc_descriptor[] = {
0x00
};
#define BLOCK_SIZE 512
#define BLOCK_COUNT 10
typedef struct
{
uint8_t BlockSpace[BLOCK_SIZE];
} BLOCK_TYPE;
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_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)
{
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)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);
return 0;
}
/*!< hid mouse report descriptor */
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
@@ -255,10 +238,31 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_configure_done_callback(void)
void usbd_event_handler(uint8_t event)
{
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
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:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
@@ -360,3 +364,32 @@ void cdc_acm_data_send_with_dtr_test(void)
}
}
}
#define BLOCK_SIZE 512
#define BLOCK_COUNT 10
typedef struct
{
uint8_t BlockSpace[BLOCK_SIZE];
} BLOCK_TYPE;
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_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)
{
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)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);
return 0;
}

View File

@@ -18,12 +18,151 @@
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USB_HS
#define MSC_MAX_MPS 512
#else
#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 uint8_t string0_descriptor[] = {
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
};
static const uint8_t string1_descriptor[] = {
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
};
static const uint8_t string2_descriptor[] = {
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'C', 0x00, /* wcChar10 */
'-', 0x00, /* wcChar11 */
'M', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
};
static const uint8_t string3_descriptor[] = {
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
};
static const uint8_t *string_descriptors[4] = { string0_descriptor, string1_descriptor, string2_descriptor, string3_descriptor };
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
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 uint8_t *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),
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, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x00),
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),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -97,6 +236,7 @@ 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 };
@@ -109,10 +249,31 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_configure_done_callback(void)
void usbd_event_handler(uint8_t event)
{
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
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:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
@@ -151,7 +312,11 @@ struct usbd_interface intf2;
void cdc_acm_msc_init(void)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(&cdc_msc_descriptor);
#else
usbd_desc_register(cdc_msc_descriptor);
#endif
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);

View File

@@ -26,14 +26,20 @@
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, CDC_MAX_MPS, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, CDC_MAX_MPS, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, CDC_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -119,13 +125,34 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_configure_done_callback(void)
void usbd_event_handler(uint8_t event)
{
/* 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);
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:
/* 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);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)

View File

@@ -14,11 +14,17 @@
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
/*!< global descriptor */
static const uint8_t cdc_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_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -104,10 +110,31 @@ volatile bool ep_tx_busy_flag = false;
#define CDC_MAX_MPS 64
#endif
void usbd_configure_done_callback(void)
void usbd_event_handler(uint8_t event)
{
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
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:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
@@ -144,8 +171,8 @@ 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)
{

274
demo/cdc_ecm_template.c Normal file
View File

@@ -0,0 +1,274 @@
#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(void)
{
}
void cdc_ecm_input_poll(void)
{
cdc_ecm_if_input(&cdc_ecm_netif);
}
void usbd_event_handler(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(void)
{
cdc_ecm_lwip_init();
usbd_desc_register(cdc_ecm_descriptor);
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf0, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_add_interface(usbd_cdc_ecm_init_intf(&intf1, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP));
usbd_initialize();
}

View File

@@ -14,11 +14,17 @@
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_RNDIS_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
/*!< global descriptor */
static const uint8_t cdc_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_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
@@ -95,20 +101,36 @@ static const uint8_t cdc_descriptor[] = {
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
#ifdef RT_USING_LWIP
#include <rtthread.h>
#include <rtdevice.h>
#include <netif/ethernetif.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);
struct eth_device rndis_dev;
void usbd_configure_done_callback(void)
{
eth_device_linkchange(&rndis_dev, RT_TRUE);
}
uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
static rt_err_t rt_usbd_rndis_control(rt_device_t dev, int cmd, void *args)
{
switch (cmd) {
@@ -139,7 +161,7 @@ rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
return usbd_rndis_eth_tx(p);
}
void usbd_rndis_data_recv(uint8_t *data, uint32_t len)
void usbd_rndis_data_recv_done(void)
{
eth_device_ready(&rndis_dev);
}
@@ -155,12 +177,120 @@ void rt_usbd_rndis_init(void)
eth_device_linkchange(&rndis_dev, RT_FALSE);
}
#else
void usbd_configure_done_callback(void)
#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 rndis_netif; //network interface
/* Network interface name */
#define IFNAME0 'E'
#define IFNAME1 'X'
err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
{
static int ret;
ret = usbd_rndis_eth_tx(p);
if (ret == 0)
return ERR_OK;
else
return ERR_BUF;
}
err_t rndisif_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 rndisif_input(struct netif *netif)
{
static err_t err;
static struct pbuf *p;
p = usbd_rndis_eth_rx();
if (p != NULL) {
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
} else {
return ERR_BUF;
}
return err;
}
void rndis_lwip_init(void)
{
struct netif *netif = &rndis_netif;
lwip_init();
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, mac, 6);
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, rndisif_init, netif_input);
netif_set_default(netif);
while (!netif_is_up(netif)) {
}
// while (dhserv_init(&dhcp_config)) {}
// while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {}
}
void usbd_rndis_data_recv_done(void)
{
}
void rndis_input_poll(void)
{
rndisif_input(&rndis_netif);
}
#endif /* RT_USING_LWIP */
void usbd_event_handler(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:
#ifdef RT_USING_LWIP
eth_device_linkchange(&rndis_dev, RT_TRUE);
#endif
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;
@@ -168,6 +298,8 @@ void cdc_rndis_init(void)
{
#ifdef RT_USING_LWIP
rt_usbd_rndis_init();
#else
rndis_lwip_init();
#endif
usbd_desc_register(cdc_descriptor);
usbd_add_interface(usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));

View File

@@ -1,284 +0,0 @@
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "DAP_config.h"
#include "DAP.h"
#define DAP_IN_EP 0x81
#define DAP_OUT_EP 0x02
#define CDC_IN_EP 0x83
#define CDC_OUT_EP 0x04
#define CDC_INT_EP 0x85
#define USBD_VID 0xd6e7
#define USBD_PID 0x3507
#define USBD_MAX_POWER 500
#define USBD_LANGID_STRING 1033
#define CMSIS_DAP_INTERFACE_SIZE (9 + 7 + 7)
#define USB_CONFIG_SIZE (9 + CMSIS_DAP_INTERFACE_SIZE + CDC_ACM_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#define WCID_VENDOR_CODE 0x01
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
///////////////////////////////////////
/// MS OS string descriptor
///////////////////////////////////////
0x12, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
/* MSFT100 */
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
WCID_VENDOR_CODE, /* bVendorCode */
0x00, /* bReserved */
};
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
///////////////////////////////////////
/// WCID descriptor
///////////////////////////////////////
0x28, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x04, 0x00, /* wIndex */
0x01, /* bCount */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
///////////////////////////////////////
/// WCID function descriptor
///////////////////////////////////////
0x00, /* bFirstInterfaceNumber */
0x01, /* bReserved */
/* WINUSB */
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
/* */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
};
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
///////////////////////////////////////
/// WCID property descriptor
///////////////////////////////////////
0x8e, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x05, 0x00, /* wIndex */
0x01, 0x00, /* wCount */
///////////////////////////////////////
/// registry propter descriptor
///////////////////////////////////////
0x84, 0x00, 0x00, 0x00, /* dwSize */
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
0x28, 0x00, /* wPropertyNameLength */
/* DeviceInterfaceGUID */
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, /* wcData_39 */
'3', 0x00, 'B', 0x00, '5', 0x00, 'A', 0x00, /* wcData_39 */
'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, /* wcData_39 */
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
'6', 0x00, '6', 0x00, '3', 0x00, '-', 0x00, /* wcData_39 */
'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, /* wcData_39 */
'E', 0x00, '4', 0x00, '6', 0x00, '4', 0x00, /* wcData_39 */
'6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, /* wcData_39 */
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
};
struct usb_msosv1_descriptor msosv1_desc = {
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
.string_len = 18,
.vendor_code = WCID_VENDOR_CODE,
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
.comp_id_property = (uint8_t *)WINUSB_IF0_WCIDProperties,
.comp_id_property_len = sizeof(WINUSB_IF0_WCIDProperties),
};
const uint8_t daplink_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
/* Configuration 0 */
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
/* Interface 0 */
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
/* Endpoint OUT 1 */
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_IN_EP, USB_ENDPOINT_TYPE_BULK, CDC_MAX_MPS, 0x00),
/* Endpoint IN 2 */
USB_ENDPOINT_DESCRIPTOR_INIT(DAP_OUT_EP, USB_ENDPOINT_TYPE_BULK, CDC_MAX_MPS, 0x00),
CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x00),
/* String 0 (LANGID) */
USB_LANGID_INIT(USBD_LANGID_STRING),
/* String 1 (Manufacturer) */
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 */
/* String 2 (Product) */
0x28, // 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
'M', 0x00, // wcChar11
'S', 0x00, // wcChar12
'I', 0x00, // wcChar13
'S', 0x00, // wcChar14
'-', 0x00, // wcChar15
'D', 0x00, // wcChar16
'A', 0x00, // wcChar17
'P', 0x00, // wcChar18
/* String 3 (Serial Number) */
0x1A, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'0', 0, // wcChar0
'1', 0, // wcChar1
'2', 0, // wcChar2
'3', 0, // wcChar3
'4', 0, // wcChar4
'5', 0, // wcChar5
'A', 0, // wcChar6
'B', 0, // wcChar7
'C', 0, // wcChar8
'D', 0, // wcChar9
'E', 0, // wcChar10
'F', 0, // wcChar11
#ifdef CONFIG_USB_HS
/* Device Qualifier */
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x10,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
#endif
/* End */
0x00
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_read_buffer[CDC_MAX_MPS];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Request[DAP_PACKET_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Response[DAP_PACKET_SIZE];
volatile bool ep_tx_busy_flag = false;
void usbd_configure_done_callback(void)
{
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, cdc_read_buffer, CDC_MAX_MPS);
usbd_ep_start_read(DAP_OUT_EP, USB_Request, DAP_PACKET_SIZE);
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
{
/* setup next out ep read transfer */
if (1) {
usbd_ep_start_read(CDC_OUT_EP, cdc_read_buffer, CDC_MAX_MPS);
}
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
{
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
void usb_dap_recv_callback(uint8_t ep, uint32_t nbytes)
{
uint32_t actual_len;
if (USB_Request[0] == ID_DAP_TransferAbort) {
usbd_ep_start_read(ep, USB_Request, DAP_PACKET_SIZE);
DAP_TransferAbort = 1;
return;
}
actual_len = DAP_ProcessCommand(USB_Request, USB_Response);
usbd_ep_start_write(DAP_IN_EP, USB_Response, actual_len);
usbd_ep_start_read(ep, USB_Request, DAP_PACKET_SIZE);
}
void usb_dap_send_callback(uint8_t ep, uint32_t nbytes)
{
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(DAP_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
static struct usbd_endpoint cdc_out_ep = {
.ep_addr = CDC_OUT_EP,
.ep_cb = usbd_cdc_acm_bulk_out
};
static struct usbd_endpoint cdc_in_ep = {
.ep_addr = CDC_IN_EP,
.ep_cb = usbd_cdc_acm_bulk_in
};
static struct usbd_endpoint dap_out_ep = {
.ep_addr = DAP_OUT_EP,
.ep_cb = usb_dap_recv_callback
};
static struct usbd_endpoint dap_in_ep = {
.ep_addr = DAP_IN_EP,
.ep_cb = usb_dap_send_callback
};
struct usbd_interface dap_interface;
struct usbd_interface intf1;
struct usbd_interface intf2;
void daplink_init(void)
{
usbd_desc_register(daplink_descriptor);
usbd_msosv1_desc_register(&msosv1_desc);
/*!< winusb */
usbd_add_interface(&dap_interface);
usbd_add_endpoint(&dap_out_ep);
usbd_add_endpoint(&dap_in_ep);
/*!< cdc acm */
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf2));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_initialize();
}

View File

@@ -137,9 +137,29 @@ const uint8_t dfu_flash_descriptor[] = {
0x00
};
void usbd_configure_done_callback(void)
void usbd_event_handler(uint8_t event)
{
/* no out ep, do nothing */
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;

View File

@@ -1,317 +0,0 @@
/**
*********************************************************************************
*
* @file ald_acmp.h
* @brief Header file of ACMP module driver.
*
* @version V1.0
* @date 26 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 26 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_ACMP_H__
#define __ALD_ACMP_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup ACMP
* @{
*/
/** @defgroup ACMP_Public_Types ACMP Public Types
* @{
*/
/**
* @brief ACMP interrupt
*/
typedef enum {
ACMP_IT_EDGE = (1U << 0), /**< Edge interrupt bit */
ACMP_IT_WARMUP = (1U << 1), /**< Warm up interrupt bit */
} acmp_it_t;
/**
* @brief ACMP interrupt flag
*/
typedef enum {
ACMP_FLAG_EDGE = (1U << 0), /**< Edge interrupt flag */
ACMP_FLAG_WARMUP = (1U << 1), /**< Warm up interrupt flag */
} acmp_flag_t;
/**
* @brief ACMP status flag
*/
typedef enum {
ACMP_STATUS_ACT = (1U << 0), /**< Edge status flag */
ACMP_STATUS_OUT = (1U << 1), /**< Warm up status flag */
} acmp_status_t;
/**
* @brief ACMP positive input
*/
typedef enum {
ACMP_POS_CH0 = 0x0U, /**< Channel 0 as positive input */
ACMP_POS_CH1 = 0x1U, /**< Channel 1 as positive input */
ACMP_POS_CH2 = 0x2U, /**< Channel 2 as positive input */
ACMP_POS_CH3 = 0x3U, /**< Channel 3 as positive input */
ACMP_POS_CH4 = 0x4U, /**< Channel 4 as positive input */
ACMP_POS_CH5 = 0x5U, /**< Channel 5 as positive input */
ACMP_POS_CH6 = 0x6U, /**< Channel 6 as positive input */
ACMP_POS_CH7 = 0x7U, /**< Channel 7 as positive input */
} acmp_pos_input_t;
/**
* @brief ACMP negative input
*/
typedef enum {
ACMP_NEG_CH0 = 0x0U, /**< Channel 0 as negative input */
ACMP_NEG_CH1 = 0x1U, /**< Channel 1 as negative input */
ACMP_NEG_CH2 = 0x2U, /**< Channel 2 as negative input */
ACMP_NEG_CH3 = 0x3U, /**< Channel 3 as negative input */
ACMP_NEG_CH4 = 0x4U, /**< Channel 4 as negative input */
ACMP_NEG_CH5 = 0x5U, /**< Channel 5 as negative input */
ACMP_NEG_CH6 = 0x6U, /**< Channel 6 as negative input */
ACMP_NEG_CH7 = 0x7U, /**< Channel 7 as negative input */
ACMP_NEG_1V25 = 0x8U, /**< 1.25v as negative input */
ACMP_NEG_2V5 = 0x9U, /**< 2.5v as negative input */
ACMP_NEG_VDD = 0xAU, /**< VDD as negative input */
} acmp_neg_input_t;
/**
* @brief ACMP mode
*/
typedef enum {
ACMP_ULTRA_LOW_POWER = 0x0U, /**< Ultra low power mode */
ACMP_LOW_POWER = 0x1U, /**< Low power mode */
ACMP_MIDDLE_POWER = 0x2U, /**< Middle power mode */
ACMP_HIGH_POWER = 0x3U, /**< High power mode */
} acmp_mode_t;
/**
* @brief ACMP warm-up time
*/
typedef enum {
ACMP_4_PCLK = 0x0U, /**< 4 hfperclk cycles */
ACMP_8_PCLK = 0x1U, /**< 4 hfperclk cycles */
ACMP_16_PCLK = 0x2U, /**< 4 hfperclk cycles */
ACMP_32_PCLK = 0x3U, /**< 4 hfperclk cycles */
ACMP_64_PCLK = 0x4U, /**< 4 hfperclk cycles */
ACMP_128_PCLK = 0x5U, /**< 4 hfperclk cycles */
ACMP_256_PCLK = 0x6U, /**< 4 hfperclk cycles */
ACMP_512_PCLK = 0x7U, /**< 4 hfperclk cycles */
} acmp_warm_time_t;
/**
* @brief ACMP hysteresis level
*/
typedef enum {
ACMP_HYST_0 = 0x0U, /**< No hysteresis */
ACMP_HYST_15 = 0x1U, /**< 15mV hysteresis */
ACMP_HYST_22 = 0x2U, /**< 22mV hysteresis */
ACMP_HYST_29 = 0x3U, /**< 29mV hysteresis */
ACMP_HYST_36 = 0x4U, /**< 36mV hysteresis */
ACMP_HYST_43 = 0x5U, /**< 43mV hysteresis */
ACMP_HYST_50 = 0x6U, /**< 50mV hysteresis */
ACMP_HYST_57 = 0x7U, /**< 57mV hysteresis */
} acmp_hystsel_t;
/**
* @brief ACMP inactive state
*/
typedef enum {
ACMP_INACTVAL_LOW = 0x0U, /**< The inactive value is 0 */
ACMP_INACTVAL_HIGH = 0x1U, /**< The inactive value is 1 */
} acmp_inactval_t;
/**
* @brief which edges set up interrupt
*/
typedef enum {
ACMP_EDGE_NONE = 0x0U, /**< Disable EDGE interrupt */
ACMP_EDGE_FALL = 0x1U, /**< Falling edges set EDGE interrupt */
ACMP_EDGE_RISE = 0x2U, /**< rise edges set EDGE interrupt */
ACMP_EDGE_ALL = 0x3U, /**< Falling edges and rise edges set EDGE interrupt */
} acmp_edge_t;
/**
* @brief ACMP output function
*/
typedef enum {
ACMP_OUT_DISABLE = 0x0U, /**< Disable acmp output */
ACMP_OUT_ENABLE = 0x1U, /**< Enable acmp output */
} acmp_out_func_t;
/**
* @brief ACMP init structure definition
*/
typedef struct {
acmp_mode_t mode; /**< ACMP operation mode */
acmp_warm_time_t warm_time; /**< ACMP warm up time */
acmp_hystsel_t hystsel; /**< ACMP hysteresis level */
acmp_pos_input_t p_port; /**< ACMP positive port select */
acmp_neg_input_t n_port; /**< ACMP negative port select */
acmp_inactval_t inactval; /**< ACMP inavtive output value */
type_func_t out_inv; /**< ACMP output inverse */
acmp_edge_t edge; /**< Select edges to set interrupt flag */
uint8_t vdd_level; /**< Select scaling factor for CDD reference level, MAX is 63 */
} acmp_init_t;
/**
* @brief ACMP Handle Structure definition
*/
typedef struct acmp_handle_s {
ACMP_TypeDef *perh; /**< Register base address */
acmp_init_t init; /**< ACMP required parameters */
lock_state_t lock; /**< Locking object */
void (*acmp_warmup_cplt_cbk)(struct acmp_handle_s *arg); /**< ACMP warm-up complete callback */
void (*acmp_edge_cplt_cbk)(struct acmp_handle_s *arg); /**< ACMP edge trigger callback */
} acmp_handle_t;
/**
* @}
*/
/** @defgroup ACMP_Public_Macros ACMP Public Macros
* @{
*/
#define ACMP_ENABLE(handle) (SET_BIT((handle)->perh->CON, ACMP_CON_EN_MSK))
#define ACMP_DISABLE(handle) (CLEAR_BIT((handle)->perh->CON, ACMP_CON_EN_MSK))
/**
* @}
*/
/** @defgroup ACMP_Private_Macros ACMP Private Macros
* @{
*/
#define IS_ACMP_TYPE(x) (((x) == ACMP0) || \
((x) == ACMP1) || \
((x) == ACMP2))
#define IS_ACMP_MODE_TYPE(x) (((x) == ACMP_ULTRA_LOW_POWER) || \
((x) == ACMP_LOW_POWER) || \
((x) == ACMP_MIDDLE_POWER) || \
((x) == ACMP_HIGH_POWER))
#define IS_ACMP_IT_TYPE(x) (((x) == ACMP_IT_EDGE) || \
((x) == ACMP_IT_WARMUP))
#define IS_ACMP_FLAG_TYPE(x) (((x) == ACMP_FLAG_EDGE) || \
((x) == ACMP_FLAG_WARMUP))
#define IS_ACMP_STATUS_TYPE(x) (((x) == ACMP_STATUS_ACT) || \
((x) == ACMP_STATUS_OUT))
#define IS_ACMP_POS_INPUT_TYPE(x) (((x) == ACMP_POS_CH0) || \
((x) == ACMP_POS_CH1) || \
((x) == ACMP_POS_CH2) || \
((x) == ACMP_POS_CH3) || \
((x) == ACMP_POS_CH4) || \
((x) == ACMP_POS_CH5) || \
((x) == ACMP_POS_CH6) || \
((x) == ACMP_POS_CH7))
#define IS_ACMP_NEG_INPUT_TYPE(x) (((x) == ACMP_NEG_CH0) || \
((x) == ACMP_NEG_CH1) || \
((x) == ACMP_NEG_CH2) || \
((x) == ACMP_NEG_CH3) || \
((x) == ACMP_NEG_CH4) || \
((x) == ACMP_NEG_CH5) || \
((x) == ACMP_NEG_CH6) || \
((x) == ACMP_NEG_CH7) || \
((x) == ACMP_NEG_1V25) || \
((x) == ACMP_NEG_2V5) || \
((x) == ACMP_NEG_VDD))
#define IS_ACMP_WARM_UP_TIME_TYPE(x) (((x) == ACMP_4_PCLK) || \
((x) == ACMP_8_PCLK) || \
((x) == ACMP_16_PCLK) || \
((x) == ACMP_32_PCLK) || \
((x) == ACMP_64_PCLK) || \
((x) == ACMP_128_PCLK) || \
((x) == ACMP_256_PCLK) || \
((x) == ACMP_512_PCLK))
#define IS_ACMP_HYSTSEL_TYPE(x) (((x) == ACMP_HYST_0) || \
((x) == ACMP_HYST_15) || \
((x) == ACMP_HYST_22) || \
((x) == ACMP_HYST_29) || \
((x) == ACMP_HYST_36) || \
((x) == ACMP_HYST_43) || \
((x) == ACMP_HYST_50) || \
((x) == ACMP_HYST_57))
#define IS_ACMP_INACTVAL_TYPE(x) (((x) == ACMP_INACTVAL_LOW) || \
((x) == ACMP_INACTVAL_HIGH))
#define IS_ACMP_EDGE_TYPE(x) (((x) == ACMP_EDGE_NONE) || \
((x) == ACMP_EDGE_FALL) || \
((x) == ACMP_EDGE_RISE) || \
((x) == ACMP_EDGE_ALL))
/**
* @}
*/
/** @addtogroup ACMP_Public_Functions
* @{
*/
/** @addtogroup ACMP_Public_Functions_Group1
* @{
*/
ald_status_t ald_acmp_init(acmp_handle_t *hperh);
/**
* @}
*/
/** @addtogroup ACMP_Public_Functions_Group2
* @{
*/
void ald_acmp_interrupt_config(acmp_handle_t *hperh, acmp_it_t it, type_func_t state);
it_status_t ald_acmp_get_it_status(acmp_handle_t *hperh, acmp_it_t it);
flag_status_t ald_acmp_get_flag_status(acmp_handle_t *hperh, acmp_flag_t flag);
flag_status_t ald_acmp_get_mask_flag_status(acmp_handle_t *hperh, acmp_flag_t flag);
void ald_acmp_clear_flag_status(acmp_handle_t *hperh, acmp_flag_t flag);
/**
* @}
*/
/** @addtogroup ACMP_Public_Functions_Group3
* @{
*/
void ald_acmp_irq_handler(acmp_handle_t *hperh);
void ald_acmp_out_config(acmp_handle_t *hperh, type_func_t state);
uint8_t ald_acmp_out_result(acmp_handle_t *hperh);
flag_status_t ald_acmp_get_status(acmp_handle_t *hperh, acmp_status_t status);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
extern "C" }
#endif
#endif

View File

@@ -1,579 +0,0 @@
/**
******************************************************************************
* @file ald_adc.h
* @brief Header file of ADC Module library.
*
* @version V1.0
* @date 28 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 28 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_ADC_H__
#define __ALD_ADC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
#include "ald_dma.h"
#include "ald_pis.h"
#include "ald_timer.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup ADC
* @{
*/
/** @defgroup ADC_Pubulic_Types ADC Pubulic Types
* @{
*/
/**
* @brief ADC State structures definition
*/
typedef enum {
ADC_STATE_RESET = 0x0U, /**< ADC not yet initialized or disabled */
ADC_STATE_READY = 0x1U, /**< ADC peripheral ready for use */
ADC_STATE_BUSY = 0x2U, /**< ADC is busy to internal process */
ADC_STATE_TIMEOUT = 0x4U, /**< TimeOut occurrence */
ADC_STATE_ERROR = 0x8U, /**< Internal error occurrence */
ADC_STATE_BUSY_N = 0x10U, /**< Normal channel busy */
ADC_STATE_BUSY_I = 0x20U, /**< Insert channel busy */
ADC_STATE_BUSY_WDG = 0x40U, /**< Insert channel busy */
} adc_state_t;
/**
*@brief ADC Error Code
*/
typedef enum {
ADC_ERROR_NONE = 0x0U, /**< No error */
ADC_ERROR_INTERNAL = 0x1U, /**< ADC IP internal error*/
ADC_ERROR_OVR = 0x2U, /**< Overrun error */
ADC_ERROR_DMA = 0x4U, /**< DMA transfer error */
} adc_error_t;
/**
*@brief ADC data alignment
*/
typedef enum {
ADC_DATAALIGN_RIGHT = 0x0U, /**< ADC data alignment right */
ADC_DATAALIGN_LEFT = 0x1U, /**< ADC data alignment left */
} adc_align_t;
/**
*@brief ADC config hannal trigger the EOC IT mode
*/
typedef enum {
ADC_NCHESEL_MODE_ALL = 0x0U, /**< ADC set RCHE after convert sequence finish */
ADC_NCHESEL_MODE_ONE = 0x1U, /**< ADC set RCHE after one convert finish */
} adc_nchesel_t;
/**
*@brief ADC channels
*/
typedef enum {
ADC_CHANNEL_0 = 0x0U, /**< ADC channel 0 */
ADC_CHANNEL_1 = 0x1U, /**< ADC channel 1 */
ADC_CHANNEL_2 = 0x2U, /**< ADC channel 2 */
ADC_CHANNEL_3 = 0x3U, /**< ADC channel 3 */
ADC_CHANNEL_4 = 0x4U, /**< ADC channel 4 */
ADC_CHANNEL_5 = 0x5U, /**< ADC channel 5 */
ADC_CHANNEL_6 = 0x6U, /**< ADC channel 6 */
ADC_CHANNEL_7 = 0x7U, /**< ADC channel 7 */
ADC_CHANNEL_8 = 0x8U, /**< ADC channel 8 */
ADC_CHANNEL_9 = 0x9U, /**< ADC channel 9 */
ADC_CHANNEL_10 = 0xAU, /**< ADC channel 10 */
ADC_CHANNEL_11 = 0xBU, /**< ADC channel 11 */
ADC_CHANNEL_12 = 0xCU, /**< ADC channel 12 */
ADC_CHANNEL_13 = 0xDU, /**< ADC channel 13 */
ADC_CHANNEL_14 = 0xEU, /**< ADC channel 14 */
ADC_CHANNEL_15 = 0xFU, /**< ADC channel 15 */
ADC_CHANNEL_16 = 0x10U, /**< ADC channel 16 */
ADC_CHANNEL_17 = 0x11U, /**< ADC channel 17 */
ADC_CHANNEL_18 = 0x12U, /**< ADC channel 18 */
} adc_channel_t;
/**
*@brief ADC sampling times
*/
typedef enum {
ADC_SAMPLETIME_1 = 0x0U, /**< ADC sampling times 1 clk */
ADC_SAMPLETIME_2 = 0x1U, /**< ADC sampling times 2 clk */
ADC_SAMPLETIME_4 = 0x2U, /**< ADC sampling times 4 clk */
ADC_SAMPLETIME_15 = 0x3U, /**< ADC sampling times 15 clk */
} adc_samp_t;
/**
*@brief ADC index channel in normal group
*/
typedef enum {
ADC_NCH_IDX_1 = 0x1U, /**< ADC normal channel index 1 */
ADC_NCH_IDX_2 = 0x2U, /**< ADC normal channel index 2 */
ADC_NCH_IDX_3 = 0x3U, /**< ADC normal channel index 3 */
ADC_NCH_IDX_4 = 0x4U, /**< ADC normal channel index 4 */
ADC_NCH_IDX_5 = 0x5U, /**< ADC normal channel index 5 */
ADC_NCH_IDX_6 = 0x6U, /**< ADC normal channel index 6 */
ADC_NCH_IDX_7 = 0x7U, /**< ADC normal channel index 7 */
ADC_NCH_IDX_8 = 0x8U, /**< ADC normal channel index 8 */
ADC_NCH_IDX_9 = 0x9U, /**< ADC normal channel index 9 */
ADC_NCH_IDX_10 = 0xAU, /**< ADC normal channel index 10 */
ADC_NCH_IDX_11 = 0xBU, /**< ADC normal channel index 11 */
ADC_NCH_IDX_12 = 0xCU, /**< ADC normal channel index 12 */
ADC_NCH_IDX_13 = 0xDU, /**< ADC normal channel index 13 */
ADC_NCH_IDX_14 = 0xEU, /**< ADC normal channel index 14 */
ADC_NCH_IDX_15 = 0xFU, /**< ADC normal channel index 15 */
ADC_NCH_IDX_16 = 0x10U, /**< ADC normal channel index 16 */
} adc_nch_idx_t;
/**
* @brief ADC index channel in insert group
*/
typedef enum {
ADC_ICH_IDX_1 = 0x1U, /**< ADC insert channel index 1 */
ADC_ICH_IDX_2 = 0x2U, /**< ADC insert channel index 2 */
ADC_ICH_IDX_3 = 0x3U, /**< ADC insert channel index 3 */
ADC_ICH_IDX_4 = 0x4U, /**< ADC insert channel index 4 */
} adc_ich_idx_t;
/**
* @brief ADC analog watchdog mode
*/
typedef enum {
ADC_ANAWTD_NONE = 0x0U, /**< No watch dog */
ADC_ANAWTD_SING_NM = 0x800200U, /**< One normal channel watch dog */
ADC_ANAWTD_SING_IST = 0x400200U, /**< One insert channel Injec watch dog */
ADC_ANAWTD_SING_NMIST = 0xC00200U, /**< One normal and insert channel watch dog */
ADC_ANAWTD_ALL_NM = 0x800000U, /**< All normal channel watch dog */
ADC_ANAWTD_ALL_IST = 0x400000U, /**< All insert channel watch dog */
ADC_ANAWTD_ALL_NMIST = 0xC00000U, /**< All normal and insert channel watch dog */
} adc_ana_wdg_t;
/**
* @brief ADC Event type
*/
typedef enum {
ADC_AWD_EVENT = (1U << 0), /**< ADC analog watch dog event */
} adc_event_type_t;
/**
* @brief ADC interrupts definition
*/
typedef enum {
ADC_IT_NCH = (1U << 5), /**< ADC it normal */
ADC_IT_AWD = (1U << 6), /**< ADC it awd */
ADC_IT_ICH = (1U << 7), /**< ADC it insert */
ADC_IT_OVR = (1U << 26), /**< ADC it overring */
} adc_it_t;
/**
* @brief ADC flags definition
*/
typedef enum {
ADC_FLAG_AWD = (1U << 0), /**<ADC flag awd */
ADC_FLAG_NCH = (1U << 1), /**<ADC flag normal mode complete */
ADC_FLAG_ICH = (1U << 2), /**<ADC flag insert mode complete*/
ADC_FLAG_OVR = (1U << 3), /**<ADC flag ovr */
ADC_FLAG_NCHS = (1U << 8), /**<ADC flag normal start */
ADC_FLAG_ICHS = (1U << 9), /**<ADC flag insert start */
} adc_flag_t;
/**
* @brief ADC CLD DIV definition
*/
typedef enum {
ADC_CKDIV_1 = 0x0U, /**< ADC CLK DIV 1 */
ADC_CKDIV_2 = 0x1U, /**< ADC CLK DIV 2 */
ADC_CKDIV_4 = 0x2U, /**< ADC CLK DIV 4 */
ADC_CKDIV_8 = 0x3U, /**< ADC CLK DIV 8 */
ADC_CKDIV_16 = 0x4U, /**< ADC CLK DIV 16 */
ADC_CKDIV_32 = 0x5U, /**< ADC CLK DIV 32 */
ADC_CKDIV_64 = 0x6U, /**< ADC CLK DIV 64 */
ADC_CKDIV_128 = 0x7U, /**< ADC CLK DIV 128 */
} adc_clk_div_t;
/**
* @brief ADC negative reference voltage definition
*/
typedef enum {
ADC_NEG_REF_VSS = 0x0U, /**< ADC negative regerence voltage vss */
ADC_NEG_REF_VREFN = 0x1U, /**< ADC negative regerence voltage vrefn */
} adc_neg_ref_t;
/**
* @brief ADC positive reference voltage definition
*/
typedef enum {
ADC_POS_REF_VDD = 0x0U, /**< ADC positive reference is VDD */
ADC_POS_REF_2V = 0x1U, /**< ADC positive reference is 2V internal voltage */
ADC_POS_REF_VREEFP = 0x2U, /**< ADC positive reference is VREEFP */
ADC_POS_REF_VREEFP_BUF = 0x3U, /**< ADC positive reference is VREEFP BUFFER */
} adc_pos_ref_t;
/**
* @brief ADC numbers of normal conversion channals
*/
typedef enum {
ADC_NCH_NR_1 = 0x0U, /**< ADC number of normal conversion 1 */
ADC_NCH_NR_2 = 0x1U, /**< ADC number of normal conversion 2 */
ADC_NCH_NR_3 = 0x2U, /**< ADC number of normal conversion 3 */
ADC_NCH_NR_4 = 0x3U, /**< ADC number of normal conversion 4 */
ADC_NCH_NR_5 = 0x4U, /**< ADC number of normal conversion 5 */
ADC_NCH_NR_6 = 0x5U, /**< ADC number of normal conversion 6 */
ADC_NCH_NR_7 = 0x6U, /**< ADC number of normal conversion 7 */
ADC_NCH_NR_8 = 0x7U, /**< ADC number of normal conversion 8 */
ADC_NCH_NR_9 = 0x8U, /**< ADC number of normal conversion 9 */
ADC_NCH_NR_10 = 0x9U, /**< ADC number of normal conversion 10 */
ADC_NCH_NR_11 = 0xAU, /**< ADC number of normal conversion 11 */
ADC_NCH_NR_12 = 0xBU, /**< ADC number of normal conversion 12 */
ADC_NCH_NR_13 = 0xCU, /**< ADC number of normal conversion 13 */
ADC_NCH_NR_14 = 0xDU, /**< ADC number of normal conversion 14 */
ADC_NCH_NR_15 = 0xEU, /**< ADC number of normal conversion 15 */
ADC_NCH_NR_16 = 0xFU, /**< ADC number of normal conversion 16 */
} adc_nch_nr_t;
/**
* @brief ADC numbers of insert conversion channals
*/
typedef enum {
ADC_ICH_NR_1 = 0x0U, /**< ADC number of insert conversion 1 */
ADC_ICH_NR_2 = 0x1U, /**< ADC number of insert conversion 2 */
ADC_ICH_NR_3 = 0x2U, /**< ADC number of insert conversion 3 */
ADC_ICH_NR_4 = 0x3U, /**< ADC number of insert conversion 4 */
} adc_ich_nr_t;
/**
* @brief ADC discontinuous mode choose
*/
typedef enum {
ADC_ALL_DISABLE = 0x0U, /**< ADC discontinuous mode all disable */
ADC_NCH_DISC_EN = 0x1U, /**< ADC normal channel discontinuous mode enable */
ADC_ICH_DISC_EN = 0x2U, /**< ADC insert channel discontinuous mode enable */
} adc_disc_mode_t;
/**
* @brief ADC numbers of channals in discontinuous conversion mode
*/
typedef enum {
ADC_DISC_NR_1 = 0x0U, /**< ADC number of discontinuous conversion 1 */
ADC_DISC_NR_2 = 0x1U, /**< ADC number of discontinuous conversion 2 */
ADC_DISC_NR_3 = 0x2U, /**< ADC number of discontinuous conversion 3 */
ADC_DISC_NR_4 = 0x3U, /**< ADC number of discontinuous conversion 4 */
ADC_DISC_NR_5 = 0x4U, /**< ADC number of discontinuous conversion 5 */
ADC_DISC_NR_6 = 0x5U, /**< ADC number of discontinuous conversion 6 */
ADC_DISC_NR_7 = 0x6U, /**< ADC number of discontinuous conversion 7 */
ADC_DISC_NR_8 = 0x7U, /**< ADC number of discontinuous conversion 8 */
} adc_disc_nr_t;
/**
* @brief ADC resolution of conversion
*/
typedef enum {
ADC_CONV_BIT_6 = 0x0U, /**< ADC resolution of conversion 6 */
ADC_CONV_BIT_8 = 0x1U, /**< ADC resolution of conversion 8 */
ADC_CONV_BIT_10 = 0x2U, /**< ADC resolution of conversion 10 */
ADC_CONV_BIT_12 = 0x3U, /**< ADC resolution of conversion 12 */
} adc_conv_bit_t;
/**
* @brief ADC external trigger mode choose
*/
typedef enum {
ADC_ETS_DISABLE = 0x0U, /**< ADC external trigger function disable */
ADC_ETS_RISE = 0x1U, /**< rise edge trigger ADC */
ADC_ETS_FALL = 0x2U, /**< fall edge trigger ADC */
ADC_ETS_RISE_FALL = 0x3U, /**< both rise and fall edge trigger ADC */
} adc_ets_t;
/**
* @brief ADC trigger conversion mode
*/
/**
* @brief Structure definition of ADC and normal group initialization
*/
typedef struct {
adc_align_t align; /**< Specifies ADC data alignment */
type_func_t scan; /**< Choose scan mode enable or not */
type_func_t cont; /**< Choose continuous mode enable or not */
adc_nch_nr_t nch_nr; /**< Length of normal ranks will be converted */
adc_ich_nr_t ich_nr; /**< Length of insert ranks will be converted */
adc_disc_mode_t disc; /**< Discontinuous mode enable or not */
adc_disc_nr_t disc_nr; /**< Number of discontinuous conversions channel */
adc_conv_bit_t data_bit; /**< The precision of conversion */
adc_clk_div_t div; /**< ADCCLK divider */
adc_nchesel_t nche_sel; /**< Trigger the NCHE FALG mode */
adc_neg_ref_t n_ref; /**< The negative reference voltage*/
adc_pos_ref_t p_ref; /**< The positive reference voltage*/
} adc_init_t;
/**
* @brief Structure definition of ADC channel for normal group
*/
typedef struct {
adc_channel_t ch; /**< The channel to configure into ADC normal group */
adc_nch_idx_t idx; /**< The rank in the normal group sequencer */
adc_samp_t samp; /**< Sampling time value to be set */
} adc_nch_conf_t;
/**
* @brief ADC Configuration analog watchdog definition
*/
typedef struct {
adc_ana_wdg_t mode; /**< Configures the ADC analog watchdog mode*/
adc_channel_t ch; /**< Selects which ADC channel to monitor by analog watchdog */
type_func_t interrupt; /**< Whether the analog watchdog is configured in interrupt */
uint32_t high_thrd; /**< The ADC analog watchdog High threshold value. */
uint32_t low_thrd; /**< The ADC analog watchdog Low threshold value. */
} adc_analog_wdg_conf_t;
/**
* @brief ADC Configuration insert Channel structure definition
*/
typedef struct {
adc_channel_t ch; /**< Selection of ADC channel to configure */
adc_ich_idx_t idx; /**< Rank in the insert group sequencer */
adc_samp_t samp; /**< Sampling time value for selected channel */
uint32_t offset; /**< The offset about converted data */
adc_ich_nr_t nr; /**< The number of insert ranks */
type_func_t auto_m; /**< insert sequence's auto function */
} adc_ich_conf_t;
/**
* @brief ADC handle Structure definition
*/
typedef struct adc_handle_s {
ADC_TypeDef *perh; /**< Register base address */
adc_init_t init; /**< ADC required parameters */
dma_handle_t hdma; /**< Pointer DMA Handler */
pis_handle_t hpis; /**< Pointer PIS Handler for connect adc and dma */
lock_state_t lock; /**< ADC locking object */
adc_state_t state; /**< ADC communication state */
adc_error_t error_code; /**< ADC Error code */
void (*normal_cplt_cbk)( struct adc_handle_s *arg); /**< Regluar Conversion complete callback */
void (*insert_cplt_cbk)( struct adc_handle_s *arg); /**< insert Conversion complete callback */
void (*wdg_cbk)( struct adc_handle_s *arg); /**< Level out of window callback */
void (*error_cbk)(struct adc_handle_s *arg); /**< adc error callback */
void (*ovr_cbk)(struct adc_handle_s *arg); /**< adc ovr callback */
} adc_handle_t;
/**
* @brief Timer trigger adc config structure definition
*/
typedef struct {
uint32_t time; /**< Timer period time uint: us */
uint16_t size; /**< Adc convert times */
uint16_t *buf; /**< Convert data buffer */
adc_neg_ref_t n_ref; /**< The negative reference voltage for adc*/
adc_pos_ref_t p_ref; /**< The positive reference voltage for adc*/
adc_channel_t adc_ch; /**< Adc channel */
uint8_t dma_ch; /**< Dma channel */
TIMER_TypeDef *p_timer; /**< Timer peripheral */
ADC_TypeDef *p_adc; /**< Adc peripheral */
void (*cplt_cbk)( struct adc_handle_s *arg); /**< Conversion complete callback */
/* private variable */
lock_state_t lock; /**< Locking object */
pis_handle_t h_pis; /**< Handle of PIS module */
dma_handle_t h_dma; /**< Handle of DMA module */
timer_handle_t h_timer; /**< Handle of TIMER module */
adc_handle_t h_adc; /**< Handle of ADC module */
adc_nch_conf_t config; /**< Struct for chanel configure */
adc_ich_conf_t i_config;/**< Struct for insert channel configuration */
} adc_timer_config_t;
/**
* @}
*/
/** @defgroup ADC_Public_Macros ADC Public Macros
* @{
*/
#define ADC_ENABLE(handle) (SET_BIT((handle)->perh->CON1, ADC_CON1_ADCEN_MSK))
#define ADC_DISABLE(handle) (CLEAR_BIT((handle)->perh->CON1, ADC_CON1_ADCEN_MSK))
#define ADC_NH_TRIG_BY_SOFT(handle) (SET_BIT((handle)->perh->CON1, ADC_CON1_NCHTRG_MSK))
#define ADC_IH_TRIG_BY_SOFT(handle) (SET_BIT((handle)->perh->CON1, ADC_CON1_ICHTRG_MSK))
#define ADC_RESET_HANDLE_STATE(handle) ((handle)->state = ADC_STATE_RESET)
#define ADC_VREF_OUT_ENABLE(handle) (SET_BIT((handle)->perh->CCR, ADC_CCR_VREFOEN_MSK))
#define ADC_VREF_OUT_DISABLE(handle) (CLEAR_BIT((handle)->perh->CCR, ADC_CCR_VREFOEN_MSK))
#define ADC_NETS_ENABLE(handle, mode) (MODIFY_REG((handle)->perh->CON1, ADC_CON1_NETS_MSK, (mode) << ADC_CON1_NETS_POSS))
#define ADC_IETS_ENABLE(handle, mode) (MODIFY_REG((handle)->perh->CON1, ADC_CON1_IETS_MSK, (mode) << ADC_CON1_IETS_POSS))
#define ADC_NETS_DISABLE(handle) (MODIFY_REG((handle)->perh->CON1, ADC_CON1_NETS_MSK, 0 << ADC_CON1_NETS_POSS))
#define ADC_IETS_DISABLE(handle) (MODIFY_REG((handle)->perh->CON1, ADC_CON1_IETS_MSK, 0 << ADC_CON1_IETS_POSS))
#define ADC_SPEED_HIGH_ENABLE(handle) (SET_BIT((handle)->perh->CCR, ADC_CCR_PWRMODSEL_MSK))
#define ADC_SPEED_HIGH_DISABLE(handle) (CLEAR_BIT((handle)->perh->CCR, ADC_CCR_PWRMODSEL_MSK))
#define ADC_CALIBRATE_ENABLE(handle) (SET_BIT((handle)->perh->CCR, ADC_CCR_TRMEN_MSK))
#define ADC_CALIBRATE_DISABLE(handle) (CLEAR_BIT((handle)->perh->CCR, ADC_CCR_TRMEN_MSK))
/**
* @}
*/
/** @defgroup ADC_Private_Macros ADC Private Macros
* @{
*/
#define IS_ADC_ICH_IDX_TYPE(x) ((x) <= ADC_ICH_IDX_4)
#define IS_ADC_NCH_IDX_TYPE(x) ((x) <= ADC_NCH_IDX_16)
#define IS_ADC_SAMPLING_TIMES_TYPE(x) (((x) == ADC_SAMPLETIME_1) || \
((x) == ADC_SAMPLETIME_2) || \
((x) == ADC_SAMPLETIME_4) || \
((x) == ADC_SAMPLETIME_15))
#define IS_ADC_CHANNELS_TYPE(x) ((x) <= ADC_CHANNEL_18)
#define IS_ADC_DATA_ALIGN_TYPE(x) (((x) == ADC_DATAALIGN_RIGHT) || \
((x) == ADC_DATAALIGN_LEFT))
#define IS_ADC_ANALOG_WTD_MODE_TYPE(x) (((x) == ADC_ANAWTD_NONE) || \
((x) == ADC_ANAWTD_SING_NM) || \
((x) == ADC_ANAWTD_SING_IST) || \
((x) == ADC_ANAWTD_SING_NMIST) || \
((x) == ADC_ANAWTD_ALL_NM) || \
((x) == ADC_ANAWTD_ALL_IST) || \
((x) == ADC_ANAWTD_ALL_NMIST))
#define IS_ADC_IT_TYPE(x) (((x) == ADC_IT_NCH) || \
((x) == ADC_IT_AWD) || \
((x) == ADC_IT_ICH) || \
((x) == ADC_IT_OVR ))
#define IS_ADC_FLAGS_TYPE(x) (((x) == ADC_FLAG_AWD) || \
((x) == ADC_FLAG_NCH) || \
((x) == ADC_FLAG_ICH) || \
((x) == ADC_FLAG_OVR) || \
((x) == ADC_FLAG_NCHS) || \
((x) == ADC_FLAG_ICHS))
#define IS_ADC_CLK_DIV_TYPE(x) (((x) == ADC_CKDIV_1) || \
((x) == ADC_CKDIV_2) || \
((x) == ADC_CKDIV_4) || \
((x) == ADC_CKDIV_8) || \
((x) == ADC_CKDIV_16) || \
((x) == ADC_CKDIV_32) || \
((x) == ADC_CKDIV_64) || \
((x) == ADC_CKDIV_128))
#define IS_ADC_NEG_REF_VOLTAGE_TYPE(x) (((x) == ADC_NEG_REF_VSS ) || \
((x) == ADC_NEG_REF_VREFN ))
#define IS_POS_REF_VOLTAGE_TYPE(x) (((x) == ADC_POS_REF_VDD) || \
((x) == ADC_POS_REF_2V) || \
((x) == ADC_POS_REF_VREEFP) || \
((x) == ADC_POS_REF_VREEFP_BUF))
#define IS_ADC_NCH_NR_TYPE(x) ((x) <= ADC_NCH_NR_16)
#define IS_ADC_ICH_NR_TYPE(x) ((x) <= ADC_ICH_NR_4)
#define IS_ADC_DISC_NR_TYPE(x) ((x) <= ADC_DISC_NR_8)
#define IS_ADC_CONV_BIT_TYPE(x) (((x) == ADC_CONV_BIT_12) || \
((x) == ADC_CONV_BIT_6) || \
((x) == ADC_CONV_BIT_8) || \
((x) == ADC_CONV_BIT_10))
#define IS_ADC_TYPE(x) (((x) == ADC0) || \
((x) == ADC1))
#define IS_ADC_NCHESEL_MODE_TYPE(x) (((x) == ADC_NCHESEL_MODE_ALL) || \
((x) == ADC_NCHESEL_MODE_ONE))
#define IS_ADC_EVENT_TYPE(x) ((x) == ADC_AWD_EVENT)
#define IS_ADC_IST_OFFSET_TYPE(x) ((x) <= 0xfff)
#define IS_HTR_TYPE(x) ((x) <= 0xfff)
#define IS_LTR_TYPE(x) ((x) <= 0xfff)
/**
* @}
*/
/** @addtogroup ADC_Public_Functions
* @{
*/
/** @addtogroup ADC_Public_Functions_Group1
* @{
*/
ald_status_t ald_adc_init(adc_handle_t *hperh);
ald_status_t ald_adc_reset(adc_handle_t *hperh);
void ald_adc_offset_adjust(uint32_t refmv);
/**
* @}
*/
/** @addtogroup ADC_Public_Functions_Group2
* @{
*/
ald_status_t ald_adc_normal_start(adc_handle_t *hperh);
ald_status_t ald_adc_normal_stop(adc_handle_t *hperh);
ald_status_t ald_adc_normal_poll_for_conversion(adc_handle_t *hperh, uint32_t timeout);
ald_status_t ald_adc_poll_for_event(adc_handle_t *hperh, adc_event_type_t event_type, uint32_t timeout);
ald_status_t ald_adc_normal_start_by_it(adc_handle_t *hperh);
ald_status_t ald_adc_normal_stop_by_it(adc_handle_t *hperh);
#ifdef ALD_DMA
ald_status_t ald_adc_start_by_dma(adc_handle_t *hperh, uint16_t *buf, uint16_t size, uint8_t channel);
ald_status_t ald_adc_stop_by_dma(adc_handle_t *hperh, uint8_t channel);
ald_status_t ald_adc_timer_trigger_adc_by_dma(adc_timer_config_t *config);
ald_status_t ald_adc_timer_trigger_insert(adc_timer_config_t *config);
#endif
uint32_t ald_adc_normal_get_value(adc_handle_t *hperh);
ald_status_t ald_adc_insert_start(adc_handle_t *hperh);
ald_status_t ald_adc_insert_stop(adc_handle_t *hperh);
ald_status_t ald_adc_insert_poll_for_conversion(adc_handle_t *hperh, uint32_t timeout);
ald_status_t ald_adc_insert_start_by_it(adc_handle_t *hperh);
ald_status_t ald_adc_insert_stop_by_it(adc_handle_t *hperh);
uint32_t ald_adc_insert_get_value(adc_handle_t *hperh, adc_ich_idx_t ih_rank);
void ald_adc_irq_handler(adc_handle_t *hperh);
/**
* @}
*/
/** @addtogroup ADC_Public_Functions_Group3
* @{
*/
ald_status_t ald_adc_normal_channel_config(adc_handle_t *hperh, adc_nch_conf_t *config);
ald_status_t ald_adc_insert_channel_config(adc_handle_t *hperh, adc_ich_conf_t *config);
ald_status_t ald_adc_analog_wdg_config(adc_handle_t *hperh, adc_analog_wdg_conf_t *config);
void ald_adc_interrupt_config(adc_handle_t *hperh, adc_it_t it, type_func_t state);
it_status_t ald_adc_get_it_status(adc_handle_t *hperh, adc_it_t it);
flag_status_t ald_adc_get_flag_status(adc_handle_t *hperh, adc_flag_t flag);
void ald_adc_clear_flag_status(adc_handle_t *hperh, adc_flag_t flag);
/**
* @}
*/
/** @addtogroup ADC_Public_Functions_Group4
* @{
*/
uint32_t ald_adc_get_state(adc_handle_t *hperh);
uint32_t ald_adc_get_error(adc_handle_t *hperh);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
extern "C" }
#endif
#endif /* __ALD_ADC_H */

View File

@@ -1,212 +0,0 @@
/**
*********************************************************************************
*
* @file ald_bkpc.h
* @brief Header file of BKPC module driver.
*
* @version V1.0
* @date 15 Dec 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 15 Dec 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_BKPC_H__
#define __ALD_BKPC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup BKPC
* @{
*/
/** @defgroup BKPC_Public_Macros BKPC Public Macros
* @{
*/
#define BKPC_LOCK() (WRITE_REG(BKPC->PROT, 0U))
#define BKPC_UNLOCK() (WRITE_REG(BKPC->PROT, 0x9669AA55U))
#define BKPC_LRC_ENABLE() \
do { \
BKPC_UNLOCK(); \
SET_BIT(BKPC->CR, BKPC_CR_LRCEN_MSK); \
BKPC_LOCK(); \
} while (0)
#define BKPC_LRC_DISABLE() \
do { \
BKPC_UNLOCK(); \
CLEAR_BIT(BKPC->CR, BKPC_CR_LRCEN_MSK); \
BKPC_LOCK(); \
} while (0)
#define BKPC_LOSM_ENABLE() \
do { \
BKPC_UNLOCK(); \
SET_BIT(BKPC->CR, BKPC_CR_LOSMEN_MSK); \
BKPC_LOCK(); \
} while (0)
#define BKPC_LOSM_DISABLE() \
do { \
BKPC_UNLOCK(); \
CLEAR_BIT(BKPC->CR, BKPC_CR_LOSMEN_MSK);\
BKPC_LOCK(); \
} while (0)
#define BKPC_LOSC_ENABLE() \
do { \
BKPC_UNLOCK(); \
SET_BIT(BKPC->CR, BKPC_CR_LOSCEN_MSK); \
BKPC_LOCK(); \
} while (0)
#define BKPC_LOSC_DISABLE() \
do { \
BKPC_UNLOCK(); \
CLEAR_BIT(BKPC->CR, BKPC_CR_LOSCEN_MSK);\
BKPC_LOCK(); \
} while (0)
#define BKPC_MRST_WAKEUP_ENABLE() \
do { \
BKPC_UNLOCK(); \
SET_BIT(BKPC->CR, BKPC_CR_MRST_WKPEN_MSK); \
BKPC_LOCK(); \
} while (0)
#define BKPC_MRST_WAKEUP_DISABLE() \
do { \
BKPC_UNLOCK(); \
CLEAR_BIT(BKPC->CR, BKPC_CR_MRST_WKPEN_MSK); \
BKPC_LOCK(); \
} while (0)
/**
* @}
*/
/** @defgroup BKPC_Public_Types BKPC Public Types
* @{
*/
/**
* @brief BKPC preipheral clock select.
*/
typedef enum {
BKPC_PREH_CLK_LOSM = 0x0U, /**< LOSM */
BKPC_PREH_CLK_LRC = 0x1U, /**< LRC */
BKPC_PREH_CLK_HRC_1M = 0x2U, /**< HRC down to 1MHz */
BKPC_PREH_CLK_HOSC_1M = 0x3U, /**< HOSC down to 1MHz */
} bkpc_preh_clk_t;
/**
* @brief Standby wakeup port select
*/
typedef enum {
PMU_STANDBY_PORT_SEL_PA0 = 0x0U, /**< Wakeup by PA0 */
PMU_STANDBY_PORT_SEL_PA1 = 0x1U, /**< Wakeup by PA1 */
PMU_STANDBY_PORT_SEL_PA2 = 0x2U, /**< Wakeup by PA2 */
PMU_STANDBY_PORT_SEL_PA3 = 0x3U, /**< Wakeup by PA3 */
PMU_STANDBY_PORT_SEL_PA4 = 0x4U, /**< Wakeup by PA4 */
PMU_STANDBY_PORT_SEL_PA5 = 0x5U, /**< Wakeup by PA5 */
PMU_STANDBY_PORT_SEL_PA6 = 0x6U, /**< Wakeup by PA6 */
PMU_STANDBY_PORT_SEL_PA7 = 0x7U, /**< Wakeup by PA7 */
PMU_STANDBY_PORT_SEL_NONE = 0xFU, /**< Wakeup by other source */
} bkpc_wakeup_port_t;
/**
* @brief Standby wakeup level
*/
typedef enum {
PMU_STANDBY_LEVEL_HIGH = 0x0U, /**< High level */
PMU_STANDBY_LEVEL_LOW = 0x1U, /**< Low level */
} bkpc_wakeup_level_t;
/**
* @}
*/
/**
* @defgroup BKPC_Private_Macros BKPC Private Macros
* @{
*/
#define IS_BKPC_WAKEUP_PORT(x) (((x) == PMU_STANDBY_PORT_SEL_PA0) || \
((x) == PMU_STANDBY_PORT_SEL_PA1) || \
((x) == PMU_STANDBY_PORT_SEL_PA2) || \
((x) == PMU_STANDBY_PORT_SEL_PA3) || \
((x) == PMU_STANDBY_PORT_SEL_PA4) || \
((x) == PMU_STANDBY_PORT_SEL_PA5) || \
((x) == PMU_STANDBY_PORT_SEL_PA6) || \
((x) == PMU_STANDBY_PORT_SEL_PA7) || \
((x) == PMU_STANDBY_PORT_SEL_NONE))
#define IS_BKPC_WAKEUP_LEVEL(x) (((x) == PMU_STANDBY_LEVEL_HIGH) || \
((x) == PMU_STANDBY_LEVEL_LOW))
#define IS_BKPC_PREH_CLOCK(x) (((x) == BKPC_PREH_CLK_LOSM) || \
((x) == BKPC_PREH_CLK_LRC) || \
((x) == BKPC_PREH_CLK_HRC_1M) || \
((x) == BKPC_PREH_CLK_HOSC_1M))
#define IS_BKPC_RAM_IDX(x) ((x) < 32)
/**
* @}
*/
/** @addtogroup BKPC_Public_Functions
* @{
*/
/** @addtogroup BKPC_Public_Functions_Group1
* @{
*/
/* control functions */
extern void ald_bkpc_standby_wakeup_config(bkpc_wakeup_port_t port, bkpc_wakeup_level_t level);
extern void ald_bkpc_rtc_clock_config(bkpc_preh_clk_t clock);
extern void ald_bkpc_tsense_clock_config(bkpc_preh_clk_t clock);
/**
* @}
*/
/** @addtogroup BKPC_Public_Functions_Group2
* @{
*/
/* IO operation functions */
extern void ald_bkpc_write_ram(uint8_t idx, uint32_t value);
extern uint32_t ald_bkpc_read_ram(uint8_t idx);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_BKPC_H__ */

View File

@@ -1,68 +0,0 @@
/**
*********************************************************************************
*
* @file ald_calc.h
* @brief Header file of CALC module driver.
*
* @version V1.0
* @date 26 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 26 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_CALC_H__
#define __ALD_CALC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup CALC
* @{
*/
/** @addtogroup CALC_Public_Functions
* @{
*/
extern uint32_t ald_calc_sqrt(uint32_t data);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_CALC_H__ */

View File

@@ -1,492 +0,0 @@
/**
******************************************************************************
* @file ald_can.h
* @brief Header file of CAN Module driver.
*
* @version V1.0
* @date 16 Apr 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 16 Apr 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_CAN_H
#define __ALD_CAN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup CAN
* @{
*/
/** @defgroup CAN_Public_Types CAN Public Types
* @{
*/
/**
* @brief ALD State structures definition
*/
typedef enum {
CAN_STATE_RESET = 0x00U, /**< CAN not yet initialized or disabled */
CAN_STATE_READY = 0x01U, /**< CAN initialized and ready for use */
CAN_STATE_BUSY = 0x02U, /**< CAN process is ongoing */
CAN_STATE_BUSY_TX = 0x11U, /**< CAN process is ongoing */
CAN_STATE_BUSY_RX0 = 0x21U, /**< CAN process is ongoing */
CAN_STATE_BUSY_RX1 = 0x41U, /**< CAN process is ongoing */
CAN_STATE_BUSY_TX_RX0 = 0x31U, /**< CAN process is ongoing */
CAN_STATE_BUSY_TX_RX1 = 0x51U, /**< CAN process is ongoing */
CAN_STATE_BUSY_RX0_RX1 = 0x61U, /**< CAN process is ongoing */
CAN_STATE_BUSY_TX_RX0_RX1 = 0x71U, /**< CAN process is ongoing */
CAN_STATE_TIMEOUT = 0x04U, /**< CAN in Timeout state */
CAN_STATE_ERROR = 0x08U, /**< CAN error state */
} can_state_t;
/**
* @brief CAN Error Code
*/
typedef enum {
CAN_ERROR_NONE = 0x00U, /**< No error */
CAN_ERROR_EWG = 0x01U, /**< EWG error */
CAN_ERROR_EPV = 0x02U, /**< EPV error */
CAN_ERROR_BOF = 0x04U, /**< BOF error */
CAN_ERROR_STF = 0x08U, /**< Stuff error */
CAN_ERROR_FOR = 0x10U, /**< Form error */
CAN_ERROR_ACK = 0x20U, /**< Acknowledgment error */
CAN_ERROR_BR = 0x40U, /**< Bit recessive */
CAN_ERROR_BD = 0x80U, /**< LEC dominant */
CAN_ERROR_CRC = 0x100U, /**< LEC transfer error */
CAN_ERROR_UNK = 0x200U, /**< Unknown error */
} can_error_t;
/**
* @brief CAN Operating Mode
*/
typedef enum {
CAN_MODE_NORMAL = 0x00U, /**< Normal mode */
CAN_MODE_LOOPBACK = 0x01U, /**< Loopback mode */
CAN_MODE_SILENT = 0x02U, /**< Silent mode */
CAN_MODE_SILENT_LOOPBACK = 0x03U, /**< Loopback combined with silent mode */
} can_operate_mode_t;
/**
* @brief CAN Synchronization Jump Width
*/
typedef enum {
CAN_SJW_1 = 0x0U, /**< 1 time quantum */
CAN_SJW_2 = 0x1U, /**< 2 time quantum */
CAN_SJW_3 = 0x2U, /**< 3 time quantum */
CAN_SJW_4 = 0x3U, /**< 4 time quantum */
} can_sjw_t;
/**
* @brief CAN Time Quantum in Bit Segment 1
*/
typedef enum {
CAN_SEG1_1 = 0x0U, /**< 1 time quantum */
CAN_SEG1_2 = 0x1U, /**< 2 time quantum */
CAN_SEG1_3 = 0x2U, /**< 3 time quantum */
CAN_SEG1_4 = 0x3U, /**< 4 time quantum */
CAN_SEG1_5 = 0x4U, /**< 5 time quantum */
CAN_SEG1_6 = 0x5U, /**< 6 time quantum */
CAN_SEG1_7 = 0x6U, /**< 7 time quantum */
CAN_SEG1_8 = 0x7U, /**< 8 time quantum */
CAN_SEG1_9 = 0x8U, /**< 9 time quantum */
CAN_SEG1_10 = 0x9U, /**< 10 time quantum */
CAN_SEG1_11 = 0xAU, /**< 11 time quantum */
CAN_SEG1_12 = 0xBU, /**< 12 time quantum */
CAN_SEG1_13 = 0xCU, /**< 13 time quantum */
CAN_SEG1_14 = 0xDU, /**< 14 time quantum */
CAN_SEG1_15 = 0xEU, /**< 15 time quantum */
CAN_SEG1_16 = 0xFU, /**< 16 time quantum */
} can_seg1_t;
/**
* @brief CAN Time Quantum in Bit Segment 2
*/
typedef enum {
CAN_SEG2_1 = 0x0U, /**< 1 time quantum */
CAN_SEG2_2 = 0x1U, /**< 2 time quantum */
CAN_SEG2_3 = 0x2U, /**< 3 time quantum */
CAN_SEG2_4 = 0x3U, /**< 4 time quantum */
CAN_SEG2_5 = 0x4U, /**< 5 time quantum */
CAN_SEG2_6 = 0x5U, /**< 6 time quantum */
CAN_SEG2_7 = 0x6U, /**< 7 time quantum */
CAN_SEG2_8 = 0x7U, /**< 8 time quantum */
} can_seg2_t;
/**
* @brief CAN Filter Mode
*/
typedef enum {
CAN_FILTER_MODE_MASK = 0x0U, /**< Identifier mask mode */
CAN_FILTER_MODE_LIST = 0x1U, /**< Identifier list mode */
} can_filter_mode_t;
/**
* @brief CAN Filter Scale
*/
typedef enum {
CAN_FILTER_SCALE_16 = 0x0U, /**< Two 16-bit filters */
CAN_FILTER_SCALE_32 = 0x1U, /**< One 32-bit filter */
} can_filter_scale_t;
/**
* @brief CAN Filter fifo
*/
typedef enum {
CAN_FILTER_FIFO0 = 0x0U, /**< FIFO 0 assignment for filter */
CAN_FILTER_FIFO1 = 0x1U, /**< FIFO 1 assignment for filter */
} can_filter_fifo_t;
/**
* @brief CAN Identifier Type
*/
typedef enum {
CAN_ID_STD = 0x0U, /**< Standard Id */
CAN_ID_EXT = 0x1U, /**< Extended Id */
} can_id_type_t;
/**
* @brief CAN Remote Transmission Request
*/
typedef enum {
CAN_RTR_DATA = 0x0U, /**< Data frame */
CAN_RTR_REMOTE = 0x1U, /**< Remote frame */
} can_remote_req_t;
/**
* @brief CAN Transmit Constants
*/
typedef enum {
CAN_TX_MAILBOX_0 = 0x0U, /**< TX mailbox index 0 */
CAN_TX_MAILBOX_1 = 0x1U, /**< TX mailbox index 1 */
CAN_TX_MAILBOX_2 = 0x2U, /**< TX mailbox index 2 */
CAN_TX_MAILBOX_NONE = 0x3U, /**< MailBox can't be used */
} can_tx_mailbox_t;
/**
* @brief CAN Receive fifo Number
*/
typedef enum {
CAN_RX_FIFO0 = 0x0U, /**< CAN fifo 0 used to receive */
CAN_RX_FIFO1 = 0x1U, /**< CAN fifo 1 used to receive */
} can_rx_fifo_t;
/**
* @brief CAN Flags
*/
typedef enum {
CAN_FLAG_SLPS = (1U << 1), /**< Sleep acknowledge flag */
CAN_FLAG_ERR = (1U << 2), /**< Error flag*/
CAN_FLAG_WK = (1U << 3), /**< Wake up flag */
CAN_FLAG_SLP = (1U << 4), /**< Sleep acknowledge flag */
CAN_FLAG_M0REQC = (1U << 20) | (1U << 0), /**< Request MailBox0 flag */
CAN_FLAG_M0TXC = (1U << 20) | (1U << 1), /**< Transmission OK MailBox0 flag */
CAN_FLAG_M1REQC = (1U << 20) | (1U << 8), /**< Request MailBox1 flag */
CAN_FLAG_M1TXC = (1U << 20) | (1U << 9), /**< Transmission OK MailBox1 flag */
CAN_FLAG_M2REQC = (1U << 20) | (1U << 16), /**< Request MailBox2 flag */
CAN_FLAG_M2TXC = (1U << 20) | (1U << 17), /**< Transmission OK MailBox2 flag */
CAN_FLAG_TXM0 = (1U << 20) | (1U << 26), /**< Transmit mailbox 0 empty flag */
CAN_FLAG_TXM1 = (1U << 20) | (1U << 27), /**< Transmit mailbox 1 empty flag */
CAN_FLAG_TXM2 = (1U << 20) | (1U << 28), /**< Transmit mailbox 2 empty flag */
CAN_FLAG_FF0 = (2U << 20) | (1U << 3), /**< FIFO 0 Full flag */
CAN_FLAG_FOV0 = (2U << 20) | (1U << 4), /**< FIFO 0 Overrun flag */
CAN_FLAG_FF1 = (3U << 20) | (1U << 3), /**< FIFO 1 Full flag */
CAN_FLAG_FOV1 = (3U << 20) | (1U << 4), /**< FIFO 1 Overrun flag */
CAN_FLAG_WARN = (4U << 20) | (1U << 0), /**< Error warning flag */
CAN_FLAG_PERR = (4U << 20) | (1U << 1), /**< Error passive flag */
CAN_FLAG_BOF = (4U << 20) | (1U << 2), /**< Bus-Off flag */
} can_flag_t;
/**
* @brief CAN Interrupts
*/
typedef enum {
CAN_IT_TXM = (1U << 0), /**< Transmit mailbox empty interrupt bit */
CAN_IT_FP0 = (1U << 1), /**< FIFO0 message pending interrupt bit */
CAN_IT_FF0 = (1U << 2), /**< FIFO0 full interrupt bit */
CAN_IT_FOV0 = (1U << 3), /**< FIFO0 overrun interrupt bit */
CAN_IT_FP1 = (1U << 4), /**< FIFO1 message pending interrupt bit */
CAN_IT_FF1 = (1U << 5), /**< FIFO1 full interrupt bit */
CAN_IT_FOV1 = (1U << 6), /**< FIFO1 overrun interrupt bit */
CAN_IT_WARN = (1U << 8), /**< Error warning interrupt bit */
CAN_IT_PERR = (1U << 9), /**< Error passive interrupt bit */
CAN_IT_BOF = (1U << 10), /**< Bus-off interrupt bit */
CAN_IT_PRERR = (1U << 11), /**< Last error code interrupt bit */
CAN_IT_ERR = (1U << 15), /**< Error interrupt bit */
CAN_IT_WK = (1U << 16), /**< wake-up interrupt bit */
CAN_IT_SLP = (1U << 17), /**< sleep interrupt bit */
} can_it_t;
/**
* @brief CAN filter configuration structure definition
*/
typedef struct {
uint32_t id_high; /**< Specifies the filter identification number */
uint32_t id_low; /**< Specifies the filter identification number */
uint32_t mask_id_high; /**< Specifies the filter mask number or identification number */
uint32_t mask_id_low; /**< Specifies the filter mask number or identification number */
can_filter_fifo_t fifo; /**< Specifies the fifo (0 or 1) which will be assigned to the filter. */
uint32_t number; /**< Specifies the filter which will be initialized. */
can_filter_mode_t mode; /**< Specifies the filter mode to be initialized. */
can_filter_scale_t scale; /**< Specifies the filter scale. */
type_func_t active; /**< Enable or disable the filter. */
} can_filter_t;
/**
* @brief CAN init structure definition
*/
typedef struct {
uint32_t psc; /**< Specifies the length of a time quantum. */
can_operate_mode_t mode; /**< Specifies the CAN operating mode. */
can_sjw_t sjw; /**< Specifies the maximum number of time quanta the CAN hardware is
allowed to lengthen or shorten a bit to perform resynchronization. */
can_seg1_t seg1; /**< Specifies the number of time quanta in Bit Segment 1. */
can_seg2_t seg2; /**< Specifies the number of time quanta in Bit Segment 2. */
type_func_t ttcm; /**< Enable or disable the time triggered communication mode. */
type_func_t abom; /**< Enable or disable the automatic bus-off management. */
type_func_t awk; /**< Enable or disable the automatic wake-up mode. */
type_func_t artx; /**< Enable or disable the non-automatic retransmission mode. */
type_func_t rfom; /**< Enable or disable the Receive fifo Locked mode. */
type_func_t txmp; /**< Enable or disable the transmit fifo priority. */
} can_init_t;
/**
* @brief CAN Tx message structure definition
*/
typedef struct {
uint32_t std; /**< Specifies the standard identifier. */
uint32_t ext; /**< Specifies the extended identifier. */
can_id_type_t type; /**< Specifies the type of identifier for the message that will be transmitted. */
can_remote_req_t rtr; /**< Specifies the type of frame for the message that will be transmitted. */
uint32_t len; /**< Specifies the length of the frame that will be transmitted. */
uint8_t data[8]; /**< Contains the data to be transmitted. */
} can_tx_msg_t;
/**
* @brief CAN Rx message structure definition
*/
typedef struct {
uint32_t std; /**< Specifies the standard identifier. */
uint32_t ext; /**< Specifies the extended identifier. */
can_id_type_t type; /**< Specifies the type of identifier for the message that will be received. */
can_remote_req_t rtr; /**< Specifies the type of frame for the received message. */
uint32_t len; /**< Specifies the length of the frame that will be received. */
uint8_t data[8]; /**< Contains the data to be received. */
uint32_t fmi; /**< Specifies the index of the filter the message stored in the mailbox passes through. */
can_rx_fifo_t num; /**< Specifies the receive fifo number. */
} can_rx_msg_t;
/**
* @brief CAN handle Structure definition
*/
typedef struct can_handle_s {
CAN_TypeDef *perh; /**< Register base address */
can_init_t init; /**< CAN required parameters */
can_rx_msg_t *rx0_msg; /**< Pointer to receive message from FIFO0 */
can_rx_msg_t *rx1_msg; /**< Pointer to receive message from FIFO1 */
lock_state_t lock; /**< CAN locking object */
can_state_t state; /**< CAN communication state */
can_error_t err; /**< CAN Error code */
void (*tx_cplt_cbk)(struct can_handle_s *arg); /**< Tx completed callback */
void (*rx_cplt_cbk)(struct can_handle_s *arg, can_rx_fifo_t num); /**< Rx completed callback */
void (*error_cbk)(struct can_handle_s *arg); /**< error callback */
} can_handle_t;
/**
* @}
*/
/** @defgroup CAN_Public_Macro CAN Public Macros
* @{
*/
#define CAN_RESET_HANDLE_STATE(x) ((x)->state = CAN_STATE_RESET)
#define CAN_RX_MSG_PENDING(x, y) (((y) == CAN_RX_FIFO0) ? \
(READ_BIT((x)->perh->RXF0, CAN_RXF0_PEND_MSK)) : (READ_BIT((x)->perh->RXF1, CAN_RXF1_PEND_MSK)))
#define CAN_DBG_FREEZE(x, y) (MODIFY_REG((x)->perh->CON, CAN_CON_DBGSTP_MSK, (y) << CAN_CON_DBGSTP_POS))
#define CAN_TX_STAMP_ENABLE(x, y) (SET_BIT((x)->perh->TxMailBox[(y)].TXFCON, CAN_TXFCON0_TXGT_MSK))
#define CAN_TX_STAMP_DISABLE(x, y) (CLEAR_BIT((x)->perh->TxMailBox[(y)].TXFCON, CAN_TXFCON0_TXGT_MSK))
/**
* @}
*/
/** @defgroup CAN_Private_Macros CAN Private Macros
* @{
*/
#define IS_CAN_ALL(x) ((x) == CAN0)
#define IS_CAN_FILTER_NUMBER(x) ((x) <= 13)
#define IS_CAN_MODE(x) (((x) == CAN_MODE_NORMAL) || \
((x) == CAN_MODE_LOOPBACK) || \
((x) == CAN_MODE_SILENT) || \
((x) == CAN_MODE_SILENT_LOOPBACK))
#define IS_CAN_SJW(x) (((x) == CAN_SJW_1) || \
((x) == CAN_SJW_2) || \
((x) == CAN_SJW_3) || \
((x) == CAN_SJW_4))
#define IS_CAN_BS1(x) ((x) <= CAN_SEG1_16)
#define IS_CAN_BS2(x) ((x) <= CAN_SEG2_8)
#define IS_CAN_FILTER_MODE(x) (((x) == CAN_FILTER_MODE_MASK) || \
((x) == CAN_FILTER_MODE_LIST))
#define IS_CAN_FILTER_SCALE(x) (((x) == CAN_FILTER_SCALE_16) || \
((x) == CAN_FILTER_SCALE_32))
#define IS_CAN_FILTER_FIFO(x) (((x) == CAN_FILTER_FIFO0) || \
((x) == CAN_FILTER_FIFO1))
#define IS_CAN_IDTYPE(x) (((x) == CAN_ID_STD) || \
((x) == CAN_ID_EXT))
#define IS_CAN_RTR(x) (((x) == CAN_RTR_DATA) || ((x) == CAN_RTR_REMOTE))
#define IS_CAN_FIFO(x) (((x) == CAN_RX_FIFO0) || ((x) == CAN_RX_FIFO1))
#define IS_CAN_TX_MAILBOX(x) ((x) <= CAN_TX_MAILBOX_NONE)
#define IS_CAN_STDID(x) ((x) <= ((uint32_t)0x7FF))
#define IS_CAN_EXTID(x) ((x) <= ((uint32_t)0x1FFFFFFF))
#define IS_CAN_DATA_LEN(x) ((x) <= ((uint8_t)0x08))
#define IS_CAN_PRESCALER(x) (((x) >= 1) && ((x) <= 1024))
#define IS_CAN_GET_FLAG(x) (((x) == CAN_FLAG_SLPS) || \
((x) == CAN_FLAG_ERR) || \
((x) == CAN_FLAG_WK) || \
((x) == CAN_FLAG_SLP) || \
((x) == CAN_FLAG_M0REQC) || \
((x) == CAN_FLAG_M0TXC) || \
((x) == CAN_FLAG_M1REQC) || \
((x) == CAN_FLAG_M1TXC) || \
((x) == CAN_FLAG_M2REQC) || \
((x) == CAN_FLAG_M2TXC) || \
((x) == CAN_FLAG_TXM0) || \
((x) == CAN_FLAG_TXM1) || \
((x) == CAN_FLAG_TXM2) || \
((x) == CAN_FLAG_FF0) || \
((x) == CAN_FLAG_FOV0) || \
((x) == CAN_FLAG_FF1) || \
((x) == CAN_FLAG_FOV1) || \
((x) == CAN_FLAG_WARN) || \
((x) == CAN_FLAG_PERR) || \
((x) == CAN_FLAG_BOF))
#define IS_CAN_CLEAR_FLAG(x) (((x) == CAN_FLAG_ERR) || \
((x) == CAN_FLAG_WK) || \
((x) == CAN_FLAG_SLP) || \
((x) == CAN_FLAG_M0REQC) || \
((x) == CAN_FLAG_M1REQC) || \
((x) == CAN_FLAG_M2REQC) || \
((x) == CAN_FLAG_FF0) || \
((x) == CAN_FLAG_FOV0) || \
((x) == CAN_FLAG_FF1) || \
((x) == CAN_FLAG_FOV1))
#define IS_CAN_IT(x) (((x) == CAN_IT_TXM) || \
((x) == CAN_IT_FP0) || \
((x) == CAN_IT_FF0) || \
((x) == CAN_IT_FOV0) || \
((x) == CAN_IT_FP1) || \
((x) == CAN_IT_FF1) || \
((x) == CAN_IT_FOV1) || \
((x) == CAN_IT_WARN) || \
((x) == CAN_IT_PERR) || \
((x) == CAN_IT_BOF) || \
((x) == CAN_IT_PRERR) || \
((x) == CAN_IT_ERR) || \
((x) == CAN_IT_WK) || \
((x) == CAN_IT_SLP))
#define CAN_TIMEOUT_VALUE 100
#define CAN_STATE_TX_MASK (1U << 4)
#define CAN_STATE_RX0_MASK (1U << 5)
#define CAN_STATE_RX1_MASK (1U << 6)
/**
* @}
*/
/** @addtogroup CAN_Public_Functions
* @{
*/
/** @addtogroup CAN_Public_Functions_Group1
* @{
*/
/* Initialization functions */
void ald_can_reset(can_handle_t *hperh);
ald_status_t ald_can_init(can_handle_t *hperh);
ald_status_t ald_can_filter_config(can_handle_t *hperh, can_filter_t *config);
/**
* @}
*/
/** @addtogroup CAN_Public_Functions_Group2
* @{
*/
/* IO operation functions */
ald_status_t ald_can_send(can_handle_t *hperh, can_tx_msg_t *msg, uint32_t timeout);
ald_status_t ald_can_send_by_it(can_handle_t *hperh, can_tx_msg_t *msg);
ald_status_t ald_can_recv(can_handle_t *hperh, can_rx_fifo_t num, can_rx_msg_t *msg, uint32_t timeout);
ald_status_t ald_can_recv_by_it(can_handle_t *hperh, can_rx_fifo_t num, can_rx_msg_t *msg);
/**
* @}
*/
/** @addtogroup CAN_Public_Functions_Group3
* @{
*/
/* Control function */
ald_status_t ald_can_sleep(can_handle_t *hperh);
ald_status_t ald_can_wake_up(can_handle_t *hperh);
void ald_can_cancel_send(can_handle_t *hperh, can_tx_mailbox_t box);
void ald_can_irq_handler(can_handle_t *hperh);
type_bool_t ald_can_get_tx_status(can_handle_t *hperh, can_tx_mailbox_t box);
void ald_can_interrupt_config(can_handle_t *hperh, can_it_t it, type_func_t state);
it_status_t ald_can_get_it_status(can_handle_t *hperh, can_it_t it);
flag_status_t ald_can_get_flag_status(can_handle_t *hperh, can_flag_t flag);
void ald_can_clear_flag_status(can_handle_t *hperh, can_flag_t flag);
/**
* @}
*/
/** @addtogroup CAN_Public_Functions_Group4
* @{
*/
/* State and Error functions */
can_state_t ald_can_get_state(can_handle_t *hperh);
can_error_t ald_can_get_error(can_handle_t *hperh);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_CAN_H */

View File

@@ -1,805 +0,0 @@
/**
*********************************************************************************
*
* @file ald_cmu.h
* @brief Header file of CMU module driver.
*
* @version V1.0
* @date 22 Nov 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 22 Nov 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_CMU_H__
#define __ALD_CMU_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
#include "ald_syscfg.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup CMU
* @{
*/
/** @defgroup CMU_Public_Macros CMU Public Macros
* @{
*/
#define CMU_HRC_SEL_BY_SW() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->CFGR, CMU_CFGR_HRCFCS_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_HRC_SEL_BY_CFGW() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->CFGR, CMU_CFGR_HRCFCS_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_HRC_DIV_1MHZ_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->CLKENR, CMU_CLKENR_HRC1MEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_HRC_DIV_1MHZ_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_HRC1MEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_HOSC_DIV_1MHZ_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->CLKENR, CMU_CLKENR_HOSC1MEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_HOSC_DIV_1MHZ_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_HOSC1MEN_MSK);\
SYSCFG_LOCK(); \
} while (0)
#define CMU_LOSC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->CLKENR, CMU_CLKENR_LOSCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LOSC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_LOSCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LRC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->CLKENR, CMU_CLKENR_LRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LRC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_LRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_ULRC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->CLKENR, CMU_CLKENR_ULRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_ULRC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_ULRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
/* Low power mode control */
#define CMU_LP_LRC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->LPENR, CMU_LPENR_LRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_LRC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->LPENR, CMU_LPENR_LRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_LOSC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->LPENR, CMU_LPENR_LOSCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_LOSC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->LPENR, CMU_LPENR_LOSCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_HRC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->LPENR, CMU_LPENR_HRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_HRC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->LPENR, CMU_LPENR_HRCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_HOSC_ENABLE() \
do { \
SYSCFG_UNLOCK(); \
SET_BIT(CMU->LPENR, CMU_LPENR_HOSCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
#define CMU_LP_HOSC_DISABLE() \
do { \
SYSCFG_UNLOCK(); \
CLEAR_BIT(CMU->LPENR, CMU_LPENR_HOSCEN_MSK); \
SYSCFG_LOCK(); \
} while (0)
/**
* @}
*/
/** @defgroup CMU_Public_Types CMU Public Types
* @{
*/
/**
* @brief CMU state structure definition
*/
typedef enum {
CMU_CLOCK_HRC = 0x1U, /**< HRC */
CMU_CLOCK_LRC = 0x2U, /**< LRC */
CMU_CLOCK_LOSC = 0x3U, /**< LOSC */
CMU_CLOCK_PLL1 = 0x4U, /**< PLL1 */
CMU_CLOCK_HOSC = 0x5U, /**< HOSC */
} cmu_clock_t;
/**
* @brief PLL1 output clock
*/
typedef enum {
CMU_PLL1_OUTPUT_36M = 0x0U, /**< x9 (36MHz) */
CMU_PLL1_OUTPUT_48M = 0x1U, /**< x12 (48MHz) */
#if defined(ES32F36xx) || defined(ES32F39xx)
CMU_PLL1_OUTPUT_72M = 0x2U, /**< x18 (72MHz) */
CMU_PLL1_OUTPUT_96M = 0x3U, /**< x24 (96MHz) */
#endif
} cmu_pll1_output_t;
/**
* @brief PLL1 referance clock
*/
typedef enum {
CMU_PLL1_INPUT_HRC_6 = 0x0U, /**< HRC / 6 */
CMU_PLL1_INPUT_PLL2 = 0x1U, /**< PLL2 */
CMU_PLL1_INPUT_HOSC = 0x2U, /**< HOSC / 1 */
CMU_PLL1_INPUT_HOSC_2 = 0x3U, /**< HOSC / 2 */
CMU_PLL1_INPUT_HOSC_3 = 0x4U, /**< HOSC / 3 */
CMU_PLL1_INPUT_HOSC_4 = 0x5U, /**< HOSC / 4 */
CMU_PLL1_INPUT_HOSC_5 = 0x6U, /**< HOSC / 5 */
CMU_PLL1_INPUT_HOSC_6 = 0x7U, /**< HOSC / 6 */
} cmu_pll1_input_t;
/**
* @brief HOSC range
*/
typedef enum {
CMU_HOSC_2M = 0x0U, /**< 0~2MHz */
CMU_HOSC_4M = 0x1U, /**< 2~4MHz */
CMU_HOSC_8M = 0x2U, /**< 4~8MHz */
CMU_HOSC_16M = 0x3U, /**< 8~16MHz */
CMU_HOSC_24M = 0x4U, /**< 16~24MHz */
} cmu_hosc_range_t;
/**
* @brief Safe clock source type
*/
typedef enum {
CMU_SAFE_CLK_HOSC = 0x0U, /**< HOSC */
CMU_SAFE_CLK_LOSC = 0x1U, /**< LOSC */
CMU_SAFE_CLK_PLL = 0x2U, /**< PLL */
} cmu_clock_safe_type_t;
/**
* @brief Frequency division select bit
*/
typedef enum {
CMU_DIV_1 = 0x0U, /**< Division by 1 */
CMU_DIV_2 = 0x1U, /**< Division by 2 */
CMU_DIV_4 = 0x2U, /**< Division by 4 */
CMU_DIV_8 = 0x3U, /**< Division by 8 */
CMU_DIV_16 = 0x4U, /**< Division by 16 */
CMU_DIV_32 = 0x5U, /**< Division by 32 */
CMU_DIV_64 = 0x6U, /**< Division by 64 */
CMU_DIV_128 = 0x7U, /**< Division by 128 */
CMU_DIV_256 = 0x8U, /**< Division by 256 */
CMU_DIV_512 = 0x9U, /**< Division by 512 */
CMU_DIV_1024 = 0xAU, /**< Division by 1024 */
CMU_DIV_2048 = 0xBU, /**< Division by 2048 */
CMU_DIV_4096 = 0xCU, /**< Division by 4096 */
} cmu_div_t;
/**
* @brief Bus type
*/
typedef enum {
CMU_HCLK_1 = 0x0U, /**< AHB1 bus */
CMU_HCLK_2 = 0x1U, /**< AHB2 bus */
CMU_SYS = 0x2U, /**< SYS bus */
CMU_PCLK_1 = 0x3U, /**< APB1 bus */
CMU_PCLK_2 = 0x4U, /**< APB2 bus */
} cmu_bus_t;
/**
* @brief Output high clock select
*/
typedef enum {
CMU_OUTPUT_HIGH_SEL_HOSC = 0x0U, /**< Select HOSC */
CMU_OUTPUT_HIGH_SEL_LOSC = 0x1U, /**< Select LOSC */
CMU_OUTPUT_HIGH_SEL_HRC = 0x2U, /**< Select HRC */
CMU_OUTPUT_HIGH_SEL_LRC = 0x3U, /**< Select LRC */
CMU_OUTPUT_HIGH_SEL_HOSM = 0x4U, /**< Select HOSM */
CMU_OUTPUT_HIGH_SEL_PLL1 = 0x5U, /**< Select PLL1 */
CMU_OUTPUT_HIGH_SEL_PLL2 = 0x6U, /**< Select PLL2 */
CMU_OUTPUT_HIGH_SEL_SYSCLK = 0x7U, /**< Select SYSCLK */
} cmu_output_high_sel_t;
/**
* @brief Output frequency division
*/
typedef enum {
CMU_OUTPUT_DIV_1 = 0x0U, /**< Division by 1 */
CMU_OUTPUT_DIV_2 = 0x1U, /**< Division by 2 */
CMU_OUTPUT_DIV_4 = 0x2U, /**< Division by 4 */
CMU_OUTPUT_DIV_8 = 0x3U, /**< Division by 8 */
CMU_OUTPUT_DIV_16 = 0x4U, /**< Division by 16 */
CMU_OUTPUT_DIV_32 = 0x5U, /**< Division by 32 */
CMU_OUTPUT_DIV_64 = 0x6U, /**< Division by 64 */
CMU_OUTPUT_DIV_128 = 0x7U, /**< Division by 128 */
} cmu_output_high_div_t;
/**
* @brief Output low clock select
*/
typedef enum {
CMU_OUTPUT_LOW_SEL_LOSC = 0x0U, /**< Select LOSC */
CMU_OUTPUT_LOW_SEL_LRC = 0x1U, /**< Select LRC */
CMU_OUTPUT_LOW_SEL_LOSM = 0x2U, /**< Select LOSM */
CMU_OUTPUT_LOW_SEL_BUZZ = 0x3U, /**< Select BUZZ */
CMU_OUTPUT_LOW_SEL_ULRC = 0x4U, /**< Select ULRC */
} cmu_output_low_sel_t;
/**
* @brief BUZZ frequency division
*/
typedef enum {
CMU_BUZZ_DIV_2 = 0x0U, /**< Division by 2 */
CMU_BUZZ_DIV_4 = 0x1U, /**< Division by 4 */
CMU_BUZZ_DIV_8 = 0x2U, /**< Division by 8 */
CMU_BUZZ_DIV_16 = 0x3U, /**< Division by 16 */
CMU_BUZZ_DIV_32 = 0x4U, /**< Division by 32 */
CMU_BUZZ_DIV_64 = 0x5U, /**< Division by 64 */
CMU_BUZZ_DIV_128 = 0x6U, /**< Division by 128 */
CMU_BUZZ_DIV_256 = 0x7U, /**< Division by 256 */
} cmu_buzz_div_t;
/**
* @brief Low power peripheral clock select
*/
typedef enum {
CMU_LP_PERH_CLOCK_SEL_PCLK2 = 0x0U, /**< Select PCLK2 */
CMU_LP_PERH_CLOCK_SEL_PLL1 = 0x1U, /**< Select PLL1 */
CMU_LP_PERH_CLOCK_SEL_PLL2 = 0x2U, /**< Select PLL2 */
CMU_LP_PERH_CLOCK_SEL_HRC = 0x3U, /**< Select HRC */
CMU_LP_PERH_CLOCK_SEL_HOSC = 0x4U, /**< Select HOSC */
CMU_LP_PERH_CLOCK_SEL_LRC = 0x5U, /**< Select LRC */
CMU_LP_PERH_CLOCK_SEL_LOSC = 0x6U, /**< Select LOSC */
CMU_LP_PERH_CLOCK_SEL_ULRC = 0x7U, /**< Select ULRC */
CMU_LP_PERH_CLOCK_SEL_HRC_1M = 0x8U, /**< Select HRC down to 1MHz */
CMU_LP_PERH_CLOCK_SEL_HOSC_1M = 0x9U, /**< Select HOSC down to 1MHz */
CMU_LP_PERH_CLOCK_SEL_LOSM = 0xAU, /**< Select LOSM */
CMU_LP_PERH_CLOCK_SEL_HOSM = 0xBU, /**< Select HOSM */
} cmu_lp_perh_clock_sel_t;
/**
* @brief LCD clock select
*/
typedef enum {
CMU_LCD_SEL_LOSM = 0x0U, /**< Select LOSM */
CMU_LCD_SEL_LOSC = 0x1U, /**< Select LOSC */
CMU_LCD_SEL_LRC = 0x2U, /**< Select LRC */
CMU_LCD_SEL_ULRC = 0x3U, /**< Select ULRC */
CMU_LCD_SEL_HRC_1M = 0x4U, /**< Select HRC down to 1MHz */
CMU_LCD_SEL_HOSC_1M = 0x5U, /**< Select HOSC down to 1MHz */
} cmu_lcd_clock_sel_t;
/**
* @brief QSPI clock select
*/
typedef enum {
CMU_QSPI_CLOCK_SEL_PCLK1 = 0x0U, /**< Select PCLK1 */
CMU_QSPI_CLOCK_SEL_HCLK2 = 0x1U, /**< Select HCLK2 */
CMU_QSPI_CLOCK_SEL_HRC = 0x2U, /**< Select HRC */
CMU_QSPI_CLOCK_SEL_HOSC = 0x3U, /**< Select HOSC */
CMU_QSPI_CLOCK_SEL_PLL1 = 0x4U, /**< Select PLL1 */
CMU_QSPI_CLOCK_SEL_HOSM = 0x5U, /**< Select HOSC security management */
} cmu_qspi_clock_sel_t;
/**
* @brief USB clock select
*/
typedef enum {
CMU_USB_CLOCK_SEL_HOSC = 0x0U, /**< Select HOSC */
CMU_USB_CLOCK_SEL_HRC = 0x1U, /**< Select HRC */
CMU_USB_CLOCK_SEL_PCLK1 = 0x2U, /**< Select PCLK1 */
CMU_USB_CLOCK_SEL_PLL1 = 0x3U, /**< Select PLL1 */
CMU_USB_CLOCK_SEL_HOSM = 0x4U, /**< Select HOSC security management */
} cmu_usb_clock_sel_t;
/**
* @brief USB clock division
*/
typedef enum {
CMU_USB_DIV_1 = 0x0U, /**< Division by 1 */
CMU_USB_DIV_2 = 0x1U, /**< Division by 2 */
CMU_USB_DIV_4 = 0x2U, /**< Division by 4 */
CMU_USB_DIV_8 = 0x3U, /**< Division by 8 */
CMU_USB_DIV_16 = 0x4U, /**< Division by 16 */
CMU_USB_DIV_32 = 0x5U, /**< Division by 32 */
CMU_USB_DIV_64 = 0x6U, /**< Division by 64 */
CMU_USB_DIV_128 = 0x7U, /**< Division by 128 */
CMU_USB_DIV_256 = 0x8U, /**< Division by 256 */
CMU_USB_DIV_512 = 0x9U, /**< Division by 512 */
CMU_USB_DIV_1024 = 0xAU, /**< Division by 1024 */
CMU_USB_DIV_2048 = 0xBU, /**< Division by 2048 */
CMU_USB_DIV_4096 = 0xCU, /**< Division by 4096 */
} cmu_usb_div_t;
/**
* @brief Peripheral clock enable/disable
* @verbatim
In this module, for the convenience of code maintenance,
TIMERx is used to indicate the sequence of the timer peripheral.
Different product series TIMERx represent different meanings:
1. For ES32F36xx series:
TIMER0 ----> AD16C4T0
TIMER1 ----> AD16C4T1
TIMER2 ----> GP32C4T0
TIMER3 ----> GP32C4T1
TIMER4 ----> BS16T0
TIMER5 ----> BS16T1
TIMER6 ----> GP16C4T0
TIMER7 ----> GP16C4T1
2. For ES32F393x/ES32F336x/ES32F392x series:
TIMER0 ----> GP16C4T0
TIMER1 ----> GP16C4T1
TIMER2 ----> GP32C4T0
TIMER3 ----> GP32C4T1
TIMER4 ----> BS16T0
TIMER5 ----> BS16T1
TIMER6 ----> GP16C4T2
TIMER7 ----> GP16C4T3
@endverbatim
*/
typedef enum {
CMU_PERH_GPIO = (1U << 0), /**< GPIO */
CMU_PERH_CRC = (1U << 1), /**< CRC */
CMU_PERH_CALC = (1U << 2), /**< CALC */
CMU_PERH_CRYPT = (1U << 3), /**< CRYPT */
CMU_PERH_TRNG = (1U << 4), /**< TRNG */
CMU_PERH_PIS = (1U << 5), /**< PIS */
CMU_PERH_EBI = (1U << 6), /**< EBI */
CMU_PERH_QSPI_H = (1U << 7), /**< QSPI AHB */
CMU_PERH_DMA = (1U << 8), /**< DMA */
CMU_PERH_USB = (1U << 10), /**< USB */
CMU_PERH_ECC = (1U << 11), /**< ECC */
CMU_PERH_TIMER0 = (1U << 0) | (1U << 27), /**< TIMER0 */
CMU_PERH_TIMER1 = (1U << 1) | (1U << 27), /**< TIMER1 */
CMU_PERH_TIMER2 = (1U << 2) | (1U << 27), /**< TIMER2 */
CMU_PERH_TIMER3 = (1U << 3) | (1U << 27), /**< TIMER3 */
CMU_PERH_TIMER4 = (1U << 4) | (1U << 27), /**< TIMER4 */
CMU_PERH_TIMER5 = (1U << 5) | (1U << 27), /**< TIMER5 */
CMU_PERH_TIMER6 = (1U << 6) | (1U << 27), /**< TIMER6 */
CMU_PERH_TIMER7 = (1U << 7) | (1U << 27), /**< TIMER7 */
CMU_PERH_UART0 = (1U << 8) | (1U << 27), /**< UART0 */
CMU_PERH_UART1 = (1U << 9) | (1U << 27), /**< UART1 */
CMU_PERH_UART2 = (1U << 10) | (1U << 27), /**< UART2 */
CMU_PERH_UART3 = (1U << 11) | (1U << 27), /**< UART3 */
CMU_PERH_UART4 = (1U << 12) | (1U << 27), /**< UART4 */
CMU_PERH_UART5 = (1U << 13) | (1U << 27), /**< UART5 */
CMU_PERH_SPI0 = (1U << 16) | (1U << 27), /**< SPI0 */
CMU_PERH_SPI1 = (1U << 17) | (1U << 27), /**< SPI1 */
CMU_PERH_SPI2 = (1U << 18) | (1U << 27), /**< SPI2 */
CMU_PERH_I2C0 = (1U << 20) | (1U << 27), /**< I2C0 */
CMU_PERH_I2C1 = (1U << 21) | (1U << 27), /**< I2C1 */
CMU_PERH_CAN = (1U << 24) | (1U << 27), /**< CAN */
CMU_PERH_QSPI_P = (1U << 25) | (1U << 27), /**< QSPI APB */
CMU_PERH_LPTIM0 = (1U << 0) | (1U << 28), /**< LPTIM0 */
CMU_PERH_LPUART0 = (1U << 2) | (1U << 28), /**< LPUART0 */
CMU_PERH_ADC0 = (1U << 4) | (1U << 28), /**< ADC0 */
CMU_PERH_ADC1 = (1U << 5) | (1U << 28), /**< ADC1 */
CMU_PERH_ACMP0 = (1U << 6) | (1U << 28), /**< ACMP0 */
CMU_PERH_ACMP1 = (1U << 7) | (1U << 28), /**< ACMP1 */
CMU_PERH_OPAMP = (1U << 8) | (1U << 28), /**< OPAMP */
CMU_PERH_DAC0 = (1U << 9) | (1U << 28), /**< DAC0 */
CMU_PERH_ACMP2 = (1U << 11) | (1U << 28), /**< ACMP2 */
CMU_PERH_WWDT = (1U << 12) | (1U << 28), /**< WWDT */
CMU_PERH_LCD = (1U << 13) | (1U << 28), /**< LCD */
CMU_PERH_IWDT = (1U << 14) | (1U << 28), /**< IWDT */
CMU_PERH_RTC = (1U << 15) | (1U << 28), /**< RTC */
CMU_PERH_TSENSE = (1U << 16) | (1U << 28), /**< TSENSE */
CMU_PERH_BKPC = (1U << 17) | (1U << 28), /**< BKPC */
CMU_PERH_DBGC = (1U << 19) | (1U << 28), /**< DBGC */
CMU_PERH_ALL = (0x7FFFFFFFU), /**< ALL */
} cmu_perh_t;
/**
* @brief CMU interrupt type
*/
typedef enum {
CMU_LOSC_STOP = 0x0U, /**< LOSC STOP INTERRUPT */
CMU_HOSC_STOP = 0x1U, /**< HOSC STOP INTERRUPT */
CMU_PLL1_UNLOCK = 0x2U, /**< PLL1 UNLOCK INTERRUPT */
CMU_LOSC_START = 0x3U, /**< LOSC START INTERRUPT */
CMU_HOSC_START = 0x4U, /**< HOSC START INTERRUPT */
} cmu_security_t;
/**
* @brief CMU clock state type
*/
typedef enum {
CMU_CLOCK_STATE_HOSCACT = (1U << 0), /**< HOSC active */
CMU_CLOCK_STATE_LOSCACT = (1U << 1), /**< LOSC active */
CMU_CLOCK_STATE_HRCACT = (1U << 2), /**< HRC active */
CMU_CLOCK_STATE_LRCACT = (1U << 3), /**< LRC active */
CMU_CLOCK_STATE_ULRCACT = (1U << 4), /**< ULRC active */
CMU_CLOCK_STATE_PLL1ACT = (1U << 8), /**< PLL1 active */
CMU_CLOCK_STATE_PLL2ACT = (1U << 9), /**< PLL2 active */
CMU_CLOCK_STATE_HOSCRDY = (1U << 16), /**< HOSC ready */
CMU_CLOCK_STATE_LOSCRDY = (1U << 17), /**< LOSC ready */
CMU_CLOCK_STATE_HRCRDY = (1U << 18), /**< HRC ready */
CMU_CLOCK_STATE_LRCRDY = (1U << 19), /**< LRC ready */
CMU_CLOCK_STATE_PLL1RDY = (1U << 24), /**< PLL1 ready */
CMU_CLOCK_STATE_PLL2RDY = (1U << 25), /**< PLL2 ready */
} cmu_clock_state_t;
/**
* @brief Stop1 clock select type
*/
typedef enum {
CMU_STOP1_CLOCK_LRC = 0x0U, /**< LRC */
CMU_STOP1_CLOCK_HRC_24M = 0x1U, /**< HRC 24MHz */
CMU_STOP1_CLOCK_HRC_2M = 0x2U, /**< HRC 2MHz */
CMU_STOP1_CLOCK_HRC_1M = 0x3U, /**< HRC divides to 1MHz */
CMU_STOP1_CLOCK_HOSC = 0x4U, /**< HOSC */
CMU_STOP1_CLOCK_HOSC_1M = 0x5U, /**< HOSC divides to 1MHz */
CMU_STOP1_CLOCK_HOSCM = 0x6U, /**< HOSC security management */
} cmu_stop1_clock_t;
/**
* @}
*/
/**
* @defgroup CMU_Private_Macros CMU Private Macros
* @{
*/
#define IS_CMU_CLOCK(x) (((x) == CMU_CLOCK_HRC) || \
((x) == CMU_CLOCK_LRC) || \
((x) == CMU_CLOCK_LOSC) || \
((x) == CMU_CLOCK_PLL1) || \
((x) == CMU_CLOCK_HOSC))
#if defined(ES32F36xx) || defined(ES32F39xx)
#define IS_CMU_PLL1_OUTPUT(x) (((x) == CMU_PLL1_OUTPUT_36M) || \
((x) == CMU_PLL1_OUTPUT_48M) || \
((x) == CMU_PLL1_OUTPUT_72M) || \
((x) == CMU_PLL1_OUTPUT_96M))
#endif
#ifdef ES32F336x
#define IS_CMU_PLL1_OUTPUT(x) (((x) == CMU_PLL1_OUTPUT_36M) || \
((x) == CMU_PLL1_OUTPUT_48M))
#endif
#define IS_CMU_PLL1_INPUT(x) (((x) == CMU_PLL1_INPUT_HRC_6) || \
((x) == CMU_PLL1_INPUT_PLL2) || \
((x) == CMU_PLL1_INPUT_HOSC) || \
((x) == CMU_PLL1_INPUT_HOSC_2) || \
((x) == CMU_PLL1_INPUT_HOSC_3) || \
((x) == CMU_PLL1_INPUT_HOSC_4) || \
((x) == CMU_PLL1_INPUT_HOSC_5) || \
((x) == CMU_PLL1_INPUT_HOSC_6))
#define IS_CMU_HOSC_RANGE(x) (((x) == CMU_HOSC_2M) || \
((x) == CMU_HOSC_4M) || \
((x) == CMU_HOSC_8M) || \
((x) == CMU_HOSC_16M) || \
((x) == CMU_HOSC_24M))
#define IS_CMU_DIV(x) (((x) == CMU_DIV_1) || \
((x) == CMU_DIV_2) || \
((x) == CMU_DIV_4) || \
((x) == CMU_DIV_8) || \
((x) == CMU_DIV_16) || \
((x) == CMU_DIV_32) || \
((x) == CMU_DIV_64) || \
((x) == CMU_DIV_128) || \
((x) == CMU_DIV_256) || \
((x) == CMU_DIV_512) || \
((x) == CMU_DIV_1024) || \
((x) == CMU_DIV_2048) || \
((x) == CMU_DIV_4096))
#define IS_CMU_BUS(x) (((x) == CMU_HCLK_1) || \
((x) == CMU_HCLK_2) || \
((x) == CMU_SYS) || \
((x) == CMU_PCLK_1) || \
((x) == CMU_PCLK_2))
#define IS_CMU_OUTPUT_HIGH_SEL(x) (((x) == CMU_OUTPUT_HIGH_SEL_HOSC) || \
((x) == CMU_OUTPUT_HIGH_SEL_LOSC) || \
((x) == CMU_OUTPUT_HIGH_SEL_HRC) || \
((x) == CMU_OUTPUT_HIGH_SEL_LRC) || \
((x) == CMU_OUTPUT_HIGH_SEL_HOSM) || \
((x) == CMU_OUTPUT_HIGH_SEL_PLL1) || \
((x) == CMU_OUTPUT_HIGH_SEL_PLL2) || \
((x) == CMU_OUTPUT_HIGH_SEL_SYSCLK))
#define IS_CMU_OUTPUT_HIGH_DIV(x) (((x) == CMU_OUTPUT_DIV_1) || \
((x) == CMU_OUTPUT_DIV_2) || \
((x) == CMU_OUTPUT_DIV_4) || \
((x) == CMU_OUTPUT_DIV_8) || \
((x) == CMU_OUTPUT_DIV_16) || \
((x) == CMU_OUTPUT_DIV_32) || \
((x) == CMU_OUTPUT_DIV_64) || \
((x) == CMU_OUTPUT_DIV_128))
#define IS_CMU_OUTPUT_LOW_SEL(x) (((x) == CMU_OUTPUT_LOW_SEL_LOSC) || \
((x) == CMU_OUTPUT_LOW_SEL_LRC ) || \
((x) == CMU_OUTPUT_LOW_SEL_LOSM) || \
((x) == CMU_OUTPUT_LOW_SEL_BUZZ) || \
((x) == CMU_OUTPUT_LOW_SEL_ULRC))
#define IS_CMU_SAFE_CLOCK_TYPE(x) (((x) == CMU_SAFE_CLK_HOSC) || \
((x) == CMU_SAFE_CLK_LOSC) || \
((x) == CMU_SAFE_CLK_PLL))
#define IS_CMU_BUZZ_DIV(x) (((x) == CMU_BUZZ_DIV_2) || \
((x) == CMU_BUZZ_DIV_4) || \
((x) == CMU_BUZZ_DIV_8) || \
((x) == CMU_BUZZ_DIV_16) || \
((x) == CMU_BUZZ_DIV_32) || \
((x) == CMU_BUZZ_DIV_64) || \
((x) == CMU_BUZZ_DIV_128) || \
((x) == CMU_BUZZ_DIV_256))
#define IS_CMU_LP_PERH_CLOCK_SEL(x) (((x) == CMU_LP_PERH_CLOCK_SEL_PCLK2) || \
((x) == CMU_LP_PERH_CLOCK_SEL_PLL1) || \
((x) == CMU_LP_PERH_CLOCK_SEL_PLL2) || \
((x) == CMU_LP_PERH_CLOCK_SEL_HRC) || \
((x) == CMU_LP_PERH_CLOCK_SEL_HOSC) || \
((x) == CMU_LP_PERH_CLOCK_SEL_LRC) || \
((x) == CMU_LP_PERH_CLOCK_SEL_LOSC) || \
((x) == CMU_LP_PERH_CLOCK_SEL_ULRC) || \
((x) == CMU_LP_PERH_CLOCK_SEL_HRC_1M) || \
((x) == CMU_LP_PERH_CLOCK_SEL_HOSC_1M) || \
((x) == CMU_LP_PERH_CLOCK_SEL_LOSM) || \
((x) == CMU_LP_PERH_CLOCK_SEL_HOSM))
#define IS_CMU_LCD_CLOCK_SEL(x) (((x) == CMU_LCD_SEL_LOSM) || \
((x) == CMU_LCD_SEL_LOSC) || \
((x) == CMU_LCD_SEL_LRC) || \
((x) == CMU_LCD_SEL_ULRC) || \
((x) == CMU_LCD_SEL_HRC_1M) || \
((x) == CMU_LCD_SEL_HOSC_1M))
#define IS_CMU_QSPI_CLOCK_SEL(x) (((x) == CMU_QSPI_CLOCK_SEL_PCLK1) || \
((x) == CMU_QSPI_CLOCK_SEL_HCLK2) || \
((x) == CMU_QSPI_CLOCK_SEL_HRC) || \
((x) == CMU_QSPI_CLOCK_SEL_HOSC) || \
((x) == CMU_QSPI_CLOCK_SEL_PLL1) || \
((x) == CMU_QSPI_CLOCK_SEL_HOSM))
#define IS_CMU_USB_CLOCK_SEL(x) (((x) == CMU_USB_CLOCK_SEL_HOSC) || \
((x) == CMU_USB_CLOCK_SEL_HRC) || \
((x) == CMU_USB_CLOCK_SEL_PCLK1) || \
((x) == CMU_USB_CLOCK_SEL_PLL1) || \
((x) == CMU_USB_CLOCK_SEL_HOSM))
#define IS_CMU_USB_DIV(x) (((x) == CMU_USB_DIV_1) || \
((x) == CMU_USB_DIV_2) || \
((x) == CMU_USB_DIV_4) || \
((x) == CMU_USB_DIV_8) || \
((x) == CMU_USB_DIV_16) || \
((x) == CMU_USB_DIV_32) || \
((x) == CMU_USB_DIV_64) || \
((x) == CMU_USB_DIV_128) || \
((x) == CMU_USB_DIV_256) || \
((x) == CMU_USB_DIV_512) || \
((x) == CMU_USB_DIV_1024) || \
((x) == CMU_USB_DIV_2048) || \
((x) == CMU_USB_DIV_4096))
#define IS_CMU_PERH(x) (((x) == CMU_PERH_GPIO) || \
((x) == CMU_PERH_CRC) || \
((x) == CMU_PERH_CALC) || \
((x) == CMU_PERH_CRYPT) || \
((x) == CMU_PERH_TRNG) || \
((x) == CMU_PERH_PIS) || \
((x) == CMU_PERH_EBI) || \
((x) == CMU_PERH_QSPI_H) || \
((x) == CMU_PERH_DMA) || \
((x) == CMU_PERH_USB) || \
((x) == CMU_PERH_ECC) || \
((x) == CMU_PERH_TIMER0) || \
((x) == CMU_PERH_TIMER1) || \
((x) == CMU_PERH_TIMER2) || \
((x) == CMU_PERH_TIMER3) || \
((x) == CMU_PERH_TIMER4) || \
((x) == CMU_PERH_TIMER5) || \
((x) == CMU_PERH_TIMER6) || \
((x) == CMU_PERH_TIMER7) || \
((x) == CMU_PERH_UART0) || \
((x) == CMU_PERH_UART1) || \
((x) == CMU_PERH_UART2) || \
((x) == CMU_PERH_UART3) || \
((x) == CMU_PERH_UART4) || \
((x) == CMU_PERH_UART5) || \
((x) == CMU_PERH_SPI0) || \
((x) == CMU_PERH_SPI1) || \
((x) == CMU_PERH_SPI2) || \
((x) == CMU_PERH_I2C0) || \
((x) == CMU_PERH_I2C1) || \
((x) == CMU_PERH_CAN) || \
((x) == CMU_PERH_QSPI_P) || \
((x) == CMU_PERH_LPTIM0) || \
((x) == CMU_PERH_LPUART0) || \
((x) == CMU_PERH_ADC0) || \
((x) == CMU_PERH_ADC1) || \
((x) == CMU_PERH_ACMP0) || \
((x) == CMU_PERH_ACMP1) || \
((x) == CMU_PERH_OPAMP) || \
((x) == CMU_PERH_DAC0) || \
((x) == CMU_PERH_ACMP2) || \
((x) == CMU_PERH_WWDT) || \
((x) == CMU_PERH_LCD) || \
((x) == CMU_PERH_IWDT) || \
((x) == CMU_PERH_RTC) || \
((x) == CMU_PERH_TSENSE) || \
((x) == CMU_PERH_BKPC) || \
((x) == CMU_PERH_DBGC) || \
((x) == CMU_PERH_ALL))
#define IS_CMU_CLOCK_STATE(x) (((x) == CMU_CLOCK_STATE_HOSCACT) || \
((x) == CMU_CLOCK_STATE_LOSCACT) || \
((x) == CMU_CLOCK_STATE_HRCACT) || \
((x) == CMU_CLOCK_STATE_LRCACT) || \
((x) == CMU_CLOCK_STATE_ULRCACT) || \
((x) == CMU_CLOCK_STATE_PLL1ACT) || \
((x) == CMU_CLOCK_STATE_PLL2ACT) || \
((x) == CMU_CLOCK_STATE_HOSCRDY) || \
((x) == CMU_CLOCK_STATE_LOSCRDY) || \
((x) == CMU_CLOCK_STATE_HRCRDY) || \
((x) == CMU_CLOCK_STATE_LRCRDY) || \
((x) == CMU_CLOCK_STATE_PLL1RDY) || \
((x) == CMU_CLOCK_STATE_PLL2RDY))
#define IS_CMU_STOP1_CLOCK(x) (((x) == CMU_STOP1_CLOCK_LRC) || \
((x) == CMU_STOP1_CLOCK_HRC_24M) || \
((x) == CMU_STOP1_CLOCK_HRC_2M) || \
((x) == CMU_STOP1_CLOCK_HRC_1M) || \
((x) == CMU_STOP1_CLOCK_HOSC) || \
((x) == CMU_STOP1_CLOCK_HOSC_1M) || \
((x) == CMU_STOP1_CLOCK_HOSCM))
/**
* @}
*/
/** @addtogroup CMU_Public_Functions
* @{
*/
/** @addtogroup CMU_Public_Functions_Group1
* @{
*/
/* System clock configure */
ald_status_t ald_cmu_clock_config_default(void);
ald_status_t ald_cmu_clock_config(cmu_clock_t clk, uint32_t clock);
void ald_cmu_pll1_config(cmu_pll1_input_t input, cmu_pll1_output_t output);
uint32_t ald_cmu_get_clock(void);
/**
* @}
*/
/** @addtogroup CMU_Public_Functions_Group2
* @{
*/
/* BUS division control */
void ald_cmu_div_config(cmu_bus_t bus, cmu_div_t div);
uint32_t ald_cmu_get_hclk1_clock(void);
uint32_t ald_cmu_get_hclk2_clock(void);
uint32_t ald_cmu_get_sys_clock(void);
uint32_t ald_cmu_get_pclk1_clock(void);
uint32_t ald_cmu_get_pclk2_clock(void);
/**
* @}
*/
/** @addtogroup CMU_Public_Functions_Group3
* @{
*/
/* Clock safe configure */
void ald_cmu_hosc_safe_config(cmu_hosc_range_t clock, type_func_t status);
void ald_cmu_losc_safe_config(type_func_t status);
void ald_cmu_pll_safe_config(type_func_t status);
uint32_t ald_cmu_current_clock_source_get(cmu_clock_safe_type_t type);
flag_status_t ald_cmu_get_clock_state(cmu_clock_state_t sr);
void ald_cmu_irq_handler(void);
void ald_cmu_irq_cbk(cmu_security_t se);
/**
* @}
*/
/** @addtogroup CMU_Public_Functions_Group4
* @{
*/
/* Clock output configure */
void ald_cmu_output_high_clock_config(cmu_output_high_sel_t sel,
cmu_output_high_div_t div, type_func_t status);
void ald_cmu_output_low_clock_config(cmu_output_low_sel_t sel, type_func_t status);
/**
* @}
*/
/** @addtogroup CMU_Public_Functions_Group5
* @{
*/
/* Peripheral Clock configure */
void ald_cmu_buzz_config(cmu_buzz_div_t div, uint16_t dat, type_func_t status);
void ald_cmu_lptim0_clock_select(cmu_lp_perh_clock_sel_t clock);
void ald_cmu_lpuart0_clock_select(cmu_lp_perh_clock_sel_t clock);
void ald_cmu_lcd_clock_select(cmu_lcd_clock_sel_t clock);
void ald_cmu_qspi_clock_select(cmu_qspi_clock_sel_t clock);
void ald_cmu_usb_clock_config(cmu_usb_clock_sel_t clock, cmu_usb_div_t div);
void ald_cmu_perh_clock_config(cmu_perh_t perh, type_func_t status);
void ald_cmu_stop1_clock_sel(cmu_stop1_clock_t clock);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_CMU_H__ */

View File

@@ -1,212 +0,0 @@
/**
*********************************************************************************
*
* @file ald_crc.h
* @brief Header file of CRC module driver.
*
* @version V1.0
* @date 18 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 18 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_CRC_H__
#define __ALD_CRC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
#include "ald_dma.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup CRC
* @{
*/
/** @defgroup CRC_Public_Types CRC Public Types
* @{
*/
/**
* @brief CRC mode
*/
typedef enum {
CRC_MODE_CCITT = 0U, /**< Ccitt */
CRC_MODE_8 = 1U, /**< Crc8 */
CRC_MODE_16 = 2U, /**< Crc16 */
CRC_MODE_32 = 3U, /**< Crc32 */
} crc_mode_t;
/**
* @brief CRC input length
*/
typedef enum {
CRC_LEN_AUTO = 0U, /**< Auto */
CRC_DATASIZE_8 = 1U, /**< Byte */
CRC_DATASIZE_16 = 2U, /**< Half word */
CRC_DATASIZE_32 = 3U, /**< Word */
} crc_datasize_t;
/**
* @brief CRC whether write error or no
*/
typedef enum {
CRC_WERR_NO = 0U, /**< No error */
CRC_WERR_ERR = 1U, /**< Error */
} crc_werr_t;
/**
* @brief CRC state structures definition
*/
typedef enum {
CRC_STATE_RESET = 0x0U, /**< Peripheral is not initialized */
CRC_STATE_READY = 0x1U, /**< Peripheral Initialized and ready for use */
CRC_STATE_BUSY = 0x2U, /**< An internal process is ongoing */
CRC_STATE_ERROR = 0x4U, /**< Error */
} crc_state_t;
/**
* @brief CRC init structure definition
*/
typedef struct {
crc_mode_t mode; /**< CRC mode */
type_func_t data_rev; /**< CRC data reverse or no */
type_func_t data_inv; /**< CRC data inverse or no */
type_func_t chs_rev; /**< CRC check sum reverse or no */
type_func_t chs_inv; /**< CRC check sum inverse or no */
uint32_t seed; /**< CRC seed */
} crc_init_t;
/**
* @brief CRC Handle Structure definition
*/
typedef struct crc_handle_s {
CRC_TypeDef *perh; /**< Register base address */
crc_init_t init; /**< CRC required parameters */
uint8_t *cal_buf; /**< The pointer of preparing buffer */
uint32_t *cal_res; /**< The pointer of result */
dma_handle_t hdma; /**< CRC DMA handle parameters */
lock_state_t lock; /**< Locking object */
crc_state_t state; /**< CRC operation state */
void (*cal_cplt_cbk)(struct crc_handle_s *arg); /**< Calculate completed callback */
void (*err_cplt_cbk)(struct crc_handle_s *arg); /**< Calculate error callback */
} crc_handle_t;
/**
* @}
*/
/** @defgroup CRC_Public_Macros CRC Public Macros
* @{
*/
#define CRC_ENABLE(handle) (SET_BIT((handle)->perh->CR, CRC_CR_EN_MSK))
#define CRC_DISABLE(handle) (CLEAR_BIT((handle)->perh->CR, CRC_CR_EN_MSK))
#define CRC_RESET(handle) (SET_BIT((handle)->perh->CR, CRC_CR_RST_MSK))
#define CRC_DMA_ENABLE(handle) (SET_BIT((handle)->perh->CR, CRC_CR_DMAEN_MSK))
#define CRC_DMA_DISABLE(handle) (CLEAR_BIT((handle)->perh->CR, CRC_CR_DMAEN_MSK))
#define CRC_CLEAR_ERROR_FLAG(handle) (SET_BIT((handle)->perh->CR, CRC_CR_WERR_MSK))
/**
* @}
*/
/** @defgroup CRC_Private_Macros CRC Private Macros
* @{
*/
#define IS_CRC(x) ((x) == CRC)
#define IS_CRC_MODE(x) (((x) == CRC_MODE_CCITT) || \
((x) == CRC_MODE_8) || \
((x) == CRC_MODE_16) || \
((x) == CRC_MODE_32))
/**
* @}
*/
/** @addtogroup CRC_Public_Functions
* @{
*/
/** @addtogroup CRC_Public_Functions_Group1
* @{
*/
ald_status_t ald_crc_init(crc_handle_t *hperh);
void ald_crc_reset(crc_handle_t *hperh);
/**
* @}
*/
/** @addtogroup CRC_Public_Functions_Group2
* @{
*/
uint32_t ald_crc_calculate(crc_handle_t *hperh, uint8_t *buf, uint32_t size);
uint32_t ald_crc_calculate_halfword(crc_handle_t *hperh, uint16_t *buf, uint32_t size);
uint32_t ald_crc_calculate_word(crc_handle_t *hperh, uint32_t *buf, uint32_t size);
/**
* @}
*/
/** @addtogroup CRC_Public_Functions_Group3
* @{
*/
ald_status_t ald_crc_calculate_by_dma(crc_handle_t *hperh, uint8_t *buf, uint32_t *res, uint16_t size, uint8_t channel);
ald_status_t ald_crc_calculate_halfword_by_dma(crc_handle_t *hperh, uint16_t *buf, uint32_t *res, uint16_t size, uint8_t channel);
ald_status_t ald_crc_calculate_word_by_dma(crc_handle_t *hperh, uint32_t *buf, uint32_t *res, uint16_t size, uint8_t channel);
ald_status_t ald_crc_dma_pause(crc_handle_t *hperh);
ald_status_t ald_crc_dma_resume(crc_handle_t *hperh);
ald_status_t ald_crc_dma_stop(crc_handle_t *hperh);
/**
* @}
*/
/** @addtogroup CRC_Public_Functions_Group4
* @{
*/
crc_state_t ald_crc_get_state(crc_handle_t *hperh);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_CRC_H__ */

View File

@@ -1,341 +0,0 @@
/**
*********************************************************************************
*
* @file ald_crypt.h
* @brief Header file of CRYPT module driver.
*
* @version V1.0
* @date 19 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 19 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_CRYPT_H__
#define __ALD_CRYPT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup CRYPT
* @{
*/
/** @defgroup CRYPT_Public_Types CRYPT Public Types
* @{
*/
/**
* @brief CRYPT encrypt or decrypt select
*/
typedef enum {
CRYPT_DECRYPT = 0U, /**< Decrypt */
CRYPT_ENCRYPT = 1U, /**< Encrypt */
} crypt_encs_t;
/**
* @brief CRYPT aes key select
*/
typedef enum {
CRYPT_BITS_128 = 0U, /**< 128bit key for aes */
CRYPT_BITS_192 = 1U, /**< 192bit key for aes */
CRYPT_BITS_256 = 2U, /**< 256bit key for aes */
} crypt_aesks_t;
/**
* @brief CRYPT mode select
*/
typedef enum {
CRYPT_MODE_ECB = 0U, /**< ECB */
CRYPT_MODE_CBC = 1U, /**< CBC */
CRYPT_MODE_CTR = 2U, /**< CTR */
} crypt_mode_t;
/**
* @brief CRYPT data type
*/
typedef enum {
CRYPT_DATA_CHANGE_NO = 0U, /**< No exchange */
CRYPT_DATA_CHANGE_16 = 1U, /**< 16bit exchange */
CRYPT_DATA_CHANGE_8 = 2U, /**< 8bit exchange */
CRYPT_DATA_CHANGE_1 = 3U, /**< 1bit exchange */
} crypt_datatype_t;
/**
* @brief CRYPT des key select
*/
typedef enum {
CRYPT_KEYS_2 = 0U, /**< 2 key for des */
CRYPT_KEYS_3 = 1U, /**< 3 key for des */
CRYPT_KEYS_1 = 2U, /**< 1 key for des */
} crypt_desks_t;
/**
* @brief CRYPT crypt select
*/
typedef enum {
CRYPT_CRYSEL_AES = 0U, /**< AES */
CRYPT_CRYSEL_DES = 1U, /**< DES */
} crypt_crysel_t;
/**
* @brief CRYPT interrupt
*/
typedef enum {
CRYPT_IT_IT = 0x80U, /**< Interrupt */
} crypt_it_t;
/**
* @brief CRYPT interrupt flag
*/
typedef enum {
CRYPT_FLAG_AESIF = 0x1U, /**< Aes flag */
CRYPT_FLAG_DESIF = 0x2U, /**< Des flag */
CRYPT_FLAG_DONE = 0x100U, /**< Complete flag */
} crypt_flag_t;
/**
* @brief CRYPT key select
*/
typedef enum {
CRYPT_AES_BITS_128 = 0x4U, /**< 128bit key of aes */
CRYPT_AES_BITS_192 = 0x6U, /**< 192bit key of aes */
CRYPT_AES_BITS_256 = 0x8U, /**< 192bit key of ase */
CRYPT_DES_KEYS_1 = 0x12U, /**< 1 key of des */
CRYPT_DES_KEYS_2 = 0x14U, /**< 2 key of des */
CRYPT_DES_KEYS_3 = 0x16U, /**< 3 key of des */
} crypt_ks_t;
/**
* @brief CRYPT state structures definition
*/
typedef enum {
CRYPT_STATE_RESET = 0x0U, /**< Peripheral is not initialized */
CRYPT_STATE_READY = 0x1U, /**< Peripheral Initialized and ready for use */
CRYPT_STATE_BUSY = 0x2U, /**< An internal process is ongoing */
CRYPT_STATE_ERROR = 0x4U, /**< Error */
} crypt_state_t;
/**
* @brief CRYPT key length
*/
typedef enum {
KEY_2_LEN = 2U, /**< Key's lenth is 2 */
KEY_4_LEN = 4U, /**< Key's lenth is 4 */
KEY_6_LEN = 6U, /**< Key's lenth is 6 */
KEY_8_LEN = 8U, /**< Key's lenth is 8 */
} crypt_key_len_t;
/**
* @brief CRYPT iv length
*/
typedef enum {
IV_2_LEN = 2U, /**< iv's lenth is 2 */
IV_4_LEN = 4U, /**< iv's lenth is 4 */
} crypt_ivr_len_t;
/**
* @brief CRYPT data type
*/
typedef enum {
DATA_32_BIT = 0U, /**< 32 bit data,don't swap */
DATA_16_BIT = 1U, /**< 16 bit data,swap */
DATA_8_BIT = 2U, /**< 8 bit data,swap */
DATA_1_BIT = 3U, /**< 1 bit data, swap */
} crypt_data_t;
/**
* @brief CRYPT init structure definition
*/
typedef struct {
crypt_mode_t mode; /**< Crypt mode */
crypt_data_t type; /**< Data type select */
crypt_ks_t key; /**< Key select */
} crypt_init_t;
/**
* @brief CRYPT Handle Structure definition
*/
typedef struct crypt_handle_s {
CRYPT_TypeDef *perh; /**< Register base address */
crypt_init_t init; /**< CRYPT required parameters */
dma_handle_t hdma_m2p; /**< CRYPT DMA handle parameters memory to crypt module */
dma_handle_t hdma_p2m; /**< CRYPT DMA handle parameters crypt module to memory */
uint8_t *plain_text; /**< Pointer to plain text */
uint8_t *cipher_text; /**< Pointer to cipher text */
uint32_t size; /**< The size of crypt data buf */
uint32_t count; /**< The count of crypt data buf */
uint32_t step; /**< The step of once crypt 2(des) or 4(aes) */
uint32_t dir; /**< ENCRYPT or DECRYPT */
uint32_t iv[4]; /**< The iv of crypt */
uint32_t iv_size; /**< The iv size */
uint32_t key[8]; /**< The key of crypt */
uint32_t key_size; /**< The key size */
lock_state_t lock; /**< Locking object */
crypt_state_t state; /**< CRYPT operation state */
void (*crypt_cplt_cbk)(struct crypt_handle_s *arg); /**< Crypt completed callback */
void (*err_cplt_cbk)(struct crypt_handle_s *arg); /**< Crypt error callback */
} crypt_handle_t;
/**
* @}
*/
/** @defgroup CRYPT_Public_Macros CRYPT Public Macros
* @{
*/
#define CRYPT_GO(handle) (SET_BIT((handle)->perh->CON, CRYPT_CON_GO_MSK))
#define CRYPT_FIFOEN_ENABLE(handle) (SET_BIT((handle)->perh->CON, CRYPT_CON_FIFOEN_MSK))
#define CRYPT_FIFOEN_DISABLE(handle) (CLEAR_BIT((handle)->perh->CON, CRYPT_CON_FIFOEN_MSK))
#define CRYPT_IVEN_ENABLE(handle) (SET_BIT((handle)->perh->CON, CRYPT_CON_IVEN_MSK))
#define CRYPT_IVEN_DISABLE(handle) (CLEAR_BIT((handle)->perh->CON, CRYPT_CON_IVEN_MSK))
#define CRYPT_IE_ENABLE(handle) (SET_BIT((handle)->perh->CON, CRYPT_CON_IE_MSK))
#define CRYPT_IE_DISABLE(handle) (CLEAR_BIT((handle)->perh->CON, CRYPT_CON_IE_MSK))
#define CRYPT_DMA_ENABLE(handle) (SET_BIT((handle)->perh->CON, CRYPT_CON_DMAEN_MSK))
#define CRYPT_DMA_DISABLE(handle) (CLEAR_BIT((handle)->perh->CON, CRYPT_CON_DMAEN_MSK))
#define CRYPT_SETDIR(handle, dir) do {(handle)->perh->CON &= ~(0x1 << CRYPT_CON_ENCS_POS); \
(handle)->perh->CON |= (dir << CRYPT_CON_ENCS_POS);} while (0)
#define CRYPT_WRITE_FIFO(handle, data) ((handle)->perh->FIFO = (data))
#define CRYPT_READ_FIFO(handle) ((handle)->perh->FIFO)
/**
* @}
*/
/** @defgroup CRYPT_Private_Macros CRYPT Private Macros
* @{
*/
#define IS_CRYPT(x) ((x) == CRYPT)
#define IS_CRYPT_MODE(x) (((x) == CRYPT_MODE_ECB) || \
((x) == CRYPT_MODE_CBC) || \
((x) == CRYPT_MODE_CTR))
#define IS_CRYPT_KS(x) (((x) == CRYPT_AES_BITS_128) || \
((x) == CRYPT_AES_BITS_192) || \
((x) == CRYPT_AES_BITS_256) || \
((x) == CRYPT_DES_KEYS_1) || \
((x) == CRYPT_DES_KEYS_2) || \
((x) == CRYPT_DES_KEYS_3))
#define IS_CRYPT_IT(x) ((x) == CRYPT_IT_IT)
#define IS_CRYPT_FLAG(x) (((x) == CRYPT_FLAG_AESIF) || \
((x) == CRYPT_FLAG_DESIF) || \
((x) == CRYPT_FLAG_DONE))
#define IS_CRYPT_IV_LEN(x) (((x) == IV_2_LEN) || \
((x) == IV_4_LEN))
#define IS_CRYPT_KEY_LEN(x) (((x) == KEY_2_LEN) || \
((x) == KEY_4_LEN) || \
((x) == KEY_6_LEN) || \
((x) == KEY_8_LEN))
/**
* @}
*/
/** @addtogroup CRYPT_Public_Functions
* @{
*/
/** @addtogroup CRYPT_Public_Functions_Group1
* @{
*/
extern ald_status_t ald_crypt_init(crypt_handle_t *hperh);
extern ald_status_t ald_crypt_write_key(crypt_handle_t *hperh, uint32_t * key, crypt_key_len_t len);
extern ald_status_t ald_crypt_read_key(crypt_handle_t *hperh, uint32_t * key, crypt_key_len_t len);
extern ald_status_t ald_crypt_write_ivr(crypt_handle_t *hperh, uint32_t * iv, crypt_ivr_len_t len);
extern ald_status_t ald_crypt_read_ivr(crypt_handle_t *hperh, uint32_t * iv, crypt_ivr_len_t len);
/**
* @}
*/
/** @addtogroup CRYPT_Public_Functions_Group2
* @{
*/
extern ald_status_t ald_crypt_encrypt(crypt_handle_t *hperh, uint8_t * plain_text, uint8_t * cipher_text, uint32_t size);
extern ald_status_t ald_crypt_decrypt(crypt_handle_t *hperh, uint8_t * cipher_text, uint8_t * plain_text, uint32_t size);
extern ald_status_t ald_crypt_gcm_verify(crypt_handle_t *hperh, uint8_t *cipher_text, uint32_t size, uint8_t *aadata, uint32_t alen, uint8_t *tag);
extern ald_status_t ald_crypt_encrypt_by_it(crypt_handle_t *hperh, uint8_t *plain_text, uint8_t *cipher_text, uint32_t size);
extern ald_status_t ald_crypt_decrypt_by_it(crypt_handle_t *hperh, uint8_t *cipher_text, uint8_t *plain_text, uint32_t size);
extern ald_status_t ald_crypt_encrypt_by_dma(crypt_handle_t *hperh, uint8_t * plain_text,
uint8_t *cipher_text, uint32_t size, uint8_t channel_m2p, uint8_t channel_p2m);
extern ald_status_t ald_crypt_decrypt_by_dma(crypt_handle_t *hperh, uint8_t * cipher_text,
uint8_t *plain_text, uint32_t size, uint8_t channel_m2p, uint8_t channel_p2m);
/**
* @}
*/
/** @addtogroup CRYPT_Public_Functions_Group3
* @{
*/
extern ald_status_t ald_crypt_dma_pause(crypt_handle_t *hperh);
extern ald_status_t ald_crypt_dma_resume(crypt_handle_t *hperh);
extern ald_status_t ald_crypt_dma_stop(crypt_handle_t *hperh);
extern void ald_crypt_irq_handler(crypt_handle_t *hperh);
/**
* @}
*/
/** @addtogroup CRYPT_Public_Functions_Group4
* @{
*/
extern void ald_crypt_interrupt_config(crypt_handle_t *hperh, crypt_it_t it, type_func_t state);
extern flag_status_t ald_crypt_get_flag_status(crypt_handle_t *hperh, crypt_flag_t flag);
extern void ald_crypt_clear_flag_status(crypt_handle_t *hperh, crypt_flag_t flag);
extern it_status_t ald_crypt_get_it_status(crypt_handle_t *hperh, crypt_it_t it);
/**
* @}
*/
/** @addtogroup CRYPT_Public_Functions_Group5
* @{
*/
extern crypt_state_t ald_crypt_get_state(crypt_handle_t *hperh);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,321 +0,0 @@
/**
******************************************************************************
* @file ald_dac.h
* @brief Header file of DAC Module library.
*
* @version V1.0
* @date 28 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 28 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_DAC_H__
#define __ALD_DAC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup DAC
* @{
*/
/** @defgroup DAC_Pubulic_Types DAC Pubulic Types
* @{
*/
/**
* @brief DAC channel
*/
typedef enum {
DAC_CHANNEL_0 = 1U, /**< DAC channel 0 */
DAC_CHANNEL_1 = 2U, /**< DAC channel 1 */
DAC_CHANNEL_COMB = 3U, /**< DAC channel 0 and 1 */
} dac_channel_t;
/**
* @brief DAC convert mode
*/
typedef enum {
DAC_CONV_MODE_CONTINUOUS = 0U, /**< DAC set in continuous mode */
DAC_CONV_MODE_SAMPLEHOLD = 1U, /**< DAC set in sample/hold mode */
DAC_CONV_MODE_SAMPLEOFF = 2U, /**< DAC set in sample/shut off mode */
} dac_conv_mode_t;
/**
* @brief DAC out mode
*/
typedef enum {
DAC_OUTPUT_DISABLE = 0U, /**< DAC output disable */
DAC_OUTPUT_PIN = 1U, /**< DAC output to pin enable */
DAC_OUTPUT_ADC = 2U, /**< DAC output to adc and acmp enable */
DAC_OUTPUT_PIN_ADC = 3U, /**< DAC output to pin, adc and acmp enable */
} dac_out_mode_t;
/**
* @brief DAC pis input channel
*/
typedef enum {
DAC_PIS_CH_0 = 0U, /**< PIS channel 0 triggers DAC channel conversion */
DAC_PIS_CH_1 = 1U, /**< PIS channel 1 triggers DAC channel conversion */
DAC_PIS_CH_2 = 2U, /**< PIS channel 2 triggers DAC channel conversion */
DAC_PIS_CH_3 = 3U, /**< PIS channel 3 triggers DAC channel conversion */
DAC_PIS_CH_4 = 4U, /**< PIS channel 4 triggers DAC channel conversion */
DAC_PIS_CH_5 = 5U, /**< PIS channel 5 triggers DAC channel conversion */
DAC_PIS_CH_6 = 6U, /**< PIS channel 6 triggers DAC channel conversion */
DAC_PIS_CH_7 = 7U, /**< PIS channel 7 triggers DAC channel conversion */
DAC_PIS_CH_8 = 8U, /**< PIS channel 8 triggers DAC channel conversion */
DAC_PIS_CH_9 = 9U, /**< PIS channel 9 triggers DAC channel conversion */
DAC_PIS_CH_10 = 10U, /**< PIS channel 10 triggers DAC channel conversion */
DAC_PIS_CH_11 = 11U, /**< PIS channel 11 triggers DAC channel conversion */
} dac_pissel_t;
/**
* @brief DAC negative reference voltage definition
*/
typedef enum {
DAC_NEG_REF_VSS = 0x0U, /**< DAC negative regerence voltage vss */
DAC_NEG_REF_VREFN = 0x1U, /**< DAC negative regerence voltage vrefn */
} dac_neg_ref_t;
/**
* @brief DAC positive reference voltage definition
*/
typedef enum {
DAC_POS_REF_VDD = 0x0U, /**< DAC posotove reference is VDD */
DAC_POS_REF_2V = 0x1U, /**< DAC posotove reference is internal 2V */
DAC_POS_REF_VREEFP = 0x2U, /**< DAC posotove reference is VREEFP */
DAC_POS_REF_VREEFP_BUF = 0x3U, /**< DAC posotove reference is VREEFP BUFFER */
} dac_pos_ref_t;
/**
* @brief Refresh interval select
*/
typedef enum {
DAC_REFRESH_8 = 0U, /**< Channel refreshed every 8 cycles */
DAC_REFRESH_16 = 1U, /**< Channel refreshed every 16 cycles */
DAC_REFRESH_32 = 2U, /**< Channel refreshed every 32 cycles */
DAC_REFRESH_64 = 3U, /**< Channel refreshed every 64 cycles */
} dac_refresh_t;
/**
* @brief DAC prescale
*/
typedef enum {
DAC_PRES_DIV_1 = 0U, /**< No division */
DAC_PRES_DIV_2 = 1U, /**< 2 clock division */
DAC_PRES_DIV_4 = 2U, /**< 4 clock division */
DAC_PRES_DIV_8 = 3U, /**< 8 clock division */
DAC_PRES_DIV_16 = 4U, /**< 16 clock division */
DAC_PRES_DIV_32 = 5U, /**< 32 clock division */
DAC_PRES_DIV_64 = 6U, /**< 64 clock division */
DAC_PRES_DIV_128 = 7U, /**< 128 clock division */
} dac_prescale_div_t;
/**
* @brief DAC output trigger select
*/
typedef enum {
DAC_TRIGGER_BY_DATA = 0U, /**< Channel is triggered by CHxDATA or COMBDATA write */
DAC_TRIGGER_BY_PIS = 1U, /**< Channel is triggered by PIS input */
} dac_trigger_t;
/**
* @brief DAC interrupt type
*/
typedef enum {
DAC_IT_CH0 = (1U << 0), /**< Channel 0 conversion complete interrupt */
DAC_IT_CH1 = (1U << 1), /**< Channel 1 conversion complete interrupt */
DAC_IT_CH0_UF = (1U << 4), /**< Channel 0 data underflow interrupt */
DAC_IT_CH1_UF = (1U << 5), /**< Channel 1 data underflow interrupt */
} dac_it_t;
/**
* @brief DAC interrupt flag type
*/
typedef enum {
DAC_FLAG_CH0 = (1U << 0), /**< Channel 0 conversion complete interrupt flag */
DAC_FLAG_CH1 = (1U << 1), /**< Channel 1 conversion complete interrupt flag */
DAC_FLAG_CH0_UF = (1U << 4), /**< Channel 0 data underflow interrupt flag */
DAC_FLAG_CH1_UF = (1U << 5), /**< Channel 1 data underflow interrupt flag */
} dac_flag_t;
/**
* @brief DAC state flag
*/
typedef enum {
DAC_CH0_BSY = (1U << 0), /**< Channel_0 is BUSY */
DAC_CH1_BSY = (1U << 1), /**< Channel_1 is BUSY */
} dac_status_t;
/**
* @brief DAC init structure definition
*/
typedef struct {
dac_conv_mode_t conv_mode; /**< Conversion mode */
dac_out_mode_t out_mode; /**< Select output mode */
dac_refresh_t refresh; /**< Refresh interval select */
dac_prescale_div_t div; /**< Prescaler setting */
type_func_t ch0_reset; /**< Select if prescaler is reset on channel 0 start */
type_func_t o_ctrl_pis; /**< Enable pis control of dac output enable */
type_func_t sine; /**< Sine mode enable/disable */
type_func_t diff; /**< Differential mode enable/disable */
dac_neg_ref_t n_ref; /**< The negative reference voltage select */
dac_pos_ref_t p_ref; /**< The positive reference voltage select */
} dac_init_t;
/**
* @brief DAC channel initialize structure definition
*/
typedef struct {
type_func_t enable; /**< DAC channel output enable/disable */
dac_trigger_t trigger; /**< Select channel conversion trigger */
type_func_t refresh_en; /**< Set automatic refresh of channel function */
dac_pissel_t pis_ch; /**< Select channel pis input channel */
} dac_channel_config_t;
/**
* @brief DAC handle Structure definition
*/
typedef struct dac_handle_s {
DAC_TypeDef *perh; /**< Register base address */
dac_init_t init; /**< DAC initialize parameters */
lock_state_t lock; /**< Locking object */
void (*cbk)(struct dac_handle_s *arg, uint32_t event); /**< DAC event callback */
} dac_handle_t;
/**
* @}
*/
/** @defgroup DAC_Public_Macros DAC Public Macros
* @{
*/
#define DAC_CH0_ENABLE() (SET_BIT(DAC0->CH0CTRL, DAC_CH0CTRL_EN_MSK))
#define DAC_CH1_ENABLE() (SET_BIT(DAC0->CH1CTRL, DAC_CH1CTRL_EN_MSK))
#define DAC_CH0_DISABLE() (CLEAR_BIT(DAC0->CH0CTRL, DAC_CH0CTRL_EN_MSK))
#define DAC_CH1_DISABLE() (CLEAR_BIT(DAC0->CH1CTRL, DAC_CH1CTRL_EN_MSK))
#define DAC_EVENT_CH0_CPLT 0x0
#define DAC_EVENT_CH1_CPLT 0x1
#define DAC_EVENT_CH0_UF 0x2
#define DAC_EVENT_CH1_UF 0x3
/**
* @}
*/
/** @defgroup DAC_Private_Macros DAC Private Macros
* @{
*/
#define IS_DAC_TYPE(x) ((x) == DAC0)
#define IS_DAC_CONVERT_TYPE(x) (((x) == DAC_CONV_MODE_CONTINUOUS) || \
((x) == DAC_CONV_MODE_SAMPLEHOLD) || \
((x) == DAC_CONV_MODE_SAMPLEOFF))
#define IS_DAC_OUTPUT_TYPE(x) (((x) == DAC_OUTPUT_DISABLE) || \
((x) == DAC_OUTPUT_PIN) || \
((x) == DAC_OUTPUT_ADC) || \
((x) == DAC_OUTPUT_PIN_ADC))
#define IS_DAC_NEG_REFRESH_TYPE(x) (((x) == DAC_NEG_REF_VSS) || \
((x) == DAC_NEG_REF_VREFN))
#define IS_DAC_POS_REFRESH_TYPE(x) (((x) == DAC_POS_REF_VDD) || \
((x) == DAC_POS_REF_2V) || \
((x) == DAC_POS_REF_VREEFP) || \
((x) == DAC_POS_REF_VREEFP_BUF))
#define IS_DAC_REFRESH_TYPE(x) (((x) == DAC_REFRESH_8) || \
((x) == DAC_REFRESH_16) || \
((x) == DAC_REFRESH_32) || \
((x) == DAC_REFRESH_64))
#define IS_DAC_CHANNEL_TYPE(x) (((x) == DAC_CHANNEL_0) || \
((x) == DAC_CHANNEL_1) || \
((x) == DAC_CHANNEL_COMB))
#define IS_DAC_PRESCALE_TYPE(x) (((x) == DAC_PRES_DIV_1) || \
((x) == DAC_PRES_DIV_2) || \
((x) == DAC_PRES_DIV_4) || \
((x) == DAC_PRES_DIV_8) || \
((x) == DAC_PRES_DIV_16) || \
((x) == DAC_PRES_DIV_32) || \
((x) == DAC_PRES_DIV_64) || \
((x) == DAC_PRES_DIV_128))
#define IS_DAC_INTERRUPT_TYPE(x) (((x) == DAC_IT_CH0) || \
((x) == DAC_IT_CH1) || \
((x) == DAC_IT_CH0_UF) || \
((x) == DAC_IT_CH1_UF))
#define IS_DAC_FLAG_TYPE(x) (((x) == DAC_FLAG_CH0) || \
((x) == DAC_FLAG_CH1) || \
((x) == DAC_FLAG_CH0_UF) || \
((x) == DAC_FLAG_CH1_UF))
#define IS_DAC_PISSEL_CH_TYPE(x) (((x) == DAC_PIS_CH_0) || \
((x) == DAC_PIS_CH_1) || \
((x) == DAC_PIS_CH_2) || \
((x) == DAC_PIS_CH_3) || \
((x) == DAC_PIS_CH_4) || \
((x) == DAC_PIS_CH_5) || \
((x) == DAC_PIS_CH_6) || \
((x) == DAC_PIS_CH_7) || \
((x) == DAC_PIS_CH_8) || \
((x) == DAC_PIS_CH_9) || \
((x) == DAC_PIS_CH_10) || \
((x) == DAC_PIS_CH_11))
#define IS_DAC_STATUS_TYPE(x) (((x) == DAC_CH0_BSY) || \
((x) == DAC_CH1_BSY))
#define IS_DAC_TRIGGER_TYPE(x) (((x) == DAC_TRIGGER_BY_DATA) || \
((x) == DAC_TRIGGER_BY_PIS))
/**
* @}
*/
/** @addtogroup DAC_Public_Functions
* @{
*/
ald_status_t ald_dac_reset(dac_handle_t *hperh);
ald_status_t ald_dac_init(dac_handle_t *hperh);
ald_status_t ald_dac_channel_config(dac_handle_t *hperh, dac_channel_config_t *config, dac_channel_t ch);
void ald_dac_output_set(dac_handle_t *hperh, dac_channel_t ch, uint32_t value);
flag_status_t ald_dac_get_status(dac_handle_t *hperh, dac_status_t status);
void ald_dac_interrupt_config(dac_handle_t *hperh, dac_it_t it, type_func_t state);
it_status_t ald_dac_get_it_status(dac_handle_t *hperh, dac_it_t it);
flag_status_t ald_dac_get_flag_status(dac_handle_t *hperh, dac_flag_t flag);
flag_status_t ald_dac_get_mask_flag_status(dac_handle_t *hperh, dac_flag_t flag);
void ald_dac_clear_flag_status(dac_handle_t *hperh, dac_flag_t flag);
void ald_dac_irq_handler(dac_handle_t *hperh);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
extern "C" }
#endif
#endif /* __ALD_DAC_H */

View File

@@ -1,172 +0,0 @@
/**
*********************************************************************************
*
* @file ald_dbgc.h
* @brief DEBUGCON module driver.
*
* @version V1.0
* @date 04 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 04 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_DBGC_H__
#define __ALD_DBGC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @defgroup DBGC DBGC
* @brief DBGC module driver
* @{
*/
/** @defgroup DBGC_Public_Types DBGC Public Types
* @{
*/
/**
* @brief Debug mode select
*/
typedef enum {
DEBC_MODE_SLEEP = (1U << 0), /**< Sleep mode */
DEBC_MODE_STOP1 = (1U << 1), /**< STOP1 mode */
DEBC_MODE_STOP2 = (1U << 2), /**< STOP2 mode */
DEBC_MODE_STANDBY = (1U << 3), /**< Standby mode */
} dbgc_mode_t;
/**
* @brief Debug peripheral select
*/
typedef enum {
DEBC_PERH_TIMER0 = (1U << 0), /**< AD16C4T0 */
DEBC_PERH_TIMER1 = (1U << 1), /**< BS16T0 */
DEBC_PERH_TIMER2 = (1U << 2), /**< GP16C2T0 */
DEBC_PERH_TIMER3 = (1U << 3), /**< GP16C2T1 */
DEBC_PERH_TIMER4 = (1U << 4), /**< BS16T1 */
DEBC_PERH_TIMER5 = (1U << 5), /**< BS16T2 */
DEBC_PERH_TIMER6 = (1U << 6), /**< GP16C4T0 */
DEBC_PERH_TIMER7 = (1U << 7), /**< BS16T3 */
DEBC_PERH_I2C0 = (1U << 8), /**< I2C0 SMBUS */
DEBC_PERH_I2C1 = (1U << 9), /**< I2C1 SMBUS */
DEBC_PERH_CAN = (1U << 12), /**< CAN */
DEBC_PERH_LPTIM0 = (1U << 0) | (1U << 16), /**< LPTIM0 */
DEBC_PERH_IWDT = (1U << 8) | (1U << 16), /**< IWDT */
DEBC_PERH_WWDT = (1U << 9) | (1U << 16), /**< WWDT */
DEBC_PERH_RTC = (1U << 10) | (1U << 16), /**< RTC */
} dbgc_perh_t;
/**
* @}
*/
/** @defgroup DBGC_Public_Functions DBGC Public Functions
* @{
*/
/**
* @brief Gets version.
* @retval Version
*/
__INLINE uint32_t ald_dbgc_get_rev_id(void)
{
return (DBGC->IDCODE >> 16);
}
/**
* @brief Gets core id.
* @retval Core id
*/
__INLINE uint32_t ald_dbgc_get_core_id(void)
{
return (DBGC->IDCODE >> 12) & 0xF;
}
/**
* @brief Gets device id
* @retval device id
*/
__INLINE uint32_t ald_dbgc_get_device_id(void)
{
return DBGC->IDCODE & 0xFFF;
}
/**
* @brief Configures low power debug mode
* @param mode: The mode of low power.
* @param state: ENABLE/DISABLE
* @retval None
*/
__INLINE void ald_dbgc_mode_config(dbgc_mode_t mode, type_func_t state)
{
if (state)
SET_BIT(DBGC->CR, mode);
else
CLEAR_BIT(DBGC->CR, mode);
}
/**
* @brief Configures peripheral debug mode
* @param perh: The peripheral.
* @param state: ENABLE/DISABLE
* @retval None
*/
__INLINE void ald_dbgc_perh_config(dbgc_perh_t perh, type_func_t state)
{
if ((perh >> 16) & 0x1) {
if (state)
SET_BIT(DBGC->APB2FZ, perh);
else
CLEAR_BIT(DBGC->APB2FZ, perh);
}
else {
if (state)
SET_BIT(DBGC->APB1FZ, perh);
else
CLEAR_BIT(DBGC->APB1FZ, perh);
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,446 +0,0 @@
/**
*********************************************************************************
*
* @file ald_dma.h
* @brief DMA module Library.
*
* @version V1.0
* @date 09 Nov 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 09 Nov 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_DMA_H__
#define __ALD_DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup DMA
* @{
*/
/**
* @defgroup DMA_Public_Macros DMA Public Macros
* @{
*/
#define DMA_CH_COUNT 12U
#define DMA_ERR 31U
/**
* @}
*/
/**
* @defgroup DMA_Public_Types DMA Public Types
* @{
*/
/**
* @brief Input source to DMA channel
* @verbatim
In this module, for the convenience of code maintenance,
TIMERx is used to indicate the sequence of the timer peripheral.
Different product series TIMERx represent different meanings:
1. For ES32F36xx series:
TIMER0 ----> AD16C4T0
TIMER1 ----> AD16C4T1
TIMER2 ----> GP32C4T0
TIMER3 ----> GP32C4T1
TIMER4 ----> BS16T0
TIMER5 ----> BS16T1
TIMER6 ----> GP16C4T0
TIMER7 ----> GP16C4T1
2. For ES32F393x/ES32F336x/ES32F392x series:
TIMER0 ----> GP16C4T0
TIMER1 ----> GP16C4T1
TIMER2 ----> GP32C4T0
TIMER3 ----> GP32C4T1
TIMER4 ----> BS16T0
TIMER5 ----> BS16T1
TIMER6 ----> GP16C4T2
TIMER7 ----> GP16C4T3
@endverbatim
*/
typedef enum {
DMA_MSEL_NONE = 0x0U, /**< NONE */
DMA_MSEL_GPIO = 0x1U, /**< GPIO */
DMA_MSEL_CRYPT = 0x2U, /**< CRYPT */
DMA_MSEL_DAC0 = 0x4U, /**< DAC0 */
DMA_MSEL_ADC0 = 0x6U, /**< ADC0 */
DMA_MSEL_CRC = 0x7U, /**< CRC */
DMA_MSEL_UART0 = 0x8U, /**< UART0 */
DMA_MSEL_UART1 = 0x9U, /**< UART1 */
DMA_MSEL_UART2 = 0xAU, /**< UART2 */
DMA_MSEL_UART3 = 0xBU, /**< UART3 */
DMA_MSEL_UART4 = 0xCU, /**< UART4 */
DMA_MSEL_UART5 = 0xDU, /**< UART5 */
DMA_MSEL_SPI0 = 0xEU, /**< SPI0 */
DMA_MSEL_SPI1 = 0xFU, /**< SPI1 */
DMA_MSEL_I2C0 = 0x10U, /**< I2C0 */
DMA_MSEL_I2C1 = 0x11U, /**< I2C1 */
DMA_MSEL_TIMER0 = 0x12U, /**< TIMER0 */
DMA_MSEL_TIMER1 = 0x13U, /**< TIMER1 */
DMA_MSEL_TIMER2 = 0x14U, /**< TIMER2 */
DMA_MSEL_TIMER3 = 0x15U, /**< TIMER3 */
DMA_MSEL_LPUART0 = 0x18U, /**< LPUART0 */
DMA_MSEL_SPI2 = 0x1AU, /**< SPI2 */
DMA_MSEL_TIMER4 = 0x1BU, /**< TIMER4 */
DMA_MSEL_TIMER5 = 0x1CU, /**< TIMER5 */
DMA_MSEL_TIMER6 = 0x1DU, /**< TIMER6 */
DMA_MSEL_TIMER7 = 0x1EU, /**< TIMER7 */
DMA_MSEL_ADC1 = 0x1FU, /**< ADC1 */
DMA_MSEL_PIS = 0x20U, /**< PIS */
DMA_MSEL_TRNG = 0x21U, /**< TRNG */
DMA_MSEL_QSPI = 0x22U, /**< QSPI */
DMA_MSEL_USB = 0x23U, /**< USB */
} dma_msel_t;
/**
* @brief Input signal to DMA channel
*/
typedef enum {
DMA_MSIGSEL_NONE = 0x0U, /**< NONE */
DMA_MSIGSEL_EXTI_0 = 0x0U, /**< External interrupt 0 */
DMA_MSIGSEL_EXTI_1 = 0x1U, /**< External interrupt 1 */
DMA_MSIGSEL_EXTI_2 = 0x2U, /**< External interrupt 2 */
DMA_MSIGSEL_EXTI_3 = 0x3U, /**< External interrupt 3 */
DMA_MSIGSEL_EXTI_4 = 0x4U, /**< External interrupt 4 */
DMA_MSIGSEL_EXTI_5 = 0x5U, /**< External interrupt 5 */
DMA_MSIGSEL_EXTI_6 = 0x6U, /**< External interrupt 6 */
DMA_MSIGSEL_EXTI_7 = 0x7U, /**< External interrupt 7 */
DMA_MSIGSEL_EXTI_8 = 0x8U, /**< External interrupt 8 */
DMA_MSIGSEL_EXTI_9 = 0x9U, /**< External interrupt 9 */
DMA_MSIGSEL_EXTI_10 = 0xAU, /**< External interrupt 10 */
DMA_MSIGSEL_EXTI_11 = 0xBU, /**< External interrupt 11 */
DMA_MSIGSEL_EXTI_12 = 0xCU, /**< External interrupt 12 */
DMA_MSIGSEL_EXTI_13 = 0xDU, /**< External interrupt 13 */
DMA_MSIGSEL_EXTI_14 = 0xEU, /**< External interrupt 14 */
DMA_MSIGSEL_EXTI_15 = 0xFU, /**< External interrupt 15 */
DMA_MSIGSEL_CRYPT_WRITE = 0x0U, /**< CRYPT write mode */
DMA_MSIGSEL_CRYPT_READ = 0x1U, /**< CRYPT read mode */
DMA_MSIGSEL_DAC0_CH0 = 0x0U, /**< DAC0 channel 0 complete */
DMA_MSIGSEL_DAC0_CH1 = 0x1U, /**< DAC0 channel 1 complete */
DMA_MSIGSEL_ADC = 0x0U, /**< ADC mode */
DMA_MSIGSEL_UART_TXEMPTY = 0x0U, /**< UART0/UART1/UART2/UART3 transmit */
DMA_MSIGSEL_UART_RNR = 0x1U, /**< UART0/UART1/UART2/UART3 receive */
DMA_MSIGSEL_UART45_RNR = 0x0U, /**< UART4/UART5 reveive */
DMA_MSIGSEL_UART45_TXEMPTY = 0x1U, /**< UART4/UART5 transmit */
DMA_MSIGSEL_SPI_RNR = 0x0U, /**< SPI receive */
DMA_MSIGSEL_SPI_TXEMPTY = 0x1U, /**< SPI transmit */
DMA_MSIGSEL_I2C_RNR = 0x0U, /**< I2C receive */
DMA_MSIGSEL_I2C_TXEMPTY = 0x1U, /**< I2C transmit */
DMA_MSIGSEL_TIMER_CH1 = 0x0U, /**< TIM channal 1 */
DMA_MSIGSEL_TIMER_CH2 = 0x1U, /**< TIM channal 2 */
DMA_MSIGSEL_TIMER_CH3 = 0x2U, /**< TIM channal 3 */
DMA_MSIGSEL_TIMER_CH4 = 0x3U, /**< TIM channal 4 */
DMA_MSIGSEL_TIMER_TRI = 0x4U, /**< TIM trigger */
DMA_MSIGSEL_TIMER_COMP = 0x5U, /**< TIM compare */
DMA_MSIGSEL_TIMER_UPDATE = 0x6U, /**< TIM update */
DMA_MSIGSEL_LPUART_RNR = 0x0U, /**< LPUART receive */
DMA_MSIGSEL_LPUART_TXEMPTY = 0x1U, /**< LPUART transmit */
DMA_MSIGSEL_PIS_CH0 = 0x0U, /**< PIS channal 0 */
DMA_MSIGSEL_PIS_CH1 = 0x1U, /**< PIS channal 1 */
DMA_MSIGSEL_PIS_CH2 = 0x2U, /**< PIS channal 2 */
DMA_MSIGSEL_PIS_CH3 = 0x3U, /**< PIS channal 3 */
DMA_MSIGSEL_PIS_CH4 = 0x4U, /**< PIS channal 4 */
DMA_MSIGSEL_PIS_CH5 = 0x5U, /**< PIS channal 5 */
DMA_MSIGSEL_PIS_CH6 = 0x6U, /**< PIS channal 6 */
DMA_MSIGSEL_PIS_CH7 = 0x7U, /**< PIS channal 7 */
DMA_MSIGSEL_PIS_CH8 = 0x8U, /**< PIS channal 8 */
DMA_MSIGSEL_PIS_CH9 = 0x9U, /**< PIS channal 9 */
DMA_MSIGSEL_PIS_CH10 = 0xAU, /**< PIS channal 10 */
DMA_MSIGSEL_PIS_CH11 = 0xBU, /**< PIS channal 11 */
DMA_MSIGSEL_PIS_CH12 = 0xCU, /**< PIS channal 12 */
DMA_MSIGSEL_PIS_CH13 = 0xDU, /**< PIS channal 13 */
DMA_MSIGSEL_PIS_CH14 = 0xEU, /**< PIS channal 14 */
DMA_MSIGSEL_PIS_CH15 = 0xFU, /**< PIS channal 15 */
DMA_MSIGSEL_QSPI_WRITE = 0x0U, /**< QSPI Write */
DMA_MSIGSEL_QSPI_READ = 0x1U, /**< QSPI Read */
DMA_MSIGSEL_EP_TX1 = 0x0U, /**< USB TX Endport 0 */
DMA_MSIGSEL_EP_TX2 = 0x1U, /**< USB TX Endport 1 */
DMA_MSIGSEL_EP_TX3 = 0x2U, /**< USB TX Endport 2 */
DMA_MSIGSEL_EP_TX4 = 0x3U, /**< USB TX Endport 3 */
DMA_MSIGSEL_EP_TX5 = 0x4U, /**< USB TX Endport 4 */
DMA_MSIGSEL_EP_RX1 = 0x8U, /**< USB RX Endport 0 */
DMA_MSIGSEL_EP_RX2 = 0x9U, /**< USB RX Endport 1 */
DMA_MSIGSEL_EP_RX3 = 0xAU, /**< USB RX Endport 2 */
DMA_MSIGSEL_EP_RX4 = 0xBU, /**< USB RX Endport 3 */
DMA_MSIGSEL_EP_RX5 = 0xCU, /**< USB RX Endport 4 */
} dma_msigsel_t;
/**
* @brief DMA Descriptor control type
*/
typedef union {
struct {
uint32_t cycle_ctrl :3; /**< DMA operating mode @ref dma_cycle_ctrl_t */
uint32_t next_useburst :1; /**< Uses the alternate data structure when complete a DMA cycle */
uint32_t n_minus_1 :10; /**< Represent the total number of DMA transfers that DMA cycle contains. */
uint32_t R_power :4; /**< Control how many DMA transfers can occur before re-arbitrates. @ref dma_arbiter_config_t */
uint32_t src_prot_ctrl :3; /**< Control the state of HPROT when reads the source data. */
uint32_t dst_prot_ctrl :3; /**< Control the state of HPROT when writes the destination data */
uint32_t src_size :2; /**< Source data size @ref dma_data_size_t */
uint32_t src_inc :2; /**< Control the source address increment. @ref dma_data_inc_t */
uint32_t dst_size :2; /**< Destination data size. @ref dma_data_size_t */
uint32_t dst_inc :2; /**< Destination address increment. @ref dma_data_inc_t */
};
uint32_t word;
} dma_ctrl_t;
/**
* @brief Channel control data structure
*/
typedef struct {
void *src; /**< Source data end pointer */
void *dst; /**< Destination data end pointer */
dma_ctrl_t ctrl; /**< Control data configuration @ref dma_ctrl_t */
uint32_t use; /**< Reserve for user */
} dma_descriptor_t;
/**
* @brief data increment
*/
typedef enum {
DMA_DATA_INC_BYTE = 0x0U, /**< Address increment by byte */
DMA_DATA_INC_HALFWORD = 0x1U, /**< Address increment by halfword */
DMA_DATA_INC_WORD = 0x2U, /**< Address increment by word */
DMA_DATA_INC_NONE = 0x3U, /**< No increment */
} dma_data_inc_t;
/**
* @brief Data size
*/
typedef enum {
DMA_DATA_SIZE_BYTE = 0x0U, /**< Byte */
DMA_DATA_SIZE_HALFWORD = 0x1U, /**< Halfword */
DMA_DATA_SIZE_WORD = 0x2U, /**< Word */
} dma_data_size_t;
/**
* @brief The operating mode of the DMA cycle
*/
typedef enum {
DMA_CYCLE_CTRL_NONE = 0x0U, /**< Stop */
DMA_CYCLE_CTRL_BASIC = 0x1U, /**< Basic */
DMA_CYCLE_CTRL_AUTO = 0x2U, /**< Auto-request */
DMA_CYCLE_CTRL_PINGPONG = 0x3U, /**< Ping-pong */
DMA_CYCLE_CTRL_MEM_SG_PRIMARY = 0x4U, /**< Memory scatter-gather using the primary structure */
DMA_CYCLE_CTRL_MEM_SG_ALTERNATE = 0x5U, /**< Memory scatter-gather using the alternate structure */
DMA_CYCLE_CTRL_PER_SG_PRIMARY = 0x6U, /**< Peripheral scatter-gather using the primary structure */
DMA_CYCLE_CTRL_PER_SG_ALTERNATE = 0x7U, /**< Peripheral scatter-gather using the alternate structure */
} dma_cycle_ctrl_t;
/**
* @brief Control how many DMA transfers can occur
* before the controller re-arbitrates
*/
typedef enum {
DMA_R_POWER_1 = 0x0U, /**< Arbitrates after each DMA transfer */
DMA_R_POWER_2 = 0x1U, /**< Arbitrates after 2 DMA transfer */
DMA_R_POWER_4 = 0x2U, /**< Arbitrates after 4 DMA transfer */
DMA_R_POWER_8 = 0x3U, /**< Arbitrates after 8 DMA transfer */
DMA_R_POWER_16 = 0x4U, /**< Arbitrates after 16 DMA transfer */
DMA_R_POWER_32 = 0x5U, /**< Arbitrates after 32 DMA transfer */
DMA_R_POWER_64 = 0x6U, /**< Arbitrates after 64 DMA transfer */
DMA_R_POWER_128 = 0x7U, /**< Arbitrates after 128 DMA transfer */
DMA_R_POWER_256 = 0x8U, /**< Arbitrates after 256 DMA transfer */
DMA_R_POWER_512 = 0x9U, /**< Arbitrates after 512 DMA transfer */
DMA_R_POWER_1024 = 0xAU, /**< Arbitrates after 1024 DMA transfer */
} dma_arbiter_config_t;
/**
* @brief Callback function pointer and param
*/
typedef struct {
void (*cplt_cbk)(void *arg); /**< DMA transfers complete callback */
void (*err_cbk)(void* arg); /**< DMA occurs error callback */
void *cplt_arg; /**< The parameter of cplt_cbk() */
void *err_arg; /**< The parameter of err_cbk() */
} dma_call_back_t;
/**
* @brief DMA channal configure structure
*/
typedef struct {
void *src; /**< Source data begin pointer */
void *dst; /**< Destination data begin pointer */
uint16_t size; /**< The total number of DMA transfers that DMA cycle contains */
dma_data_size_t data_width; /**< Data width, @ref dma_data_size_t */
dma_data_inc_t src_inc; /**< Source increment type. @ref dma_data_inc_t */
dma_data_inc_t dst_inc; /**< Destination increment type. @ref dma_data_inc_t */
dma_arbiter_config_t R_power; /**< Control how many DMA transfers can occur before re-arbitrates. @ref dma_arbiter_config_t */
type_func_t primary; /**< Use primary descriptor or alternate descriptor */
type_func_t burst; /**< Enable/Disable the useburst setting for this channel */
type_func_t high_prio; /**< High priority or default priority */
type_func_t interrupt; /**< Enable/disable interrupt */
dma_msel_t msel; /**< Input source to DMA channel @ref dma_msel_t */
dma_msigsel_t msigsel; /**< Input signal to DMA channel @ref dma_msigsel_t */
uint8_t channel; /**< Channel index */
} dma_config_t;
/**
* @brief DMA handle structure definition
*/
typedef struct {
DMA_TypeDef *perh; /**< DMA registers base address */
dma_config_t config; /**< Channel configure structure. @ref dma_config_t */
void (*cplt_cbk)(void *arg); /**< DMA transfers complete callback */
void (*err_cbk)(void *arg); /**< DMA bus occurs error callback */
void *cplt_arg; /**< The parameter of cplt_cbk() */
void *err_arg; /**< The parameter of err_cbk() */
} dma_handle_t;
/**
* @brief Descriptor complete state
*/
typedef enum {
DMA_DESCP_CPLT_PRI = 0x0U, /**< Primary descriptor has been completed */
DMA_DESCP_CPLT_ALT = 0x1U, /**< Alternate descriptor has been completed */
DMA_DESCP_CPLT_ALL = 0x2U, /**< Both primary and alternate descriptors have been completed */
} dma_descrp_cplt_t;
/**
* @}
*/
/**
* @defgroup DMA_Private_Macros DMA Private Macros
* @{
*/
#define IS_DMA_MSEL_TYPE(x) ((x) <= DMA_MSEL_USB)
#define IS_DMA_MSIGSEL_TYPE(x) ((x) <= 0xF)
#define IS_DMA_DATAINC_TYPE(x) (((x) == DMA_DATA_INC_BYTE) || \
((x) == DMA_DATA_INC_HALFWORD) || \
((x) == DMA_DATA_INC_WORD) || \
((x) == DMA_DATA_INC_NONE))
#define IS_DMA_DATASIZE_TYPE(x) (((x) == DMA_DATA_SIZE_BYTE) || \
((x) == DMA_DATA_SIZE_HALFWORD) || \
((x) == DMA_DATA_SIZE_WORD))
#define IS_CYCLECTRL_TYPE(x) (((x) == DMA_CYCLE_CTRL_NONE) || \
((x) == DMA_CYCLE_CTRL_BASIC) || \
((x) == DMA_CYCLE_CTRL_AUTO) || \
((x) == DMA_CYCLE_CTRL_PINGPONG) || \
((x) == DMA_CYCLE_CTRL_MEM_SG_PRIMARY) || \
((x) == DMA_CYCLE_CTRL_MEM_SG_ALTERNATE) || \
((x) == DMA_CYCLE_CTRL_PER_SG_PRIMARY) || \
((x) == DMA_CYCLE_CTRL_PER_SG_ALTERNATE))
#define IS_DMA_ARBITERCONFIG_TYPE(x) (((x) == DMA_R_POWER_1) || \
((x) == DMA_R_POWER_2) || \
((x) == DMA_R_POWER_4) || \
((x) == DMA_R_POWER_8) || \
((x) == DMA_R_POWER_16) || \
((x) == DMA_R_POWER_32) || \
((x) == DMA_R_POWER_64) || \
((x) == DMA_R_POWER_128) || \
((x) == DMA_R_POWER_256) || \
((x) == DMA_R_POWER_512) || \
((x) == DMA_R_POWER_1024))
#define IS_DMA(x) ((x) == DMA0)
#define IS_DMA_CHANNEL(x) ((x) <= 11)
#define IS_DMA_DATA_SIZE(x) ((x) <= 1024)
#define IS_DMA_IT_TYPE(x) (((x) <= 11) || ((x) == 31))
/**
* @}
*/
/**
* @addtogroup DMA_Public_Functions
* @{
*/
/** @addtogroup DMA_Public_Functions_Group1
* @{
*/
/* Initialization functions */
extern void ald_dma_reset(DMA_TypeDef *DMAx);
extern void ald_dma_init(DMA_TypeDef *DMAx);
extern void ald_dma_config_struct(dma_config_t *p);
extern void ald_dma_config_sg_alt_desc(dma_descriptor_t *desc, dma_config_t *config, uint8_t memory);
/**
* @}
*/
/** @addtogroup DMA_Public_Functions_Group2
* @{
*/
/* Configure DMA channel functions */
extern void ald_dma_config_auto(dma_handle_t *hperh);
extern void ald_dma_restart_auto(dma_handle_t *hperh, void *src, void *dst, uint16_t size);
extern void ald_dma_config_auto_easy(DMA_TypeDef *DMAx, void *src, void *dst,
uint16_t size, uint8_t channel, void (*cbk)(void *arg));
extern void ald_dma_config_basic(dma_handle_t *hperh);
extern void ald_dma_restart_basic(dma_handle_t *hperh, void *src, void *dst, uint16_t size);
extern void ald_dma_config_basic_easy(DMA_TypeDef *DMAx, void *src, void *dst, uint16_t size, dma_msel_t msel,
dma_msigsel_t msigsel, uint8_t channel, void (*cbk)(void *arg));
extern void ald_dma_config_ping_pong(DMA_TypeDef *DMAx, dma_config_t *config,
uint8_t first, void (*cbk)(void *arg));
extern void ald_dma_config_sg_mem(DMA_TypeDef *DMAx, dma_descriptor_t *desc,
uint32_t nr, uint8_t channel, void (*cbk)(void *arg));
extern void ald_dma_config_sg_per(DMA_TypeDef *DMAx, dma_descriptor_t *desc, uint32_t nr, uint8_t burst,
dma_msel_t msel, dma_msigsel_t msigsel, uint8_t channel, void (*cbk)(void *arg));
/**
* @}
*/
/** @addtogroup DMA_Public_Functions_Group3
* @{
*/
/* DMA control functions */
extern void ald_dma_channel_config(DMA_TypeDef *DMAx, uint8_t channel, type_func_t state);
extern void ald_dma_interrupt_config(DMA_TypeDef *DMAx, uint8_t channel, type_func_t state);
extern it_status_t ald_dma_get_it_status(DMA_TypeDef *DMAx, uint8_t channel);
extern flag_status_t ald_dma_get_flag_status(DMA_TypeDef *DMAx, uint8_t channel);
extern void ald_dma_clear_flag_status(DMA_TypeDef *DMAx, uint8_t channel);
extern dma_descrp_cplt_t ald_dma_descriptor_cplt_get(DMA_TypeDef *DMAx, uint8_t channel);
extern void ald_dma_irq_handler(void);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__ALD_DMA_H__ */

View File

@@ -1,602 +0,0 @@
/**
*********************************************************************************
*
* @file ald_ebi.h
* @brief Header file of EBI module driver.
*
* @version V1.0
* @date 20 Nov 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 20 Nov 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_EBI_H__
#define __ALD_EBI_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup EBI
* @{
*/
/**
* @defgroup EBI_Public_Macros EBI Public Macros
* @{
*/
#define EBI_NOR_SRAM_TypeDef EBI_Bank1_TypeDef
#define EBI_NOR_SRAM_EXTENDED_TypeDef EBI_Bank1E_TypeDef
#define EBI_NAND_TypeDef EBI_Bank2_3_TypeDef
#define EBI_LCD_TypeDef EBI_Bank1_LCD_TypeDef
#define EBI_NOR_SRAM_DEVICE EBI_Bank1
#define EBI_NOR_SRAM_EXTENDED_DEVICE EBI_Bank1E
#define EBI_NAND_DEVICE EBI_Bank2_3
#define EBI_LCD_DEVICE EBI_Bank1_LCD
#define EBI_NAND_BANK2 0x00000010U
#define EBI_NAND_BANK3 0x00000100U
/* PCTRLR register clear mask */
#define PCTRLR_CLEAR_MASK ((uint32_t)(EBI_PCTRLRx_WAITEN_MSK | EBI_PCTRLRx_MEMBKEN_MSK | \
EBI_PCTRLRx_MEMTYP_MSK | EBI_PCTRLRx_DATBUSWID_MSK | \
EBI_PCTRLRx_ECCEN_MSK | EBI_PCTRLRx_CRDLY_MSK | \
EBI_PCTRLRx_ARDLY_MSK | EBI_PCTRLRx_ECCPSIZE_MSK))
/* PMEMR register clear mask */
#define PMEMR_CLEAR_MASK ((uint32_t)(EBI_PMEMRx_MEMSETUP_MSK | EBI_PMEMRx_MEMWAIT_MSK | \
EBI_PMEMRx_MEMHOLD_MSK | EBI_PMEMRx_MEMHIZT_MSK))
/* PATTR register clear mask */
#define PATTR_CLEAR_MASK ((uint32_t)(EBI_PATTRx_ATTSETUP_MSK | EBI_PATTRx_ATTWAIT_MSK | \
EBI_PATTRx_ATTHOLD_MSK | EBI_PATTRx_ATTHIZT_MSK))
/* BCTRLR register clear mask */
#define BCTRLR_CLEAR_MASK ((uint32_t)(EBI_BCTRLRx_FLASHACCEN_MSK | EBI_BCTRLRx_MUXEN_MSK | \
EBI_BCTRLRx_MEMTYP_MSK | EBI_BCTRLRx_MEMWID_MSK | \
EBI_BCTRLRx_BURSTEN_MSK | EBI_BCTRLRx_WAITPOL_MSK | \
EBI_BCTRLRx_WRAPMODE_MSK | EBI_BCTRLRx_WAITCFG_MSK | \
EBI_BCTRLRx_WREN_MSK | EBI_BCTRLRx_WAITEN_MSK | \
EBI_BCTRLRx_EXTMODEN_MSK | EBI_BCTRLRx_ASYNCWAIT_MSK | \
EBI_BCTRLRx_RWCBURSTEN_MSK))
/* BTR register clear mask */
#define BTR_CLEAR_MASK ((uint32_t)(EBI_BTRx_ADDATASETUP_MSK | EBI_BTRx_ADDHOLD_MSK | \
EBI_BTRx_DATAHOLD_MSK | EBI_BTRx_BUSTURN_MSK | \
EBI_BTRx_CLKDIV_MSK | EBI_BTRx_DATALAT_MSK | \
EBI_BTRx_ACCMODE_MSK))
/* BWRTR register clear mask */
#define BWTR_CLEAR_MASK ((uint32_t)(EBI_BWRTRx_ADDATASETUP_MSK | EBI_BWRTRx_ADDHOLD_MSK | \
EBI_BWRTRx_DATAHOLD_MSK | EBI_BWRTRx_BUSTURN_MSK | \
EBI_BWRTRx_ACCMODE_MSK))
#define LCDCTRL_CLEAR_MASK ((uint32_t)(EBI_LCDCTRLx_HSYNCPOL_POS | EBI_LCDCTRLx_VSYNCPOL_MSK | \
EBI_LCDCTRLx_DENPOL_MSK | EBI_LCDCTRLx_LCDEN_MSK | \
EBI_LCDCTRLx_LCDINT_MSK | EBI_LCDCTRLx_DCLKPOL_MSK | \
EBI_LCDCTRLx_DATASETUP_MSK))
/**
* @}
*/
/** @defgroup EBI_Public_Types EBI Public Types
* @{
*/
/**
* @brief EBI Access Mode
*/
typedef enum {
EBI_ACCESS_MODE_A = 0x0U, /**< EBI access mode A */
EBI_ACCESS_MODE_B = (0x1U << 28), /**< EBI access mode B */
EBI_ACCESS_MODE_C = (0x2U << 28), /**< EBI access mode C */
EBI_ACCESS_MODE_D = (0x3U << 28), /**< EBI access mode D */
} ebi_access_mode_t;
/**
* @brief EBI NORSRAM Timing parameters structure definition
*/
typedef struct {
uint32_t addr_setup; /**< Address setup HCLK cycles number, the value between 0 and 15 */
uint32_t addr_hold; /**< Address hold HCLK cycles number, the value between 0 and 15 */
uint32_t data_setup; /**< Data setup HCLK cycles number, the value between 1 and 255 */
uint32_t bus_dur; /**< Bus turnaround duration HCLK cycles, the value between 0 and 15 */
uint32_t div; /**< Defines the period of CLK clock signal, the value between 2 and 16 */
uint32_t latency; /**< Issue clock cycles before getting the first data, the value between 2 and 17 */
ebi_access_mode_t mode; /**< Specifies the asynchronous access mode */
} ald_ebi_nor_sram_timing_t;
/**
* @brief EBI_Wait_feature EBI Wait feature
*/
typedef enum {
EBI_NAND_WAIT_FEATURE_DISABLE = 0x0U, /**< NAND wait feature disable */
EBI_NAND_WAIT_FEATURE_ENABLE = (0x1U << 1), /**< NAND wait feature enable */
} ebi_nand_wait_feature_t;
/**
* @brief EBI NAND Data Width
*/
typedef enum {
EBI_NAND_MEM_BUS_WIDTH_8 = 0x0U, /**< NAND mem bus width 8-bits */
EBI_NAND_MEM_BUS_WIDTH_16 = (0x3U << 4), /**< NAND mem bus width 16-bits */
} ebi_nand_mem_bus_width_t;
/**
* @brief EBI NAND ECC STATE
*/
typedef enum {
EBI_NAND_ECC_DISABLE = 0U, /**< NAND ecc disable */
EBI_NAND_ECC_ENABLE = (0x1U << 6), /**< NAND ecc enable */
} ebi_nand_ecc_t;
/**
* @brief EBI ECC Page Size
*/
typedef enum {
EBI_NAND_ECC_PAGE_SIZE_256BYTE = 0U, /**< NAND ecc page size 256 bytes */
EBI_NAND_ECC_PAGE_SIZE_512BYTE = (0x1U << 17), /**< NAND ecc page size 512 bytes */
EBI_NAND_ECC_PAGE_SIZE_1024BYTE = (0x2U << 17), /**< NAND ecc page size 1024 bytes */
EBI_NAND_ECC_PAGE_SIZE_2048BYTE = (0x3U << 17), /**< NAND ecc page size 2048 bytes */
EBI_NAND_ECC_PAGE_SIZE_4096BYTE = (0x4U << 17), /**< NAND ecc page size 4096 bytes */
EBI_NAND_ECC_PAGE_SIZE_8192BYTE = (0x5U << 17), /**< NAND ecc page size 8192 bytes */
} ebi_md_ecc_page_size_t;
/**
* @brief EBI NAND Configuration Structure definition
*/
typedef struct {
uint32_t bank; /**< Specifies the NAND memory device that will be used */
ebi_nand_wait_feature_t wait; /**< Enables or disables the Wait feature for the NAND Memory device */
ebi_nand_mem_bus_width_t width; /**< Specifies the external memory device width */
ebi_nand_ecc_t ecc; /**< Enables or disables the ECC computation */
ebi_md_ecc_page_size_t size; /**< Defines the page size for the extended ECC */
uint32_t cle_time; /**< Number of HCLK cycles between CLE low and RE low, the value between 0 and 255 */
uint32_t ale_time; /**< Number of HCLK cycles between ALE low and RE low */
} ald_ebi_nand_init_t;
/**
* @brief EBI NAND Timing parameters structure definition
*/
typedef struct {
uint32_t time; /**< Number of cycles to setup address, the value between 0 and 255 */
uint32_t wait_time; /**< Number of HCLK cycles to assert the command ,the value between 0 and 255 */
uint32_t hold_time; /**< Number of HCLK cycles to hold address or data, the value between 0 and 255 */
uint32_t hiz_time; /**< Number of HCLK cycles data bus is kept in HiZ, the value between 0 and 255 */
} ald_ebi_nand_timing_t;
/**
* @brief EBI Data Address Bus Multiplexing
*/
typedef enum {
EBI_DATA_ADDRESS_MUX_DISABLE = 0x0U, /**< Data address mux disable */
EBI_DATA_ADDRESS_MUX_ENABLE = (0x1U << 1), /**< Data address mux enable */
} ebi_data_address_mux_t;
/**
* @brief EBI NOR/SRAM Bank
*/
typedef enum {
EBI_NORSRAM_BANK1 = 0x0U, /**< Norsram bank 1 */
EBI_NORSRAM_BANK2 = 0x2U, /**< Norsram bank 2 */
EBI_NORSRAM_BANK3 = 0x4U, /**< Norsram bank 3 */
EBI_NORSRAM_BANK4 = 0x6U, /**< Norsram bank 4 */
} ebi_norsram_bank_t;
/**
* @brief EBI Memory Type
*/
typedef enum {
EBI_MEMORY_TYPE_SRAM = 0x0U, /**< Memory tyepe SRAM */
EBI_MEMORY_TYPE_PSRAM = (0x1U << 2), /**< Memory tyepe PSRAM */
EBI_MEMORY_TYPE_NOR = (0x2U << 2), /**< Memory tyepe NOR */
} ebi_memory_type_t;
/**
* @brief EBI NOR/SRAM Data Width
*/
typedef enum {
EBI_NORSRAM_MEM_BUS_WIDTH_8 = 0x0U, /**< Norsram Memory width 8-bits */
EBI_NORSRAM_MEM_BUS_WIDTH_16 = (0x1U << 4), /**< Norsram Memory width 16-bits */
EBI_NORSRAM_MEM_BUS_WIDTH_32 = (0x2U << 4), /**< Norsram Memory width 32-bits */
} ebi_norsram_mem_bus_width_t;
/**
* @brief EBI NOR/SRAM Flash Access
*/
typedef enum {
EBI_NORSRAM_FLASH_ACCESS_DISABLE = 0x0U, /**< Norsram flash access disable */
EBI_NORSRAM_FLASH_ACCESS_ENABLE = (0x1U << 6), /**< Norsram flash access enable */
} ebi_norsram_flash_access_t;
/**
* @brief EBI Burst Access Mode
*/
typedef enum {
EBI_BURST_ACCESS_MODE_DISABLE = 0x0U, /**< Burst access disable */
EBI_BURST_ACCESS_MODE_ENABLE = (0x1U << 8), /**< Burst access enable */
} ebi_burst_access_mode_t;
/**
* @brief EBI Wait Signal Polarity
*/
typedef enum {
EBI_WAIT_SIGNAL_POLARITY_LOW = 0x0U, /**< Wait signal polarity low */
EBI_WAIT_SIGNAL_POLARITY_HIGH = (0x1U << 9), /**< Wait signal polarity high */
} ebi_wait_signal_polarity_t;
/**
* @brief EBI Wrap Mode
*/
typedef enum {
EBI_WRAP_MODE_DISABLE = 0x0U, /**< Wrap mode disable */
EBI_WRAP_MODE_ENABLE = (0x1U << 10), /**< Wrap mode enable */
} ebi_wrap_mode_t;
/**
* @brief EBI Wait Timing
*/
typedef enum {
EBI_WAIT_TIMING_BEFORE_WS = 0x0U, /**< Wait timing before ws */
EBI_WAIT_TIMING_DURING_WS = (0x1U << 11), /**< Wait timing during ws */
} ebi_wait_timing_t;
/**
* @brief EBI Write Operation State
*/
typedef enum {
EBI_WRITE_OPERATION_DISABLE = 0x0U, /**< Write operation disable */
EBI_WRITE_OPERATION_ENABLE = (0x1U << 12), /**< Write operation enable */
} ebi_write_operation_t;
/**
* @brief EBI Wait Signal
*/
typedef enum {
EBI_WAIT_SIGNAL_DISABLE = 0x0U, /**< Wait signal disable */
EBI_WAIT_SIGNAL_ENABLE = (0x1U << 13), /**< Wait signal enable */
} ebi_wait_signal_t;
/**
* @brief EBI Extended Mode
*/
typedef enum {
EBI_EXTENDED_MODE_DISABLE = 0x0U, /**< EBI extended mode disable */
EBI_EXTENDED_MODE_ENABLE = (0x1U << 14), /**< EBI extended mode enable */
} ebi_extended_mode_t;
/**
* @brief EBI Asynchronous Wait
*/
typedef enum {
EBI_ASYNCHRONOUS_WAIT_DISABLE = 0x0U, /**< Asynchronous wait disable */
EBI_ASYNCHRONOUS_WAIT_ENABLE = (0x1U << 15), /**< Asynchronous wait enable */
} ebi_asynchronous_wait_t;
/**
* @brief EBI Write Burst
*/
typedef enum {
EBI_WRITE_BURST_DISABLE = 0x0U, /**< Write burst disable */
EBI_WRITE_BURST_ENABLE = (0x1U << 19), /**< Write burst enable */
} ebi_write_burst_t;
/**
* @brief EBI PCR Memory Type
*/
typedef enum {
EBI_PCTRLR_MEMORY_TYPE_None = 0x0U, /**< PCR memory type none */
EBI_PCTRLR_MEMORY_TYPE_NAND = (0x1U << 3), /**< PCR memory type nand */
} ebi_pctrlr_memory_type_t;
/**
* @brief EBI Interrupt definition
*/
typedef enum {
EBI_IT_RISING_EDGE = (1U << 3), /**< Rising edge trigger interrupt */
EBI_IT_LEVEL = (1U << 4), /**< Level trigger interrupt */
EBI_IT_FALLING_EDGE = (1U << 5), /**< Falling edge trigger interrupt */
} ebi_it_t;
/**
* @brief EBI Flag definition
*/
typedef enum {
EBI_FLAG_RISING_EDGE = (1U << 0), /**< Rising edge flag */
EBI_FLAG_LEVEL = (1U << 1), /**< Level flag */
EBI_FLAG_FALLING_EDGE = (1U << 2), /**< Falling edge flag */
EBI_FLAG_FEMPT = (1U << 6), /**< Rising edge trigger interrupt */
} ebi_flag_t;
/**
* @brief EBI LCD_Horizontal Synch Polarity definition
*/
typedef enum {
EBI_LCD_HSYNCPOL_LOW = 0x0U, /**< Horizontal synch polarity low */
EBI_LCD_HSYNCPOL_HIGH = (0x1U << 29), /**< Horizontal synch polarity high */
} ebi_lcd_hsyncpol_t;
/**
* @brief EBI LCD Vertical Synch Polarity definition
*/
typedef enum {
EBI_LCD_VSYNCPOL_LOW = 0x0U, /**< Vertical synch polarity low */
EBI_LCD_VSYNCPOL_HIGH = (0x1U << 28), /**< Vertical synch polarity high */
} ebi_lcd_vsyncpol_t;
/**
* @brief EBI LCD Data Enable Polarity definition
*/
typedef enum {
EBI_LCD_DENPOL_LOW = 0x0U, /**< LCD data enable polarity low */
EBI_LCD_DENPOL_HIGH = (0x1U << 27), /**< LCD data enable polarity high */
} ebi_lcd_denpol_t;
/**
* @brief EBI LCD Enable definition
*/
typedef enum {
EBI_LCD_LCDEN_DISABLE = 0x0U, /**< LCD disable */
EBI_LCD_LCDEN_ENABLE = (0x1U << 26), /**< LCD data enable polarity low */
} ebi_lcd_lcden_t;
/**
* @brief EBI LCD Init Enable definition
*/
typedef enum {
EBI_LCD_LCDINT_DISABLE = 0x0U, /**< LCD init disable */
EBI_LCD_LCDINT_ENABLE = (0x1 << 25), /**< LCD init enable */
} ebi_lcd_lcdint_t;
/**
* @brief EBI LCD Data Clock definition
*/
typedef enum {
EBI_LCD_DCLKPOL_FALLING = 0x0U, /**< LCD data clock falling edge */
EBI_LCD_DCLKPOL_RISING = (0x1U << 24), /**< LCD data clock rising edge */
} ebi_lcd_dclkpol_t;
/**
* @brief EBI LCD parameters structure definition
*/
typedef struct {
uint8_t bank; /**< Specifies the NORSRAM memory device */
ebi_lcd_hsyncpol_t h_polarity; /**< Horizontal sync polarity */
ebi_lcd_vsyncpol_t v_polarity; /**< Vertical sync polarity */
ebi_lcd_denpol_t data_polarity; /**< Data enable polarity */
ebi_lcd_lcden_t enable; /**< LCD enable */
ebi_lcd_dclkpol_t clk_polarity; /**< Data clock polarity */
ebi_lcd_lcdint_t reset; /**< LCD Reset */
uint8_t setup; /**< Data setup time */
uint8_t v_width; /**< Vsync pulse width */
uint8_t h_width; /**< Hsync puluse width */
uint16_t nr_line; /**< Frame line number */
uint16_t nr_pixel; /**< Frame pixel number */
} ebi_lcd_init_t;
/**
* @brief NOR LCD handle Structure definition
*/
typedef struct {
EBI_LCD_TypeDef *inst;
ebi_lcd_init_t init;
} ebi_lcd_handle_t;
/**
* @brief EBI NORSRAM Configuration Structure definition
*/
typedef struct {
uint32_t bank; /**< Specifies the NORSRAM memory device, the value can be one of 0 ~ 3 */
ebi_data_address_mux_t mux; /**< Address and data values are multiplexed or not */
ebi_memory_type_t type; /**< Specifies the type of external memory */
ebi_norsram_mem_bus_width_t width; /**< Specifies the external memory device width */
ebi_burst_access_mode_t acc_mode; /**< Enables or disables the burst access mode for Flash memory */
ebi_wait_signal_polarity_t polarity; /**< Wait signal polarity, valid only in burst mode */
ebi_wrap_mode_t wrap_mode; /**< Enables or disables the Wrapped burst access mode, only in burst mode */
ebi_wait_timing_t active; /**< Specifies if the wait signal is asserted, only in burst mode */
ebi_write_operation_t write; /**< Enables or disables the write operation */
ebi_wait_signal_t signal; /**< Enables or disables the wait state insertion, only in burst mode */
ebi_extended_mode_t ext_mode; /**< Enables or disables the extended mode */
ebi_asynchronous_wait_t wait; /**< Enables or disables wait signal during asynchronous transfers */
ebi_write_burst_t burst; /**< Enables or disables the write burst operation */
} ald_ebi_nor_sram_init_t;
/**
* @}
*/
/** @defgroup EBI_Private_Macros EBI Private Macros
* @{
*/
#define IS_EBI_NORSRAM_BANK(x) (((x) == EBI_NORSRAM_BANK1) || \
((x) == EBI_NORSRAM_BANK2) || \
((x) == EBI_NORSRAM_BANK3) || \
((x) == EBI_NORSRAM_BANK4))
#define IS_EBI_MUX(x) (((x) == EBI_DATA_ADDRESS_MUX_DISABLE) || \
((x) == EBI_DATA_ADDRESS_MUX_ENABLE))
#define IS_EBI_MEMORY(x) (((x) == EBI_MEMORY_TYPE_SRAM) || \
((x) == EBI_MEMORY_TYPE_PSRAM) || \
((x) == EBI_MEMORY_TYPE_NOR))
#define IS_EBI_NORSRAM_MEMORY_WIDTH(x) (((x) == EBI_NORSRAM_MEM_BUS_WIDTH_8) || \
((x) == EBI_NORSRAM_MEM_BUS_WIDTH_16) || \
((x) == EBI_NORSRAM_MEM_BUS_WIDTH_32))
#define IS_EBI_WRITE_BURST(x) (((x) == EBI_WRITE_BURST_DISABLE) || \
((x) == EBI_WRITE_BURST_ENABLE))
#define IS_EBI_ACCESS_MODE(x) (((x) == EBI_ACCESS_MODE_A) || \
((x) == EBI_ACCESS_MODE_B) || \
((x) == EBI_ACCESS_MODE_C) || \
((x) == EBI_ACCESS_MODE_D))
#define IS_EBI_NAND_BANK(x) (((x) == EBI_NAND_BANK2) || \
((x) == EBI_NAND_BANK3))
#define IS_EBI_WAIT_FEATURE(x) (((x) == EBI_NAND_WAIT_FEATURE_DISABLE) || \
((x) == EBI_NAND_WAIT_FEATURE_ENABLE))
#define IS_EBI_NAND_MEMORY_WIDTH(x) (((x) == EBI_NAND_MEM_BUS_WIDTH_8) || \
((x) == EBI_NAND_MEM_BUS_WIDTH_16))
#define IS_EBI_ECC_STATE(x) (((x) == EBI_NAND_ECC_DISABLE) || \
((x) == EBI_NAND_ECC_ENABLE))
#define IS_EBI_ECCPAGE_SIZE(x) (((x) == EBI_NAND_ECC_PAGE_SIZE_256BYTE) || \
((x) == EBI_NAND_ECC_PAGE_SIZE_512BYTE) || \
((x) == EBI_NAND_ECC_PAGE_SIZE_1024BYTE) || \
((x) == EBI_NAND_ECC_PAGE_SIZE_2048BYTE) || \
((x) == EBI_NAND_ECC_PAGE_SIZE_4096BYTE) || \
((x) == EBI_NAND_ECC_PAGE_SIZE_8192BYTE))
#define IS_EBI_LCD_DEVICE(x) ((x) == EBI_LCD_DEVICE)
#define IS_EBI_HORIZONTAL_SYNCH(x) (((x) == EBI_LCD_HSYNCPOL_LOW) || \
((x) == EBI_LCD_HSYNCPOL_HIGH))
#define IS_EBI_VERTICAL_SYNCH(x) (((x) == EBI_LCD_VSYNCPOL_LOW) || \
((x) == EBI_LCD_VSYNCPOL_HIGH))
#define IS_EBI_DATA_ENABLE(x) (((x) == EBI_LCD_DENPOL_LOW) || \
((x) == EBI_LCD_DENPOL_HIGH))
#define IS_EBI_LCD_ENABLE(x) (((x) == EBI_LCD_LCDEN_DISABLE) || \
((x) == EBI_LCD_LCDEN_ENABLE))
#define IS_EBI_LCD_RESET(x) (((x) == EBI_LCD_LCDINT_DISABLE) || \
((x) == EBI_LCD_LCDINT_ENABLE))
#define IS_EBI_DATA_CLOCK(x) (((x) == EBI_LCD_DCLKPOL_FALLING) || \
((x) == EBI_LCD_DCLKPOL_RISING))
#define IS_EBI_LCD_DATASETUP_TIME(x) ((x) < 255U)
#define IS_EBI_HYSNC_PULSE_WIDTH(x) ((x) < 255U)
#define IS_EBI_VSYNC_PULSE_WIDTH(x) ((x) < 255U)
#define IS_EBI_FRAME_LINE_NUMBER(x) (((x) >= 1U) && ((x) < 65535))
#define IS_EBI_FRAME_PIXEL_NUMBER(x) (((x) >= 1U) && ((x) < 65535))
#define IS_EBI_TCLR_TIME(x) ((x) <= 255U)
#define IS_EBI_TAR_TIME(x) ((x) <= 255U)
#define IS_EBI_SETUP_TIME(x) ((x) <= 255U)
#define IS_EBI_WAIT_TIME(x) ((x) <= 255U)
#define IS_EBI_HOLD_TIME(x) ((x) <= 255U)
#define IS_EBI_HIZ_TIME(x) ((x) <= 255U)
#define IS_EBI_NORSRAM_DEVICE(x) ((x) == EBI_NOR_SRAM_DEVICE)
#define IS_EBI_NORSRAM_EXTENDED_DEVICE(x) ((x) == EBI_NOR_SRAM_EXTENDED_DEVICE)
#define IS_EBI_NAND_DEVICE(x) ((x) == EBI_NAND_DEVICE)
#define IS_EBI_BURSTMODE(x) (((x) == EBI_BURST_ACCESS_MODE_DISABLE) || \
((x) == EBI_BURST_ACCESS_MODE_ENABLE))
#define IS_EBI_WAIT_POLARITY(x) (((x) == EBI_WAIT_SIGNAL_POLARITY_LOW) || \
((x) == EBI_WAIT_SIGNAL_POLARITY_HIGH))
#define IS_EBI_WRAP_MODE(x) (((x) == EBI_WRAP_MODE_DISABLE) || \
((x) == EBI_WRAP_MODE_ENABLE))
#define IS_EBI_WAIT_SIGNAL_ACTIVE(x) (((x) == EBI_WAIT_TIMING_BEFORE_WS) || \
((x) == EBI_WAIT_TIMING_DURING_WS))
#define IS_EBI_WRITE_OPERATION(x) (((x) == EBI_WRITE_OPERATION_DISABLE) || \
((x) == EBI_WRITE_OPERATION_ENABLE))
#define IS_EBI_WAITE_SIGNAL(x) (((x) == EBI_WAIT_SIGNAL_DISABLE) || \
((x) == EBI_WAIT_SIGNAL_ENABLE))
#define IS_EBI_EXTENDED_MODE(x) (((x) == EBI_EXTENDED_MODE_DISABLE) || \
((x) == EBI_EXTENDED_MODE_ENABLE))
#define IS_EBI_ASYNWAIT(x) (((x) == EBI_ASYNCHRONOUS_WAIT_DISABLE) || \
((x) == EBI_ASYNCHRONOUS_WAIT_ENABLE))
#define IS_EBI_CLK_DIV(x) (((x) >= 1U) && ((x) <= 16U))
#define IS_EBI_DATA_LATENCY(x) (((x) >= 1U) && ((x) <= 17U))
#define IS_EBI_ADDRESS_SETUP_TIME(x) ((x) <= 15U)
#define IS_EBI_ADDRESS_HOLD_TIME(x) (((x) > 0U) && ((x) <= 15U))
#define IS_EBI_DATASETUP_TIME(x) (((x) > 0U) && ((x) <= 255U))
#define IS_EBI_TURNAROUND_TIME(x) ((x) <= 15U)
#define IS_EBI_BANK_NUMBER(x) (((x) > 0U) && ((x) <= 4U))
/**
* @}
*/
/** @addtogroup EBI_Public_Functions
* @{
*/
/** @addtogroup EBI_Public_Functions_Group1
* @{
*/
/* NOR-FLASH SRAM initialize functions */
void ald_ebi_nor_sram_init(EBI_NOR_SRAM_TypeDef *dev, ald_ebi_nor_sram_init_t *init);
void ald_ebi_nor_sram_timing_init(EBI_NOR_SRAM_TypeDef *dev, ald_ebi_nor_sram_timing_t *timing, uint32_t bank);
void ald_ebi_nor_sram_ext_timing_init(EBI_NOR_SRAM_EXTENDED_TypeDef *dev, ald_ebi_nor_sram_timing_t *timing, uint32_t bank, uint32_t mode);
ald_status_t ald_ebi_nor_sram_deinit(EBI_NOR_SRAM_TypeDef *dev, EBI_NOR_SRAM_EXTENDED_TypeDef *e_dev, uint32_t bank);
/**
* @}
*/
/** @addtogroup EBI_Public_Functions_Group2
* @{
*/
/* NOR/SRAM Control functions */
void ald_ebi_nor_sram_enable(EBI_NOR_SRAM_TypeDef *dev, uint32_t bank);
void ald_ebi_nor_sram_disable(EBI_NOR_SRAM_TypeDef *dev, uint32_t bank);
void ald_ebi_nor_sram_write_enable(EBI_NOR_SRAM_TypeDef *dev, uint32_t bank);
void ald_ebi_nor_sram_write_disable(EBI_NOR_SRAM_TypeDef *dev, uint32_t bank);
/**
* @}
*/
/** @addtogroup EBI_Public_Functions_Group3
* @{
*/
/* NAND-FLASH initialize functions */
void ald_ebi_nand_init(EBI_NAND_TypeDef *dev, ald_ebi_nand_init_t *init);
void ald_ebi_nand_comm_timing_init(EBI_NAND_TypeDef *dev, ald_ebi_nand_timing_t *timing, uint32_t bank);
void ald_ebi_nand_attr_timing_init(EBI_NAND_TypeDef *dev, ald_ebi_nand_timing_t *timing, uint32_t bank);
void ald_ebi_nand_deinit(EBI_NAND_TypeDef *dev, uint32_t bank);
/**
* @}
*/
/** @addtogroup EBI_Public_Functions_Group4
* @{
*/
/* NAND-FLASH control functions */
void ald_ebi_nand_enable(EBI_NAND_TypeDef *dev, uint32_t bank);
void ald_ebi_nand_disable(EBI_NAND_TypeDef *dev, uint32_t bank);
void ald_ebi_nand_enable_it(EBI_NAND_TypeDef *dev, uint32_t bank, ebi_it_t it);
void ald_ebi_nand_disable_it(EBI_NAND_TypeDef *dev, uint32_t bank, ebi_it_t it);
void ald_ebi_nand_ecc_enable(EBI_NAND_TypeDef *dev, uint32_t bank);
void ald_ebi_nand_ecc_disable(EBI_NAND_TypeDef *dev, uint32_t bank);
ald_status_t ald_ebi_nand_get_ecc(EBI_NAND_TypeDef *dev, uint32_t *val, uint32_t bank, uint32_t timeout);
flag_status_t ald_ebi_nand_get_flag(EBI_NAND_TypeDef *dev, uint32_t bank, ebi_flag_t flag);
void ald_ebi_nand_clear_flag(EBI_NAND_TypeDef *dev, uint32_t bank, ebi_flag_t flag);
/**
* @}
*/
/** @addtogroup EBI_Public_Functions_Group5
* @{
*/
void ald_ebi_lcd_init(ebi_lcd_handle_t *hlcd);
void ald_ebi_lcd_reset(ebi_lcd_handle_t *hlcd);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_EBI_H__ */

View File

@@ -1,146 +0,0 @@
/**
*********************************************************************************
*
* @file ald_flash.h
* @brief Header file of FLASH driver
*
* @version V1.0
* @date 17 Jun 2019
* @author AE Team
* @note
* Change Logs:
* Date Author Notes
* 17 Jun 2019 AE Team The first version
*
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**********************************************************************************
*/
#ifndef __ALD_FLASH_H__
#define __ALD_FLASH_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "utils.h"
/** @addtogroup ES32FXXX_ALD
* @{
*/
/** @addtogroup FLASH
* @{
*/
/**
* @defgroup FLASH_Private_Macros FLASH Private Macros
* @{
*/
#define FLASH_REG_UNLOCK() \
do { \
if (op_cmd == OP_FLASH) { \
WRITE_REG(MSC->FLASHKEY, 0x8ACE0246); \
WRITE_REG(MSC->FLASHKEY, 0x9BDF1357); \
} \
else { \
WRITE_REG(MSC->INFOKEY, 0x7153BFD9); \
WRITE_REG(MSC->INFOKEY, 0x0642CEA8); \
} \
} while (0)
#define FLASH_REQ() (SET_BIT(MSC->FLASHCR, MSC_FLASHCR_FLASHREQ_MSK))
#define FLASH_REQ_FIN() (CLEAR_BIT(MSC->FLASHCR, MSC_FLASHCR_FLASHREQ_MSK))
#define FLASH_IAP_ENABLE() (SET_BIT(MSC->FLASHCR, MSC_FLASHCR_IAPEN_MSK))
#define FLASH_IAP_DISABLE() (CLEAR_BIT(MSC->FLASHCR, MSC_FLASHCR_IAPEN_MSK))
#define FLASH_BASE_ADDR 0x00000000
#define FLASH_PAGE_SIZE 1024UL
#define FLASH_WORD_SIZE 8UL
#define FLASH_TOTAL_SIZE 512UL
#define FLASH_PAGE_MASK (FLASH_PAGE_SIZE - 1)
#define FLASH_WORD_MASK (FLASH_WORD_SIZE - 1)
#define IS_FLASH_ADDRESS(ADDR) ((ADDR) < (FLASH_BASE_ADDR + FLASH_PAGE_SIZE * FLASH_TOTAL_SIZE))
#define IS_4BYTES_ALIGN(ADDR) (((uint32_t)(ADDR) & 0x3) == 0 ? 1 : 0)
#define FLASH_PAGE_ADDR(ADDR) ((ADDR) & (~FLASH_PAGE_MASK))
#define FLASH_PAGEEND_ADDR(ADDR) ((ADDR) | FLASH_PAGE_MASK)
#define FLASH_WORD_ADDR(ADDR) ((ADDR) & (~FLASH_WORD_MASK))
#define FLASH_WORDEND_ADDR(ADDR) ((ADDR) | FLASH_WORD_MASK)
#define INFO_PAGE_SIZE 1024UL
#define INFO_PAGE_MASK (INFO_PAGE_SIZE - 1)
#define INFO_PAGE_ADDR(ADDR) ((ADDR) & (~INFO_PAGE_MASK))
#ifdef USE_FLASH_FIFO
#define FLASH_FIFO 1
#else
#define FLASH_FIFO 0
#endif
/**
* @}
*/
/** @defgroup FLASH_Private_Types FLASH Private Types
* @{
*/
typedef enum {
FLASH_CMD_AE = 0x000051AEU, /**< Program area erase all */
FLASH_CMD_PE = 0x00005EA1U, /**< Page erase */
FLASH_CMD_WP = 0x00005DA2U, /**< Word program */
FLASH_CMD_WP_FAST = 0x00005CA3U, /**< Flash quickly program */
FLASH_CMD_DATAPE = 0x00005BA4U, /**< Data flash page page erase */
FLASH_CMD_DATAWP = 0x00005AA5U, /**< Data flash word program */
FLASH_CMD_DATAWP_FAST = 0x000059A6U, /**< Data flash quickly program */
FLASH_CMD_NP_AE = 0x000050AFU, /**< No-private area erase all */
} flash_cmd_type;
typedef enum {
OP_FLASH = 0U, /**< Operate Pragram area */
OP_INFO = 1U, /**< Operate info area */
} op_cmd_type;
/**
* @}
*/
/** @addtogroup Flash_Private_Functions
* @{
*/
ald_status_t flash_page_erase(uint32_t addr);
ald_status_t flash_word_program(uint32_t addr, uint32_t *data, uint32_t len, uint32_t fifo);
/**
* @}
*/
/** @addtogroup Flash_Public_Functions
* @{
*/
ald_status_t ald_flash_read(uint32_t *ram_addr, uint32_t addr, uint16_t len);
ald_status_t ald_flash_write(uint32_t addr, uint8_t *buf, uint16_t len);
ald_status_t ald_flash_erase(uint32_t addr, uint16_t len);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ALD_FLASH_H__ */

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