Compare commits
533 Commits
v1.1.0
...
v1.5.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e5713ab89 | ||
|
|
05e5730cc2 | ||
|
|
d6f912c48d | ||
|
|
7465a59eaa | ||
|
|
e301e1f0a9 | ||
|
|
401dded10a | ||
|
|
03fc8b668a | ||
|
|
edc0c95db2 | ||
|
|
10e7fb60b4 | ||
|
|
619fb4fa5b | ||
|
|
eadcf7530b | ||
|
|
43692c0ba2 | ||
|
|
383d9b3141 | ||
|
|
01a25c7d93 | ||
|
|
5e45d15292 | ||
|
|
b19f70575a | ||
|
|
4f831f58ef | ||
|
|
684041f285 | ||
|
|
dbfcdb55af | ||
|
|
dd4c4fe180 | ||
|
|
3a028f7acf | ||
|
|
8c100cdccd | ||
|
|
6064c0beef | ||
|
|
dc5e8dc5ed | ||
|
|
4d3770b5d0 | ||
|
|
336aa91d24 | ||
|
|
7a0e8cae1a | ||
|
|
a92b5488b0 | ||
|
|
5253d5aa6b | ||
|
|
8393ed986a | ||
|
|
19f7548b60 | ||
|
|
ba2f91f24c | ||
|
|
2d8c4ca56a | ||
|
|
0ba374253b | ||
|
|
7affefe7f9 | ||
|
|
910f1f64ad | ||
|
|
96cbbfc1be | ||
|
|
9d06a940f0 | ||
|
|
c659bdc604 | ||
|
|
40f164e81e | ||
|
|
e0289d79f9 | ||
|
|
6516a470c8 | ||
|
|
bf2ba7324a | ||
|
|
cf22bcf252 | ||
|
|
d122f2d8f7 | ||
|
|
d012974a0e | ||
|
|
609305a28f | ||
|
|
d4dfb03afc | ||
|
|
a41000a000 | ||
|
|
e29d87bb20 | ||
|
|
93a8457700 | ||
|
|
3f736a3622 | ||
|
|
ccbe0232dc | ||
|
|
9aa7a76353 | ||
|
|
8bc602dc74 | ||
|
|
51ef13d217 | ||
|
|
7d93f7d0f0 | ||
|
|
5990e5c607 | ||
|
|
577ebd0999 | ||
|
|
c27458d71a | ||
|
|
644ac2b37f | ||
|
|
d3de69ae38 | ||
|
|
33dd56b7ce | ||
|
|
8aad86f66b | ||
|
|
0c3a64516d | ||
|
|
95d968bd57 | ||
|
|
4edd86c872 | ||
|
|
166795bd72 | ||
|
|
a838edb3e6 | ||
|
|
894b80d9ed | ||
|
|
4c8d448ca2 | ||
|
|
4897d6d622 | ||
|
|
e0fedaa956 | ||
|
|
d10b88c1a1 | ||
|
|
dd8ec4bbcf | ||
|
|
e6fb6af4a9 | ||
|
|
947f8530ef | ||
|
|
73c8062518 | ||
|
|
3f190b127d | ||
|
|
215db93943 | ||
|
|
c916f63bc3 | ||
|
|
8392ba6810 | ||
|
|
e5989ee41a | ||
|
|
364eb60396 | ||
|
|
dae76cb7bd | ||
|
|
339a99a728 | ||
|
|
6f25f797ed | ||
|
|
9a26c50900 | ||
|
|
91684e0677 | ||
|
|
4a9c90ddc0 | ||
|
|
83695e77cf | ||
|
|
5666fcb540 | ||
|
|
e9257baa5d | ||
|
|
f48fa44368 | ||
|
|
d9c0d27174 | ||
|
|
44dc3c00f6 | ||
|
|
4d5aa30778 | ||
|
|
e581097309 | ||
|
|
6378fb88d0 | ||
|
|
db0f5475b4 | ||
|
|
27c307abed | ||
|
|
374e6d6e4d | ||
|
|
c09ceb2537 | ||
|
|
56afada2cc | ||
|
|
8ac0b65b30 | ||
|
|
68434ccf7d | ||
|
|
17a591f719 | ||
|
|
23d2327a52 | ||
|
|
de7a73bc2f | ||
|
|
147dc4ab5d | ||
|
|
20c298b6ba | ||
|
|
0c5d2ad729 | ||
|
|
e90b29c2e7 | ||
|
|
ac6db49d00 | ||
|
|
43e6b5b1b1 | ||
|
|
40122200d1 | ||
|
|
e85d898503 | ||
|
|
e592a548e9 | ||
|
|
afc9213cd1 | ||
|
|
0826c164da | ||
|
|
609c85db68 | ||
|
|
d3aafb2174 | ||
|
|
95baa7845c | ||
|
|
c827c2e50b | ||
|
|
49d9775a1b | ||
|
|
5573472397 | ||
|
|
fd033f25c5 | ||
|
|
3e9f2b7777 | ||
|
|
efbfc9d70f | ||
|
|
f447de38dc | ||
|
|
8f44b8bad8 | ||
|
|
c399be3ea2 | ||
|
|
1aa2d038aa | ||
|
|
6769eac6e0 | ||
|
|
646e84bedc | ||
|
|
322595b910 | ||
|
|
ea27f5b238 | ||
|
|
d4940ebd22 | ||
|
|
e1398982f3 | ||
|
|
76b7a0172b | ||
|
|
6c3b828e77 | ||
|
|
0a295ee5eb | ||
|
|
5b74cecc4a | ||
|
|
99e2e6bfd4 | ||
|
|
64394bf246 | ||
|
|
1a1b475523 | ||
|
|
a1ac569236 | ||
|
|
570d2b5ff8 | ||
|
|
cc9c226aba | ||
|
|
1be34f4d36 | ||
|
|
515b83e0f8 | ||
|
|
be6537637c | ||
|
|
e6801fcbb8 | ||
|
|
75e6dc6300 | ||
|
|
effee4d4c2 | ||
|
|
05b46c8bad | ||
|
|
ddc19a9d65 | ||
|
|
886f1ec6b4 | ||
|
|
7980cb056c | ||
|
|
f86443a70b | ||
|
|
bfc1139d80 | ||
|
|
8d2afc1540 | ||
|
|
87b8a4ad7f | ||
|
|
9ff35e9020 | ||
|
|
a03a9cd481 | ||
|
|
88d57eb99b | ||
|
|
5850e27743 | ||
|
|
015aa77487 | ||
|
|
4416dfa5cf | ||
|
|
d874bed6aa | ||
|
|
7f75da270f | ||
|
|
1a39169f6e | ||
|
|
82a0d243f8 | ||
|
|
ac3be8cb3a | ||
|
|
a72ecd2202 | ||
|
|
c6bdacee6d | ||
|
|
ea03856337 | ||
|
|
1c1217f8fa | ||
|
|
093a1836f0 | ||
|
|
70ef616676 | ||
|
|
6517919bd2 | ||
|
|
2b72d8c6d8 | ||
|
|
261502f3b2 | ||
|
|
e3ff8ffe6a | ||
|
|
24fc172ad8 | ||
|
|
58d552d03d | ||
|
|
d0edc30c11 | ||
|
|
6ea1e2f94f | ||
|
|
037c2a8323 | ||
|
|
608ee773de | ||
|
|
c51a6f35a6 | ||
|
|
a13bee0663 | ||
|
|
fd1baa62df | ||
|
|
6e6fdda62a | ||
|
|
f02ff21cfb | ||
|
|
d6aae26371 | ||
|
|
77136aa743 | ||
|
|
4784017f56 | ||
|
|
149fb046bc | ||
|
|
f437b3e51c | ||
|
|
65151b9534 | ||
|
|
05315b7ea5 | ||
|
|
f1a1434047 | ||
|
|
a20e312b55 | ||
|
|
83b5d842c7 | ||
|
|
e425b992be | ||
|
|
0b81f3b2a2 | ||
|
|
287eb130ac | ||
|
|
525884a00f | ||
|
|
2c52445639 | ||
|
|
df888eb9bc | ||
|
|
5a15f714f5 | ||
|
|
bb79408275 | ||
|
|
2b6eebcbb2 | ||
|
|
ab59beebd4 | ||
|
|
c377747e67 | ||
|
|
2f14ee7a7b | ||
|
|
0d65bbc6ba | ||
|
|
76bbd09fed | ||
|
|
a8ef0c4cac | ||
|
|
b461f4e2d1 | ||
|
|
5fb7d4d0e9 | ||
|
|
8cb95b04cf | ||
|
|
df7ecdf019 | ||
|
|
68bf529608 | ||
|
|
02340e0f44 | ||
|
|
171b36e766 | ||
|
|
0371bb921c | ||
|
|
7ec7891fe4 | ||
|
|
da391c6cf9 | ||
|
|
b56b67182a | ||
|
|
e6fde5efab | ||
|
|
0487af6900 | ||
|
|
be2880a7e8 | ||
|
|
97e2a38b4a | ||
|
|
a139a70782 | ||
|
|
cb6a0c2ad6 | ||
|
|
bacacdb32c | ||
|
|
0323ffb424 | ||
|
|
89e93f6c93 | ||
|
|
1deab668ef | ||
|
|
fbe2e3f8a3 | ||
|
|
d03dfe43ca | ||
|
|
e42e99e975 | ||
|
|
8a7979378d | ||
|
|
a8a5d95f8f | ||
|
|
02ac1db3ff | ||
|
|
0d561ea313 | ||
|
|
e603389638 | ||
|
|
b932cc5803 | ||
|
|
5f43dc8662 | ||
|
|
f5ce56990c | ||
|
|
f517adcf6d | ||
|
|
2a563dc41f | ||
|
|
b045a1d490 | ||
|
|
563fbf58e1 | ||
|
|
8435f1af32 | ||
|
|
2726e2e7b6 | ||
|
|
e8b22163bb | ||
|
|
35da8d6747 | ||
|
|
43dc854b4d | ||
|
|
f0fc75179e | ||
|
|
f1e7043384 | ||
|
|
e4954d4194 | ||
|
|
07c6c296ed | ||
|
|
500367dd82 | ||
|
|
1efc29be5f | ||
|
|
143a5ce3fd | ||
|
|
b171b28a75 | ||
|
|
668e414917 | ||
|
|
03f8711b20 | ||
|
|
393756f111 | ||
|
|
4a252c3f73 | ||
|
|
4b2000b405 | ||
|
|
9720eb2f76 | ||
|
|
68badf6f4c | ||
|
|
907d23871e | ||
|
|
70944027c5 | ||
|
|
a41da8928e | ||
|
|
bbcc767465 | ||
|
|
72e8eb7d84 | ||
|
|
18d9c21553 | ||
|
|
cbd6955bde | ||
|
|
b4bbe69d12 | ||
|
|
e1cbccc58a | ||
|
|
dfc90da28a | ||
|
|
8451bc64bb | ||
|
|
3fc30cd058 | ||
|
|
e95387c558 | ||
|
|
35a76f58bb | ||
|
|
564d568732 | ||
|
|
9394f1f8d6 | ||
|
|
bef45dc360 | ||
|
|
50b62c946d | ||
|
|
b399ff63ce | ||
|
|
4c4ee7f003 | ||
|
|
1c2fd3407a | ||
|
|
1927566dfc | ||
|
|
b7556b2ddc | ||
|
|
f1058c5e1a | ||
|
|
643578e5be | ||
|
|
390e24fbe5 | ||
|
|
ba02a48873 | ||
|
|
c766cbe91e | ||
|
|
9dd52fddf0 | ||
|
|
9c14ea19a9 | ||
|
|
218fa8e85d | ||
|
|
eb147d7276 | ||
|
|
c0bfbf7952 | ||
|
|
1a9c1481f4 | ||
|
|
3d3c6bb5a2 | ||
|
|
a942ec85a8 | ||
|
|
a4a06573ea | ||
|
|
7fab3c29f0 | ||
|
|
4f3a3f496e | ||
|
|
e4b56cee89 | ||
|
|
53114c0f16 | ||
|
|
29aaf56396 | ||
|
|
c24eea6077 | ||
|
|
8fa517016e | ||
|
|
35807fb9d9 | ||
|
|
6e7502ec07 | ||
|
|
ab7ef4b116 | ||
|
|
adee4b6727 | ||
|
|
6c92681e48 | ||
|
|
31cd834ded | ||
|
|
a1274bad0a | ||
|
|
c377ebfc61 | ||
|
|
1decfd0365 | ||
|
|
dc0070b054 | ||
|
|
755d067650 | ||
|
|
69fe1598ed | ||
|
|
0f8ec31981 | ||
|
|
3bf74d2101 | ||
|
|
10437a7d13 | ||
|
|
a1ab76dd3e | ||
|
|
27394f5759 | ||
|
|
740627cf3c | ||
|
|
7a26ad5082 | ||
|
|
ff2070d14b | ||
|
|
0cb245e6d3 | ||
|
|
556bf91879 | ||
|
|
5d87a750ac | ||
|
|
8a4f210ee7 | ||
|
|
82f11fa647 | ||
|
|
47e6ed1c75 | ||
|
|
b4d54d2aa6 | ||
|
|
96db9b96da | ||
|
|
62da380c25 | ||
|
|
66e3ffb90d | ||
|
|
afa77ec20b | ||
|
|
0f8c145d93 | ||
|
|
3cf2d6da31 | ||
|
|
bf9a236c9a | ||
|
|
bf8e092627 | ||
|
|
e9a7eb9eeb | ||
|
|
277f3940f6 | ||
|
|
bf54bc2ff1 | ||
|
|
77af563898 | ||
|
|
f57234e668 | ||
|
|
3429f833f3 | ||
|
|
9d265f2398 | ||
|
|
935325175f | ||
|
|
6fd87902b5 | ||
|
|
b1660f743f | ||
|
|
f197716f52 | ||
|
|
62ed025ddc | ||
|
|
883c0a5dc5 | ||
|
|
cf0137686d | ||
|
|
48a125b28d | ||
|
|
e2877d3fe0 | ||
|
|
3429f73a65 | ||
|
|
3c102bd265 | ||
|
|
ba098529af | ||
|
|
2d63b52d0b | ||
|
|
5f28438eec | ||
|
|
edf4e5c7fc | ||
|
|
865d2f5d96 | ||
|
|
3336919e0d | ||
|
|
8b070570a7 | ||
|
|
af792eabab | ||
|
|
3be08d16f7 | ||
|
|
5dafdcb895 | ||
|
|
f24c37d3aa | ||
|
|
a7a7afc6bb | ||
|
|
66b893e64f | ||
|
|
3a3de9cb69 | ||
|
|
13e4670f3d | ||
|
|
1d9a36b61c | ||
|
|
b1c81a92f5 | ||
|
|
af92236cf4 | ||
|
|
0985a7e5fa | ||
|
|
8b805ee6d7 | ||
|
|
5e6bd78f80 | ||
|
|
f2133f5ca2 | ||
|
|
9657585f1f | ||
|
|
a225ee383b | ||
|
|
60747ce435 | ||
|
|
490cac1a0f | ||
|
|
207fb7b128 | ||
|
|
d23a8a8d00 | ||
|
|
4243394225 | ||
|
|
62c9c8b747 | ||
|
|
7b38b4b323 | ||
|
|
e1aa49e086 | ||
|
|
fabeebd4c5 | ||
|
|
58550b3ed5 | ||
|
|
363533be4c | ||
|
|
074662a50d | ||
|
|
532e05e293 | ||
|
|
b55d40e512 | ||
|
|
263a66ed9b | ||
|
|
775ac135de | ||
|
|
aecae9434b | ||
|
|
5a7042fe15 | ||
|
|
18c4454228 | ||
|
|
cd8b103a71 | ||
|
|
8ecbd32483 | ||
|
|
d0f79ff668 | ||
|
|
7272ccfc02 | ||
|
|
e081642c76 | ||
|
|
b51da4fbf9 | ||
|
|
97c5e37453 | ||
|
|
cdd308f3e8 | ||
|
|
6db4fbba4c | ||
|
|
102801e45c | ||
|
|
0ceb7ef885 | ||
|
|
ae5a9d1e57 | ||
|
|
7ebcafe158 | ||
|
|
81cebaf78c | ||
|
|
5fec929b93 | ||
|
|
4bf0e126af | ||
|
|
ccef9b92cc | ||
|
|
9cb992bed7 | ||
|
|
183d49efbd | ||
|
|
8d18a8b6e5 | ||
|
|
5f79fdc865 | ||
|
|
2f5f2b906f | ||
|
|
0556ae199b | ||
|
|
2da4edf76b | ||
|
|
45e9a2fde8 | ||
|
|
5b72907f6d | ||
|
|
6abe6befa8 | ||
|
|
7ee77b42ee | ||
|
|
404225ade4 | ||
|
|
694b201ff7 | ||
|
|
23e2787a43 | ||
|
|
a3302584ce | ||
|
|
8625e4409e | ||
|
|
190fb36c43 | ||
|
|
a24d2bdc07 | ||
|
|
ceaf0923c5 | ||
|
|
2cb6c598c1 | ||
|
|
4e6b0d0923 | ||
|
|
017eb5560d | ||
|
|
b97fc903c0 | ||
|
|
81ddf9bded | ||
|
|
8995cf9568 | ||
|
|
76f58b93fe | ||
|
|
70c7f1ccbd | ||
|
|
29c72f3455 | ||
|
|
51b9640489 | ||
|
|
32f96f4248 | ||
|
|
e3886fe99d | ||
|
|
d8714d8169 | ||
|
|
9d5479e0c3 | ||
|
|
ed8a3ceca3 | ||
|
|
3592794393 | ||
|
|
4357a1d7d1 | ||
|
|
c1cb6e397b | ||
|
|
c8be4d6fd3 | ||
|
|
725d635c76 | ||
|
|
1eef5f3e35 | ||
|
|
1dd45e3e5a | ||
|
|
8119a500b2 | ||
|
|
c5f2ffa6f9 | ||
|
|
db10c62b59 | ||
|
|
808cd454a3 | ||
|
|
a41c66c2c3 | ||
|
|
6ef086a085 | ||
|
|
5494b0e99a | ||
|
|
a6d539792f | ||
|
|
7b5d8f29d4 | ||
|
|
e7616399b7 | ||
|
|
a21947ff22 | ||
|
|
078e21066c | ||
|
|
2335e08ef2 | ||
|
|
64f8a86569 | ||
|
|
4164e687f0 | ||
|
|
4da3550582 | ||
|
|
22121bc54d | ||
|
|
68708c0f3a | ||
|
|
5cd50410e6 | ||
|
|
74bb03b8b4 | ||
|
|
bc6ed589b0 | ||
|
|
f99e4ce113 | ||
|
|
d6d1b67761 | ||
|
|
3c16d7c61c | ||
|
|
0d647cf9c0 | ||
|
|
eef3e116b8 | ||
|
|
bfa4490e6c | ||
|
|
2bfb7255cd | ||
|
|
f28b1c61ba | ||
|
|
f4a0ba9839 | ||
|
|
26e2436847 | ||
|
|
6cb442503d | ||
|
|
9dbc441082 | ||
|
|
44c408959b | ||
|
|
aa1a30d581 | ||
|
|
235139ad77 | ||
|
|
b2af686e67 | ||
|
|
15b97f3348 | ||
|
|
9145add9af | ||
|
|
ce241024b1 | ||
|
|
1d38fde61a | ||
|
|
b628c737ec | ||
|
|
e40c72f3a8 | ||
|
|
b4c455e5e6 | ||
|
|
2660af5d87 | ||
|
|
869b5809f3 | ||
|
|
4c062d4442 | ||
|
|
bba4b46fa4 | ||
|
|
2e862f3864 | ||
|
|
6369ead152 | ||
|
|
969c0342f0 | ||
|
|
5bd8ea8925 | ||
|
|
7910666998 | ||
|
|
39693f4702 | ||
|
|
f489619c20 | ||
|
|
215534982a | ||
|
|
6af1c143d3 | ||
|
|
9e9772fde7 | ||
|
|
b545830f70 |
311
.cmake-format.json
Normal file
311
.cmake-format.json
Normal file
@@ -0,0 +1,311 @@
|
||||
{
|
||||
"_help_parse": "Options affecting listfile parsing",
|
||||
"parse": {
|
||||
"_help_additional_commands": [
|
||||
"Specify structure for custom cmake functions"
|
||||
],
|
||||
"additional_commands": {
|
||||
"foo": {
|
||||
"flags": [
|
||||
"BAR",
|
||||
"BAZ"
|
||||
],
|
||||
"kwargs": {
|
||||
"HEADERS": "*",
|
||||
"SOURCES": "*",
|
||||
"DEPENDS": "*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_help_override_spec": [
|
||||
"Override configurations per-command where available"
|
||||
],
|
||||
"override_spec": {},
|
||||
"_help_vartags": [
|
||||
"Specify variable tags."
|
||||
],
|
||||
"vartags": [],
|
||||
"_help_proptags": [
|
||||
"Specify property tags."
|
||||
],
|
||||
"proptags": []
|
||||
},
|
||||
"_help_format": "Options affecting formatting.",
|
||||
"format": {
|
||||
"_help_disable": [
|
||||
"Disable formatting entirely, making cmake-format a no-op"
|
||||
],
|
||||
"disable": false,
|
||||
"_help_line_width": [
|
||||
"How wide to allow formatted cmake files"
|
||||
],
|
||||
"line_width": 120,
|
||||
"_help_tab_size": [
|
||||
"How many spaces to tab for indent"
|
||||
],
|
||||
"tab_size": 4,
|
||||
"_help_use_tabchars": [
|
||||
"If true, lines are indented using tab characters (utf-8",
|
||||
"0x09) instead of <tab_size> space characters (utf-8 0x20).",
|
||||
"In cases where the layout would require a fractional tab",
|
||||
"character, the behavior of the fractional indentation is",
|
||||
"governed by <fractional_tab_policy>"
|
||||
],
|
||||
"use_tabchars": false,
|
||||
"_help_fractional_tab_policy": [
|
||||
"If <use_tabchars> is True, then the value of this variable",
|
||||
"indicates how fractional indentions are handled during",
|
||||
"whitespace replacement. If set to 'use-space', fractional",
|
||||
"indentation is left as spaces (utf-8 0x20). If set to",
|
||||
"`round-up` fractional indentation is replaced with a single",
|
||||
"tab character (utf-8 0x09) effectively shifting the column",
|
||||
"to the next tabstop"
|
||||
],
|
||||
"fractional_tab_policy": "use-space",
|
||||
"_help_max_subgroups_hwrap": [
|
||||
"If an argument group contains more than this many sub-groups",
|
||||
"(parg or kwarg groups) then force it to a vertical layout."
|
||||
],
|
||||
"max_subgroups_hwrap": 2,
|
||||
"_help_max_pargs_hwrap": [
|
||||
"If a positional argument group contains more than this many",
|
||||
"arguments, then force it to a vertical layout."
|
||||
],
|
||||
"max_pargs_hwrap": 6,
|
||||
"_help_max_rows_cmdline": [
|
||||
"If a cmdline positional group consumes more than this many",
|
||||
"lines without nesting, then invalidate the layout (and nest)"
|
||||
],
|
||||
"max_rows_cmdline": 2,
|
||||
"_help_separate_ctrl_name_with_space": [
|
||||
"If true, separate flow control names from their parentheses",
|
||||
"with a space"
|
||||
],
|
||||
"separate_ctrl_name_with_space": false,
|
||||
"_help_separate_fn_name_with_space": [
|
||||
"If true, separate function names from parentheses with a",
|
||||
"space"
|
||||
],
|
||||
"separate_fn_name_with_space": false,
|
||||
"_help_dangle_parens": [
|
||||
"If a statement is wrapped to more than one line, than dangle",
|
||||
"the closing parenthesis on its own line."
|
||||
],
|
||||
"dangle_parens": true,
|
||||
"_help_dangle_align": [
|
||||
"If the trailing parenthesis must be 'dangled' on its on",
|
||||
"line, then align it to this reference: `prefix`: the start",
|
||||
"of the statement, `prefix-indent`: the start of the",
|
||||
"statement, plus one indentation level, `child`: align to",
|
||||
"the column of the arguments"
|
||||
],
|
||||
"dangle_align": "prefix",
|
||||
"_help_min_prefix_chars": [
|
||||
"If the statement spelling length (including space and",
|
||||
"parenthesis) is smaller than this amount, then force reject",
|
||||
"nested layouts."
|
||||
],
|
||||
"min_prefix_chars": 4,
|
||||
"_help_max_prefix_chars": [
|
||||
"If the statement spelling length (including space and",
|
||||
"parenthesis) is larger than the tab width by more than this",
|
||||
"amount, then force reject un-nested layouts."
|
||||
],
|
||||
"max_prefix_chars": 10,
|
||||
"_help_max_lines_hwrap": [
|
||||
"If a candidate layout is wrapped horizontally but it exceeds",
|
||||
"this many lines, then reject the layout."
|
||||
],
|
||||
"max_lines_hwrap": 2,
|
||||
"_help_line_ending": [
|
||||
"What style line endings to use in the output."
|
||||
],
|
||||
"line_ending": "unix",
|
||||
"_help_command_case": [
|
||||
"Format command names consistently as 'lower' or 'upper' case"
|
||||
],
|
||||
"command_case": "canonical",
|
||||
"_help_keyword_case": [
|
||||
"Format keywords consistently as 'lower' or 'upper' case"
|
||||
],
|
||||
"keyword_case": "unchanged",
|
||||
"_help_always_wrap": [
|
||||
"A list of command names which should always be wrapped"
|
||||
],
|
||||
"always_wrap": [],
|
||||
"_help_enable_sort": [
|
||||
"If true, the argument lists which are known to be sortable",
|
||||
"will be sorted lexicographicall"
|
||||
],
|
||||
"enable_sort": true,
|
||||
"_help_autosort": [
|
||||
"If true, the parsers may infer whether or not an argument",
|
||||
"list is sortable (without annotation)."
|
||||
],
|
||||
"autosort": false,
|
||||
"_help_require_valid_layout": [
|
||||
"By default, if cmake-format cannot successfully fit",
|
||||
"everything into the desired linewidth it will apply the",
|
||||
"last, most agressive attempt that it made. If this flag is",
|
||||
"True, however, cmake-format will print error, exit with non-",
|
||||
"zero status code, and write-out nothing"
|
||||
],
|
||||
"require_valid_layout": false,
|
||||
"_help_layout_passes": [
|
||||
"A dictionary mapping layout nodes to a list of wrap",
|
||||
"decisions. See the documentation for more information."
|
||||
],
|
||||
"layout_passes": {}
|
||||
},
|
||||
"_help_markup": "Options affecting comment reflow and formatting.",
|
||||
"markup": {
|
||||
"_help_bullet_char": [
|
||||
"What character to use for bulleted lists"
|
||||
],
|
||||
"bullet_char": "*",
|
||||
"_help_enum_char": [
|
||||
"What character to use as punctuation after numerals in an",
|
||||
"enumerated list"
|
||||
],
|
||||
"enum_char": ".",
|
||||
"_help_first_comment_is_literal": [
|
||||
"If comment markup is enabled, don't reflow the first comment",
|
||||
"block in each listfile. Use this to preserve formatting of",
|
||||
"your copyright/license statements."
|
||||
],
|
||||
"first_comment_is_literal": true,
|
||||
"_help_literal_comment_pattern": [
|
||||
"If comment markup is enabled, don't reflow any comment block",
|
||||
"which matches this (regex) pattern. Default is `None`",
|
||||
"(disabled)."
|
||||
],
|
||||
"literal_comment_pattern": null,
|
||||
"_help_fence_pattern": [
|
||||
"Regular expression to match preformat fences in comments",
|
||||
"default= ``r'^\\s*([`~]{3}[`~]*)(.*)$'``"
|
||||
],
|
||||
"fence_pattern": "^\\s*([`~]{3}[`~]*)(.*)$",
|
||||
"_help_ruler_pattern": [
|
||||
"Regular expression to match rulers in comments default=",
|
||||
"``r'^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'``"
|
||||
],
|
||||
"ruler_pattern": "^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$",
|
||||
"_help_explicit_trailing_pattern": [
|
||||
"If a comment line matches starts with this pattern then it",
|
||||
"is explicitly a trailing comment for the preceeding",
|
||||
"argument. Default is '#<'"
|
||||
],
|
||||
"explicit_trailing_pattern": "#<",
|
||||
"_help_hashruler_min_length": [
|
||||
"If a comment line starts with at least this many consecutive",
|
||||
"hash characters, then don't lstrip() them off. This allows",
|
||||
"for lazy hash rulers where the first hash char is not",
|
||||
"separated by space"
|
||||
],
|
||||
"hashruler_min_length": 10,
|
||||
"_help_canonicalize_hashrulers": [
|
||||
"If true, then insert a space between the first hash char and",
|
||||
"remaining hash chars in a hash ruler, and normalize its",
|
||||
"length to fill the column"
|
||||
],
|
||||
"canonicalize_hashrulers": true,
|
||||
"_help_enable_markup": [
|
||||
"enable comment markup parsing and reflow"
|
||||
],
|
||||
"enable_markup": true
|
||||
},
|
||||
"_help_lint": "Options affecting the linter",
|
||||
"lint": {
|
||||
"_help_disabled_codes": [
|
||||
"a list of lint codes to disable"
|
||||
],
|
||||
"disabled_codes": [],
|
||||
"_help_function_pattern": [
|
||||
"regular expression pattern describing valid function names"
|
||||
],
|
||||
"function_pattern": "[0-9a-z_]+",
|
||||
"_help_macro_pattern": [
|
||||
"regular expression pattern describing valid macro names"
|
||||
],
|
||||
"macro_pattern": "[0-9A-Z_]+",
|
||||
"_help_global_var_pattern": [
|
||||
"regular expression pattern describing valid names for",
|
||||
"variables with global (cache) scope"
|
||||
],
|
||||
"global_var_pattern": "[A-Z][0-9A-Z_]+",
|
||||
"_help_internal_var_pattern": [
|
||||
"regular expression pattern describing valid names for",
|
||||
"variables with global scope (but internal semantic)"
|
||||
],
|
||||
"internal_var_pattern": "_[A-Z][0-9A-Z_]+",
|
||||
"_help_local_var_pattern": [
|
||||
"regular expression pattern describing valid names for",
|
||||
"variables with local scope"
|
||||
],
|
||||
"local_var_pattern": "[a-z][a-z0-9_]+",
|
||||
"_help_private_var_pattern": [
|
||||
"regular expression pattern describing valid names for",
|
||||
"privatedirectory variables"
|
||||
],
|
||||
"private_var_pattern": "_[0-9a-z_]+",
|
||||
"_help_public_var_pattern": [
|
||||
"regular expression pattern describing valid names for public",
|
||||
"directory variables"
|
||||
],
|
||||
"public_var_pattern": "[A-Z][0-9A-Z_]+",
|
||||
"_help_argument_var_pattern": [
|
||||
"regular expression pattern describing valid names for",
|
||||
"function/macro arguments and loop variables."
|
||||
],
|
||||
"argument_var_pattern": "[a-z][a-z0-9_]+",
|
||||
"_help_keyword_pattern": [
|
||||
"regular expression pattern describing valid names for",
|
||||
"keywords used in functions or macros"
|
||||
],
|
||||
"keyword_pattern": "[A-Z][0-9A-Z_]+",
|
||||
"_help_max_conditionals_custom_parser": [
|
||||
"In the heuristic for C0201, how many conditionals to match",
|
||||
"within a loop in before considering the loop a parser."
|
||||
],
|
||||
"max_conditionals_custom_parser": 2,
|
||||
"_help_min_statement_spacing": [
|
||||
"Require at least this many newlines between statements"
|
||||
],
|
||||
"min_statement_spacing": 1,
|
||||
"_help_max_statement_spacing": [
|
||||
"Require no more than this many newlines between statements"
|
||||
],
|
||||
"max_statement_spacing": 2,
|
||||
"max_returns": 6,
|
||||
"max_branches": 12,
|
||||
"max_arguments": 5,
|
||||
"max_localvars": 15,
|
||||
"max_statements": 50
|
||||
},
|
||||
"_help_encode": "Options affecting file encoding",
|
||||
"encode": {
|
||||
"_help_emit_byteorder_mark": [
|
||||
"If true, emit the unicode byte-order mark (BOM) at the start",
|
||||
"of the file"
|
||||
],
|
||||
"emit_byteorder_mark": false,
|
||||
"_help_input_encoding": [
|
||||
"Specify the encoding of the input file. Defaults to utf-8"
|
||||
],
|
||||
"input_encoding": "utf-8",
|
||||
"_help_output_encoding": [
|
||||
"Specify the encoding of the output file. Defaults to utf-8.",
|
||||
"Note that cmake only claims to support utf-8 so be careful",
|
||||
"when using anything else"
|
||||
],
|
||||
"output_encoding": "utf-8"
|
||||
},
|
||||
"_help_misc": "Miscellaneous configurations options.",
|
||||
"misc": {
|
||||
"_help_per_command": [
|
||||
"A dictionary containing any per-command configuration",
|
||||
"overrides. Currently only `command_case` is supported."
|
||||
],
|
||||
"per_command": {}
|
||||
}
|
||||
}
|
||||
85
.github/ISSUE_TEMPLATE/1-bug-report.yml
vendored
Normal file
85
.github/ISSUE_TEMPLATE/1-bug-report.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
name: "🐞 上报bug / Bug report"
|
||||
description: "提交bug以让改进软件功能 / Create a report to help us improve"
|
||||
labels: ["peding"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢上报新的问题!请填写以下信息,以帮助我们更好地理解问题。请注意,如果您不按模板填写issue,那您的issue可能会被关闭或者删除!
|
||||
我们的工作语言是中文或者英文,请使用这两种语言之一填写issue。
|
||||
|
||||
Thank you for reporting a new issue! Please fill in the following information to help us better understand the problem. Please note that if you do not fill in the issue according to the template, your issue may be closed or deleted!
|
||||
Our working languages are Chinese or English, please use one of these two languages to fill in the issue.
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: 描述一下这个bug / Describe the bug
|
||||
description: 请使用简介并详细的语句,来描述这个bug。 / A clear and concise description of what the bug is.
|
||||
placeholder: 我准备……我想要……但是实际上它……了 / I am doing ... What I expect is ... What actually happening is ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: 复现步骤 / To Reproduce
|
||||
description: 按照下面的步骤,可以复现bug / Steps to reproduce the behavior
|
||||
placeholder: 首先……然后……接着…… / Go to '...', Click on '....', Scroll down to '....'
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: target
|
||||
attributes:
|
||||
label: 设备信息 / Target Device
|
||||
description: 您使用的板子/芯片型号、使用的引脚、以及USB IP类型 / Your target board/chip model, the pins you used, and the type of USB IP you used
|
||||
placeholder: |-
|
||||
板子型号:HPM5301EVKLite
|
||||
引脚:PA24 PA25
|
||||
USB IP:/
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: log
|
||||
attributes:
|
||||
label: 日志 / Log
|
||||
description: 请提供输出 log
|
||||
placeholder: |-
|
||||
[D/USB] EP0 send 18 bytes, 0 remained
|
||||
[D/USB] EP0 recv out status
|
||||
[D/USB] EP0 send 0 bytes, 0 remained
|
||||
[D/USB] EP0 send 18 bytes, 0 remained
|
||||
[D/USB] EP0 recv out status
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
以下的部分仅在移植的时候需要填写,如果不是移植问题,请忽略这部分。
|
||||
The following section is only required when porting, if it is not a porting issue, please ignore this section.
|
||||
|
||||
- type: textarea
|
||||
id: configure
|
||||
attributes:
|
||||
label: 配置 / Configuration
|
||||
description: 请确认 USB 中断,时钟,引脚,寄存器地址是否正确,并截图 / Please confirm that the USB interrupt, clock, pin, and register address are correct, and provide a screenshot
|
||||
|
||||
- type: textarea
|
||||
id: USBIrq
|
||||
attributes:
|
||||
label: USB中断 / USB Interrupt
|
||||
description: 请确认是否能进入USB中断
|
||||
|
||||
- type: textarea
|
||||
id: cache
|
||||
attributes:
|
||||
label: 缓存 / Cache
|
||||
description: 芯片是否带有 cache功能,是否做了 no cache 处理,并截图 / Whether the chip has a cache function, whether no cache processing is done, and provide a screenshot
|
||||
|
||||
- type: checkboxes
|
||||
id: bussiness
|
||||
attributes:
|
||||
label: 商业 / Business
|
||||
description: 是否流片并销售 / Whether it is mass-produced and sold
|
||||
options:
|
||||
- label: 是 / Yes
|
||||
17
.github/workflows/cppcheck.yml
vendored
Normal file
17
.github/workflows/cppcheck.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: Cppcheck action
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: cppcheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: cppcheck
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt install cppcheck
|
||||
cppcheck --enable=warning,portability,performance --language=c --platform=unix32 --std=c99 --force . -i third_party/ -i class/template -i port/template/
|
||||
28
.github/workflows/deploy-docs.yml
vendored
Normal file
28
.github/workflows/deploy-docs.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Deploy docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- uses: ammaraskar/sphinx-action@8.0.2
|
||||
with:
|
||||
docs-folder: "docs/"
|
||||
- uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: docs/build/html
|
||||
|
||||
|
||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
||||
[submodule "third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth"]
|
||||
path = third_party/zephyr_bluetooth-2.7.5/zephyr_bluetooth
|
||||
url = git@github.com:sakumisu/zephyr_bluetooth.git
|
||||
[submodule "third_party/nimble-1.6.0/nimble"]
|
||||
path = third_party/nimble-1.6.0/nimble
|
||||
url = git@github.com:sakumisu/mynewt-nimble.git
|
||||
url = https://github.com/sakumisu/zephyr_bluetooth.git
|
||||
|
||||
242
CMakeLists.txt
242
CMakeLists.txt
@@ -1,57 +1,201 @@
|
||||
add_library(cherryusb STATIC)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
target_include_directories(cherryusb PUBLIC
|
||||
common
|
||||
core
|
||||
osal
|
||||
class/cdc
|
||||
class/hid
|
||||
class/msc
|
||||
class/audio
|
||||
class/video
|
||||
class/hub
|
||||
class/wireless
|
||||
)
|
||||
if(CONFIG_CHERRYUSB)
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE)
|
||||
target_sources(cherryusb PRIVATE core/usbd_core.c)
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC)
|
||||
target_sources(cherryusb PRIVATE class/cdc/usbd_cdc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||
target_sources(cherryusb PRIVATE class/hid/usbd_hid.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_MSC)
|
||||
target_sources(cherryusb PRIVATE class/msc/usbd_msc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
|
||||
target_sources(cherryusb PRIVATE class/audio/usbd_audio.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
|
||||
target_sources(cherryusb PRIVATE class/video/usbd_video.c)
|
||||
endif()
|
||||
endif()
|
||||
if(BL_SDK_BASE)
|
||||
message(STATUS "enable cherryusb in bouffalo_sdk")
|
||||
|
||||
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
|
||||
set(CONFIG_CHERRYUSB_DEVICE_CDC_ACM 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)
|
||||
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_HID 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_MSC 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CP210X 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_FTDI 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_PL2303 1)
|
||||
|
||||
set(CONFIG_CHERRYUSB_DEVICE_BL 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_EHCI_BL 1)
|
||||
set(CONFIG_CHERRYUSB_OSAL "freertos")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||
list(REMOVE_DUPLICATES cherryusb_srcs)
|
||||
list(REMOVE_DUPLICATES cherryusb_incs)
|
||||
|
||||
sdk_generate_library(cherryusb)
|
||||
sdk_add_include_directories(${cherryusb_incs})
|
||||
sdk_library_add_sources(${cherryusb_srcs})
|
||||
elseif(ESP_PLATFORM)
|
||||
message(STATUS "enable cherryusb in esp-idf")
|
||||
|
||||
set(CONFIG_CHERRYUSB_DEVICE_DWC2_ESP 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_DWC2_ESP 1)
|
||||
set(CONFIG_CHERRYUSB_OSAL "idf")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||
list(REMOVE_DUPLICATES cherryusb_srcs)
|
||||
list(REMOVE_DUPLICATES cherryusb_incs)
|
||||
|
||||
set(ldfragments "osal/idf/linker.lf")
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_ECM
|
||||
OR CONFIG_CHERRYUSB_HOST_CDC_RNDIS
|
||||
OR CONFIG_CHERRYUSB_HOST_CDC_NCM
|
||||
OR CONFIG_CHERRYUSB_HOST_ASIX
|
||||
OR CONFIG_CHERRYUSB_HOST_RTL8152
|
||||
OR CONFIG_CHERRYUSB_HOST_BL616
|
||||
)
|
||||
idf_component_get_property(lwip lwip COMPONENT_LIB)
|
||||
target_compile_definitions(${lwip} PRIVATE "-DPBUF_POOL_BUFSIZE=1600")
|
||||
endif()
|
||||
|
||||
idf_component_get_property(freertos_include freertos ORIG_INCLUDE_PATH)
|
||||
|
||||
idf_component_register(
|
||||
SRCS
|
||||
${cherryusb_srcs}
|
||||
INCLUDE_DIRS
|
||||
${cherryusb_incs}
|
||||
${freertos_include}
|
||||
PRIV_REQUIRES
|
||||
usb
|
||||
LDFRAGMENTS
|
||||
${ldfragments}
|
||||
)
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST)
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "osal/idf/usbh_class_info.ld")
|
||||
|
||||
# 强制链接器不删除符号
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_acm_class_info")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_data_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_HID)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u hid_custom_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u msc_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_ecm_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u rndis_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cdc_ncm_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_VIDEO)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u video_ctrl_class_info")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u video_streaming_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u audio_ctrl_intf_class_info")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u audio_streaming_intf_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
|
||||
if(CONFIG_USBHOST_BLUETOOTH_HCI_H4)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bluetooth_h4_nrf_class_info")
|
||||
else()
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bluetooth_class_info")
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_ASIX)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u asix_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_RTL8152)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u rtl8152_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_FTDI)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ftdi_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CH34X)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ch34x_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CP210X)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cp210x_class_info")
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_PL2303)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u pl2303_class_info")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB)
|
||||
set_source_files_properties("class/audio/usbd_audio.c" PROPERTIES COMPILE_FLAGS -Wno-maybe-uninitialized)
|
||||
endif()
|
||||
elseif(ZEPHYR_BASE)
|
||||
message(STATUS "enable cherryusb in zephyr")
|
||||
|
||||
set(CONFIG_CHERRYUSB_OSAL "zephyr")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||
list(REMOVE_DUPLICATES cherryusb_srcs)
|
||||
list(REMOVE_DUPLICATES cherryusb_incs)
|
||||
|
||||
if (CONFIG_SHELL)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/platform/zephyr/usb_cmd.c)
|
||||
endif ()
|
||||
|
||||
zephyr_library()
|
||||
if(cherryusb_incs)
|
||||
zephyr_include_directories(${cherryusb_incs})
|
||||
endif()
|
||||
if(cherryusb_srcs)
|
||||
zephyr_library_sources(${cherryusb_srcs})
|
||||
endif()
|
||||
|
||||
if (CONFIG_CHERRYUSB_HOST)
|
||||
zephyr_linker_sources(SECTIONS zephyr/usbh_class_info.ld)
|
||||
endif()
|
||||
elseif(HPM_SDK_BASE)
|
||||
message(STATUS "enable cherryusb in hpm_sdk")
|
||||
|
||||
set(CONFIG_CHERRYUSB_DEVICE_CDC_ACM 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
|
||||
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)
|
||||
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_HID 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_MSC 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_CP210X 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_FTDI 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_PL2303 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_BL616 1)
|
||||
|
||||
set(CONFIG_CHERRYUSB_DEVICE_HPM 1)
|
||||
set(CONFIG_CHERRYUSB_HOST_EHCI_HPM 1)
|
||||
set(CONFIG_CHERRYUSB_OSAL "freertos")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake)
|
||||
list(REMOVE_DUPLICATES cherryusb_srcs)
|
||||
list(REMOVE_DUPLICATES cherryusb_incs)
|
||||
|
||||
sdk_inc(${cherryusb_incs})
|
||||
sdk_src(${cherryusb_srcs})
|
||||
endif()
|
||||
|
||||
if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
||||
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
|
||||
target_sources(cherryusb PRIVATE osal/usb_osal_freertos.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
|
||||
target_sources(cherryusb PRIVATE osal/usb_osal_rtthread.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "yoc")
|
||||
target_sources(cherryusb PRIVATE osal/usb_osal_yoc.c)
|
||||
endif()
|
||||
endif()
|
||||
3
CherryUSB.svg
Normal file
3
CherryUSB.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 38 KiB |
356
Kconfig
Normal file
356
Kconfig
Normal file
@@ -0,0 +1,356 @@
|
||||
# Kconfig file for CherryUSB
|
||||
menuconfig CHERRYUSB
|
||||
bool "CherryUSB Configuration"
|
||||
default n
|
||||
|
||||
if CHERRYUSB
|
||||
|
||||
menuconfig CHERRYUSB_DEVICE
|
||||
bool "Enable usb device mode"
|
||||
default n
|
||||
|
||||
if CHERRYUSB_DEVICE
|
||||
choice
|
||||
prompt "Select usb device speed"
|
||||
default CHERRYUSB_DEVICE_SPEED_FS
|
||||
config CHERRYUSB_DEVICE_SPEED_FS
|
||||
bool "FS"
|
||||
config CHERRYUSB_DEVICE_SPEED_HS
|
||||
bool "HS"
|
||||
config CHERRYUSB_DEVICE_SPEED_AUTO
|
||||
bool "AUTO"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Select usb device ip, and some ip need config in usb_config.h, please check"
|
||||
default CHERRYUSB_DEVICE_CUSTOM
|
||||
config CHERRYUSB_DEVICE_CUSTOM
|
||||
bool "CUSTOM (Implement it yourself)"
|
||||
config CHERRYUSB_DEVICE_FSDEV_ST
|
||||
bool "fsdev_st"
|
||||
config CHERRYUSB_DEVICE_FSDEV_CUSTOM
|
||||
bool "fsdev_custom"
|
||||
config CHERRYUSB_DEVICE_DWC2_ST
|
||||
bool "dwc2_st"
|
||||
config CHERRYUSB_DEVICE_DWC2_ESP
|
||||
bool "dwc2_esp"
|
||||
config CHERRYUSB_DEVICE_DWC2_KENDRYTE
|
||||
bool "dwc2_kendryte"
|
||||
config CHERRYUSB_DEVICE_DWC2_AT
|
||||
bool "dwc2_at"
|
||||
config CHERRYUSB_DEVICE_DWC2_HC
|
||||
bool "dwc2_hc"
|
||||
config CHERRYUSB_DEVICE_DWC2_NATION
|
||||
bool "dwc2_nation"
|
||||
config CHERRYUSB_DEVICE_DWC2_GD
|
||||
bool "dwc2_gd"
|
||||
config CHERRYUSB_DEVICE_DWC2_CUSTOM
|
||||
bool "dwc2_custom"
|
||||
config CHERRYUSB_DEVICE_MUSB_ES
|
||||
bool "musb_es"
|
||||
config CHERRYUSB_DEVICE_MUSB_SUNXI
|
||||
bool "musb_sunxi"
|
||||
config CHERRYUSB_DEVICE_MUSB_BK
|
||||
bool "musb_bk"
|
||||
config CHERRYUSB_DEVICE_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config CHERRYUSB_DEVICE_CHIPIDEA_MCX
|
||||
bool "chipidea_mcx"
|
||||
config CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
|
||||
bool "chipidea_custom"
|
||||
config CHERRYUSB_DEVICE_KINETIS_MCX
|
||||
bool "kinetis_mcx"
|
||||
config CHERRYUSB_DEVICE_KINETIS_MM32
|
||||
bool "kinetis_mm32"
|
||||
config CHERRYUSB_DEVICE_KINETIS_CUSTOM
|
||||
bool "kinetis_custom"
|
||||
config CHERRYUSB_DEVICE_BL
|
||||
bool "bouffalo"
|
||||
config CHERRYUSB_DEVICE_HPM
|
||||
bool "hpm"
|
||||
config CHERRYUSB_DEVICE_AIC
|
||||
bool "aic"
|
||||
config CHERRYUSB_DEVICE_RP2040
|
||||
bool "rp2040"
|
||||
config CHERRYUSB_DEVICE_CH32
|
||||
bool "ch32"
|
||||
config CHERRYUSB_DEVICE_PUSB2
|
||||
bool "pusb2"
|
||||
endchoice
|
||||
|
||||
config CHERRYUSB_DEVICE_CDC_ACM
|
||||
bool
|
||||
prompt "Enable usb cdc acm device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_HID
|
||||
bool
|
||||
prompt "Enable usb hid device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_MSC
|
||||
bool
|
||||
prompt "Enable usb msc device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_AUDIO
|
||||
bool
|
||||
prompt "Enable usb audio device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_VIDEO
|
||||
bool
|
||||
prompt "Enable usb video device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_CDC_RNDIS
|
||||
bool
|
||||
prompt "Enable usb cdc rndis device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_CDC_ECM
|
||||
bool
|
||||
prompt "Enable usb cdc ecm device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_DFU
|
||||
bool
|
||||
prompt "Enable usb dfu device"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_DEVICE_ADB
|
||||
bool
|
||||
prompt "Enable usb adb device"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Select usb device template"
|
||||
default CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||
bool "none (Implement it yourself)"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
|
||||
bool "cdc_acm"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_MSC
|
||||
bool "msc"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
|
||||
bool "hid_keyboard"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
|
||||
bool "hid_mouse"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
|
||||
bool "hid_custom"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_VIDEO
|
||||
bool "video"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
|
||||
bool "audio_v1_mic_speaker_multichan"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
|
||||
bool "audio_v2_mic_speaker_multichan"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
|
||||
bool "cdc_rndis"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
|
||||
bool "cdc_ecm"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
|
||||
bool "cdc_ncm"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
|
||||
bool "cdc_acm_msc"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
|
||||
bool "cdc_acm_msc_hid"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
|
||||
bool "winusbv1"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
|
||||
bool "winusbv2_cdc"
|
||||
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
|
||||
bool "winusbv2_hid"
|
||||
endchoice
|
||||
|
||||
endif
|
||||
|
||||
menuconfig CHERRYUSB_HOST
|
||||
bool "Enable usb host mode"
|
||||
default n
|
||||
|
||||
if CHERRYUSB_HOST
|
||||
choice
|
||||
prompt "Select usb host ip, and some ip need config in usb_config.h, please check"
|
||||
default CHERRYUSB_HOST_CUSTOM
|
||||
config CHERRYUSB_HOST_CUSTOM
|
||||
bool "CUSTOM (Implement it yourself)"
|
||||
config CHERRYUSB_HOST_EHCI_BL
|
||||
bool "ehci_bouffalo"
|
||||
config CHERRYUSB_HOST_EHCI_HPM
|
||||
bool "ehci_hpm"
|
||||
config CHERRYUSB_HOST_EHCI_AIC
|
||||
bool "ehci_aic"
|
||||
config CHERRYUSB_HOST_EHCI_MCX
|
||||
bool "ehci_mcx"
|
||||
config CHERRYUSB_HOST_EHCI_NUC980
|
||||
bool "ehci_nuc980"
|
||||
config CHERRYUSB_HOST_EHCI_MA35D0
|
||||
bool "ehci_ma35d0"
|
||||
config CHERRYUSB_HOST_EHCI_CUSTOM
|
||||
bool "ehci_custom"
|
||||
config CHERRYUSB_HOST_DWC2_ST
|
||||
bool "dwc2_st"
|
||||
config CHERRYUSB_HOST_DWC2_ESP
|
||||
bool "dwc2_esp"
|
||||
config CHERRYUSB_HOST_DWC2_KENDRYTE
|
||||
bool "dwc2_kendryte"
|
||||
config CHERRYUSB_HOST_DWC2_HC
|
||||
bool "dwc2_hc"
|
||||
config CHERRYUSB_HOST_DWC2_NATION
|
||||
bool "dwc2_nation"
|
||||
config CHERRYUSB_HOST_DWC2_CUSTOM
|
||||
bool "dwc2_custom"
|
||||
config CHERRYUSB_HOST_MUSB_ES
|
||||
bool "musb_es"
|
||||
config CHERRYUSB_HOST_MUSB_SUNXI
|
||||
bool "musb_sunxi"
|
||||
config CHERRYUSB_HOST_MUSB_BK
|
||||
bool "musb_bk"
|
||||
config CHERRYUSB_HOST_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config CHERRYUSB_HOST_PUSB2
|
||||
bool "pusb2"
|
||||
config CHERRYUSB_HOST_XHCI_PHYTIUM
|
||||
bool "xhci_phytium"
|
||||
config CHERRYUSB_HOST_XHCI_CUSTOM
|
||||
bool "xhci"
|
||||
config CHERRYUSB_HOST_KINETIS_MCX
|
||||
bool "kinetis_mcx"
|
||||
config CHERRYUSB_HOST_KINETIS_MM32
|
||||
bool "kinetis_mm32"
|
||||
config CHERRYUSB_HOST_KINETIS_CUSTOM
|
||||
bool "kinetis_custom"
|
||||
config CHERRYUSB_HOST_RP2040
|
||||
bool "rp2040"
|
||||
endchoice
|
||||
|
||||
config CHERRYUSB_HOST_CDC_ACM
|
||||
bool
|
||||
prompt "Enable usb cdc acm driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_HID
|
||||
bool
|
||||
prompt "Enable usb hid driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_MSC
|
||||
bool
|
||||
prompt "Enable usb msc driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_CDC_ECM
|
||||
bool
|
||||
prompt "Enable usb cdc ecm driver"
|
||||
select USBHOST_PLATFORM_CDC_ECM
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_CDC_RNDIS
|
||||
bool
|
||||
prompt "Enable usb rndis driver"
|
||||
select USBHOST_PLATFORM_CDC_RNDIS
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm driver"
|
||||
select USBHOST_PLATFORM_CDC_NCM
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_VIDEO
|
||||
bool
|
||||
prompt "Enable usb video driver, it is commercial charge"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_AUDIO
|
||||
bool
|
||||
prompt "Enable usb audio driver, it is commercial charge"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_BLUETOOTH
|
||||
bool
|
||||
prompt "Enable usb bluetooth driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_ASIX
|
||||
bool
|
||||
prompt "Enable usb asix driver"
|
||||
select USBHOST_PLATFORM_ASIX
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_RTL8152
|
||||
bool
|
||||
prompt "Enable usb rtl8152 driver"
|
||||
select USBHOST_PLATFORM_RTL8152
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_FTDI
|
||||
bool
|
||||
prompt "Enable usb ftdi driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_CH34X
|
||||
bool
|
||||
prompt "Enable usb ch34x driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_CP210X
|
||||
bool
|
||||
prompt "Enable usb cp210x driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_PL2303
|
||||
bool
|
||||
prompt "Enable usb pl2303 driver"
|
||||
default n
|
||||
|
||||
config CHERRYUSB_HOST_AOA
|
||||
bool
|
||||
prompt "Enable usb aoa driver"
|
||||
default n
|
||||
|
||||
config USBHOST_PLATFORM_CDC_ECM
|
||||
bool
|
||||
|
||||
config USBHOST_PLATFORM_CDC_RNDIS
|
||||
bool
|
||||
|
||||
config USBHOST_PLATFORM_CDC_NCM
|
||||
bool
|
||||
|
||||
config USBHOST_PLATFORM_ASIX
|
||||
bool
|
||||
|
||||
config USBHOST_PLATFORM_RTL8152
|
||||
bool
|
||||
|
||||
config CHERRYUSB_HOST_TEMPLATE
|
||||
bool
|
||||
prompt "Use usb host template"
|
||||
default n
|
||||
|
||||
if CHERRYUSB_HOST_TEMPLATE
|
||||
config TEST_USBH_CDC_ACM
|
||||
int
|
||||
prompt "demo for test cdc acm"
|
||||
default 0
|
||||
depends on CHERRYUSB_HOST_CDC_ACM
|
||||
config TEST_USBH_HID
|
||||
int
|
||||
prompt "demo for test hid"
|
||||
default 0
|
||||
depends on CHERRYUSB_HOST_HID
|
||||
config TEST_USBH_MSC
|
||||
int
|
||||
prompt "demo for test msc"
|
||||
default 0
|
||||
depends on CHERRYUSB_HOST_MSC
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
359
Kconfig.rtt
Normal file
359
Kconfig.rtt
Normal file
@@ -0,0 +1,359 @@
|
||||
# Kconfig file for package CherryUSB
|
||||
menuconfig RT_USING_CHERRYUSB
|
||||
bool "Using USB with CherryUSB"
|
||||
default n
|
||||
|
||||
if RT_USING_CHERRYUSB
|
||||
|
||||
menuconfig RT_CHERRYUSB_DEVICE
|
||||
bool "Enable usb device mode"
|
||||
default n
|
||||
|
||||
if RT_CHERRYUSB_DEVICE
|
||||
choice
|
||||
prompt "Select usb device speed"
|
||||
default RT_CHERRYUSB_DEVICE_SPEED_FS
|
||||
config RT_CHERRYUSB_DEVICE_SPEED_FS
|
||||
bool "FS"
|
||||
config RT_CHERRYUSB_DEVICE_SPEED_HS
|
||||
bool "HS"
|
||||
config RT_CHERRYUSB_DEVICE_SPEED_AUTO
|
||||
bool "AUTO"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Select usb device ip, and some ip need config in usb_config.h, please check"
|
||||
default RT_CHERRYUSB_DEVICE_CUSTOM
|
||||
config RT_CHERRYUSB_DEVICE_CUSTOM
|
||||
bool "CUSTOM (Implement it yourself)"
|
||||
config RT_CHERRYUSB_DEVICE_FSDEV_ST
|
||||
bool "fsdev_st"
|
||||
config RT_CHERRYUSB_DEVICE_FSDEV_CUSTOM
|
||||
bool "fsdev_custom"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_ST
|
||||
bool "dwc2_st"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_ESP
|
||||
bool "dwc2_esp"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE
|
||||
bool "dwc2_kendryte"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_AT
|
||||
bool "dwc2_at"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_HC
|
||||
bool "dwc2_hc"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_NATION
|
||||
bool "dwc2_nation"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_GD
|
||||
bool "dwc2_gd"
|
||||
config RT_CHERRYUSB_DEVICE_DWC2_CUSTOM
|
||||
bool "dwc2_custom"
|
||||
config RT_CHERRYUSB_DEVICE_MUSB_ES
|
||||
bool "musb_es"
|
||||
config RT_CHERRYUSB_DEVICE_MUSB_SUNXI
|
||||
bool "musb_sunxi"
|
||||
config RT_CHERRYUSB_DEVICE_MUSB_BK
|
||||
bool "musb_bk"
|
||||
config RT_CHERRYUSB_DEVICE_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX
|
||||
bool "chipidea_mcx"
|
||||
config RT_CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
|
||||
bool "chipidea_custom"
|
||||
config RT_CHERRYUSB_DEVICE_KINETIS_MCX
|
||||
bool "kinetis_mcx"
|
||||
config RT_CHERRYUSB_DEVICE_KINETIS_MM32
|
||||
bool "kinetis_mm32"
|
||||
config RT_CHERRYUSB_DEVICE_KINETIS_CUSTOM
|
||||
bool "kinetis_custom"
|
||||
config RT_CHERRYUSB_DEVICE_BL
|
||||
bool "bouffalo"
|
||||
config RT_CHERRYUSB_DEVICE_HPM
|
||||
bool "hpm"
|
||||
config RT_CHERRYUSB_DEVICE_AIC
|
||||
bool "aic"
|
||||
config RT_CHERRYUSB_DEVICE_RP2040
|
||||
bool "rp2040"
|
||||
config RT_CHERRYUSB_DEVICE_CH32
|
||||
bool "ch32"
|
||||
config RT_CHERRYUSB_DEVICE_PUSB2
|
||||
bool "pusb2"
|
||||
config RT_CHERRYUSB_DEVICE_NRF5X
|
||||
bool "nrf5x"
|
||||
endchoice
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_CDC_ACM
|
||||
bool
|
||||
prompt "Enable usb cdc acm device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_HID
|
||||
bool
|
||||
prompt "Enable usb hid device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_MSC
|
||||
bool
|
||||
prompt "Enable usb msc device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_AUDIO
|
||||
bool
|
||||
prompt "Enable usb audio device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_VIDEO
|
||||
bool
|
||||
prompt "Enable usb video device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_CDC_RNDIS
|
||||
bool
|
||||
prompt "Enable usb cdc rndis device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_CDC_ECM
|
||||
bool
|
||||
prompt "Enable usb cdc ecm device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm device"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_DEVICE_DFU
|
||||
bool
|
||||
prompt "Enable usb dfu device"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Select usb device template"
|
||||
default RT_CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||
bool "none (Implement it yourself)"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
|
||||
bool "cdc_acm"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
|
||||
bool "msc_ram"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
|
||||
bool "msc_blkdev"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
|
||||
bool "hid_keyboard"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
|
||||
bool "hid_mouse"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
|
||||
bool "hid_custom"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_VIDEO
|
||||
bool "video"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
|
||||
bool "audio_v1_mic_speaker_multichan"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
|
||||
bool "audio_v2_mic_speaker_multichan"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
|
||||
bool "cdc_rndis"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
|
||||
bool "cdc_ecm"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
|
||||
bool "cdc_ncm"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
|
||||
bool "cdc_acm_msc"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
|
||||
bool "cdc_acm_msc_hid"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
|
||||
bool "winusbv1"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
|
||||
bool "winusbv2_cdc"
|
||||
config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
|
||||
bool "winusbv2_hid"
|
||||
endchoice
|
||||
|
||||
config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
|
||||
string "usb device msc block device name"
|
||||
depends on RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
|
||||
default "sd0"
|
||||
|
||||
endif
|
||||
|
||||
menuconfig RT_CHERRYUSB_HOST
|
||||
bool "Enable usb host mode"
|
||||
default n
|
||||
|
||||
if RT_CHERRYUSB_HOST
|
||||
choice
|
||||
prompt "Select usb host ip, and some ip need config in usb_config.h, please check"
|
||||
default RT_CHERRYUSB_HOST_CUSTOM
|
||||
config RT_CHERRYUSB_HOST_CUSTOM
|
||||
bool "CUSTOM (Implement it yourself)"
|
||||
config RT_CHERRYUSB_HOST_EHCI_BL
|
||||
bool "ehci_bouffalo"
|
||||
config RT_CHERRYUSB_HOST_EHCI_HPM
|
||||
bool "ehci_hpm"
|
||||
config RT_CHERRYUSB_HOST_EHCI_AIC
|
||||
bool "ehci_aic"
|
||||
config RT_CHERRYUSB_HOST_EHCI_MCX
|
||||
bool "ehci_mcx"
|
||||
config RT_CHERRYUSB_HOST_EHCI_NUC980
|
||||
bool "ehci_nuc980"
|
||||
config RT_CHERRYUSB_HOST_EHCI_MA35D0
|
||||
bool "ehci_ma35d0"
|
||||
config RT_CHERRYUSB_HOST_EHCI_CUSTOM
|
||||
bool "ehci_custom"
|
||||
config RT_CHERRYUSB_HOST_DWC2_ST
|
||||
bool "dwc2_st"
|
||||
config RT_CHERRYUSB_HOST_DWC2_ESP
|
||||
bool "dwc2_esp"
|
||||
config RT_CHERRYUSB_HOST_DWC2_KENDRYTE
|
||||
bool "dwc2_kendryte"
|
||||
config RT_CHERRYUSB_HOST_DWC2_HC
|
||||
bool "dwc2_hc"
|
||||
config RT_CHERRYUSB_HOST_DWC2_NATION
|
||||
bool "dwc2_nation"
|
||||
config RT_CHERRYUSB_HOST_DWC2_CUSTOM
|
||||
bool "dwc2_custom"
|
||||
config RT_CHERRYUSB_HOST_MUSB_ES
|
||||
bool "musb_es"
|
||||
config RT_CHERRYUSB_HOST_MUSB_SUNXI
|
||||
bool "musb_sunxi"
|
||||
config RT_CHERRYUSB_HOST_MUSB_BK
|
||||
bool "musb_bk"
|
||||
config RT_CHERRYUSB_HOST_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config RT_CHERRYUSB_HOST_PUSB2
|
||||
bool "pusb2"
|
||||
config RT_CHERRYUSB_HOST_XHCI
|
||||
bool "xhci"
|
||||
config RT_CHERRYUSB_HOST_RP2040
|
||||
bool "rp2040"
|
||||
endchoice
|
||||
|
||||
config RT_CHERRYUSB_HOST_CDC_ACM
|
||||
bool
|
||||
prompt "Enable usb cdc acm driver"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_HID
|
||||
bool
|
||||
prompt "Enable usb hid driver"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_MSC
|
||||
bool
|
||||
prompt "Enable usb msc driver"
|
||||
default n
|
||||
select RT_USING_DFS
|
||||
select RT_USING_DFS_ELMFAT
|
||||
|
||||
config RT_CHERRYUSB_HOST_CDC_ECM
|
||||
bool
|
||||
prompt "Enable usb cdc ecm driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_CDC_ECM
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_CDC_RNDIS
|
||||
bool
|
||||
prompt "Enable usb rndis driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_CDC_RNDIS
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_CDC_NCM
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_VIDEO
|
||||
bool
|
||||
prompt "Enable usb video driver, it is commercial charge"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_AUDIO
|
||||
bool
|
||||
prompt "Enable usb audio driver, it is commercial charge"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_BLUETOOTH
|
||||
bool
|
||||
prompt "Enable usb bluetooth driver"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_ASIX
|
||||
bool
|
||||
prompt "Enable usb asix driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_ASIX
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_RTL8152
|
||||
bool
|
||||
prompt "Enable usb rtl8152 driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_RTL8152
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_FTDI
|
||||
bool
|
||||
prompt "Enable usb ftdi driver"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_CH34X
|
||||
bool
|
||||
prompt "Enable usb ch34x driver"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_CP210X
|
||||
bool
|
||||
prompt "Enable usb cp210x driver"
|
||||
default n
|
||||
|
||||
config RT_CHERRYUSB_HOST_PL2303
|
||||
bool
|
||||
prompt "Enable usb pl2303 driver"
|
||||
default n
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_CDC_ECM
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_CDC_RNDIS
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_CDC_NCM
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_ASIX
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_RTL8152
|
||||
bool
|
||||
|
||||
config RT_LWIP_PBUF_POOL_BUFSIZE
|
||||
int "The size of each pbuf in the pbuf pool"
|
||||
range 1500 2000
|
||||
default 1600
|
||||
|
||||
config CONFIG_USB_DFS_MOUNT_POINT
|
||||
string "usb host dfs mount point"
|
||||
depends on RT_CHERRYUSB_HOST_MSC
|
||||
default "/"
|
||||
|
||||
config RT_CHERRYUSB_HOST_TEMPLATE
|
||||
bool
|
||||
prompt "Use usb host template"
|
||||
default n
|
||||
|
||||
if RT_CHERRYUSB_HOST_TEMPLATE
|
||||
config TEST_USBH_CDC_ACM
|
||||
int
|
||||
prompt "demo for test cdc acm"
|
||||
default 0
|
||||
depends on CHERRYUSB_HOST_CDC_ACM
|
||||
config TEST_USBH_HID
|
||||
int
|
||||
prompt "demo for test hid"
|
||||
default 0
|
||||
depends on CHERRYUSB_HOST_HID
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
399
Kconfig.rttpkg
Normal file
399
Kconfig.rttpkg
Normal file
@@ -0,0 +1,399 @@
|
||||
# Kconfig file for package CherryUSB
|
||||
menuconfig PKG_USING_CHERRYUSB
|
||||
depends on RT_VER_NUM < 0x50200
|
||||
bool "CherryUSB: tiny and portable USB host/device stack for embedded system with USB IP"
|
||||
default n
|
||||
|
||||
if PKG_USING_CHERRYUSB
|
||||
|
||||
menuconfig PKG_CHERRYUSB_DEVICE
|
||||
bool "Enable usb device mode"
|
||||
default n
|
||||
|
||||
if PKG_CHERRYUSB_DEVICE
|
||||
choice
|
||||
prompt "Select usb device speed"
|
||||
default PKG_CHERRYUSB_DEVICE_SPEED_FS
|
||||
config PKG_CHERRYUSB_DEVICE_SPEED_FS
|
||||
bool "FS"
|
||||
config PKG_CHERRYUSB_DEVICE_SPEED_HS
|
||||
bool "HS"
|
||||
config PKG_CHERRYUSB_DEVICE_SPEED_AUTO
|
||||
bool "AUTO"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Select usb device ip, and some ip need config in usb_config.h, please check"
|
||||
default PKG_CHERRYUSB_DEVICE_CUSTOM
|
||||
config PKG_CHERRYUSB_DEVICE_CUSTOM
|
||||
bool "CUSTOM (Implement it yourself)"
|
||||
config PKG_CHERRYUSB_DEVICE_FSDEV_ST
|
||||
bool "fsdev_st"
|
||||
config PKG_CHERRYUSB_DEVICE_FSDEV_CUSTOM
|
||||
bool "fsdev_custom"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_ST
|
||||
bool "dwc2_st"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_ESP
|
||||
bool "dwc2_esp"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_KENDRYTE
|
||||
bool "dwc2_kendryte"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_AT
|
||||
bool "dwc2_at"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_HC
|
||||
bool "dwc2_hc"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_NATION
|
||||
bool "dwc2_nation"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_GD
|
||||
bool "dwc2_gd"
|
||||
config PKG_CHERRYUSB_DEVICE_DWC2_CUSTOM
|
||||
bool "dwc2_custom"
|
||||
config PKG_CHERRYUSB_DEVICE_MUSB_ES
|
||||
bool "musb_es"
|
||||
config PKG_CHERRYUSB_DEVICE_MUSB_SUNXI
|
||||
bool "musb_sunxi"
|
||||
config PKG_CHERRYUSB_DEVICE_MUSB_BK
|
||||
bool "musb_bk"
|
||||
config PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX
|
||||
bool "chipidea_mcx"
|
||||
config PKG_CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM
|
||||
bool "chipidea_custom"
|
||||
config PKG_CHERRYUSB_DEVICE_KINETIS_MCX
|
||||
bool "kinetis_mcx"
|
||||
config PKG_CHERRYUSB_DEVICE_KINETIS_MM32
|
||||
bool "kinetis_mm32"
|
||||
config PKG_CHERRYUSB_DEVICE_KINETIS_CUSTOM
|
||||
bool "kinetis_custom"
|
||||
config PKG_CHERRYUSB_DEVICE_BL
|
||||
bool "bouffalo"
|
||||
config PKG_CHERRYUSB_DEVICE_HPM
|
||||
bool "hpm"
|
||||
config PKG_CHERRYUSB_DEVICE_AIC
|
||||
bool "aic"
|
||||
config PKG_CHERRYUSB_DEVICE_RP2040
|
||||
bool "rp2040"
|
||||
config PKG_CHERRYUSB_DEVICE_CH32
|
||||
bool "ch32"
|
||||
config PKG_CHERRYUSB_DEVICE_PUSB2
|
||||
bool "pusb2"
|
||||
endchoice
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_CDC_ACM
|
||||
bool
|
||||
prompt "Enable usb cdc acm device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_HID
|
||||
bool
|
||||
prompt "Enable usb hid device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_MSC
|
||||
bool
|
||||
prompt "Enable usb msc device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_AUDIO
|
||||
bool
|
||||
prompt "Enable usb audio device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_VIDEO
|
||||
bool
|
||||
prompt "Enable usb video device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_CDC_RNDIS
|
||||
bool
|
||||
prompt "Enable usb cdc rndis device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_CDC_ECM
|
||||
bool
|
||||
prompt "Enable usb cdc ecm device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm device"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_DEVICE_DFU
|
||||
bool
|
||||
prompt "Enable usb dfu device"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Select usb device template"
|
||||
default PKG_CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_NONE
|
||||
bool "none (Implement it yourself)"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
|
||||
bool "cdc_acm"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC
|
||||
bool "msc_ram"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
|
||||
bool "msc_blkdev"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
|
||||
bool "hid_keyboard"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
|
||||
bool "hid_mouse"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
|
||||
bool "hid_custom"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_VIDEO
|
||||
bool "video"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
|
||||
bool "audio_v1_mic_speaker_multichan"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
|
||||
bool "audio_v2_mic_speaker_multichan"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
|
||||
bool "cdc_rndis"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
|
||||
bool "cdc_ecm"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
|
||||
bool "cdc_ncm"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
|
||||
bool "cdc_acm_msc"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
|
||||
bool "cdc_acm_msc_hid"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
|
||||
bool "winusbv1"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
|
||||
bool "winusbv2_cdc"
|
||||
config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
|
||||
bool "winusbv2_hid"
|
||||
endchoice
|
||||
|
||||
config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
|
||||
string "usb device msc block device name"
|
||||
depends on PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
|
||||
default "sd0"
|
||||
|
||||
endif
|
||||
|
||||
menuconfig PKG_CHERRYUSB_HOST
|
||||
bool "Enable usb host mode"
|
||||
default n
|
||||
|
||||
if PKG_CHERRYUSB_HOST
|
||||
choice
|
||||
prompt "Select usb host ip, and some ip need config in usb_config.h, please check"
|
||||
default PKG_CHERRYUSB_HOST_CUSTOM
|
||||
config PKG_CHERRYUSB_HOST_CUSTOM
|
||||
bool "CUSTOM (Implement it yourself)"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_BL
|
||||
bool "ehci_bouffalo"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_HPM
|
||||
bool "ehci_hpm"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_AIC
|
||||
bool "ehci_aic"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_MCX
|
||||
bool "ehci_mcx"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_NUC980
|
||||
bool "ehci_nuc980"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_MA35D0
|
||||
bool "ehci_ma35d0"
|
||||
config PKG_CHERRYUSB_HOST_EHCI_CUSTOM
|
||||
bool "ehci_custom"
|
||||
config PKG_CHERRYUSB_HOST_DWC2_ST
|
||||
bool "dwc2_st"
|
||||
config PKG_CHERRYUSB_HOST_DWC2_ESP
|
||||
bool "dwc2_esp"
|
||||
config PKG_CHERRYUSB_HOST_DWC2_KENDRYTE
|
||||
bool "dwc2_kendryte"
|
||||
config PKG_CHERRYUSB_HOST_DWC2_HC
|
||||
bool "dwc2_hc"
|
||||
config PKG_CHERRYUSB_HOST_DWC2_NATION
|
||||
bool "dwc2_nation"
|
||||
config PKG_CHERRYUSB_HOST_DWC2_CUSTOM
|
||||
bool "dwc2_custom"
|
||||
config PKG_CHERRYUSB_HOST_MUSB_ES
|
||||
bool "musb_es"
|
||||
config PKG_CHERRYUSB_HOST_MUSB_SUNXI
|
||||
bool "musb_sunxi"
|
||||
config PKG_CHERRYUSB_HOST_MUSB_BK
|
||||
bool "musb_bk"
|
||||
config PKG_CHERRYUSB_HOST_MUSB_CUSTOM
|
||||
bool "musb_custom"
|
||||
config PKG_CHERRYUSB_HOST_PUSB2
|
||||
bool "pusb2"
|
||||
config PKG_CHERRYUSB_HOST_XHCI
|
||||
bool "xhci"
|
||||
config PKG_CHERRYUSB_HOST_RP2040
|
||||
bool "rp2040"
|
||||
endchoice
|
||||
|
||||
config PKG_CHERRYUSB_HOST_CDC_ACM
|
||||
bool
|
||||
prompt "Enable usb cdc acm driver"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_HID
|
||||
bool
|
||||
prompt "Enable usb hid driver"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_MSC
|
||||
bool
|
||||
prompt "Enable usb msc driver"
|
||||
default n
|
||||
select RT_USING_DFS
|
||||
select RT_USING_DFS_ELMFAT
|
||||
|
||||
config PKG_CHERRYUSB_HOST_CDC_ECM
|
||||
bool
|
||||
prompt "Enable usb cdc ecm driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_CDC_ECM
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_CDC_RNDIS
|
||||
bool
|
||||
prompt "Enable usb rndis driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_CDC_RNDIS
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_CDC_NCM
|
||||
bool
|
||||
prompt "Enable usb cdc ncm driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_CDC_NCM
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_VIDEO
|
||||
bool
|
||||
prompt "Enable usb video driver, it is commercial charge"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_AUDIO
|
||||
bool
|
||||
prompt "Enable usb audio driver, it is commercial charge"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_BLUETOOTH
|
||||
bool
|
||||
prompt "Enable usb bluetooth driver"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_ASIX
|
||||
bool
|
||||
prompt "Enable usb asix driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_ASIX
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_RTL8152
|
||||
bool
|
||||
prompt "Enable usb rtl8152 driver"
|
||||
select RT_USING_LWIP
|
||||
select CONFIG_USBHOST_PLATFORM_RTL8152
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_FTDI
|
||||
bool
|
||||
prompt "Enable usb ftdi driver"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_CH34X
|
||||
bool
|
||||
prompt "Enable usb ch34x driver"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_CP210X
|
||||
bool
|
||||
prompt "Enable usb cp210x driver"
|
||||
default n
|
||||
|
||||
config PKG_CHERRYUSB_HOST_PL2303
|
||||
bool
|
||||
prompt "Enable usb pl2303 driver"
|
||||
default n
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_CDC_ECM
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_CDC_RNDIS
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_CDC_NCM
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_ASIX
|
||||
bool
|
||||
|
||||
config CONFIG_USBHOST_PLATFORM_RTL8152
|
||||
bool
|
||||
|
||||
config RT_LWIP_PBUF_POOL_BUFSIZE
|
||||
int "The size of each pbuf in the pbuf pool"
|
||||
range 1500 2000
|
||||
default 1600
|
||||
|
||||
config CONFIG_USB_DFS_MOUNT_POINT
|
||||
string "usb host dfs mount point"
|
||||
depends on RT_CHERRYUSB_HOST_MSC
|
||||
default "/"
|
||||
|
||||
config PKG_CHERRYUSB_HOST_TEMPLATE
|
||||
bool
|
||||
prompt "Use usb host template"
|
||||
default n
|
||||
|
||||
if PKG_CHERRYUSB_HOST_TEMPLATE
|
||||
config TEST_USBH_CDC_ACM
|
||||
int
|
||||
prompt "demo for test cdc acm"
|
||||
default 0
|
||||
depends on PKG_CHERRYUSB_HOST_CDC_ACM
|
||||
config TEST_USBH_HID
|
||||
int
|
||||
prompt "demo for test hid"
|
||||
default 0
|
||||
depends on PKG_CHERRYUSB_HOST_HID
|
||||
endif
|
||||
endif
|
||||
|
||||
config PKG_CHERRYUSB_PATH
|
||||
string
|
||||
default "/packages/system/CherryUSB"
|
||||
|
||||
choice
|
||||
prompt "Version"
|
||||
default PKG_USING_CHERRYUSB_V010500
|
||||
help
|
||||
Select the package version
|
||||
|
||||
config PKG_USING_CHERRYUSB_LATEST_VERSION
|
||||
bool "latest"
|
||||
config PKG_USING_CHERRYUSB_V010500
|
||||
bool "v1.5.0"
|
||||
config PKG_USING_CHERRYUSB_V010403
|
||||
bool "v1.4.3"
|
||||
config PKG_USING_CHERRYUSB_V010402
|
||||
bool "v1.4.2"
|
||||
config PKG_USING_CHERRYUSB_V010400
|
||||
bool "v1.4.0"
|
||||
config PKG_USING_CHERRYUSB_V010301
|
||||
bool "v1.3.1"
|
||||
config PKG_USING_CHERRYUSB_V010300
|
||||
bool "v1.3.0"
|
||||
config PKG_USING_CHERRYUSB_V010200
|
||||
bool "v1.2.0"
|
||||
config PKG_USING_CHERRYUSB_V001002
|
||||
bool "v0.10.2"
|
||||
endchoice
|
||||
|
||||
config PKG_CHERRYUSB_VER
|
||||
string
|
||||
default "latest" if PKG_USING_CHERRYUSB_LATEST_VERSION
|
||||
default "v1.5.0" if PKG_USING_CHERRYUSB_V010500
|
||||
default "v1.4.3" if PKG_USING_CHERRYUSB_V010403
|
||||
default "v1.4.2" if PKG_USING_CHERRYUSB_V010402
|
||||
default "v1.4.0" if PKG_USING_CHERRYUSB_V010400
|
||||
default "v1.3.1" if PKG_USING_CHERRYUSB_V010301
|
||||
default "v1.3.0" if PKG_USING_CHERRYUSB_V010300
|
||||
default "v1.2.0" if PKG_USING_CHERRYUSB_V010200
|
||||
default "v0.10.2" if PKG_USING_CHERRYUSB_V001002
|
||||
endif
|
||||
179
README.md
179
README.md
@@ -1,12 +1,18 @@
|
||||
# CherryUSB
|
||||
**English | [简体中文](README_zh.md)**
|
||||
|
||||
[中文版](./README_zh.md)
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
|
||||
<p align="center">
|
||||
<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"></a>
|
||||
<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
|
||||
<a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
|
||||
<a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
|
||||
</p>
|
||||
|
||||
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP.
|
||||
CherryUSB is a tiny and beautiful, high performance and portable USB host and device stack for embedded system with USB IP.
|
||||
|
||||

|
||||

|
||||
|
||||
## Why choose
|
||||
## Why choose CherryUSB
|
||||
|
||||
### Easy to study USB
|
||||
|
||||
@@ -17,12 +23,12 @@ In order to make it easier for users to learn USB basics, enumeration, driver lo
|
||||
- Class-drivers and porting-drivers are templating and simplification
|
||||
- Clear API classification (slave: initialisation, registration api, command callback api, data sending and receiving api; host: initialisation, lookup api, data sending and receiving api)
|
||||
|
||||
### Easy to use USB
|
||||
### Easy to use USB
|
||||
|
||||
In order to facilitate the use of the USB interface and to take into account the fact that users have learned about uart and dma, the following advantages have been designed for the data sending and receiving class of interface:
|
||||
|
||||
- Equivalent to using uart tx dma/uart rx dma
|
||||
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does the packetization process)
|
||||
- There is no limit to the length of send and receive, the user does not need to care about the USB packetization process (the porting driver does it)
|
||||
|
||||
### Easy to bring out USB performance
|
||||
|
||||
@@ -32,31 +38,18 @@ Taking into account USB performance issues and trying to achieve the theoretical
|
||||
- Memory zero copy
|
||||
- If IP has DMA then uses DMA mode (DMA with hardware packetization)
|
||||
- Unlimited length make it easier to interface with hardware DMA and take advantage of DMA
|
||||
- Subcontracting function is handled in interrupt
|
||||
- Packetization is handled in interrupt
|
||||
|
||||
## Directoy Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── class
|
||||
├── common
|
||||
├── core
|
||||
├── demo
|
||||
├── docs
|
||||
├── osal
|
||||
├── packet capture
|
||||
└── port
|
||||
└── tools
|
||||
|
||||
```
|
||||
## Directory Structure
|
||||
|
||||
| Directory | Description |
|
||||
|:-------------:|:---------------------------:|
|
||||
|class | usb class driver |
|
||||
|common | usb spec macros and utils |
|
||||
|core | usb core implementation |
|
||||
|demo | different chips demo |
|
||||
|demo | usb device and host demo |
|
||||
|osal | os wrapper |
|
||||
|platform | class support for other os |
|
||||
|docs | doc for guiding |
|
||||
|port | usb dcd and hcd porting |
|
||||
|tools | tool url |
|
||||
@@ -65,53 +58,58 @@ Taking into account USB performance issues and trying to achieve the theoretical
|
||||
|
||||
CherryUSB Device Stack provides a unified framework of functions for standard device requests, CLASS requests, VENDOR requests and custom special requests. The object-oriented and chained approach allows the user to quickly get started with composite devices without having to worry about the underlying logic. At the same time, a standard dcd porting interface has been standardised for adapting different USB IPs to achieve ip-oriented programming.
|
||||
|
||||
CherryUSB Device Stack has the following functions:
|
||||
CherryUSB Device Stack has the following functions:
|
||||
|
||||
- Support USB2.0 full and high speed, USB3.0 super speed
|
||||
- Support USB2.0 full and high speed(USB3.0 super speed TODO)
|
||||
- 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_ACM, CDC_ECM)
|
||||
- Support Human Interface Device (HID)
|
||||
- Support Mass Storage Class (MSC)
|
||||
- Support USB VIDEO CLASS (UVC1.0、UVC1.5)
|
||||
- Support USB AUDIO CLASS (UAC1.0、UAC2.0)
|
||||
- Support USB VIDEO CLASS (UVC1.0, UVC1.5)
|
||||
- Support USB AUDIO CLASS (UAC1.0, UAC2.0)
|
||||
- Support Device Firmware Upgrade CLASS (DFU)
|
||||
- Support USB MIDI CLASS (MIDI)
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- Support WINUSB1.0、WINUSB2.0(with BOS)
|
||||
- Support WINUSB1.0, WINUSB2.0, WEBUSB, BOS
|
||||
- Support Vendor class
|
||||
- Support UF2
|
||||
- Support Android Debug Bridge (Only support shell)
|
||||
- Support multi device with the same USB IP
|
||||
|
||||
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|
||||
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|
||||
|usbd_video.c | 2494 | 0 | 84 | 0 |
|
||||
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
|
||||
|usbd_core.c | ~6000 | (512(default) + 320) * bus | 0 | 0 |
|
||||
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | ~3800 | (128 + 512(default)) * bus | 16 * bus | 0 |
|
||||
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|
||||
|usbd_video.c | ~3700 | 0 | 132 * bus | 0 |
|
||||
|usbd_rndis.c | ~4000 | 2 * 1580(default)+156+8 | 80 | 0 |
|
||||
|
||||
## Host Stack Overview
|
||||
|
||||
The CherryUSB Host Stack has a standard enumeration implementation for devices mounted on roothubs and external hubs, and a standard interface for different Classes to indicate what the Class driver needs to do after enumeration and after disconnection. A standard hcd porting interface has also been standardised for adapting different USB IPs for IP-oriented programming. Finally, the host stack is managed using os, and provides osal to make a adaptation for different os.
|
||||
The CherryUSB Host Stack has a standard enumeration implementation for devices mounted on root hubs and external hubs, and a standard interface for different Classes to indicate what the Class driver needs to do after enumeration and after disconnection. A standard hcd porting interface has also been standardised for adapting different USB IPs for IP-oriented programming. Finally, the host stack is managed using os, and provides osal to make a adaptation for different os.
|
||||
|
||||
CherryUSB Host Stack has the following functions:
|
||||
CherryUSB Host Stack has the following functions:
|
||||
|
||||
- Support low speed, full speed, high speed and super speed devices
|
||||
- Automatic loading of supported Class drivers
|
||||
- Support blocking transfers and asynchronous transfers
|
||||
- Support Composite Device
|
||||
- Multi-level HUB support, expandable up to 7 levels
|
||||
- Multi-level HUB support, expandable up to 7 levels(Testing hub with 10 ports works well,only support dwc2/ehci/xhci/rp2040)
|
||||
- Support Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- Support Human Interface Device (HID)
|
||||
- Support Mass Storage Class (MSC)
|
||||
- Support USB Video CLASS
|
||||
- Support USB Audio CLASS
|
||||
- Support USB Video CLASS (UVC1.0, UVC1.5)
|
||||
- Support USB Audio CLASS (UAC1.0)
|
||||
- Support Remote NDIS (RNDIS)
|
||||
- Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm)
|
||||
- Support Vendor class
|
||||
- Support Vendor class (serial, net, wifi)
|
||||
- Support USB modeswitch
|
||||
- Support Android Open Accessory
|
||||
- Support multi host with the same USB IP
|
||||
|
||||
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
|
||||
@@ -120,18 +118,19 @@ CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|
||||
|usbh_core.c | ~10000(enable lsusb)/ ~7500(disable lsusb) | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus | raw_config_desc |
|
||||
|usbh_hub.c | ~6000 | (32 + 4 * (1+x)) * bus | 12 + sizeof(struct usbh_hub) * x | 0 |
|
||||
|usbh_cdc_acm.c | ~900 | 7 * x | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~3400 | 128 * x | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1400 | 64 * x | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~5700 | 128 * x | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~8400 | 128 * x | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~5200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|usbh_cdc_ncm.c | ~3500 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|
||||
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|
||||
|
||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
@@ -141,7 +140,7 @@ Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affe
|
||||
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
|
||||
```
|
||||
|
||||
x is affected by the following macros:
|
||||
x is affected by the following macros:
|
||||
|
||||
```
|
||||
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
|
||||
@@ -151,34 +150,76 @@ x is affected by the following macros:
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
```
|
||||
|
||||
## USB IP Support
|
||||
|
||||
Only standard and commercial USB IP are listed.
|
||||
|
||||
| IP | device | host | Support status |
|
||||
|:----------------:|:----------:|:--------:|:--------------:|
|
||||
| OHCI(intel) | none | OHCI | √ |
|
||||
| EHCI(intel) | none | EHCI | √ |
|
||||
| XHCI(intel) | none | XHCI | √ |
|
||||
| UHCI(intel) | none | UHCI | × |
|
||||
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
|
||||
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||
| DWC3(synopsys) | DWC3 | XHCI | × |
|
||||
|
||||
## Documentation Tutorial
|
||||
|
||||
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
|
||||
Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/).
|
||||
|
||||
## Video Tutorial
|
||||
|
||||
USB basic concepts and how the CherryUSB Device stack is implemented, see [CherryUSB Device Stack Tutorial](https://www.bilibili.com/video/BV1Ef4y1t73d).
|
||||
CherryUSB Cheese (based V1.4.3): https://www.bilibili.com/cheese/play/ss707687201 .
|
||||
|
||||
## Graphical Config Tool
|
||||
## Descriptor Generator Tool
|
||||
|
||||
[chryusb_configurator](https://github.com/Egahp/chryusb_configurator) is written in **electron + vite2 + ts** framework,currently used to automate the generation of descriptor arrays, with additional functionality to be added later.
|
||||
TODO
|
||||
|
||||
## Demo Repo
|
||||
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|ST | STM32F1x/STM32F4/STM32H7 | fsdev/dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|
||||
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|
||||
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|
||||
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Long-term |
|
||||
|Actionstech | ATS30xx | dwc2 |[action_zephyr_repo](https://github.com/CherryUSB/lv_port_actions_technology/tree/master/action_technology_sdk)|>=1.4.0 | Long-term |
|
||||
|Nationstech | n32h4x | dwc2 |[nation_repo](https://github.com/CherryUSB/cherryusb_nation)|>=1.5.0 | Long-term |
|
||||
|Raspberry pi | rp2040/rp2350 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|
||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|
||||
## Package Support
|
||||
|
||||
CherryUSB package is available as follows:
|
||||
|
||||
- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
|
||||
- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
|
||||
- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
|
||||
|
||||
## Commercial Support
|
||||
|
||||
Refer to https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html.
|
||||
|
||||
## Contact
|
||||
|
||||
QQ group: 642693751
|
||||
CherryUSB discord: https://discord.com/invite/wFfvrSAey8.
|
||||
|
||||
## Company Support
|
||||
|
||||
Thanks to the following companies for their support (in no particular order):
|
||||
|
||||
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" /> <img src="docs/assets/canaan.jpg" width="100" height="80" />
|
||||
<img src="docs/assets/actions.jpg" width="100" height="80" /> <img src="docs/assets/nationstech.jpg" width="100" height="80" />
|
||||
|
||||
165
README_zh.md
165
README_zh.md
@@ -1,12 +1,18 @@
|
||||
# CherryUSB
|
||||
**[English](README.md) | 简体中文**
|
||||
|
||||
[English](./README.md)
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">CherryUSB</h1>
|
||||
<p align="center">
|
||||
<a href="https://github.com/cherry-embedded/CherryUSB/releases"><img src="https://img.shields.io/github/release/cherry-embedded/CherryUSB.svg"></a>
|
||||
<a href="https://github.com/cherry-embedded/CherryUSB/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cherry-embedded/CherryUSB.svg?style=flat-square"></a>
|
||||
<a href="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml"><img src="https://github.com/cherry-embedded/CherryUSB/actions/workflows/deploy-docs.yml/badge.svg"> </a>
|
||||
<a href="https://discord.com/invite/wFfvrSAey8"><img src="https://img.shields.io/badge/Discord-blue?logo=discord&style=flat-square"> </a>
|
||||
</p>
|
||||
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。
|
||||
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的高性能 USB 主从协议栈。
|
||||
|
||||

|
||||

|
||||
|
||||
## 为什么选择
|
||||
## 为什么选择 CherryUSB
|
||||
|
||||
### 易于学习 USB
|
||||
|
||||
@@ -22,7 +28,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
|
||||
为了方便用户使用 USB 接口,考虑到用户学习过 uart 和 dma,因此,设计的数据收发类接口具备以下优点:
|
||||
|
||||
- 等价于使用 uart tx dma/uart rx dma
|
||||
- 收发长度没有限制,用户不需要关心 USB 分包过程(porting 驱动做分包过程)
|
||||
- 收发长度没有限制,用户不需要关心 USB 分包过程(分包过程在 porting 中处理)
|
||||
|
||||
### 易于发挥 USB 性能
|
||||
|
||||
@@ -32,30 +38,19 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
|
||||
- Memory zero copy
|
||||
- IP 如果带 DMA 则使用 DMA 模式(DMA 带硬件分包功能)
|
||||
- 长度无限制,方便对接硬件 DMA 并且发挥 DMA 的优势
|
||||
- 分包功能在中断中处理
|
||||
- 分包过程在中断中执行
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
.
|
||||
├── class
|
||||
├── common
|
||||
├── core
|
||||
├── demo
|
||||
├── docs
|
||||
├── osal
|
||||
└── port
|
||||
└── tools
|
||||
```
|
||||
|
||||
| 目录名 | 描述 |
|
||||
|:-------------:|:-------------------------------:|
|
||||
|class | usb class 类主从驱动 |
|
||||
|common | usb spec 定义、常用宏、标准接口定义 |
|
||||
|core | usb 主从协议栈核心实现 |
|
||||
|demo | 示例 |
|
||||
|demo | 主从 class demo |
|
||||
|docs | 文档 |
|
||||
|osal | os 封装层 |
|
||||
|platform | 其他 os 全家桶适配 |
|
||||
|port | usb 主从需要实现的 porting 接口 |
|
||||
|tools | 工具链接 |
|
||||
|
||||
@@ -65,7 +60,7 @@ CherryUSB Device 协议栈对标准设备请求、CLASS 请求、VENDOR 请求
|
||||
|
||||
CherryUSB Device 协议栈当前实现以下功能:
|
||||
|
||||
- 支持 USB2.0 全速和高速设备,USB3.0 超速设备
|
||||
- 支持 USB2.0 全速和高速设备(USB3.0 超高速 TODO)
|
||||
- 支持端点中断注册功能,porting 给用户自己处理中断里的数据
|
||||
- 支持复合设备
|
||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
@@ -76,40 +71,45 @@ CherryUSB Device 协议栈当前实现以下功能:
|
||||
- 支持 Device Firmware Upgrade CLASS (DFU)
|
||||
- 支持 USB MIDI CLASS (MIDI)
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
|
||||
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 UF2
|
||||
- 支持 Android Debug Bridge (Only support shell)
|
||||
- 支持相同 USB IP 的多从机
|
||||
|
||||
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|
||||
|usbd_core.c | 3516 | 256(default) + 320 | 0 | 0 |
|
||||
|usbd_cdc.c | 392 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | 2839 | 128 + 512(default) | 16 | 0 |
|
||||
|usbd_hid.c | 364 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | 1455 | 0 | 0 | 0 |
|
||||
|usbd_video.c | 2494 | 0 | 84 | 0 |
|
||||
|usbd_rndis.c | 2109 | 3340 | 76 | 0 |
|
||||
|usbd_core.c | ~6000 | (512(default) + 320) * bus | 0 | 0 |
|
||||
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|
||||
|usbd_msc.c | ~3800 | (128 + 512(default)) * bus | 16 * bus | 0 |
|
||||
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|
||||
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|
||||
|usbd_video.c | ~3700 | 0 | 132 * bus | 0 |
|
||||
|usbd_rndis.c | ~4000 | 2 * 1580(default)+156+8 | 80 | 0 |
|
||||
|
||||
## Host 协议栈简介
|
||||
|
||||
CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了一套标准的枚举实现,对不同的 Class 类也规范了一套标准接口,用来指示在枚举后和断开连接后该 Class 驱动需要做的事情。同时,规范了一套标准的 hcd porting 接口,用于适配不同的 USB IP,达到面向 IP 编程。最后,协议栈使用 OS 管理,并提供了 osal 用来适配不同的 os。
|
||||
CherryUSB Host 协议栈对挂载在 root hub、外部 hub 上的设备规范了一套标准的枚举实现,对不同的 Class 类也规范了一套标准接口,用来指示在枚举后和断开连接后该 Class 驱动需要做的事情。同时,规范了一套标准的 hcd porting 接口,用于适配不同的 USB IP,达到面向 IP 编程。最后,协议栈使用 OS 管理,并提供了 osal 用来适配不同的 os。
|
||||
|
||||
CherryUSB Host 协议栈当前实现以下功能:
|
||||
|
||||
- 支持 low speed,full speed,high speed 和 super speed 设备
|
||||
- 自动加载支持的Class 驱动
|
||||
- 支持阻塞式传输和异步传输
|
||||
- 支持复合设备
|
||||
- 支持多级 HUB,最高可拓展到 7 级
|
||||
- 支持多级 HUB,最高可拓展到 7 级(目前测试 1拖 10 没有问题,仅支持 dwc2/ehci/xhci/rp2040)
|
||||
- 支持 Communication Device Class (CDC_ACM, CDC_ECM)
|
||||
- 支持 Human Interface Device (HID)
|
||||
- 支持 Mass Storage Class (MSC)
|
||||
- Support USB Video CLASS
|
||||
- Support USB Audio CLASS
|
||||
- Support USB Video CLASS (UVC1.0、UVC1.5)
|
||||
- Support USB Audio CLASS (UAC1.0)
|
||||
- 支持 Remote NDIS (RNDIS)
|
||||
- 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能)
|
||||
- 支持 Vendor 类 class
|
||||
- 支持 Vendor 类 class (serial, net, wifi)
|
||||
- 支持 USB modeswitch
|
||||
- 支持 Android Open Accessory
|
||||
- 支持相同 USB IP 的多主机
|
||||
|
||||
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
||||
@@ -118,16 +118,17 @@ CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||
|
||||
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|
||||
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|
||||
|usbh_core.c | ~7700 | 512 + 8 * (1+x) *n | 28 | 0 |
|
||||
|usbh_hub.c | ~5600 | 32 + 4* (1+x) | 12 + sizeof(struct usbh_hub) * (1+x) | 0 |
|
||||
|usbh_cdc_acm.c | ~1200 | 7 | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~2500 | 32 | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1000 | 128 | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~3700 | 128 | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~3100 | 128 | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~3900 | 4096 + 2 * 2048 | sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2500 | 2 * 1514 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|usbh_bluetooth.c | ~2300 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|
||||
|usbh_core.c | ~10000(enable lsusb)/ ~7500(disable lsusb) | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus | raw_config_desc |
|
||||
|usbh_hub.c | ~6000 | (32 + 4 * (1+x)) * bus | 12 + sizeof(struct usbh_hub) * x | 0 |
|
||||
|usbh_cdc_acm.c | ~900 | 7 * x | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|
||||
|usbh_msc.c | ~3400 | 128 * x | 4 + sizeof(struct usbh_msc) * x | 0 |
|
||||
|usbh_hid.c | ~1400 | 64 * x | 4 + sizeof(struct usbh_hid) * x | 0 |
|
||||
|usbh_video.c | ~5700 | 128 * x | 4 + sizeof(struct usbh_video) * x | 0 |
|
||||
|usbh_audio.c | ~8400 | 128 * x | 4 + sizeof(struct usbh_audio) * x | 0 |
|
||||
|usbh_rndis.c | ~5200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|
||||
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|
||||
|usbh_cdc_ncm.c | ~3500 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|
||||
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|
||||
|
||||
其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
|
||||
|
||||
@@ -149,34 +150,78 @@ x 受以下宏影响:
|
||||
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
|
||||
```
|
||||
|
||||
## USB IP 支持情况
|
||||
|
||||
仅列举标准 USB IP 和商业性 USB IP
|
||||
|
||||
| IP | device | host | Support status |
|
||||
|:----------------:|:----------:|:--------:|:--------------:|
|
||||
| OHCI(intel) | none | OHCI | √ |
|
||||
| EHCI(intel) | none | EHCI | √ |
|
||||
| XHCI(intel) | none | XHCI | √ |
|
||||
| UHCI(intel) | none | UHCI | × |
|
||||
| DWC2(synopsys) | DWC2 | DWC2 | √ |
|
||||
| MUSB(mentor) | MUSB | MUSB | √ |
|
||||
| FOTG210(faraday)| FOTG210 | EHCI | √ |
|
||||
| CHIPIDEA(synopsys)| CHIPIDEA | EHCI | √ |
|
||||
| CDNS2(cadence) | CDNS2 | CDNS2 | √ |
|
||||
| CDNS3(cadence) | CDNS3 | XHCI | × |
|
||||
| DWC3(synopsys) | DWC3 | XHCI | × |
|
||||
|
||||
## 文档教程
|
||||
|
||||
CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
|
||||
CherryUSB 快速入门、USB 基本概念、API 手册、Class 基本概念和例程,参考 [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)。
|
||||
|
||||
## 视频教程
|
||||
|
||||
USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [CherryUSB Device 协议栈教程](https://www.bilibili.com/video/BV1Ef4y1t73d).
|
||||
CherryUSB 课程(基于 V1.4.3):https://www.bilibili.com/cheese/play/ss707687201 。
|
||||
|
||||
## 图形化界面配置工具
|
||||
## 描述符生成工具
|
||||
|
||||
[chryusb_configurator](https://github.com/Egahp/chryusb_configurator) 采用 **electron + vite2 + ts** 框架编写,当前用于自动化生成描述符数组,后续会增加其他功能。
|
||||
TODO
|
||||
|
||||
## 示例仓库
|
||||
|
||||
| Manufacturer | CHIP or Series | USB IP| Repo Url | Support version | Support status |
|
||||
|:--------------------:|:------------------:|:-----:|:--------:|:------------------:|:-------------:|
|
||||
|Bouffalolab | BL702/BL616/BL808 | bouffalolab/ehci|[bouffalo_sdk](https://github.com/CherryUSB/bouffalo_sdk)|<= latest | Long-term |
|
||||
|ST | STM32F1x | fsdev |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|ST | STM32F4/STM32H7 | dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6750 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with Essemi |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|v0.10.2 | Long-term |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|Espressif | esp32s3 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | the same with ST |
|
||||
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|<= v0.10.2 | No more updated |
|
||||
|Raspberry pi | rp2040 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= v0.10.2 | No more updated |
|
||||
|ST | STM32F1x/STM32F4/STM32H7 | fsdev/dwc2 |[stm32_repo](https://github.com/CherryUSB/cherryusb_stm32)|<= latest | Long-term |
|
||||
|HPMicro | HPM6000/HPM5000 | hpm/ehci |[hpm_sdk](https://github.com/CherryUSB/hpm_sdk)|<= latest | Long-term |
|
||||
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/CherryUSB/cherryusb_es32)|<= latest | Long-term |
|
||||
|Phytium | e2000 | pusb2/xhci |[phytium_repo](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)|>=1.4.0 | Long-term |
|
||||
|Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term |
|
||||
|Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term |
|
||||
|NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term |
|
||||
|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/k230_sdk)|v1.2.0 | Long-term |
|
||||
|Actionstech | ATS30xx | dwc2 |[action_zephyr_repo](https://github.com/CherryUSB/lv_port_actions_technology/tree/master/action_technology_sdk)|>=1.4.0 | Long-term |
|
||||
|Nationstech | n32h4x | dwc2 |[nation_repo](https://github.com/CherryUSB/cherryusb_nation)|>=1.5.0 | Long-term |
|
||||
|Raspberry pi | rp2040/rp2350 | rp2040 |[pico-examples](https://github.com/CherryUSB/pico-examples)|<= latest | Long-term |
|
||||
|AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb |
|
||||
|Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb |
|
||||
|Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD |
|
||||
|WCH | CH32V307/ch58x | ch32_usbfs/ch32_usbhs/ch58x |[wch_repo](https://github.com/CherryUSB/cherryusb_wch)|<= v0.10.2 | TBD |
|
||||
|
||||
## Contact
|
||||
## 软件包支持
|
||||
|
||||
QQ 群:642693751
|
||||
CherryUSB 软件包可以通过以下方式获取:
|
||||
|
||||
- [RT-Thread](https://packages.rt-thread.org/detail.html?package=CherryUSB)
|
||||
- [YOC](https://www.xrvm.cn/document?temp=usb-host-protocol-stack-device-driver-adaptation-instructions&slug=yocbook)
|
||||
- [ESP-Registry](https://components.espressif.com/components/cherry-embedded/cherryusb)
|
||||
|
||||
## 商业支持
|
||||
|
||||
参考 https://cherryusb.readthedocs.io/zh-cn/latest/support/index.html 。
|
||||
|
||||
## 联系
|
||||
|
||||
CherryUSB QQ群:642693751
|
||||
|
||||
CherryUSB 微信群:与我联系后邀请加入
|
||||
|
||||
## 支持企业
|
||||
|
||||
感谢以下企业支持(顺序不分先后):
|
||||
|
||||
<img src="docs/assets/bouffalolab.jpg" width="100" height="80"/> <img src="docs/assets/hpmicro.jpg" width="100" height="80" /> <img src="docs/assets/eastsoft.jpg" width="100" height="80" /> <img src="docs/assets/rtthread.jpg" width="100" height="80" /> <img src="docs/assets/sophgo.jpg" width="100" height="80" /> <img src="docs/assets/phytium.jpg" width="100" height="80" /> <img src="docs/assets/thead.jpg" width="100" height="80" /> <img src="docs/assets/nuvoton.jpg" width="100" height="80" /> <img src="docs/assets/artinchip.jpg" width="100" height="80" /> <img src="docs/assets/bekencorp.jpg" width="100" height="80" /> <img src="docs/assets/nxp.png" width="100" height="80" /> <img src="docs/assets/espressif.png" width="100" height="80" /> <img src="docs/assets/canaan.jpg" width="100" height="80" />
|
||||
<img src="docs/assets/actions.jpg" width="100" height="80" /> <img src="docs/assets/nationstech.jpg" width="100" height="80" />
|
||||
|
||||
320
SConscript
320
SConscript
@@ -1,17 +1,27 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
path = [cwd + '/common']
|
||||
path = [cwd]
|
||||
path += [cwd + '/common']
|
||||
path += [cwd + '/core']
|
||||
path += [cwd + '/class/hub']
|
||||
path += [cwd + '/class/cdc']
|
||||
path += [cwd + '/class/msc']
|
||||
path += [cwd + '/class/hid']
|
||||
path += [cwd + '/class/audio']
|
||||
path += [cwd + '/class/video']
|
||||
path += [cwd + '/class/wireless']
|
||||
path += [cwd + '/class/midi']
|
||||
path += [cwd + '/class/adb']
|
||||
path += [cwd + '/class/dfu']
|
||||
path += [cwd + '/class/midi']
|
||||
path += [cwd + '/class/vendor/net']
|
||||
path += [cwd + '/class/vendor/serial']
|
||||
path += [cwd + '/class/vendor/wifi']
|
||||
src = []
|
||||
|
||||
LIBS = []
|
||||
LIBPATH = []
|
||||
CPPDEFINES = []
|
||||
|
||||
# USB DEVICE
|
||||
@@ -20,11 +30,85 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
src += Glob('core/usbd_core.c')
|
||||
src += Glob('osal/usb_osal_rtthread.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_SPEED_HS']):
|
||||
CPPDEFINES+=['CONFIG_USB_HS']
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC']):
|
||||
src += Glob('class/cdc/usbd_cdc.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV_ST']):
|
||||
src += Glob('port/fsdev/usb_dc_fsdev.c')
|
||||
src += Glob('port/fsdev/usb_glue_st.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV_CUSTOM']):
|
||||
src += Glob('port/fsdev/usb_dc_fsdev.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_ST']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_ESP']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_esp.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_KENDRYTE']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_kendryte.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_AT']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_at.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_HC']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_hc.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_NATION']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_nation.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_GD']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_gd.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_CUSTOM']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_ES']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
src += Glob('port/musb/usb_glue_es.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
src += Glob('port/musb/usb_glue_sunxi.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_BK']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
src += Glob('port/musb/usb_glue_bk.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
|
||||
path += [cwd + '/port/chipidea']
|
||||
src += Glob('port/chipidea/usb_dc_chipidea.c')
|
||||
src += Glob('port/nxp/usb_glue_mcx.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM']):
|
||||
path += [cwd + '/port/chipidea']
|
||||
src += Glob('port/chipidea/usb_dc_chipidea.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_KINETIS_MCX']):
|
||||
src += Glob('port/kinetis/usb_dc_kinetis.c')
|
||||
src += Glob('port/kinetis/usb_glue_mcx.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_KINETIS_CUSTOM']):
|
||||
src += Glob('port/kinetis/usb_dc_kinetis.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_BL']):
|
||||
src += Glob('port/bouffalolab/usb_dc_bl.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
|
||||
src += Glob('port/hpmicro/usb_dc_hpm.c')
|
||||
src += Glob('port/hpmicro/usb_glue_hpm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AIC']):
|
||||
src += Glob('port/aic/usb_dc_aic.c')
|
||||
src += Glob('port/aic/usb_dc_aic_ll.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||
src += Glob('port/ch32/usb_dc_usbhs.c')
|
||||
else:
|
||||
src += Glob('port/ch32/usb_dc_usbfs.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/rt-thread']
|
||||
src += Glob('port/pusb2/rt-thread/usb_dc_glue_phytium.c')
|
||||
if GetDepend(['ARCH_ARMV8']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_dc_a64.a']
|
||||
if GetDepend(['ARCH_ARM_CORTEX_A']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_dc_a32_softfp_neon.a']
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ACM']):
|
||||
src += Glob('class/cdc/usbd_cdc_acm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
|
||||
src += Glob('class/hid/usbd_hid.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC']):
|
||||
@@ -33,114 +117,186 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||
src += Glob('class/audio/usbd_audio.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO']):
|
||||
src += Glob('class/video/usbd_video.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_RNDIS']):
|
||||
src += Glob('class/wireless/usbd_rndis.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ECM']):
|
||||
src += Glob('class/cdc/usbd_cdc_ecm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_NCM']):
|
||||
src += Glob('class/cdc/usbd_cdc_ncm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_USING_DFU']):
|
||||
src += Glob('class/dfu/usbd_dfu.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_TEMPLATE']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
|
||||
src += Glob('demo/cdc_acm_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_MOUSE_TEMPLATE']):
|
||||
src += Glob('demo/hid_mouse_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_KEYBOARD_TEMPLATE']):
|
||||
src += Glob('demo/hid_keyboard_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC']):
|
||||
src += Glob('demo/msc_ram_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_STORAGE_TEMPLATE']):
|
||||
src += Glob('demo/msc_storage_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
|
||||
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
|
||||
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO_TEMPLATE']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']):
|
||||
src += Glob('platform/rtthread/usbd_msc_blkdev.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']):
|
||||
src += Glob('demo/hid_mouse_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']):
|
||||
src += Glob('demo/hid_keyboard_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM']):
|
||||
src += Glob('demo/hid_custom_inout_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_VIDEO']):
|
||||
src += Glob('demo/video_static_mjpeg_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS_TEMPLATE']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER']):
|
||||
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER']):
|
||||
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS']):
|
||||
src += Glob('demo/cdc_rndis_template.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']):
|
||||
src += Glob('port/fsdev/usb_dc_fsdev.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']):
|
||||
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_STM32']):
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
|
||||
src += Glob('port/musb/usb_dc_musb.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
|
||||
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HPM']):
|
||||
src += Glob('port/hpm/usb_dc_hpm.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32_CH32V307']):
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||
src += Glob('port/ch32/usb_dc_usbhs.c')
|
||||
else:
|
||||
src += Glob('port/ch32/usb_dc_usbfs.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/common']
|
||||
path += [cwd + '/port/pusb2/fpusb2']
|
||||
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
||||
src += Glob('port/pusb2/usb_dc_pusb2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM']):
|
||||
src += Glob('demo/cdc_ecm_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']):
|
||||
src += Glob('demo/cdc_ncm_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']):
|
||||
src += Glob('demo/cdc_acm_msc_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']):
|
||||
src += Glob('demo/cdc_acm_hid_msc_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1']):
|
||||
src += Glob('demo/winusb1.0_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC']):
|
||||
src += Glob('demo/winusb2.0_cdc_template.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID']):
|
||||
src += Glob('demo/winusb2.0_hid_template.c')
|
||||
|
||||
# USB HOST
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||
path += [cwd + '/osal']
|
||||
path += [cwd + '/class/hub']
|
||||
src += Glob('core/usbh_core.c')
|
||||
src += Glob('class/hub/usbh_hub.c')
|
||||
src += Glob('osal/usb_osal_rtthread.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC']):
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_BL']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_bouffalo.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/hpmicro/usb_hc_hpm.c')
|
||||
src += Glob('port/hpmicro/usb_glue_hpm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_AIC']):
|
||||
path += [cwd + '/port/ehci']
|
||||
path += [cwd + '/port/ohci']
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_aic.c')
|
||||
src += Glob('port/ohci/usb_hc_ohci.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_MCX']):
|
||||
path += [cwd + '/port/chipidea']
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/nxp/usb_glue_mcx.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_NUC980']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_nuc980.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_MA35D0']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
src += Glob('port/ehci/usb_glue_ma35d0.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_CUSTOM']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ST']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_ESP']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_esp.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_KENDRYTE']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_kendryte.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_HC']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_hc.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_NATION']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
src += Glob('port/dwc2/usb_glue_nation.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_CUSTOM']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_STANDARD']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_ES']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
src += Glob('port/musb/usb_glue_es.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
src += Glob('port/musb/usb_glue_sunxi.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_BK']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
src += Glob('port/musb/usb_glue_bk.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_MCX']):
|
||||
src += Glob('port/kinetis/usb_hc_kinetis.c')
|
||||
src += Glob('port/kinetis/usb_glue_mcx.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_CUSTOM']):
|
||||
src += Glob('port/kinetis/usb_hc_kinetis.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/rt-thread']
|
||||
src += Glob('port/pusb2/rt-thread/usb_hc_glue_phytium.c')
|
||||
if GetDepend(['ARCH_ARMV8']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_hc_a64.a']
|
||||
if GetDepend(['ARCH_ARM_CORTEX_A']):
|
||||
LIBPATH = [cwd + '/port/pusb2']
|
||||
LIBS = ['libpusb2_hc_a32_softfp_neon.a']
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
|
||||
path += [cwd + '/port/xhci/phytium/rt-thread']
|
||||
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium_plat.c')
|
||||
src += Glob('port/xhci/phytium/rt-thread/usb_glue_phytium.c')
|
||||
if GetDepend(['ARCH_ARMV8']):
|
||||
LIBPATH = [cwd + '/port/xhci/phytium']
|
||||
LIBS = ['libxhci_a64.a']
|
||||
if GetDepend(['ARCH_ARM_CORTEX_A']):
|
||||
LIBPATH = [cwd + '/port/xhci/phytium']
|
||||
LIBS = ['libxhci_a32_softfp_neon.a']
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ACM']):
|
||||
src += Glob('class/cdc/usbh_cdc_acm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_HID']):
|
||||
src += Glob('class/hid/usbh_hid.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
|
||||
src += Glob('class/msc/usbh_msc.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_RNDIS']):
|
||||
src += Glob('class/wireless/usbh_rndis.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ECM']):
|
||||
src += Glob('class/cdc/usbh_cdc_ecm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_NCM']):
|
||||
src += Glob('class/cdc/usbh_cdc_ncm.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_VIDEO']):
|
||||
src += Glob('class/video/usbh_video.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_AUDIO']):
|
||||
src += Glob('class/audio/usbh_audio.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_BLUETOOTH']):
|
||||
src += Glob('class/wireless/usbh_bluetooth.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
|
||||
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2_STM32']):
|
||||
src += Glob('port/dwc2/usb_glue_st.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']):
|
||||
src += Glob('port/musb/usb_hc_musb.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
|
||||
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI']):
|
||||
src += Glob('port/ehci/usb_hc_ehci.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_EHCI_HPM']):
|
||||
src += Glob('port/ehci/usb_glue_hpm.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']):
|
||||
src += Glob('port/xhci/usb_hc_xhci.c')
|
||||
src += Glob('port/xhci/xhci_dbg.c')
|
||||
src += Glob('port/xhci/xhci.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']):
|
||||
path += [cwd + '/port/pusb2/common']
|
||||
path += [cwd + '/port/pusb2/fpusb2']
|
||||
src += Glob('port/pusb2/fpusb2' + '/*.c')
|
||||
src += Glob('port/pusb2/usb_hc_pusb2.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_ASIX']):
|
||||
src += Glob('class/vendor/net/usbh_asix.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_RTL8152']):
|
||||
src += Glob('class/vendor/net/usbh_rtl8152.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_FTDI']):
|
||||
src += Glob('class/vendor/serial/usbh_ftdi.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CH34X']):
|
||||
src += Glob('class/vendor/serial/usbh_ch34x.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_CP210X']):
|
||||
src += Glob('class/vendor/serial/usbh_cp210x.c')
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_PL2303']):
|
||||
src += Glob('class/vendor/serial/usbh_pl2303.c')
|
||||
|
||||
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
|
||||
CPPDEFINES+=['TEST_USBH_MSC=0']
|
||||
src += Glob('demo/usb_host.c')
|
||||
|
||||
if GetDepend('RT_USING_DFS'):
|
||||
src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
|
||||
|
||||
src += Glob('third_party/rt-thread-5.0/msh_cmd.c')
|
||||
if GetDepend('RT_USING_DFS') and GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
|
||||
src += Glob('platform/rtthread/usbh_dfs.c')
|
||||
|
||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||
if GetDepend('PKG_CHERRYUSB_HOST_CDC_ECM') \
|
||||
or GetDepend('PKG_CHERRYUSB_HOST_CDC_RNDIS') \
|
||||
or GetDepend('PKG_CHERRYUSB_HOST_CDC_NCM') \
|
||||
or GetDepend('PKG_CHERRYUSB_HOST_ASIX') \
|
||||
or GetDepend('PKG_CHERRYUSB_HOST_RTL8152'):
|
||||
src += Glob('platform/rtthread/usbh_lwip.c')
|
||||
|
||||
src += Glob('platform/rtthread/usb_msh.c')
|
||||
src += Glob('platform/rtthread/usb_check.c')
|
||||
|
||||
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], LIBS = LIBS, LIBPATH=LIBPATH, CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||
|
||||
Return('group')
|
||||
|
||||
|
||||
4
VERSION
4
VERSION
@@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 1
|
||||
PATCHLEVEL = 99
|
||||
VERSION_MINOR = 5
|
||||
PATCHLEVEL = 0
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = 0
|
||||
|
||||
361
cherryusb.cmake
Normal file
361
cherryusb.cmake
Normal file
@@ -0,0 +1,361 @@
|
||||
#
|
||||
# Copyright (c) 2024, sakumisu
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# cmake-format: off
|
||||
|
||||
# set(CONFIG_CHERRYUSB_DEVICE 1)
|
||||
# set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
|
||||
# set(CONFIG_CHERRYUSB_DEVICE_HID 1)
|
||||
# set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
|
||||
# set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
|
||||
# set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)
|
||||
# set(CONFIG_CHERRYUSB_DEVICE_DWC2_ST 1)
|
||||
|
||||
# set(CONFIG_CHERRYUSB_HOST 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_HID 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_MSC 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_ASIX 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
|
||||
# set(CONFIG_CHERRYUSB_HOST_DWC2_ST 1)
|
||||
|
||||
# set(CONFIG_CHERRYUSB_OSAL "freertos")
|
||||
# cmake-format: on
|
||||
|
||||
list(
|
||||
APPEND
|
||||
cherryusb_incs
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/common
|
||||
${CMAKE_CURRENT_LIST_DIR}/core
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hub
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/cdc
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hid
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/msc
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/audio
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/video
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/wireless
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/midi
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/adb
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/dfu
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/aoa
|
||||
)
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbd_core.c)
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC_ACM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_acm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_HID)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbd_hid.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_MSC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/msc/usbd_msc.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_AUDIO)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbd_audio.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_VIDEO)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbd_video.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC_ECM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_ecm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC_NCM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbd_cdc_ncm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_CDC_RNDIS)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbd_rndis.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_DFU)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/dfu/usbd_dfu.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_DEVICE_ADB)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/adb/usbd_adb.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_DEVICE_FSDEV_ST)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_glue_st.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_FSDEV_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_ST)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_st.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_ESP)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_KENDRYTE)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_kendryte.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_AT)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_at.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_HC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_hc.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_GD)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_gd.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_DWC2_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_dc_dwc2.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_ES)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_es.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_SUNXI)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_sunxi.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_BK)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_CHIPIDEA_MCX)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_dc_chipidea.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/nxp/usb_glue_mcx.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_KINETIS_MCX)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_dc_kinetis.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_CHIPIDEA_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea/usb_dc_chipidea.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_HPM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpmicro/usb_dc_hpm.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpmicro/usb_glue_hpm.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/hpmicro)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_BL)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/bouffalolab/usb_dc_bl.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_AIC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/aic/usb_dc_aic_ll.c)
|
||||
elseif(CONFIG_CHERRYUSB_DEVICE_RP2040)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_dc_rp2040.c)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/core/usbh_core.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hub/usbh_hub.c
|
||||
)
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_acm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_ECM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ecm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_RNDIS)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_rndis.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_NCM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/cdc/usbh_cdc_ncm.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_HID)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/hid/usbh_hid.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/msc/usbh_msc.c)
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_MSC_FATFS)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/port/fatfs_usbh.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/diskio.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ff.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ffsystem.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source/ffunicode.c)
|
||||
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/fatfs-0.14/source)
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_VIDEO)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/video/usbh_video.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_AUDIO)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/audio/usbh_audio.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_BLUETOOTH)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/wireless/usbh_bluetooth.c)
|
||||
|
||||
set(BLUETOOTH_PATH ${CMAKE_CURRENT_LIST_DIR}/third_party/zephyr_bluetooth-2.7.5)
|
||||
|
||||
list(
|
||||
APPEND
|
||||
cherryusb_srcs
|
||||
${BLUETOOTH_PATH}/ble_hci_usbh.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/beacon/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_hr/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_ht/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_multilink/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/central_multilink/src/central_multilink.c
|
||||
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/handsfree/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/ibeacon/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral/src/cts.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_csc/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_dis/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_esp/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hids/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hids/src/hog.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_hr/src/main.c
|
||||
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ht/src/main.c
|
||||
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ht/src/hts.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_identity/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_identity/src/peripheral_identity.c
|
||||
# ${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_ots/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/peripheral_sc_only/src/main.c
|
||||
${BLUETOOTH_PATH}/zephyr_bluetooth/examples/scan_adv/src/main.c
|
||||
)
|
||||
|
||||
include(${BLUETOOTH_PATH}/zephyr_bluetooth/zephyr_bluetooth.cmake)
|
||||
list(APPEND cherryusb_srcs ${zephyr_bluetooth_srcs})
|
||||
list(APPEND cherryusb_incs ${zephyr_bluetooth_incs})
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_ASIX)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net/usbh_asix.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_RTL8152)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net/usbh_rtl8152.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CH34X)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_ch34x.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_CP210X)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_cp210x.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_FTDI)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_ftdi.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_PL2303)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial/usbh_pl2303.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_BL616)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c)
|
||||
endif()
|
||||
if(CONFIG_CHERRYUSB_HOST_AOA)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_CDC_ECM
|
||||
OR CONFIG_CHERRYUSB_HOST_CDC_RNDIS
|
||||
OR CONFIG_CHERRYUSB_HOST_CDC_NCM
|
||||
OR CONFIG_CHERRYUSB_HOST_ASIX
|
||||
OR CONFIG_CHERRYUSB_HOST_RTL8152
|
||||
OR CONFIG_CHERRYUSB_HOST_BL616
|
||||
)
|
||||
list(APPEND cherryusb_srcs platform/lwip/usbh_lwip.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYUSB_HOST_EHCI_BL)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
# list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_bouffalo.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_EHCI_HPM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
# list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpmicro/usb_hc_hpm.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpmicro/usb_glue_hpm.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/hpmicro)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_EHCI_AIC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ohci/usb_hc_ohci.c)
|
||||
# list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_glue_aic.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ohci)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_EHCI_MCX)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
# list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/nxp/usb_glue_mcx.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/chipidea)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_EHCI_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci.c)
|
||||
# list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/ehci/usb_hc_ehci_iso.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/port/ehci)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_DWC2_ST)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_st.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_DWC2_ESP)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_esp.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_DWC2_KENDRYTE)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_kendryte.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_DWC2_HC)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_glue_hc.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_DWC2_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/dwc2/usb_hc_dwc2.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_MUSB_ES)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_es.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_MUSB_SUNXI)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_sunxi.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_MUSB_BK)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_MUSB_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_KINETIS_MCX)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_KINETIS_CUSTOM)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
|
||||
elseif(CONFIG_CHERRYUSB_HOST_RP2040)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_hc_rp2040.c)
|
||||
endif()
|
||||
|
||||
if(CHERRYUSB_HOST_TEMPLATE)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/demo/usb_host.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED CONFIG_CHERRYUSB_OSAL)
|
||||
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_freertos.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_rtthread.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "idf")
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/osal/idf)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/idf/usb_osal_idf.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "threadx")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_threadx.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "zephyr")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/osal/usb_osal_zephyr.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYRB)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb/chry_ringbuffer.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherryrb)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CHERRYMP)
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c)
|
||||
list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp)
|
||||
if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_freertos.c)
|
||||
elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread")
|
||||
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_rtthread.c)
|
||||
endif()
|
||||
endif()
|
||||
@@ -6,15 +6,15 @@
|
||||
#ifndef CHERRYUSB_CONFIG_H
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#define CHERRYUSB_VERSION 0x010100
|
||||
#define CHERRYUSB_VERSION_STR "v1.1.0"
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||
#ifdef __RTTHREAD__
|
||||
#include <rtthread.h>
|
||||
|
||||
#define usb_malloc(size) malloc(size)
|
||||
#define usb_free(ptr) free(ptr)
|
||||
#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USB_DBG_LEVEL
|
||||
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
|
||||
@@ -23,30 +23,56 @@
|
||||
/* Enable print with color */
|
||||
#define CONFIG_USB_PRINTF_COLOR_ENABLE
|
||||
|
||||
/* data align size when use dma */
|
||||
/* data align size when use dma or use dcache */
|
||||
#ifndef CONFIG_USB_ALIGN_SIZE
|
||||
#define CONFIG_USB_ALIGN_SIZE 4
|
||||
#endif
|
||||
|
||||
// #define CONFIG_USB_DCACHE_ENABLE
|
||||
|
||||
/* attribute data into no cache ram */
|
||||
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
|
||||
|
||||
/* use usb_memcpy default for high performance but cost more flash memory.
|
||||
* And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
|
||||
*/
|
||||
// #define CONFIG_USB_MEMCPY_DISABLE
|
||||
|
||||
/* ================= USB Device Stack Configuration ================ */
|
||||
|
||||
#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
|
||||
|
||||
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
|
||||
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
|
||||
/* Ep0 in and out transfer buffer */
|
||||
#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
|
||||
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
|
||||
#endif
|
||||
|
||||
/* Setup packet log for debug */
|
||||
// #define CONFIG_USBDEV_SETUP_LOG_PRINT
|
||||
|
||||
/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
|
||||
* Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
|
||||
*/
|
||||
// #define CONFIG_USBDEV_EP0_INDATA_NO_COPY
|
||||
|
||||
/* Check if the input descriptor is correct */
|
||||
// #define CONFIG_USBDEV_DESC_CHECK
|
||||
|
||||
/* Enable test mode */
|
||||
// #define CONFIG_USBDEV_TEST_MODE
|
||||
|
||||
/* enable advance desc register api */
|
||||
#define CONFIG_USBDEV_ADVANCE_DESC
|
||||
|
||||
/* move ep0 setup handler from isr to thread */
|
||||
// #define CONFIG_USBDEV_EP0_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP0_PRIO
|
||||
#define CONFIG_USBDEV_EP0_PRIO 4
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP0_STACKSIZE
|
||||
#define CONFIG_USBDEV_EP0_STACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_MAX_LUN
|
||||
#define CONFIG_USBDEV_MSC_MAX_LUN 1
|
||||
#endif
|
||||
@@ -67,6 +93,10 @@
|
||||
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
|
||||
#endif
|
||||
|
||||
/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
|
||||
// #define CONFIG_USBDEV_MSC_POLLING
|
||||
|
||||
/* move msc read & write from isr to thread */
|
||||
// #define CONFIG_USBDEV_MSC_THREAD
|
||||
|
||||
#ifndef CONFIG_USBDEV_MSC_PRIO
|
||||
@@ -81,8 +111,9 @@
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
/* rndis transfer buffer size, must be a multiple of (1536 + 44)*/
|
||||
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
|
||||
@@ -94,10 +125,10 @@
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
|
||||
/* ================ USB HOST Stack Configuration ================== */
|
||||
|
||||
#define CONFIG_USBHOST_MAX_BUS 1
|
||||
#define CONFIG_USBHOST_MAX_RHPORTS 1
|
||||
#define CONFIG_USBHOST_MAX_EXTHUBS 1
|
||||
#define CONFIG_USBHOST_MAX_EHPORTS 4
|
||||
@@ -123,10 +154,14 @@
|
||||
//#define CONFIG_USBHOST_GET_STRING_DESC
|
||||
|
||||
// #define CONFIG_USBHOST_MSOS_ENABLE
|
||||
#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
|
||||
#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
|
||||
#endif
|
||||
|
||||
/* Ep0 max transfer buffer */
|
||||
#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
|
||||
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
|
||||
#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
|
||||
@@ -136,6 +171,51 @@
|
||||
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
|
||||
* you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
|
||||
*/
|
||||
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE
|
||||
#define CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE (2048)
|
||||
#endif
|
||||
/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
|
||||
#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE
|
||||
#define CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE (2048)
|
||||
#endif
|
||||
|
||||
#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
|
||||
|
||||
@@ -148,23 +228,108 @@
|
||||
|
||||
/* ================ USB Device Port Configuration ================*/
|
||||
|
||||
#ifndef CONFIG_USBDEV_MAX_BUS
|
||||
#define CONFIG_USBDEV_MAX_BUS 1 // for now, bus num must be 1 except hpm ip
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_EP_NUM
|
||||
#define CONFIG_USBDEV_EP_NUM 8
|
||||
#endif
|
||||
|
||||
// #define CONFIG_USBDEV_SOF_ENABLE
|
||||
|
||||
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */
|
||||
// #define CONFIG_USB_HS
|
||||
|
||||
/* ---------------- FSDEV Configuration ---------------- */
|
||||
//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
|
||||
|
||||
/* ---------------- DWC2 Configuration ---------------- */
|
||||
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
|
||||
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
|
||||
*/
|
||||
// #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
|
||||
/* IN Endpoints Max packet Size / 4 */
|
||||
// #define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (0 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX5_FIFO_SIZE (0 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
|
||||
// #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
|
||||
|
||||
// #define CONFIG_USB_DWC2_DMA_ENABLE
|
||||
|
||||
/* ---------------- MUSB Configuration ---------------- */
|
||||
// #define CONFIG_USB_MUSB_SUNXI
|
||||
|
||||
/* ================ USB Host Port Configuration ==================*/
|
||||
#ifndef CONFIG_USBHOST_MAX_BUS
|
||||
#define CONFIG_USBHOST_MAX_BUS 1
|
||||
#endif
|
||||
|
||||
// #define CONFIG_USBHOST_PIPE_NUM 10
|
||||
#ifndef CONFIG_USBHOST_PIPE_NUM
|
||||
#define CONFIG_USBHOST_PIPE_NUM 10
|
||||
#endif
|
||||
|
||||
/* ================ EHCI Configuration ================ */
|
||||
/* ---------------- EHCI Configuration ---------------- */
|
||||
|
||||
#define CONFIG_USB_EHCI_HCCR_OFFSET (0x0)
|
||||
#define CONFIG_USB_EHCI_HCOR_OFFSET (0x10)
|
||||
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
|
||||
// #define CONFIG_USB_EHCI_INFO_ENABLE
|
||||
#define CONFIG_USB_EHCI_QH_NUM CONFIG_USBHOST_PIPE_NUM
|
||||
#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USB_EHCI_QH_NUM * 3)
|
||||
#define CONFIG_USB_EHCI_ITD_NUM 4
|
||||
// #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
|
||||
// #define CONFIG_USB_EHCI_CONFIGFLAG
|
||||
// #define CONFIG_USB_EHCI_PORT_POWER
|
||||
// #define CONFIG_USB_EHCI_PRINT_HW_PARAM
|
||||
// #define CONFIG_USB_EHCI_ISO
|
||||
// #define CONFIG_USB_EHCI_WITH_OHCI
|
||||
// #define CONFIG_USB_EHCI_DESC_DCACHE_ENABLE
|
||||
|
||||
/* ---------------- OHCI Configuration ---------------- */
|
||||
#define CONFIG_USB_OHCI_HCOR_OFFSET (0x0)
|
||||
#define CONFIG_USB_OHCI_ED_NUM CONFIG_USBHOST_PIPE_NUM
|
||||
#define CONFIG_USB_OHCI_TD_NUM 3
|
||||
// #define CONFIG_USB_OHCI_DESC_DCACHE_ENABLE
|
||||
|
||||
/* ---------------- XHCI Configuration ---------------- */
|
||||
#define CONFIG_USB_XHCI_HCCR_OFFSET (0x0)
|
||||
|
||||
/* ---------------- DWC2 Configuration ---------------- */
|
||||
/* largest non-periodic USB packet used / 4 */
|
||||
// #define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
|
||||
/* largest periodic USB packet used / 4 */
|
||||
// #define CONFIG_USB_DWC2_PTX_FIFO_SIZE (1024 / 4)
|
||||
/*
|
||||
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
|
||||
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
|
||||
*/
|
||||
// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
|
||||
|
||||
/* ---------------- MUSB Configuration ---------------- */
|
||||
// #define CONFIG_USB_MUSB_SUNXI
|
||||
|
||||
/* ================ USB Dcache Configuration ==================*/
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
/* style 1*/
|
||||
// void usb_dcache_clean(uintptr_t addr, uint32_t size);
|
||||
// void usb_dcache_invalidate(uintptr_t addr, uint32_t size);
|
||||
// void usb_dcache_flush(uintptr_t addr, uint32_t size);
|
||||
|
||||
/* style 2*/
|
||||
// #define usb_dcache_clean(addr, size)
|
||||
// #define usb_dcache_invalidate(addr, size)
|
||||
// #define usb_dcache_flush(addr, size)
|
||||
#endif
|
||||
|
||||
#ifndef usb_phyaddr2ramaddr
|
||||
#define usb_phyaddr2ramaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
#ifndef usb_ramaddr2phyaddr
|
||||
#define usb_ramaddr2phyaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
310
class/adb/usbd_adb.c
Normal file
310
class/adb/usbd_adb.c
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_adb.h"
|
||||
|
||||
#define ADB_OUT_EP_IDX 0
|
||||
#define ADB_IN_EP_IDX 1
|
||||
|
||||
#define ADB_STATE_READ_MSG 0
|
||||
#define ADB_STATE_READ_DATA 1
|
||||
#define ADB_STATE_WRITE_MSG 2
|
||||
#define ADB_STATE_WRITE_DATA 3
|
||||
#define ADB_STATE_AWRITE_MSG 4
|
||||
#define ADB_STATE_AWRITE_DATA 5
|
||||
|
||||
#define MAX_PAYLOAD_V1 (4 * 1024)
|
||||
#define MAX_PAYLOAD_V2 (256 * 1024)
|
||||
#define MAX_PAYLOAD MAX_PAYLOAD_V1
|
||||
#define A_VERSION 0x01000000
|
||||
|
||||
#define A_SYNC 0x434e5953
|
||||
#define A_CNXN 0x4e584e43
|
||||
#define A_OPEN 0x4e45504f
|
||||
#define A_OKAY 0x59414b4f
|
||||
#define A_CLSE 0x45534c43
|
||||
#define A_WRTE 0x45545257
|
||||
#define A_AUTH 0x48545541
|
||||
|
||||
struct adb_msg {
|
||||
uint32_t command; /* command identifier constant (A_CNXN, ...) */
|
||||
uint32_t arg0; /* first argument */
|
||||
uint32_t arg1; /* second argument */
|
||||
uint32_t data_length; /* length of payload (0 is allowed) */
|
||||
uint32_t data_crc32; /* crc32 of data payload */
|
||||
uint32_t magic; /* command ^ 0xffffffff */
|
||||
};
|
||||
|
||||
struct adb_packet {
|
||||
USB_MEM_ALIGNX struct adb_msg msg;
|
||||
USB_MEM_ALIGNX uint8_t payload[USB_ALIGN_UP(MAX_PAYLOAD, CONFIG_USB_ALIGN_SIZE)];
|
||||
};
|
||||
|
||||
struct usbd_adb {
|
||||
uint8_t state;
|
||||
uint8_t common_state;
|
||||
uint8_t write_state;
|
||||
bool writable;
|
||||
uint32_t localid;
|
||||
uint32_t shell_remoteid;
|
||||
uint32_t file_remoteid;
|
||||
} adb_client;
|
||||
|
||||
static struct usbd_endpoint adb_ep_data[2];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION struct adb_packet tx_packet;
|
||||
USB_NOCACHE_RAM_SECTION struct adb_packet rx_packet;
|
||||
|
||||
static inline uint32_t adb_packet_checksum(struct adb_packet *packet)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < packet->msg.data_length; ++i) {
|
||||
sum += (uint32_t)(packet->payload[i]);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t usbd_adb_get_remoteid(uint32_t localid)
|
||||
{
|
||||
if (localid == ADB_SHELL_LOALID) {
|
||||
return adb_client.shell_remoteid;
|
||||
} else {
|
||||
return adb_client.file_remoteid;
|
||||
}
|
||||
}
|
||||
|
||||
static void adb_send_msg(struct adb_packet *packet)
|
||||
{
|
||||
adb_client.common_state = ADB_STATE_WRITE_MSG;
|
||||
|
||||
packet->msg.data_crc32 = adb_packet_checksum(packet);
|
||||
packet->msg.magic = packet->msg.command ^ 0xffffffff;
|
||||
|
||||
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
|
||||
}
|
||||
|
||||
static void adb_send_okay(struct adb_packet *packet, uint32_t localid)
|
||||
{
|
||||
packet->msg.command = A_OKAY;
|
||||
packet->msg.arg0 = localid;
|
||||
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
|
||||
packet->msg.data_length = 0;
|
||||
|
||||
adb_send_msg(&tx_packet);
|
||||
}
|
||||
|
||||
static void adb_send_close(struct adb_packet *packet, uint32_t localid, uint32_t remoteid)
|
||||
{
|
||||
packet->msg.command = A_CLSE;
|
||||
packet->msg.arg0 = localid;
|
||||
packet->msg.arg1 = remoteid;
|
||||
packet->msg.data_length = 0;
|
||||
|
||||
adb_send_msg(&tx_packet);
|
||||
}
|
||||
|
||||
void usbd_adb_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
|
||||
if (adb_client.common_state == ADB_STATE_READ_MSG) {
|
||||
if (nbytes != sizeof(struct adb_msg)) {
|
||||
USB_LOG_ERR("invalid adb msg size:%d\r\n", (unsigned int)nbytes);
|
||||
return;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("command:%x arg0:%x arg1:%x len:%d\r\n",
|
||||
rx_packet.msg.command,
|
||||
rx_packet.msg.arg0,
|
||||
rx_packet.msg.arg1,
|
||||
rx_packet.msg.data_length);
|
||||
|
||||
if (rx_packet.msg.data_length) {
|
||||
/* setup next out ep read transfer */
|
||||
adb_client.common_state = ADB_STATE_READ_DATA;
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, rx_packet.payload, rx_packet.msg.data_length);
|
||||
} else {
|
||||
if (rx_packet.msg.command == A_CLSE) {
|
||||
adb_client.writable = false;
|
||||
usbd_adb_notify_write_done();
|
||||
USB_LOG_INFO("Close remoteid:%x\r\n", rx_packet.msg.arg0);
|
||||
}
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
}
|
||||
} else if (adb_client.common_state == ADB_STATE_READ_DATA) {
|
||||
switch (rx_packet.msg.command) {
|
||||
case A_SYNC:
|
||||
|
||||
break;
|
||||
case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
|
||||
char *support_feature = "device::"
|
||||
"ro.product.name=cherryadb;"
|
||||
"ro.product.model=cherrysh;"
|
||||
"ro.product.device=cherryadb;"
|
||||
"features=cmd,shell_v1";
|
||||
|
||||
tx_packet.msg.command = A_CNXN;
|
||||
tx_packet.msg.arg0 = A_VERSION;
|
||||
tx_packet.msg.arg1 = MAX_PAYLOAD;
|
||||
tx_packet.msg.data_length = strlen(support_feature);
|
||||
memcpy(tx_packet.payload, support_feature, strlen(support_feature));
|
||||
|
||||
adb_send_msg(&tx_packet);
|
||||
|
||||
adb_client.writable = false;
|
||||
break;
|
||||
case A_OPEN: /* OPEN(local-id, 0, "destination") */
|
||||
rx_packet.payload[rx_packet.msg.data_length] = '\0';
|
||||
|
||||
if (strncmp((const char *)rx_packet.payload, "shell:", 6) == 0) {
|
||||
adb_client.localid = ADB_SHELL_LOALID;
|
||||
adb_client.shell_remoteid = rx_packet.msg.arg0;
|
||||
adb_send_okay(&tx_packet, ADB_SHELL_LOALID);
|
||||
|
||||
USB_LOG_INFO("Open shell service, remoteid:%x\r\n", rx_packet.msg.arg0);
|
||||
} else if (strncmp((const char *)rx_packet.payload, "sync:", 5) == 0) {
|
||||
adb_client.localid = ADB_FILE_LOALID;
|
||||
adb_client.file_remoteid = rx_packet.msg.arg0;
|
||||
adb_send_okay(&tx_packet, ADB_FILE_LOALID);
|
||||
USB_LOG_INFO("Open file service, remoteid:%x\r\n", rx_packet.msg.arg0);
|
||||
}
|
||||
break;
|
||||
case A_OKAY:
|
||||
|
||||
break;
|
||||
case A_CLSE:
|
||||
|
||||
break;
|
||||
case A_WRTE: /* WRITE(local-id, remote-id, "data") */
|
||||
if ((rx_packet.msg.arg0 == adb_client.shell_remoteid) && (rx_packet.msg.arg1 == ADB_SHELL_LOALID)) {
|
||||
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
|
||||
} else if ((rx_packet.msg.arg0 == adb_client.file_remoteid) && (rx_packet.msg.arg1 == ADB_FILE_LOALID)) {
|
||||
adb_send_okay(&tx_packet, rx_packet.msg.arg1);
|
||||
} else {
|
||||
adb_send_close(&tx_packet, 0, rx_packet.msg.arg0);
|
||||
}
|
||||
break;
|
||||
case A_AUTH:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_adb_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
if (adb_client.common_state == ADB_STATE_WRITE_MSG) {
|
||||
if (tx_packet.msg.data_length) {
|
||||
adb_client.common_state = ADB_STATE_WRITE_DATA;
|
||||
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
|
||||
} else {
|
||||
if (rx_packet.msg.command == A_WRTE) {
|
||||
adb_client.writable = true;
|
||||
if (adb_client.localid == ADB_SHELL_LOALID) {
|
||||
usbd_adb_notify_shell_read(rx_packet.payload, rx_packet.msg.data_length);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
}
|
||||
} else if (adb_client.common_state == ADB_STATE_WRITE_DATA) {
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
} else if (adb_client.write_state == ADB_STATE_AWRITE_MSG) {
|
||||
if (tx_packet.msg.data_length) {
|
||||
adb_client.write_state = ADB_STATE_AWRITE_DATA;
|
||||
usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
|
||||
} else {
|
||||
}
|
||||
} else if (adb_client.write_state == ADB_STATE_AWRITE_DATA) {
|
||||
usbd_adb_notify_write_done();
|
||||
}
|
||||
}
|
||||
|
||||
void adb_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_INIT:
|
||||
break;
|
||||
case USBD_EVENT_DEINIT:
|
||||
break;
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
adb_client.common_state = ADB_STATE_READ_MSG;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
intf->class_interface_handler = NULL;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = adb_notify_handler;
|
||||
|
||||
adb_ep_data[ADB_OUT_EP_IDX].ep_addr = out_ep;
|
||||
adb_ep_data[ADB_OUT_EP_IDX].ep_cb = usbd_adb_bulk_out;
|
||||
adb_ep_data[ADB_IN_EP_IDX].ep_addr = in_ep;
|
||||
adb_ep_data[ADB_IN_EP_IDX].ep_cb = usbd_adb_bulk_in;
|
||||
|
||||
usbd_add_endpoint(busid, &adb_ep_data[ADB_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(busid, &adb_ep_data[ADB_IN_EP_IDX]);
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
bool usbd_adb_can_write(void)
|
||||
{
|
||||
return adb_client.writable;
|
||||
}
|
||||
|
||||
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len)
|
||||
{
|
||||
struct adb_packet *packet;
|
||||
|
||||
packet = &tx_packet;
|
||||
packet->msg.command = A_WRTE;
|
||||
packet->msg.arg0 = localid;
|
||||
packet->msg.arg1 = usbd_adb_get_remoteid(localid);
|
||||
packet->msg.data_length = len;
|
||||
memcpy(packet->payload, data, len);
|
||||
|
||||
packet->msg.data_crc32 = adb_packet_checksum(packet);
|
||||
packet->msg.magic = packet->msg.command ^ 0xffffffff;
|
||||
|
||||
adb_client.write_state = ADB_STATE_AWRITE_MSG;
|
||||
usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usbd_adb_close(uint32_t localid)
|
||||
{
|
||||
adb_send_close(&tx_packet, 0, usbd_adb_get_remoteid(localid));
|
||||
}
|
||||
38
class/adb/usbd_adb.h
Normal file
38
class/adb/usbd_adb.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_ADB_H
|
||||
#define USBD_ADB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ADB_SHELL_LOALID 0x01
|
||||
#define ADB_FILE_LOALID 0x02
|
||||
|
||||
// clang-format off
|
||||
#define ADB_DESCRIPTOR_INIT(bFirstInterface, in_ep, out_ep, wMaxPacketSize) \
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(bFirstInterface, 0x00, 0x02, 0xff, 0x42, 0x01, 0x02), \
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(in_ep, 0x02, wMaxPacketSize, 0x00), \
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(out_ep, 0x02, wMaxPacketSize, 0x00)
|
||||
// clang-format on
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep);
|
||||
|
||||
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len);
|
||||
void usbd_adb_notify_file_read(uint8_t *data, uint32_t len);
|
||||
void usbd_adb_notify_write_done(void);
|
||||
bool usbd_adb_can_write(void);
|
||||
int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len);
|
||||
void usbd_adb_close(uint32_t localid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_ADB_H */
|
||||
48
class/aoa/usb_aoa.h
Normal file
48
class/aoa/usb_aoa.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_AOA_H
|
||||
#define USB_AOA_H
|
||||
|
||||
//AOA 1.0
|
||||
#define AOA_ACCESSORY_VENDOR_ID 0x18D1
|
||||
#define AOA_ACCESSORY_PRODUCT_ID 0x2D00
|
||||
#define AOA_ACCESSORY_ADB_PRODUCT_ID 0x2D01
|
||||
|
||||
//AOA 2.0
|
||||
#define AOA_AUDIO_PRODUCT_ID 0x2D02
|
||||
#define AOA_AUDIO_ADB_PRODUCT_ID 0x2D03
|
||||
#define AOA_ACCESSORY_AUDIO_PRODUCT_ID 0x2D04
|
||||
#define AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID 0x2D05
|
||||
|
||||
//AOA 1.0
|
||||
#define AOA_ACCESSORY_GET_PROTOCOL 51
|
||||
#define AOA_ACCESSORY_SEND_STRING 52
|
||||
#define AOA_ACCESSORY_START 53
|
||||
|
||||
//AOA 2.0
|
||||
#define AOA_ACCESSORY_REGISTER_HID 54
|
||||
#define AOA_ACCESSORY_UNREGISTER_HID 55
|
||||
#define AOA_ACCESSORY_SET_HID_REPORT_DESC 56
|
||||
#define AOA_ACCESSORY_SEND_HID_EVENT 57
|
||||
#define AOA_ACCESSORY_SET_AUDIO_MODE 58
|
||||
|
||||
#define AOA_ACCESSORY_STRING_MANUFACTURER 0
|
||||
#define AOA_ACCESSORY_STRING_MODEL 1
|
||||
#define AOA_ACCESSORY_STRING_DESCRIPTION 2
|
||||
#define AOA_ACCESSORY_STRING_VERSION 3
|
||||
#define AOA_ACCESSORY_STRING_URI 4
|
||||
#define AOA_ACCESSORY_STRING_SERIAL 5
|
||||
|
||||
struct aoa_string_info {
|
||||
char acc_manufacturer[64];
|
||||
char acc_model[64];
|
||||
char acc_description[64];
|
||||
char acc_version[64];
|
||||
char acc_uri[64];
|
||||
char acc_serial[64];
|
||||
};
|
||||
|
||||
#endif /* USB_AOA_H */
|
||||
289
class/aoa/usbh_aoa.c
Normal file
289
class/aoa/usbh_aoa.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_aoa.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_aoa"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/aoa"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_aoa_buffer[USB_ALIGN_UP(128, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_aoa g_aoa_class;
|
||||
|
||||
int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
setup = hport->setup;
|
||||
|
||||
if (setup == NULL) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Try switch into aoa mode\r\n");
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_GET_PROTOCOL;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("AOA version: v%d.%d\r\n", g_aoa_buffer[0], g_aoa_buffer[1]);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = AOA_ACCESSORY_STRING_MANUFACTURER;
|
||||
setup->wLength = strlen(info->acc_manufacturer) + 1;
|
||||
|
||||
memcpy(g_aoa_buffer, info->acc_manufacturer, strlen(info->acc_manufacturer));
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = AOA_ACCESSORY_STRING_MODEL;
|
||||
setup->wLength = strlen(info->acc_model) + 1;
|
||||
|
||||
memcpy(g_aoa_buffer, info->acc_model, strlen(info->acc_model));
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = AOA_ACCESSORY_STRING_DESCRIPTION;
|
||||
setup->wLength = strlen(info->acc_description) + 1;
|
||||
|
||||
memcpy(g_aoa_buffer, info->acc_description, strlen(info->acc_description));
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = AOA_ACCESSORY_STRING_VERSION;
|
||||
setup->wLength = strlen(info->acc_version) + 1;
|
||||
|
||||
memcpy(g_aoa_buffer, info->acc_version, strlen(info->acc_version));
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = AOA_ACCESSORY_STRING_URI;
|
||||
setup->wLength = strlen(info->acc_uri) + 1;
|
||||
|
||||
memcpy(g_aoa_buffer, info->acc_uri, strlen(info->acc_uri));
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_STRING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = AOA_ACCESSORY_STRING_SERIAL;
|
||||
setup->wLength = strlen(info->acc_serial) + 1;
|
||||
|
||||
memcpy(g_aoa_buffer, info->acc_serial, strlen(info->acc_serial));
|
||||
ret = usbh_control_transfer(hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_START;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Switch into aoa mode success, wait usb device restart...\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
uint8_t len;
|
||||
uint32_t offset;
|
||||
|
||||
if (!aoa_class || !aoa_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = aoa_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_REGISTER_HID;
|
||||
setup->wValue = id;
|
||||
setup->wIndex = report_len;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(aoa_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
while (report_len > 0) {
|
||||
len = report_len > 64 ? 64 : report_len;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SET_HID_REPORT_DESC;
|
||||
setup->wValue = id;
|
||||
setup->wIndex = offset;
|
||||
setup->wLength = len;
|
||||
|
||||
memcpy(g_aoa_buffer, report + offset, len);
|
||||
ret = usbh_control_transfer(aoa_class->hport, setup, g_aoa_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += len;
|
||||
report_len -= len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
uint8_t len;
|
||||
uint32_t offset;
|
||||
|
||||
if (!aoa_class || !aoa_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = aoa_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = AOA_ACCESSORY_SEND_HID_EVENT;
|
||||
setup->wValue = id;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = event_len;
|
||||
|
||||
memcpy(g_aoa_buffer, event, event_len);
|
||||
return usbh_control_transfer(aoa_class->hport, setup, event);
|
||||
}
|
||||
|
||||
static int usbh_aoa_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_aoa *aoa_class = &g_aoa_class;
|
||||
|
||||
memset(aoa_class, 0, sizeof(struct usbh_aoa));
|
||||
|
||||
aoa_class->hport = hport;
|
||||
aoa_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = aoa_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(aoa_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(aoa_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register AOA Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_aoa_run(aoa_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_aoa_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_aoa *aoa_class = (struct usbh_aoa *)hport->config.intf[intf].priv;
|
||||
|
||||
if (aoa_class) {
|
||||
if (aoa_class->bulkin) {
|
||||
usbh_kill_urb(&aoa_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (aoa_class->bulkout) {
|
||||
usbh_kill_urb(&aoa_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister AOA Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_aoa_stop(aoa_class);
|
||||
}
|
||||
|
||||
memset(aoa_class, 0, sizeof(struct usbh_aoa));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_aoa_run(struct usbh_aoa *aoa_class)
|
||||
{
|
||||
(void)aoa_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_aoa_stop(struct usbh_aoa *aoa_class)
|
||||
{
|
||||
(void)aoa_class;
|
||||
}
|
||||
|
||||
static const uint16_t aoa_id_table[][2] = {
|
||||
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_PRODUCT_ID },
|
||||
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_ADB_PRODUCT_ID },
|
||||
{ AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_PRODUCT_ID },
|
||||
{ AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_ADB_PRODUCT_ID },
|
||||
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_PRODUCT_ID },
|
||||
{ AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct usbh_class_driver aoa_class_driver = {
|
||||
.driver_name = "aoa",
|
||||
.connect = usbh_aoa_connect,
|
||||
.disconnect = usbh_aoa_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info aoa_intf_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xff,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = aoa_id_table,
|
||||
.class_driver = &aoa_class_driver
|
||||
};
|
||||
40
class/aoa/usbh_aoa.h
Normal file
40
class/aoa/usbh_aoa.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_AOA_H
|
||||
#define USBH_AOA_H
|
||||
|
||||
#include "usb_aoa.h"
|
||||
|
||||
struct usbh_aoa {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
|
||||
uint8_t intf;
|
||||
uint8_t minor;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info);
|
||||
int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len);
|
||||
int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len);
|
||||
|
||||
void usbh_aoa_run(struct usbh_aoa *aoa_class);
|
||||
void usbh_aoa_stop(struct usbh_aoa *aoa_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_AOA_H */
|
||||
@@ -132,11 +132,11 @@
|
||||
#define AUDIO_FORMAT_ALAW 0x0004
|
||||
#define AUDIO_FORMAT_MULAW 0x0005
|
||||
|
||||
#define AUDIO_V2_FORMAT_PCM 0x00000001
|
||||
#define AUDIO_V2_FORMAT_PCM8 0x00000002
|
||||
#define AUDIO_V2_FORMAT_IEEE_FLOAT 0x00000004
|
||||
#define AUDIO_V2_FORMAT_ALAW 0x00000008
|
||||
#define AUDIO_V2_FORMAT_MULAW 0x00000010
|
||||
#define AUDIO_V2_FORMAT_PCM 0x00000001
|
||||
#define AUDIO_V2_FORMAT_PCM8 0x00000002
|
||||
#define AUDIO_V2_FORMAT_IEEE_FLOAT 0x00000004
|
||||
#define AUDIO_V2_FORMAT_ALAW 0x00000008
|
||||
#define AUDIO_V2_FORMAT_MULAW 0x00000010
|
||||
|
||||
/* bmChannelConfig: a bitmap field that indicates which spatial locations
|
||||
* are occupied by the channels present in the cluster. The bit allocations
|
||||
@@ -648,6 +648,18 @@ struct audio_cs_if_ac_feature_unit_descriptor {
|
||||
|
||||
#define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + (ch + 1) * n)
|
||||
|
||||
struct audio_cs_if_ac_selector_unit_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bUnitID;
|
||||
uint8_t bNrInPins;
|
||||
uint8_t baSourceID[1];
|
||||
uint8_t iSelector;
|
||||
} __PACKED;
|
||||
|
||||
#define AUDIO_SIZEOF_AC_SELECTOR_UNIT_DESC(n) (6 + n)
|
||||
|
||||
struct audio_cs_if_as_general_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
@@ -810,7 +822,120 @@ struct audio_cs_ep_ep_general_descriptor {
|
||||
0x00, /* wLockDelay */ \
|
||||
0x00
|
||||
|
||||
#define AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bSubFrameSize, 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_PROTOCOL_UNDEFINED, /* 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_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
|
||||
bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
|
||||
0x01, /* bDelay */ \
|
||||
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag : AUDIO_FORMAT_PCM */ \
|
||||
0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
|
||||
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
|
||||
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
|
||||
bNrChannels, /* bNrChannels */ \
|
||||
bSubFrameSize, /* bSubFrameSize : Bytes per audio subframe */ \
|
||||
bBitResolution, /* bBitResolution : bits per sample */ \
|
||||
(PP_NARG(__VA_ARGS__)/3), /* bSamFreqType : only one frequency supported */ \
|
||||
__VA_ARGS__, /* tSamFreq : Audio sampling frequency coded on 3 bytes */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
|
||||
0x05, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
bInterval, /* bInterval : one packet per frame */ \
|
||||
0x00, /* bRefresh */ \
|
||||
bFeedbackEndpointAddress, /* bSynchAddress */ \
|
||||
0x07, /* bLength */ \
|
||||
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
|
||||
AUDIO_EP_CONTROL_SAMPLING_FEQ, /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */ \
|
||||
0x00, /* bLockDelayUnits */ \
|
||||
0x00, /* wLockDelay */ \
|
||||
0x00, \
|
||||
0x09, /* 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 */ \
|
||||
0x03, /* bRefresh, 8ms */ \
|
||||
0x00 /* bSynchAddress */
|
||||
|
||||
#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
|
||||
#define AUDIO_AS_FEEDBACK_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07 + 0x09)
|
||||
|
||||
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bSubFrameSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval, ...) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
bAlternateSetting, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
|
||||
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
|
||||
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
|
||||
bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
|
||||
0x01, /* bDelay */ \
|
||||
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag : AUDIO_FORMAT_PCM */ \
|
||||
0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
|
||||
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
|
||||
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
|
||||
bNrChannels, /* bNrChannels */ \
|
||||
bSubFrameSize, /* bSubFrameSize : Bytes per audio subframe */ \
|
||||
bBitResolution, /* bBitResolution : bits per sample */ \
|
||||
(PP_NARG(__VA_ARGS__)/3), /* bSamFreqType : only one frequency supported */ \
|
||||
__VA_ARGS__, /* tSamFreq : Audio sampling frequency coded on 3 bytes */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
bInterval, /* bInterval : one packet per frame */ \
|
||||
0x00, /* bRefresh */ \
|
||||
0x00, /* bSynchAddress */ \
|
||||
0x07, /* bLength */ \
|
||||
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
|
||||
AUDIO_EP_CONTROL_SAMPLING_FEQ, /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */ \
|
||||
0x00, /* bLockDelayUnits */ \
|
||||
0x00, /* wLockDelay */ \
|
||||
0x00
|
||||
|
||||
#define AUDIO_AS_ALTSETTING_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
|
||||
|
||||
#define AUDIO_AS_ALTSETTING0_DESCRIPTOR_INIT(bInterfaceNumber) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
|
||||
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
|
||||
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
|
||||
0x00 /* iInterface */
|
||||
|
||||
#define AUDIO_MS_STANDARD_DESCRIPTOR_INIT(bInterfaceNumber, bNumEndpoints) \
|
||||
0x09, /* bLength */ \
|
||||
@@ -1096,6 +1221,58 @@ struct audio_v2_control_range3_param_block {
|
||||
0x00, /* wLockDelay */ \
|
||||
0x00
|
||||
|
||||
#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
bAlternateSetting, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
|
||||
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
|
||||
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x10, /* bLength */ \
|
||||
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
|
||||
bTerminalLink, /* bTerminalLink : Unit ID of the Output or Input Terminal*/ \
|
||||
0x00, /* bmControls */ \
|
||||
AUDIO_FORMAT_TYPE_I, /* bFormatType : AUDIO_FORMAT_TYPE_I */ \
|
||||
DBVAL(AUDIO_V2_FORMAT_PCM), /* bmFormats PCM */ \
|
||||
bNrChannels, /* bNrChannels */ \
|
||||
DBVAL(bmChannelConfig), /* bmChannelConfig */ \
|
||||
0x00, /* iChannelNames */ \
|
||||
0x06, /* bLength */ \
|
||||
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
|
||||
AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
|
||||
bSubslotSize, /* bSubslotSize */ \
|
||||
bBitResolution, /* bBitResolution */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (SampleRate * SlotByteSize * NumChannels) */ \
|
||||
bInterval, /* bInterval */ \
|
||||
0x08, /* bLength */ \
|
||||
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
|
||||
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
|
||||
0x00, /* bmAttributes */ \
|
||||
0x00, /* bmControls */ \
|
||||
0x00, /* bLockDelayUnits */ \
|
||||
0x00, /* wLockDelay */ \
|
||||
0x00
|
||||
|
||||
#define AUDIO_V2_AS_ALTSETTING0_DESCRIPTOR_INIT(bInterfaceNumber) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
|
||||
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
|
||||
AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
|
||||
0x00 /* iInterface */
|
||||
|
||||
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval, bFeedbackEndpointAddress) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -1150,16 +1327,32 @@ struct audio_v2_control_range3_param_block {
|
||||
bFeedbackEndpointAddress, /* bFeedbackEndpointAddress Revise Dir to bEndpointAddress */ \
|
||||
0x11, /* bmAttributes: TransferType=Isochronous SyncType=None EndpointType=Feedback */ \
|
||||
WBVAL(4), /* XXXX wMaxPacketSize in Bytes */ \
|
||||
bInterval /* bInterval */ \
|
||||
bInterval /* bInterval */
|
||||
|
||||
// clang-format on
|
||||
|
||||
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
|
||||
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
|
||||
#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
|
||||
#define AUDIO_V2_AS_ALTSETTING_DESCRIPTOR_INIT_LEN (0x09 + 0x10 + 0x06 + 0x07 + 0x08)
|
||||
#define AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08 + 0x07)
|
||||
|
||||
#define AUDIO_SAMPLE_FREQ_NUM(num) (uint8_t)(num), (uint8_t)((num >> 8))
|
||||
#define AUDIO_SAMPLE_FREQ_3B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
|
||||
#define AUDIO_SAMPLE_FREQ_4B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), \
|
||||
(uint8_t)((frq >> 16)), (uint8_t)((frq >> 24))
|
||||
|
||||
/* format 10.14 */
|
||||
#define AUDIO_FREQ_TO_FEEDBACK_FS(freq) ((freq << 10) / 1000)
|
||||
#define AUDIO_FEEDBACK_TO_BUF_FS(buf, feedback) \
|
||||
buf[0] = ((feedback << 4) & 0xFFU); \
|
||||
buf[1] = (((feedback << 4) >> 8U) & 0xFFU); \
|
||||
buf[2] = (((feedback << 4) >> 16U) & 0xFFU)
|
||||
|
||||
/* format 16.16 */
|
||||
#define AUDIO_FREQ_TO_FEEDBACK_HS(freq) ((freq << 13) / 1000)
|
||||
#define AUDIO_FEEDBACK_TO_BUF_HS(buf, feedback) \
|
||||
buf[0] = (((feedback & 0x00001FFFu) << 3) & 0xFFu); \
|
||||
buf[1] = ((((feedback & 0x00001FFFu) << 3) >> 8) & 0xFFu); \
|
||||
buf[2] = (((feedback & 0x01FFE000u) >> 13) & 0xFFu); \
|
||||
buf[3] = (((feedback & 0x01FFE000u) >> 21) & 0xFFu)
|
||||
|
||||
#endif /* USB_AUDIO_H */
|
||||
|
||||
@@ -62,7 +62,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
|
||||
setup->bRequest);
|
||||
|
||||
uint8_t entity_id;
|
||||
uint8_t ep;
|
||||
uint8_t ep = 0;
|
||||
uint8_t subtype = 0x01;
|
||||
uint8_t control_selector;
|
||||
uint8_t ch;
|
||||
@@ -136,27 +136,26 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
|
||||
memcpy(&volume, *data, *len);
|
||||
if (volume < 0x8000) {
|
||||
volume_db = volume / 256;
|
||||
} else if (volume > 0x8000) {
|
||||
volume_db = (0xffff - volume + 1) / -256;
|
||||
} else {
|
||||
volume_db = (volume - 0x10000) / 256;
|
||||
}
|
||||
volume_db += 128; /* 0 ~ 255 */
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
|
||||
usbd_audio_set_volume(busid, ep, ch, volume_db);
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
volume_db = usbd_audio_get_volume(busid, ep, ch);
|
||||
volume_db -= 128;
|
||||
if (volume_db >= 0) {
|
||||
volume = volume_db * 256;
|
||||
} else {
|
||||
volume = volume_db * 256 + 0xffff + 1;
|
||||
volume = volume_db * 256 + 0x10000;
|
||||
}
|
||||
USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
|
||||
memcpy(*data, &volume, 2);
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
(*data)[0] = 0x00; /* -2560/256 dB */
|
||||
(*data)[1] = 0xdb;
|
||||
(*data)[0] = 0x00; /* -100 dB */
|
||||
(*data)[1] = 0x9c;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
@@ -165,7 +164,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
(*data)[0] = 0x00; /* -256/256 dB */
|
||||
(*data)[0] = 0x00; /* 1 dB */
|
||||
(*data)[1] = 0x01;
|
||||
*len = 2;
|
||||
break;
|
||||
@@ -178,22 +177,31 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
|
||||
case AUDIO_REQUEST_CUR:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
volume_db = usbd_audio_get_volume(busid, ep, ch);
|
||||
volume = volume_db;
|
||||
if (volume_db >= 0) {
|
||||
volume = volume_db * 256;
|
||||
} else {
|
||||
volume = volume_db * 256 + 0x10000;
|
||||
}
|
||||
USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
|
||||
memcpy(*data, &volume, 2);
|
||||
*len = 2;
|
||||
} else {
|
||||
memcpy(&volume, *data, *len);
|
||||
volume_db = volume;
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
|
||||
if (volume < 0x8000) {
|
||||
volume_db = volume / 256;
|
||||
} else {
|
||||
volume_db = (volume - 0x10000) / 256;
|
||||
}
|
||||
USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
|
||||
usbd_audio_set_volume(busid, ep, ch, volume_db);
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_RANGE:
|
||||
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
|
||||
*((uint16_t *)(*data + 0)) = 1;
|
||||
*((uint16_t *)(*data + 2)) = 0;
|
||||
*((uint16_t *)(*data + 4)) = 100;
|
||||
*((uint16_t *)(*data + 6)) = 1;
|
||||
*((uint16_t *)(*data + 2)) = 0x9c00; /* MIN -100 dB */
|
||||
*((uint16_t *)(*data + 4)) = 0x0000; /* MAX 0 dB */
|
||||
*((uint16_t *)(*data + 6)) = 0x100; /* RES 1 dB */
|
||||
*len = 8;
|
||||
} else {
|
||||
}
|
||||
@@ -287,7 +295,7 @@ static void audio_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
|
||||
struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
|
||||
struct usbd_interface *intf,
|
||||
uint16_t uac_version,
|
||||
struct audio_entity_info *table,
|
||||
@@ -312,33 +320,70 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
|
||||
return intf;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume)
|
||||
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
(void)volume_db;
|
||||
}
|
||||
|
||||
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
(void)mute;
|
||||
}
|
||||
|
||||
__WEAK bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)ch;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)sampling_freq;
|
||||
}
|
||||
|
||||
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)sampling_freq_table;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_open(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
}
|
||||
|
||||
__WEAK void usbd_audio_close(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
}
|
||||
@@ -27,7 +27,7 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface
|
||||
void usbd_audio_open(uint8_t busid, uint8_t intf);
|
||||
void usbd_audio_close(uint8_t busid, uint8_t intf);
|
||||
|
||||
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume);
|
||||
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db);
|
||||
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
|
||||
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
|
||||
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);
|
||||
|
||||
@@ -21,22 +21,18 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
#ifndef CONFIG_USBHOST_MAX_AUDIO_CLASS
|
||||
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 4
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[128];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_audio_buf[USB_ALIGN_UP(128, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
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;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_AUDIO_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_audio_class[devno], 0, sizeof(struct usbh_audio));
|
||||
g_audio_class[devno].minor = devno;
|
||||
return &g_audio_class[devno];
|
||||
@@ -47,17 +43,17 @@ static struct usbh_audio *usbh_audio_class_alloc(void)
|
||||
|
||||
static void usbh_audio_class_free(struct usbh_audio *audio_class)
|
||||
{
|
||||
int devno = audio_class->minor;
|
||||
uint8_t devno = audio_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(audio_class, 0, sizeof(struct usbh_audio));
|
||||
}
|
||||
|
||||
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq)
|
||||
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution)
|
||||
{
|
||||
struct usb_setup_packet *setup = audio_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
uint8_t mult;
|
||||
uint16_t mps;
|
||||
@@ -65,24 +61,33 @@ int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t s
|
||||
uint8_t intf = 0xff;
|
||||
uint8_t altsetting = 1;
|
||||
|
||||
if (!audio_class || !audio_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = audio_class->hport->setup;
|
||||
|
||||
if (audio_class->is_opened) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->module_num; i++) {
|
||||
if (strcmp(name, audio_class->module[i].name) == 0) {
|
||||
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
|
||||
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
|
||||
if (audio_class->module[i].altsetting[j].sampfreq[k] == samp_freq) {
|
||||
intf = audio_class->module[i].data_intf;
|
||||
altsetting = j;
|
||||
goto freq_found;
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
|
||||
intf = audio_class->as_msg_table[i].stream_intf;
|
||||
for (uint8_t j = 1; j < audio_class->as_msg_table[i].num_of_altsetting; j++) {
|
||||
if (audio_class->as_msg_table[i].as_format[j].bBitResolution == bitresolution) {
|
||||
for (uint8_t k = 0; k < audio_class->as_msg_table[i].as_format[j].bSamFreqType; k++) {
|
||||
uint32_t freq = 0;
|
||||
|
||||
memcpy(&freq, &audio_class->as_msg_table[i].as_format[j].tSamFreq[3 * k], 3);
|
||||
if (freq == samp_freq) {
|
||||
altsetting = j;
|
||||
goto freq_found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -USB_ERR_NODEV;
|
||||
|
||||
freq_found:
|
||||
@@ -100,16 +105,18 @@ freq_found:
|
||||
|
||||
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
|
||||
setup->bRequest = AUDIO_REQUEST_SET_CUR;
|
||||
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
|
||||
setup->wIndex = ep_desc->bEndpointAddress;
|
||||
setup->wLength = 3;
|
||||
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].ep_attr & AUDIO_EP_CONTROL_SAMPLING_FEQ) {
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_ENDPOINT;
|
||||
setup->bRequest = AUDIO_REQUEST_SET_CUR;
|
||||
setup->wValue = (AUDIO_EP_CONTROL_SAMPLING_FEQ << 8) | 0x00;
|
||||
setup->wIndex = ep_desc->bEndpointAddress;
|
||||
setup->wLength = 3;
|
||||
|
||||
memcpy(g_audio_buf, &samp_freq, 3);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
memcpy(g_audio_buf, &samp_freq, 3);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
@@ -122,22 +129,27 @@ freq_found:
|
||||
USBH_EP_INIT(audio_class->isoout, ep_desc);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Open audio module :%s, altsetting: %u\r\n", name, altsetting);
|
||||
USB_LOG_INFO("Open audio stream :%s, altsetting: %u\r\n", name, altsetting);
|
||||
audio_class->is_opened = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
{
|
||||
struct usb_setup_packet *setup = audio_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint8_t intf = 0xff;
|
||||
uint8_t altsetting = 1;
|
||||
|
||||
for (size_t i = 0; i < audio_class->module_num; i++) {
|
||||
if (strcmp(name, audio_class->module[i].name) == 0) {
|
||||
intf = audio_class->module[i].data_intf;
|
||||
if (!audio_class || !audio_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = audio_class->hport->setup;
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
|
||||
intf = audio_class->as_msg_table[i].stream_intf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +157,17 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Close audio module :%s\r\n", name);
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("Close audio stream :%s\r\n", name);
|
||||
audio_class->is_opened = false;
|
||||
|
||||
ep_desc = &audio_class->hport->config.intf[intf].altsetting[altsetting].ep[0].ep_desc;
|
||||
@@ -159,104 +181,195 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_SET_INTERFACE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume)
|
||||
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db)
|
||||
{
|
||||
struct usb_setup_packet *setup = audio_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
uint8_t intf = 0xff;
|
||||
uint8_t feature_id = 0xff;
|
||||
uint8_t intf;
|
||||
uint16_t volume_hex;
|
||||
int volume_min_db;
|
||||
int volume_max_db;
|
||||
|
||||
for (size_t i = 0; i < audio_class->module_num; i++) {
|
||||
if (strcmp(name, audio_class->module[i].name) == 0) {
|
||||
intf = audio_class->ctrl_intf;
|
||||
feature_id = audio_class->module[i].feature_unit_id;
|
||||
if (!audio_class || !audio_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if ((volume_db > 127) || (volume_db < -127)) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
setup = audio_class->hport->setup;
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
|
||||
feature_id = audio_class->as_msg_table[i].feature_terminal_id;
|
||||
intf = audio_class->as_msg_table[i].stream_intf;
|
||||
}
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
if (feature_id == 0xff) {
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = AUDIO_REQUEST_GET_CUR;
|
||||
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
|
||||
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur, g_audio_buf, 2);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = AUDIO_REQUEST_GET_MIN;
|
||||
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
|
||||
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min, g_audio_buf, 2);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = AUDIO_REQUEST_GET_MAX;
|
||||
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
|
||||
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max, g_audio_buf, 2);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = AUDIO_REQUEST_GET_RES;
|
||||
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
|
||||
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
|
||||
setup->wLength = 2;
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_res, g_audio_buf, 2);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = AUDIO_REQUEST_SET_CUR;
|
||||
setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch;
|
||||
setup->wIndex = (feature_id << 8) | intf;
|
||||
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
|
||||
setup->wLength = 2;
|
||||
|
||||
volume_hex = -0xDB00 / 100 * volume + 0xdb00;
|
||||
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) {
|
||||
volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256;
|
||||
} else {
|
||||
volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256;
|
||||
}
|
||||
|
||||
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) {
|
||||
volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256;
|
||||
} else {
|
||||
volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get ch:%u dB range: %ddB ~ %ddB\r\n", ch, volume_min_db, volume_max_db);
|
||||
|
||||
if (volume_db >= 0) {
|
||||
volume_hex = volume_db * 256;
|
||||
if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) {
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
} else {
|
||||
volume_hex = volume_db * 256 + 0x10000;
|
||||
if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) {
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(g_audio_buf, &volume_hex, 2);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, NULL);
|
||||
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur = volume_hex;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute)
|
||||
{
|
||||
struct usb_setup_packet *setup = audio_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
uint8_t intf = 0xff;
|
||||
uint8_t feature_id = 0xff;
|
||||
uint8_t intf = 0xff;
|
||||
|
||||
for (size_t i = 0; i < audio_class->module_num; i++) {
|
||||
if (strcmp(name, audio_class->module[i].name) == 0) {
|
||||
intf = audio_class->ctrl_intf;
|
||||
feature_id = audio_class->module[i].feature_unit_id;
|
||||
if (!audio_class || !audio_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = audio_class->hport->setup;
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) {
|
||||
feature_id = audio_class->as_msg_table[i].feature_terminal_id;
|
||||
intf = audio_class->as_msg_table[i].stream_intf;
|
||||
}
|
||||
}
|
||||
|
||||
if (intf == 0xff) {
|
||||
if (feature_id == 0xff) {
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = AUDIO_REQUEST_SET_CUR;
|
||||
setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch;
|
||||
setup->wIndex = (feature_id << 8) | intf;
|
||||
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
memcpy(g_audio_buf, &mute, 1);
|
||||
ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].mute = mute;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_audio_list_module(struct usbh_audio *audio_class)
|
||||
{
|
||||
USB_LOG_INFO("============= Audio module information ===================\r\n");
|
||||
USB_LOG_INFO("bcdADC :%04x\r\n", audio_class->bcdADC);
|
||||
USB_LOG_INFO("Num of modules :%u\r\n", audio_class->module_num);
|
||||
USB_LOG_INFO("Num of altsettings:%u\r\n", audio_class->num_of_intf_altsettings);
|
||||
USB_LOG_RAW("bcdADC :%04x\r\n", audio_class->bcdADC);
|
||||
USB_LOG_RAW("Num of audio stream :%u\r\n", audio_class->stream_intf_num);
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->module_num; i++) {
|
||||
USB_LOG_INFO(" module name :%s\r\n", audio_class->module[i].name);
|
||||
USB_LOG_INFO(" module feature unit id :%d\r\n", audio_class->module[i].feature_unit_id);
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
USB_LOG_RAW("\tstream name :%s\r\n", audio_class->as_msg_table[i].stream_name);
|
||||
USB_LOG_RAW("\tstream intf :%u\r\n", audio_class->as_msg_table[i].stream_intf);
|
||||
USB_LOG_RAW("\tNum of altsetting :%u\r\n", audio_class->as_msg_table[i].num_of_altsetting);
|
||||
|
||||
for (uint8_t j = 0; j < audio_class->num_of_intf_altsettings; j++) {
|
||||
for (uint8_t j = 0; j < audio_class->as_msg_table[i].num_of_altsetting; j++) {
|
||||
if (j == 0) {
|
||||
USB_LOG_INFO(" Ingore altsetting 0\r\n");
|
||||
USB_LOG_RAW("\t\tIngore altsetting 0\r\n");
|
||||
continue;
|
||||
}
|
||||
USB_LOG_INFO(" Altsetting %u\r\n", j);
|
||||
USB_LOG_INFO(" module channels :%u\r\n", audio_class->module[i].altsetting[j].channels);
|
||||
//USB_LOG_INFO(" module format_type :%u\r\n",audio_class->module[i].altsetting[j].format_type);
|
||||
USB_LOG_INFO(" module bitresolution :%u\r\n", audio_class->module[i].altsetting[j].bitresolution);
|
||||
USB_LOG_INFO(" module sampfreq num :%u\r\n", audio_class->module[i].altsetting[j].sampfreq_num);
|
||||
USB_LOG_RAW("\t\tAltsetting :%u\r\n", j);
|
||||
USB_LOG_RAW("\t\t\tbNrChannels :%u\r\n", audio_class->as_msg_table[i].as_format[j].bNrChannels);
|
||||
USB_LOG_RAW("\t\t\tbBitResolution :%u\r\n", audio_class->as_msg_table[i].as_format[j].bBitResolution);
|
||||
USB_LOG_RAW("\t\t\tbSamFreqType :%u\r\n", audio_class->as_msg_table[i].as_format[j].bSamFreqType);
|
||||
|
||||
for (uint8_t k = 0; k < audio_class->module[i].altsetting[j].sampfreq_num; k++) {
|
||||
USB_LOG_INFO(" module sampfreq :%d hz\r\n", audio_class->module[i].altsetting[j].sampfreq[k]);
|
||||
for (uint8_t k = 0; k < audio_class->as_msg_table[i].as_format[j].bSamFreqType; k++) {
|
||||
uint32_t freq = 0;
|
||||
|
||||
memcpy(&freq, &audio_class->as_msg_table[i].as_format[j].tSamFreq[3 * k], 3);
|
||||
USB_LOG_RAW("\t\t\t\tSampleFreq :%u\r\n", freq);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,14 +380,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
|
||||
static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret;
|
||||
uint8_t cur_iface = 0xff;
|
||||
uint8_t cur_iface_count = 0xff;
|
||||
uint8_t cur_alt_setting = 0xff;
|
||||
uint8_t cur_iface = 0;
|
||||
uint8_t cur_iface_count = 0;
|
||||
uint8_t cur_alt_setting = 0;
|
||||
uint8_t input_offset = 0;
|
||||
uint8_t output_offset = 0;
|
||||
uint8_t feature_unit_offset = 0;
|
||||
uint8_t format_offset = 0;
|
||||
uint8_t *p;
|
||||
struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
|
||||
|
||||
struct usbh_audio *audio_class = usbh_audio_class_alloc();
|
||||
if (audio_class == NULL) {
|
||||
@@ -284,8 +397,6 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
audio_class->hport = hport;
|
||||
audio_class->ctrl_intf = intf;
|
||||
audio_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
|
||||
|
||||
hport->config.intf[intf].priv = audio_class;
|
||||
|
||||
p = hport->raw_config_desc;
|
||||
@@ -311,72 +422,49 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
case AUDIO_CONTROL_INPUT_TERMINAL: {
|
||||
struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p;
|
||||
|
||||
audio_class->module[input_offset].input_terminal_id = desc->bTerminalID;
|
||||
audio_class->module[input_offset].input_terminal_type = desc->wTerminalType;
|
||||
audio_class->module[input_offset].input_channel_config = desc->wChannelConfig;
|
||||
|
||||
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
|
||||
audio_class->module[input_offset].terminal_link_id = desc->bTerminalID;
|
||||
}
|
||||
if (desc->wTerminalType == AUDIO_INTERM_MIC) {
|
||||
audio_class->module[input_offset].name = "mic";
|
||||
}
|
||||
memcpy(&ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor));
|
||||
input_offset++;
|
||||
} break;
|
||||
break;
|
||||
case AUDIO_CONTROL_OUTPUT_TERMINAL: {
|
||||
struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p;
|
||||
audio_class->module[output_offset].output_terminal_id = desc->bTerminalID;
|
||||
audio_class->module[output_offset].output_terminal_type = desc->wTerminalType;
|
||||
if (desc->wTerminalType == AUDIO_TERMINAL_STREAMING) {
|
||||
audio_class->module[output_offset].terminal_link_id = desc->bTerminalID;
|
||||
}
|
||||
if (desc->wTerminalType == AUDIO_OUTTERM_SPEAKER) {
|
||||
audio_class->module[output_offset].name = "speaker";
|
||||
}
|
||||
|
||||
memcpy(&ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor));
|
||||
output_offset++;
|
||||
} break;
|
||||
case AUDIO_CONTROL_FEATURE_UNIT: {
|
||||
struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p;
|
||||
audio_class->module[feature_unit_offset].feature_unit_id = desc->bUnitID;
|
||||
audio_class->module[feature_unit_offset].feature_unit_controlsize = desc->bControlSize;
|
||||
|
||||
for (uint8_t j = 0; j < desc->bControlSize; j++) {
|
||||
audio_class->module[feature_unit_offset].feature_unit_controls[j] = p[6 + j];
|
||||
}
|
||||
memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength);
|
||||
feature_unit_offset++;
|
||||
} break;
|
||||
case AUDIO_CONTROL_PROCESSING_UNIT:
|
||||
default:
|
||||
USB_LOG_ERR("Do not support %02x subtype\r\n", p[DESC_bDescriptorSubType]);
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
} else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
|
||||
switch (p[DESC_bDescriptorSubType]) {
|
||||
case AUDIO_STREAMING_GENERAL: {
|
||||
struct audio_cs_if_as_general_descriptor *desc = (struct audio_cs_if_as_general_descriptor *)p;
|
||||
|
||||
break;
|
||||
/* all altsetting have the same general */
|
||||
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].stream_intf = cur_iface;
|
||||
memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_general, desc, sizeof(struct audio_cs_if_as_general_descriptor));
|
||||
} break;
|
||||
case AUDIO_STREAMING_FORMAT_TYPE: {
|
||||
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
|
||||
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].num_of_altsetting = (cur_alt_setting + 1);
|
||||
memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_format[cur_alt_setting], desc, desc->bLength);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if ((cur_iface < (audio_class->ctrl_intf + cur_iface_count)) && (cur_iface > audio_class->ctrl_intf)) {
|
||||
switch (p[DESC_bDescriptorSubType]) {
|
||||
case AUDIO_STREAMING_GENERAL:
|
||||
|
||||
break;
|
||||
case AUDIO_STREAMING_FORMAT_TYPE: {
|
||||
struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p;
|
||||
|
||||
audio_class->module[format_offset].data_intf = cur_iface;
|
||||
audio_class->module[format_offset].altsetting[cur_alt_setting].channels = desc->bNrChannels;
|
||||
audio_class->module[format_offset].altsetting[cur_alt_setting].format_type = desc->bFormatType;
|
||||
audio_class->module[format_offset].altsetting[cur_alt_setting].bitresolution = desc->bBitResolution;
|
||||
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq_num = desc->bSamFreqType;
|
||||
|
||||
for (uint8_t j = 0; j < desc->bSamFreqType; j++) {
|
||||
audio_class->module[format_offset].altsetting[cur_alt_setting].sampfreq[j] = (uint32_t)(p[10 + j] << 16) |
|
||||
(uint32_t)(p[9 + j] << 8) |
|
||||
(uint32_t)(p[8 + j] << 0);
|
||||
}
|
||||
if (cur_alt_setting == (hport->config.intf[intf + 1].altsetting_num - 1)) {
|
||||
format_offset++;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AUDIO_ENDPOINT_DESCRIPTOR_TYPE:
|
||||
if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
|
||||
if (p[DESC_bDescriptorSubType] == AUDIO_ENDPOINT_GENERAL) {
|
||||
struct audio_cs_ep_ep_general_descriptor *desc = (struct audio_cs_ep_ep_general_descriptor *)p;
|
||||
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].ep_attr = desc->bmAttributes;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -387,16 +475,98 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
p += p[DESC_bLength];
|
||||
}
|
||||
|
||||
if ((input_offset != output_offset) && (input_offset != feature_unit_offset) && (input_offset != format_offset)) {
|
||||
if ((input_offset != output_offset) && (input_offset != feature_unit_offset)) {
|
||||
USB_LOG_ERR("Audio control descriptor is invalid\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
audio_class->module_num = input_offset;
|
||||
if (cur_iface_count == 0xff) {
|
||||
USB_LOG_ERR("Audio descriptor must have iad descriptor\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < audio_class->module_num; i++) {
|
||||
ret = usbh_audio_close(audio_class, audio_class->module[i].name);
|
||||
audio_class->stream_intf_num = input_offset;
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
/* Search 0x0101 in input or output desc */
|
||||
for (uint8_t streamidx = 0; streamidx < audio_class->stream_intf_num; streamidx++) {
|
||||
if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_input.bTerminalID) {
|
||||
/* INPUT --> FEATURE UNIT --> OUTPUT */
|
||||
audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[streamidx].ac_input.bTerminalID;
|
||||
|
||||
/* Search input terminal id in feature desc */
|
||||
for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
|
||||
if (ac_msg_table[streamidx].ac_input.bTerminalID == ac_msg_table[featureidx].ac_feature_unit.bSourceID) {
|
||||
audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
|
||||
|
||||
/* Search feature unit id in output desc */
|
||||
for (uint8_t outputid = 0; outputid < audio_class->stream_intf_num; outputid++) {
|
||||
if (ac_msg_table[featureidx].ac_feature_unit.bUnitID == ac_msg_table[outputid].ac_output.bSourceID) {
|
||||
audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[outputid].ac_output.bTerminalID;
|
||||
|
||||
switch (ac_msg_table[outputid].ac_output.wTerminalType) {
|
||||
case AUDIO_OUTTERM_SPEAKER:
|
||||
audio_class->as_msg_table[i].stream_name = "speaker";
|
||||
break;
|
||||
case AUDIO_OUTTERM_HEADPHONES:
|
||||
audio_class->as_msg_table[i].stream_name = "headphoens";
|
||||
break;
|
||||
case AUDIO_OUTTERM_HEADDISPLAY:
|
||||
audio_class->as_msg_table[i].stream_name = "headdisplay";
|
||||
break;
|
||||
default:
|
||||
audio_class->as_msg_table[i].stream_name = "unknown";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_output.bTerminalID) {
|
||||
/* OUTPUT --> FEATURE UNIT --> INPUT */
|
||||
audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[streamidx].ac_output.bTerminalID;
|
||||
|
||||
/* Search output terminal id in feature desc */
|
||||
for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) {
|
||||
if (ac_msg_table[streamidx].ac_output.bSourceID == ac_msg_table[featureidx].ac_feature_unit.bUnitID) {
|
||||
audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID;
|
||||
|
||||
/* Search feature unit id in input desc */
|
||||
for (uint8_t inputid = 0; inputid < audio_class->stream_intf_num; inputid++) {
|
||||
if (ac_msg_table[featureidx].ac_feature_unit.bSourceID == ac_msg_table[inputid].ac_input.bTerminalID) {
|
||||
audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[inputid].ac_input.bTerminalID;
|
||||
|
||||
switch (ac_msg_table[inputid].ac_input.wTerminalType) {
|
||||
case AUDIO_INTERM_MIC:
|
||||
audio_class->as_msg_table[i].stream_name = "mic";
|
||||
break;
|
||||
default:
|
||||
audio_class->as_msg_table[i].stream_name = "unknown";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
if (audio_class->as_msg_table[i].stream_name == NULL) {
|
||||
USB_LOG_ERR("Audio stream search fail\r\n");
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) {
|
||||
ret = usbh_audio_close(audio_class, audio_class->as_msg_table[i].stream_name);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to close audio module :%s\r\n", audio_class->module[i].name);
|
||||
USB_LOG_ERR("Fail to close audio stream :%s\r\n", audio_class->as_msg_table[i].stream_name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -436,20 +606,26 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
static int usbh_audio_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_audio_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_audio_run(struct usbh_audio *audio_class)
|
||||
{
|
||||
(void)audio_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_audio_stop(struct usbh_audio *audio_class)
|
||||
{
|
||||
(void)audio_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver audio_ctrl_class_driver = {
|
||||
@@ -466,20 +642,18 @@ const struct usbh_class_driver audio_streaming_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
|
||||
.class = USB_DEVICE_CLASS_AUDIO,
|
||||
.subclass = AUDIO_SUBCLASS_AUDIOCONTROL,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
|
||||
.bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOCONTROL,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = NULL,
|
||||
.class_driver = &audio_ctrl_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
|
||||
.class = USB_DEVICE_CLASS_AUDIO,
|
||||
.subclass = AUDIO_SUBCLASS_AUDIOSTREAMING,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_AUDIO,
|
||||
.bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = NULL,
|
||||
.class_driver = &audio_streaming_class_driver
|
||||
};
|
||||
|
||||
@@ -8,34 +8,31 @@
|
||||
|
||||
#include "usb_audio.h"
|
||||
|
||||
struct usbh_audio_format_type {
|
||||
uint8_t channels;
|
||||
uint8_t format_type;
|
||||
uint8_t bitresolution;
|
||||
uint8_t sampfreq_num;
|
||||
uint32_t sampfreq[3];
|
||||
#ifndef CONFIG_USBHOST_AUDIO_MAX_STREAMS
|
||||
#define CONFIG_USBHOST_AUDIO_MAX_STREAMS 3
|
||||
#endif
|
||||
|
||||
struct usbh_audio_ac_msg {
|
||||
struct audio_cs_if_ac_input_terminal_descriptor ac_input;
|
||||
struct audio_cs_if_ac_feature_unit_descriptor ac_feature_unit;
|
||||
struct audio_cs_if_ac_output_terminal_descriptor ac_output;
|
||||
};
|
||||
|
||||
/**
|
||||
* bSourceID in feature_unit = input_terminal_id
|
||||
* bSourceID in output_terminal = feature_unit_id
|
||||
* terminal_link_id = input_terminal_id or output_terminal_id (if input_terminal_type or output_terminal_type is 0x0101)
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct usbh_audio_module {
|
||||
const char *name;
|
||||
uint8_t data_intf;
|
||||
struct usbh_audio_as_msg {
|
||||
const char *stream_name;
|
||||
uint8_t stream_intf;
|
||||
uint8_t input_terminal_id;
|
||||
uint16_t input_terminal_type;
|
||||
uint16_t input_channel_config;
|
||||
uint8_t feature_terminal_id;
|
||||
uint8_t output_terminal_id;
|
||||
uint16_t output_terminal_type;
|
||||
uint8_t feature_unit_id;
|
||||
uint8_t feature_unit_controlsize;
|
||||
uint8_t feature_unit_controls[8];
|
||||
uint8_t terminal_link_id;
|
||||
struct usbh_audio_format_type altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
|
||||
uint8_t ep_attr;
|
||||
uint8_t num_of_altsetting;
|
||||
uint16_t volume_min;
|
||||
uint16_t volume_max;
|
||||
uint16_t volume_res;
|
||||
uint16_t volume_cur;
|
||||
bool mute;
|
||||
struct audio_cs_if_as_general_descriptor as_general;
|
||||
struct audio_cs_if_as_format_type_descriptor as_format[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
|
||||
};
|
||||
|
||||
struct usbh_audio {
|
||||
@@ -50,18 +47,19 @@ struct usbh_audio {
|
||||
bool is_opened;
|
||||
uint16_t bcdADC;
|
||||
uint8_t bInCollection;
|
||||
uint8_t num_of_intf_altsettings;
|
||||
struct usbh_audio_module module[2];
|
||||
uint8_t module_num;
|
||||
uint8_t stream_intf_num;
|
||||
struct usbh_audio_as_msg as_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS];
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq);
|
||||
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution);
|
||||
int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
|
||||
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume);
|
||||
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db);
|
||||
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
|
||||
|
||||
void usbh_audio_run(struct usbh_audio *audio_class);
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
|
||||
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
|
||||
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
|
||||
#define CDC_FUNC_DESC_NCM 0x1A
|
||||
|
||||
/* CDC class-specific request codes */
|
||||
/* (usbcdc11.pdf, 6.2, Table 46) */
|
||||
@@ -156,6 +157,17 @@
|
||||
#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
|
||||
#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
|
||||
#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
|
||||
#define CDC_REQUEST_GET_NTB_PARAMETERS 0x80
|
||||
#define CDC_REQUEST_GET_NET_ADDRESS 0x81
|
||||
#define CDC_REQUEST_SET_NET_ADDRESS 0x82
|
||||
#define CDC_REQUEST_GET_NTB_FORMAT 0x83
|
||||
#define CDC_REQUEST_SET_NTB_FORMAT 0x84
|
||||
#define CDC_REQUEST_GET_NTB_INPUT_SIZE 0x85
|
||||
#define CDC_REQUEST_SET_NTB_INPUT_SIZE 0x86
|
||||
#define CDC_REQUEST_GET_MAX_DATAGRAM_SIZE 0x87
|
||||
#define CDC_REQUEST_SET_MAX_DATAGRAM_SIZE 0x88
|
||||
#define CDC_REQUEST_GET_CRC_MODE 0x89
|
||||
#define CDC_REQUEST_SET_CRC_MODE 0x90
|
||||
|
||||
/* Communication feature selector codes */
|
||||
/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
|
||||
@@ -263,6 +275,10 @@
|
||||
#define CDC_ECM_NOTIFY_CODE_RESPONSE_AVAILABLE 0x01
|
||||
#define CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE 0x2A
|
||||
|
||||
#define CDC_NCM_NTH16_SIGNATURE 0x484D434E
|
||||
#define CDC_NCM_NDP16_SIGNATURE_NCM0 0x304D434E
|
||||
#define CDC_NCM_NDP16_SIGNATURE_NCM1 0x314D434E
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Structures based on usbcdc11.pdf (www.usb.org)
|
||||
*----------------------------------------------------------------------------*/
|
||||
@@ -339,7 +355,7 @@ struct cdc_acm_notification {
|
||||
} __PACKED;
|
||||
|
||||
/** Ethernet Networking Functional Descriptor */
|
||||
struct cdc_ecm_descriptor {
|
||||
struct cdc_eth_descriptor {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
@@ -350,7 +366,7 @@ struct cdc_ecm_descriptor {
|
||||
uint8_t bNumberPowerFilters;
|
||||
} __PACKED;
|
||||
|
||||
struct cdc_ecm_notification {
|
||||
struct cdc_eth_notification {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bNotificationType;
|
||||
uint16_t wValue;
|
||||
@@ -359,6 +375,41 @@ struct cdc_ecm_notification {
|
||||
uint8_t data[8];
|
||||
} __PACKED;
|
||||
|
||||
struct cdc_ncm_ntb_parameters {
|
||||
uint16_t wLength;
|
||||
uint16_t bmNtbFormatsSupported;
|
||||
uint32_t dwNtbInMaxSize;
|
||||
uint16_t wNdbInDivisor;
|
||||
uint16_t wNdbInPayloadRemainder;
|
||||
uint16_t wNdbInAlignment;
|
||||
uint16_t wReserved;
|
||||
uint32_t dwNtbOutMaxSize;
|
||||
uint16_t wNdbOutDivisor;
|
||||
uint16_t wNdbOutPayloadRemainder;
|
||||
uint16_t wNdbOutAlignment;
|
||||
uint16_t wNtbOutMaxDatagrams;
|
||||
};
|
||||
|
||||
struct cdc_ncm_nth16 {
|
||||
uint32_t dwSignature;
|
||||
uint16_t wHeaderLength;
|
||||
uint16_t wSequence;
|
||||
uint16_t wBlockLength;
|
||||
uint16_t wNdpIndex;
|
||||
};
|
||||
|
||||
struct cdc_ncm_ndp16_datagram {
|
||||
uint16_t wDatagramIndex;
|
||||
uint16_t wDatagramLength;
|
||||
};
|
||||
|
||||
struct cdc_ncm_ndp16 {
|
||||
uint32_t dwSignature;
|
||||
uint16_t wLength;
|
||||
uint16_t wNextNdpIndex;
|
||||
struct cdc_ncm_ndp16_datagram datagram[];
|
||||
};
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
@@ -370,7 +421,7 @@ struct cdc_ecm_notification {
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -379,7 +430,7 @@ struct cdc_ecm_notification {
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -438,8 +489,8 @@ struct cdc_ecm_notification {
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
|
||||
0x01, /* bFunctionSubClass */ \
|
||||
0x03, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -447,8 +498,8 @@ struct cdc_ecm_notification {
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
|
||||
CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
|
||||
0x01, /* bInterfaceSubClass */ \
|
||||
0x03, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
@@ -473,7 +524,7 @@ struct cdc_ecm_notification {
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x08, 0x00, /* wMaxPacketSize */ \
|
||||
0x10, /* bInterval */ \
|
||||
0x05, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
@@ -499,7 +550,7 @@ struct cdc_ecm_notification {
|
||||
|
||||
#define DBVAL_BE(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF)
|
||||
|
||||
/*Length of template descriptor: 66 bytes*/
|
||||
/*Length of template descriptor: 71 bytes*/
|
||||
#define CDC_ECM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_ECM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
||||
@@ -537,9 +588,84 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx)
|
||||
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
|
||||
str_idx, /* Device's MAC string index */\
|
||||
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
|
||||
WBVAL(wMaxSegmentSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
|
||||
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
|
||||
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x10, 0x00, /* wMaxPacketSize */ \
|
||||
0x05, /* bInterval */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
|
||||
0x00, /* bInterfaceSubClass */ \
|
||||
0x00, /* bInterfaceProtocol */ \
|
||||
0x00, /* iInterface */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
out_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00, /* bInterval */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
in_ep, /* bEndpointAddress */ \
|
||||
0x02, /* bmAttributes */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
|
||||
0x00 /* bInterval */
|
||||
// clang-format on
|
||||
|
||||
/*Length of template descriptor: 77 bytes*/
|
||||
#define CDC_NCM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 13 + 6 + 7 + 9 + 7 + 7)
|
||||
// clang-format off
|
||||
#define CDC_NCM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, wMaxPacketSize, \
|
||||
eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) \
|
||||
/* Interface Associate */ \
|
||||
0x08, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bFirstInterface */ \
|
||||
0x02, /* bInterfaceCount */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
|
||||
CDC_NETWORK_CONTROL_MODEL, /* bFunctionSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bFunctionProtocol */ \
|
||||
0x00, /* iFunction */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
bFirstInterface, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
|
||||
CDC_NETWORK_CONTROL_MODEL, /* bInterfaceSubClass */ \
|
||||
CDC_COMMON_PROTOCOL_NONE, /* bInterfaceProtocol */ \
|
||||
str_idx, /* iInterface */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
|
||||
WBVAL(CDC_V1_10), /* bcdCDC */ \
|
||||
0x05, /* bLength */ \
|
||||
CDC_CS_INTERFACE, /* bDescriptorType */ \
|
||||
CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
|
||||
bFirstInterface, /* bMasterInterface */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
|
||||
/* CDC ETH Functional Descriptor */ \
|
||||
0x0D, /* bFunctionLength */\
|
||||
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */\
|
||||
CDC_FUNC_DESC_ETHERNET_NETWORKING, /* Ethernet Networking functional descriptor subtype */\
|
||||
str_idx, /* Device's MAC string index */\
|
||||
DBVAL_BE(eth_statistics), /* Ethernet statistics (bitmap) */\
|
||||
WBVAL(wMaxPacketSize),/* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */\
|
||||
WBVAL(wNumberMCFilters), /* wNumberMCFilters: the number of multicast filters */\
|
||||
bNumberPowerFilters, /* bNumberPowerFilters: the number of wakeup power filters */\
|
||||
0x06, \
|
||||
CDC_CS_INTERFACE, \
|
||||
CDC_FUNC_DESC_NCM, \
|
||||
0x00, 0x01, \
|
||||
0x23, \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
int_ep, /* bEndpointAddress */ \
|
||||
|
||||
@@ -1,29 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_CDC_H
|
||||
#define USBD_CDC_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
// legacy for old version
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
/* Init cdc acm interface driver */
|
||||
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
|
||||
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
|
||||
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_CDC_H */
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_cdc_acm.h"
|
||||
|
||||
const char *stop_name[] = { "1", "1.5", "2" };
|
||||
const char *parity_name[] = { "N", "O", "E", "M", "S" };
|
||||
@@ -42,7 +42,7 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
|
||||
memcpy(&line_coding, *data, setup->wLength);
|
||||
USB_LOG_DBG("Set intf:%d linecoding <%d %d %s %s>\r\n",
|
||||
intf_num,
|
||||
line_coding.dwDTERate,
|
||||
(unsigned int)line_coding.dwDTERate,
|
||||
line_coding.bDataBits,
|
||||
parity_name[line_coding.bParityType],
|
||||
stop_name[line_coding.bCharFormat]);
|
||||
@@ -67,7 +67,7 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
|
||||
*len = 7;
|
||||
USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
|
||||
intf_num,
|
||||
line_coding.dwDTERate,
|
||||
(unsigned int)line_coding.dwDTERate,
|
||||
line_coding.bCharFormat,
|
||||
line_coding.bParityType,
|
||||
line_coding.bDataBits);
|
||||
@@ -85,6 +85,8 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
|
||||
|
||||
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
intf->class_interface_handler = cdc_acm_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
@@ -95,10 +97,16 @@ struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interfa
|
||||
|
||||
__WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)line_coding;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
|
||||
line_coding->dwDTERate = 2000000;
|
||||
line_coding->bDataBits = 8;
|
||||
line_coding->bParityType = 0;
|
||||
@@ -107,12 +115,20 @@ __WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc
|
||||
|
||||
__WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)dtr;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)rts;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
}
|
||||
29
class/cdc/usbd_cdc_acm.h
Normal file
29
class/cdc/usbd_cdc_acm.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_CDC_ACM_H
|
||||
#define USBD_CDC_ACM_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init cdc acm interface driver */
|
||||
struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding);
|
||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr);
|
||||
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts);
|
||||
void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_CDC_ACM_H */
|
||||
@@ -7,23 +7,21 @@
|
||||
#include "usbd_cdc_ecm.h"
|
||||
|
||||
#define CDC_ECM_OUT_EP_IDX 0
|
||||
#define CDC_ECM_IN_EP_IDX 1
|
||||
#define CDC_ECM_INT_EP_IDX 2
|
||||
#define CDC_ECM_IN_EP_IDX 1
|
||||
#define CDC_ECM_INT_EP_IDX 2
|
||||
|
||||
/* Ethernet Maximum Segment size, typically 1514 bytes */
|
||||
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1536U
|
||||
|
||||
/* Describe EndPoints configuration */
|
||||
static struct usbd_endpoint cdc_ecm_ep_data[3];
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define CDC_ECM_MAX_PACKET_SIZE 512
|
||||
#else
|
||||
#define CDC_ECM_MAX_PACKET_SIZE 64
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[USB_ALIGN_UP(CONFIG_CDC_ECM_ETH_MAX_SEGSZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[USB_ALIGN_UP(CONFIG_CDC_ECM_ETH_MAX_SEGSZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
#endif
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[USB_ALIGN_UP(16, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
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;
|
||||
|
||||
@@ -35,7 +33,7 @@ static uint32_t g_connect_speed_table[2] = { CDC_ECM_CONNECT_SPEED_UPSTREAM,
|
||||
|
||||
void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed)
|
||||
{
|
||||
struct cdc_ecm_notification *notify = (struct cdc_ecm_notification *)g_cdc_ecm_notify_buf;
|
||||
struct cdc_eth_notification *notify = (struct cdc_eth_notification *)g_cdc_ecm_notify_buf;
|
||||
uint8_t bytes2send = 0;
|
||||
|
||||
notify->bmRequestType = CDC_ECM_BMREQUEST_TYPE_ECM;
|
||||
@@ -74,8 +72,10 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes2send) {
|
||||
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
|
||||
if (usb_device_is_configured(0)) {
|
||||
if (bytes2send) {
|
||||
usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,21 +85,25 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
|
||||
"bRequest 0x%02x\r\n",
|
||||
setup->bRequest);
|
||||
|
||||
(void)busid;
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
g_cmd_intf = LO_BYTE(setup->wIndex);
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case CDC_REQUEST_SET_ETHERNET_PACKET_FILTER:
|
||||
/* bit0 Promiscuous
|
||||
/* bit0 Promiscuous
|
||||
* bit1 ALL Multicast
|
||||
* bit2 Directed
|
||||
* bit3 Broadcast
|
||||
* bit4 Multicast
|
||||
*/
|
||||
if (g_current_net_status == 0) {
|
||||
g_current_net_status = 1;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
g_connect_speed_table[0] = 100000000; /* 100 Mbps */
|
||||
g_connect_speed_table[1] = 100000000; /* 100 Mbps */
|
||||
usbd_cdc_ecm_set_connect(true, g_connect_speed_table);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||
@@ -111,15 +115,19 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
|
||||
|
||||
void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)busid;
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
g_current_net_status = 0;
|
||||
g_cdc_ecm_rx_data_length = 0;
|
||||
g_cdc_ecm_tx_data_length = 0;
|
||||
g_cdc_ecm_rx_data_buffer = NULL;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -129,36 +137,45 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
|
||||
void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
g_cdc_ecm_rx_data_length += nbytes;
|
||||
(void)busid;
|
||||
|
||||
if (nbytes < CDC_ECM_MAX_PACKET_SIZE) {
|
||||
g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer;
|
||||
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||
} else {
|
||||
usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], CDC_ECM_MAX_PACKET_SIZE);
|
||||
}
|
||||
g_cdc_ecm_rx_data_length = nbytes;
|
||||
usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_data_length);
|
||||
}
|
||||
|
||||
void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % CDC_ECM_MAX_PACKET_SIZE) == 0 && nbytes) {
|
||||
(void)busid;
|
||||
|
||||
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(0, ep, NULL, 0);
|
||||
} else {
|
||||
usbd_cdc_ecm_data_send_done(g_cdc_ecm_tx_data_length);
|
||||
g_cdc_ecm_tx_data_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if (g_current_net_status == 1) {
|
||||
g_current_net_status = 2;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table);
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
if (g_current_net_status == 2) {
|
||||
g_current_net_status = 3;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE, 0, g_connect_speed_table);
|
||||
} else {
|
||||
g_current_net_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (g_cdc_ecm_tx_data_length > 0) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
@@ -166,14 +183,17 @@ int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len)
|
||||
g_cdc_ecm_tx_data_length = len;
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length);
|
||||
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length);
|
||||
return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, len);
|
||||
}
|
||||
|
||||
void usbd_cdc_ecm_start_read_next(void)
|
||||
int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
g_cdc_ecm_rx_data_length = 0;
|
||||
g_cdc_ecm_rx_data_buffer = NULL;
|
||||
usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, CDC_ECM_MAX_PACKET_SIZE);
|
||||
return usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, buf, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
@@ -181,19 +201,19 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
if (g_cdc_ecm_rx_data_buffer == NULL) {
|
||||
if (g_cdc_ecm_rx_data_length == 0) {
|
||||
return NULL;
|
||||
}
|
||||
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
usbd_cdc_ecm_start_read_next();
|
||||
usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||
usb_memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length);
|
||||
p->len = g_cdc_ecm_rx_data_length;
|
||||
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length);
|
||||
usbd_cdc_ecm_start_read_next();
|
||||
usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -202,6 +222,10 @@ int usbd_cdc_ecm_eth_tx(struct pbuf *p)
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer;
|
||||
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (g_cdc_ecm_tx_data_length > 0) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
@@ -212,13 +236,11 @@ int usbd_cdc_ecm_eth_tx(struct pbuf *p)
|
||||
|
||||
buffer = g_cdc_ecm_tx_buffer;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
usb_memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
g_cdc_ecm_tx_data_length = p->tot_len;
|
||||
|
||||
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, g_cdc_ecm_tx_data_length);
|
||||
return usbd_cdc_ecm_start_write(g_cdc_ecm_tx_buffer, p->tot_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -243,11 +265,30 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const
|
||||
return intf;
|
||||
}
|
||||
|
||||
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2])
|
||||
int usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2])
|
||||
{
|
||||
memcpy(g_connect_speed_table, speed, 8);
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (connect) {
|
||||
g_current_net_status = 2;
|
||||
memcpy(g_connect_speed_table, speed, 8);
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL);
|
||||
} else {
|
||||
g_current_net_status = 1;
|
||||
usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_DISCONNECTED, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len)
|
||||
__WEAK void usbd_cdc_ecm_data_recv_done(uint32_t len)
|
||||
{
|
||||
}
|
||||
(void)len;
|
||||
}
|
||||
|
||||
__WEAK void usbd_cdc_ecm_data_send_done(uint32_t len)
|
||||
{
|
||||
(void)len;
|
||||
}
|
||||
|
||||
@@ -12,21 +12,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Ethernet Maximum Segment size, typically 1514 bytes */
|
||||
#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
||||
|
||||
/* Init cdc ecm interface driver */
|
||||
struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]);
|
||||
int usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]);
|
||||
|
||||
/* Api for eth only without any net stack */
|
||||
uint8_t *usbd_cdc_ecm_get_tx_buffer(void);
|
||||
void usbd_cdc_ecm_send_done(void);
|
||||
void usbd_cdc_ecm_data_recv_done(uint32_t len);
|
||||
void usbd_cdc_ecm_data_send_done(uint32_t len);
|
||||
int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len);
|
||||
void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len);
|
||||
void usbd_cdc_ecm_start_read_next(void);
|
||||
int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len);
|
||||
|
||||
#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP
|
||||
#include "lwip/netif.h"
|
||||
|
||||
@@ -12,18 +12,18 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/ttyACM%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[64];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_acm_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_cdc_acm g_cdc_acm_class[CONFIG_USBHOST_MAX_CDC_ACM_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_cdc_acm_class[devno], 0, sizeof(struct usbh_cdc_acm));
|
||||
g_cdc_acm_class[devno].minor = devno;
|
||||
return &g_cdc_acm_class[devno];
|
||||
@@ -34,17 +34,22 @@ static struct usbh_cdc_acm *usbh_cdc_acm_class_alloc(void)
|
||||
|
||||
static void usbh_cdc_acm_class_free(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
int devno = cdc_acm_class->minor;
|
||||
uint8_t devno = cdc_acm_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
struct usb_setup_packet *setup = cdc_acm_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cdc_acm_class || !cdc_acm_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cdc_acm_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
|
||||
@@ -52,33 +57,43 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_
|
||||
setup->wIndex = cdc_acm_class->intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
memcpy(g_cdc_acm_buf, line_coding, sizeof(struct cdc_line_coding));
|
||||
memcpy(g_cdc_acm_buf[cdc_acm_class->minor], line_coding, sizeof(struct cdc_line_coding));
|
||||
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
|
||||
return usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
struct usb_setup_packet *setup = cdc_acm_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!cdc_acm_class || !cdc_acm_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cdc_acm_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = cdc_acm_class->intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf);
|
||||
ret = usbh_control_transfer(cdc_acm_class->hport, setup, g_cdc_acm_buf[cdc_acm_class->minor]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(line_coding, g_cdc_acm_buf, sizeof(struct cdc_line_coding));
|
||||
memcpy(line_coding, g_cdc_acm_buf[cdc_acm_class->minor], sizeof(struct cdc_line_coding));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts)
|
||||
{
|
||||
struct usb_setup_packet *setup = cdc_acm_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cdc_acm_class || !cdc_acm_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cdc_acm_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
|
||||
@@ -216,20 +231,26 @@ int usbh_cdc_acm_bulk_out_transfer(struct usbh_cdc_acm *cdc_acm_class, uint8_t *
|
||||
|
||||
static int usbh_cdc_data_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_cdc_data_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
(void)cdc_acm_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||
{
|
||||
(void)cdc_acm_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_acm_class_driver = {
|
||||
@@ -245,21 +266,19 @@ const struct usbh_class_driver cdc_data_class_driver = {
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_CDC,
|
||||
.subclass = CDC_ABSTRACT_CONTROL_MODEL,
|
||||
.protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
|
||||
.bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = NULL,
|
||||
.class_driver = &cdc_acm_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_CDC_DATA,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = NULL,
|
||||
.class_driver = &cdc_data_class_driver
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@ struct usbh_cdc_acm {
|
||||
|
||||
uint8_t intf;
|
||||
uint8_t minor;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -21,18 +21,23 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
|
||||
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE 1514U
|
||||
#define CONFIG_USBHOST_CDC_ECM_PKT_FILTER 0x000C
|
||||
#define CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE 1514U
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[16];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_inttx_buffer[USB_ALIGN_UP(16, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_cdc_ecm g_cdc_ecm_class;
|
||||
|
||||
static int usbh_cdc_ecm_set_eth_packet_filter(struct usbh_cdc_ecm *cdc_ecm_class, uint16_t filter_value)
|
||||
{
|
||||
struct usb_setup_packet *setup = cdc_ecm_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cdc_ecm_class || !cdc_ecm_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cdc_ecm_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SET_ETHERNET_PACKET_FILTER;
|
||||
@@ -95,7 +100,7 @@ static int usbh_cdc_ecm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
break;
|
||||
case CDC_CS_INTERFACE:
|
||||
if ((cur_iface == cdc_ecm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
|
||||
struct cdc_ecm_descriptor *desc = (struct cdc_ecm_descriptor *)p;
|
||||
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
|
||||
mac_str_idx = desc->iMACAddress;
|
||||
cdc_ecm_class->max_segment_size = desc->wMaxSegmentSize;
|
||||
goto get_mac;
|
||||
@@ -139,8 +144,8 @@ get_mac:
|
||||
cdc_ecm_class->mac[4],
|
||||
cdc_ecm_class->mac[5]);
|
||||
|
||||
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE) {
|
||||
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SEGSZE, cdc_ecm_class->max_segment_size);
|
||||
if (cdc_ecm_class->max_segment_size > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE) {
|
||||
USB_LOG_ERR("CDC ECM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, cdc_ecm_class->max_segment_size);
|
||||
} else {
|
||||
USB_LOG_INFO("CDC ECM Max Segment Size:%u\r\n", cdc_ecm_class->max_segment_size);
|
||||
}
|
||||
@@ -176,7 +181,7 @@ get_mac:
|
||||
}
|
||||
}
|
||||
|
||||
/* bit0 Promiscuous
|
||||
/* bit0 Promiscuous
|
||||
* bit1 ALL Multicast
|
||||
* bit2 Directed
|
||||
* bit3 Broadcast
|
||||
@@ -188,7 +193,7 @@ get_mac:
|
||||
}
|
||||
USB_LOG_INFO("Set CDC ECM packet filter:%04x\r\n", CONFIG_USBHOST_CDC_ECM_PKT_FILTER);
|
||||
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
@@ -226,14 +231,12 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_rx_thread(void *argument)
|
||||
void usbh_cdc_ecm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
uint32_t g_cdc_ecm_rx_length;
|
||||
int ret;
|
||||
err_t err;
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
|
||||
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
USB_LOG_INFO("Create cdc ecm rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
@@ -249,36 +252,33 @@ find_class:
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(128);
|
||||
}
|
||||
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_length], USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkin_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkin, g_cdc_ecm_rx_buffer, CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_cdc_ecm_rx_length += g_cdc_ecm_class.bulkin_urb.actual_length;
|
||||
g_cdc_ecm_rx_length = g_cdc_ecm_class.bulkin_urb.actual_length;
|
||||
|
||||
if (g_cdc_ecm_class.bulkin_urb.actual_length != USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
|
||||
/* A transfer is complete because last packet is a short packet.
|
||||
* Short packet is not zero, match g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize).
|
||||
* Short packet is zero, check if g_cdc_ecm_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 512 < 1514.
|
||||
* This case is always true
|
||||
*/
|
||||
if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize) ||
|
||||
(g_cdc_ecm_class.bulkin_urb.actual_length < CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE)) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
usbh_cdc_ecm_eth_input(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
|
||||
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
} else {
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
|
||||
}
|
||||
g_cdc_ecm_rx_length = 0;
|
||||
} else {
|
||||
/* read continue util read short packet */
|
||||
/* There's no way to run here. */
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
@@ -288,38 +288,31 @@ delete:
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void)
|
||||
{
|
||||
int ret;
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer = g_cdc_ecm_tx_buffer;
|
||||
return g_cdc_ecm_tx_buffer;
|
||||
}
|
||||
|
||||
int usbh_cdc_ecm_eth_output(uint32_t buflen)
|
||||
{
|
||||
if (g_cdc_ecm_class.connect_status == false) {
|
||||
return ERR_BUF;
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
USB_LOG_DBG("txlen:%d\r\n", buflen);
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
|
||||
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
return usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
(void)cdc_ecm_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
(void)cdc_ecm_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_ecm_class_driver = {
|
||||
@@ -330,10 +323,9 @@ const struct usbh_class_driver cdc_ecm_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_CDC,
|
||||
.subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
|
||||
.protocol = CDC_COMMON_PROTOCOL_NONE,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
|
||||
.bInterfaceSubClass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL,
|
||||
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
|
||||
.id_table = NULL,
|
||||
.class_driver = &cdc_ecm_class_driver
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,9 +8,6 @@
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
struct usbh_cdc_ecm {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
@@ -23,15 +20,13 @@ struct usbh_cdc_ecm {
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
|
||||
|
||||
uint8_t mac[6];
|
||||
bool connect_status;
|
||||
uint16_t max_segment_size;
|
||||
uint32_t speed[2];
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gateway;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -43,11 +38,13 @@ int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
|
||||
|
||||
err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p);
|
||||
void usbh_cdc_ecm_rx_thread(void *argument);
|
||||
uint8_t *usbh_cdc_ecm_get_eth_txbuf(void);
|
||||
int usbh_cdc_ecm_eth_output(uint32_t buflen);
|
||||
void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_cdc_ecm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_CDC_ACM_H */
|
||||
#endif /* USBH_CDC_ECM_H */
|
||||
|
||||
411
class/cdc/usbh_cdc_ncm.c
Normal file
411
class/cdc/usbh_cdc_ncm.c
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_cdc_ncm.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_cdc_ncm"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/cdc_ncm"
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||
#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
|
||||
|
||||
/* interface descriptor field offsets */
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE 1514U
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_rx_buffer[CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_tx_buffer[CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_inttx_buffer[USB_ALIGN_UP(16, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ncm_buf[USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_cdc_ncm g_cdc_ncm_class;
|
||||
|
||||
static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, struct cdc_ncm_ntb_parameters *param)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!cdc_ncm_class || !cdc_ncm_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cdc_ncm_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_NTB_PARAMETERS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = cdc_ncm_class->ctrl_intf;
|
||||
setup->wLength = 28;
|
||||
|
||||
ret = usbh_control_transfer(cdc_ncm_class->hport, setup, g_cdc_ncm_buf);
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)param, g_cdc_ncm_buf, ret - 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_ntb_parameters(struct cdc_ncm_ntb_parameters *param)
|
||||
{
|
||||
USB_LOG_RAW("CDC NCM ntb parameters:\r\n");
|
||||
USB_LOG_RAW("wLength: 0x%02x \r\n", param->wLength);
|
||||
USB_LOG_RAW("bmNtbFormatsSupported: %s \r\n", param->bmNtbFormatsSupported ? "NTB16" : "NTB32");
|
||||
|
||||
USB_LOG_RAW("dwNtbInMaxSize: 0x%08x \r\n", (unsigned int)param->dwNtbInMaxSize);
|
||||
USB_LOG_RAW("wNdbInDivisor: 0x%02x \r\n", param->wNdbInDivisor);
|
||||
USB_LOG_RAW("wNdbInPayloadRemainder: 0x%02x \r\n", param->wNdbInPayloadRemainder);
|
||||
USB_LOG_RAW("wNdbInAlignment: 0x%02x \r\n", param->wNdbInAlignment);
|
||||
|
||||
USB_LOG_RAW("dwNtbOutMaxSize: 0x%08x \r\n", (unsigned int)param->dwNtbOutMaxSize);
|
||||
USB_LOG_RAW("wNdbOutDivisor: 0x%02x \r\n", param->wNdbOutDivisor);
|
||||
USB_LOG_RAW("wNdbOutPayloadRemainder: 0x%02x \r\n", param->wNdbOutPayloadRemainder);
|
||||
USB_LOG_RAW("wNdbOutAlignment: 0x%02x \r\n", param->wNdbOutAlignment);
|
||||
|
||||
USB_LOG_RAW("wNtbOutMaxDatagrams: 0x%02x \r\n", param->wNtbOutMaxDatagrams);
|
||||
}
|
||||
|
||||
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||
{
|
||||
int ret;
|
||||
|
||||
usbh_int_urb_fill(&cdc_ncm_class->intin_urb, cdc_ncm_class->hport, cdc_ncm_class->intin, g_cdc_ncm_inttx_buffer, 16, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&cdc_ncm_class->intin_urb);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION) {
|
||||
if (g_cdc_ncm_inttx_buffer[2] == CDC_ECM_NET_CONNECTED) {
|
||||
cdc_ncm_class->connect_status = true;
|
||||
} else {
|
||||
cdc_ncm_class->connect_status = false;
|
||||
}
|
||||
} else if (g_cdc_ncm_inttx_buffer[1] == CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE) {
|
||||
memcpy(cdc_ncm_class->speed, &g_cdc_ncm_inttx_buffer[8], 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_cdc_ncm_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint8_t altsetting = 0;
|
||||
char mac_buffer[12];
|
||||
uint8_t *p;
|
||||
uint8_t cur_iface = 0xff;
|
||||
uint8_t mac_str_idx = 0xff;
|
||||
|
||||
struct usbh_cdc_ncm *cdc_ncm_class = &g_cdc_ncm_class;
|
||||
|
||||
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
|
||||
|
||||
cdc_ncm_class->hport = hport;
|
||||
cdc_ncm_class->ctrl_intf = intf;
|
||||
cdc_ncm_class->data_intf = intf + 1;
|
||||
|
||||
hport->config.intf[intf].priv = cdc_ncm_class;
|
||||
hport->config.intf[intf + 1].priv = NULL;
|
||||
|
||||
p = hport->raw_config_desc;
|
||||
while (p[DESC_bLength]) {
|
||||
switch (p[DESC_bDescriptorType]) {
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
cur_iface = p[INTF_DESC_bInterfaceNumber];
|
||||
//cur_alt_setting = p[INTF_DESC_bAlternateSetting];
|
||||
break;
|
||||
case CDC_CS_INTERFACE:
|
||||
if ((cur_iface == cdc_ncm_class->ctrl_intf) && p[DESC_bDescriptorSubType] == CDC_FUNC_DESC_ETHERNET_NETWORKING) {
|
||||
struct cdc_eth_descriptor *desc = (struct cdc_eth_descriptor *)p;
|
||||
mac_str_idx = desc->iMACAddress;
|
||||
cdc_ncm_class->max_segment_size = desc->wMaxSegmentSize;
|
||||
goto get_mac;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
}
|
||||
|
||||
get_mac:
|
||||
if (mac_str_idx == 0xff) {
|
||||
USB_LOG_ERR("Do not find cdc ncm mac string\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(mac_buffer, 0, 12);
|
||||
ret = usbh_get_string_desc(cdc_ncm_class->hport, mac_str_idx, (uint8_t *)mac_buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0, j = 0; i < 12; i += 2, j++) {
|
||||
char byte_str[3];
|
||||
byte_str[0] = mac_buffer[i];
|
||||
byte_str[1] = mac_buffer[i + 1];
|
||||
byte_str[2] = '\0';
|
||||
|
||||
uint32_t byte = strtoul(byte_str, NULL, 16);
|
||||
cdc_ncm_class->mac[j] = (unsigned char)byte;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("CDC NCM MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
cdc_ncm_class->mac[0],
|
||||
cdc_ncm_class->mac[1],
|
||||
cdc_ncm_class->mac[2],
|
||||
cdc_ncm_class->mac[3],
|
||||
cdc_ncm_class->mac[4],
|
||||
cdc_ncm_class->mac[5]);
|
||||
|
||||
if (cdc_ncm_class->max_segment_size > CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE) {
|
||||
USB_LOG_ERR("CDC NCM Max Segment Size is overflow, default is %u, but now %u\r\n", CONFIG_USBHOST_CDC_NCM_ETH_MAX_SEGSZE, cdc_ncm_class->max_segment_size);
|
||||
} else {
|
||||
USB_LOG_INFO("CDC NCM Max Segment Size:%u\r\n", cdc_ncm_class->max_segment_size);
|
||||
}
|
||||
|
||||
usbh_cdc_ncm_get_ntb_parameters(cdc_ncm_class, &cdc_ncm_class->ntb_param);
|
||||
print_ntb_parameters(&cdc_ncm_class->ntb_param);
|
||||
|
||||
/* enable int ep */
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
USBH_EP_INIT(cdc_ncm_class->intin, ep_desc);
|
||||
|
||||
if (hport->config.intf[intf + 1].altsetting_num > 1) {
|
||||
altsetting = hport->config.intf[intf + 1].altsetting_num - 1;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[altsetting].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[altsetting].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Select cdc ncm altsetting: %d\r\n", altsetting);
|
||||
usbh_set_interface(cdc_ncm_class->hport, cdc_ncm_class->data_intf, altsetting);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(cdc_ncm_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(cdc_ncm_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_cdc_ncm_run(cdc_ncm_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)hport->config.intf[intf].priv;
|
||||
|
||||
if (cdc_ncm_class) {
|
||||
if (cdc_ncm_class->bulkin) {
|
||||
usbh_kill_urb(&cdc_ncm_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (cdc_ncm_class->bulkout) {
|
||||
usbh_kill_urb(&cdc_ncm_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (cdc_ncm_class->intin) {
|
||||
usbh_kill_urb(&cdc_ncm_class->intin_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_cdc_ncm_stop(cdc_ncm_class);
|
||||
}
|
||||
|
||||
memset(cdc_ncm_class, 0, sizeof(struct usbh_cdc_ncm));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
uint32_t g_cdc_ncm_rx_length;
|
||||
int ret;
|
||||
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
uint32_t transfer_size = CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE;
|
||||
#else
|
||||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
USB_LOG_INFO("Create cdc ncm rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
g_cdc_ncm_class.connect_status = false;
|
||||
if (usbh_find_class_instance("/dev/cdc_ncm") == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
while (g_cdc_ncm_class.connect_status == false) {
|
||||
ret = usbh_cdc_ncm_get_connect_status(&g_cdc_ncm_class);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
}
|
||||
|
||||
g_cdc_ncm_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkin_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkin, &g_cdc_ncm_rx_buffer[g_cdc_ncm_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_cdc_ncm_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_cdc_ncm_rx_length += g_cdc_ncm_class.bulkin_urb.actual_length;
|
||||
|
||||
/* A transfer is complete because last packet is a short packet.
|
||||
* Short packet is not zero, match g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize).
|
||||
* Short packet is zero, check if g_cdc_ncm_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 1024 < 2048.
|
||||
*/
|
||||
if ((g_cdc_ncm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ncm_class.bulkin->wMaxPacketSize)) ||
|
||||
(g_cdc_ncm_class.bulkin_urb.actual_length < transfer_size)) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ncm_rx_length);
|
||||
|
||||
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_rx_buffer[0];
|
||||
if ((nth16->dwSignature != CDC_NCM_NTH16_SIGNATURE) ||
|
||||
(nth16->wHeaderLength != 12) ||
|
||||
(nth16->wBlockLength != g_cdc_ncm_rx_length)) {
|
||||
USB_LOG_ERR("invalid rx nth16\r\n");
|
||||
g_cdc_ncm_rx_length = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex];
|
||||
if ((ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM0) && (ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM1)) {
|
||||
USB_LOG_ERR("invalid rx ndp16\r\n");
|
||||
g_cdc_ncm_rx_length = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t datagram_num = (ndp16->wLength - 8) / 4;
|
||||
|
||||
USB_LOG_DBG("datagram num:%02x\r\n", datagram_num);
|
||||
for (uint16_t i = 0; i < datagram_num; i++) {
|
||||
struct cdc_ncm_ndp16_datagram *ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex + 8 + 4 * i];
|
||||
if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
|
||||
USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
|
||||
|
||||
uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
|
||||
usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength);
|
||||
}
|
||||
}
|
||||
|
||||
g_cdc_ncm_rx_length = 0;
|
||||
} else {
|
||||
#if CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
if (g_cdc_ncm_rx_length == CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
|
||||
#else
|
||||
if ((g_cdc_ncm_rx_length + (16 * 1024)) > CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
USB_LOG_INFO("Delete cdc ncm rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void)
|
||||
{
|
||||
return &g_cdc_ncm_tx_buffer[16];
|
||||
}
|
||||
|
||||
int usbh_cdc_ncm_eth_output(uint32_t buflen)
|
||||
{
|
||||
struct cdc_ncm_ndp16_datagram *ndp16_datagram;
|
||||
|
||||
if (g_cdc_ncm_class.connect_status == false) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_tx_buffer[0];
|
||||
|
||||
nth16->dwSignature = CDC_NCM_NTH16_SIGNATURE;
|
||||
nth16->wHeaderLength = 12;
|
||||
nth16->wSequence = g_cdc_ncm_class.bulkout_sequence++;
|
||||
nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(buflen, 4);
|
||||
nth16->wNdpIndex = 16 + USB_ALIGN_UP(buflen, 4);
|
||||
|
||||
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex];
|
||||
|
||||
ndp16->dwSignature = CDC_NCM_NDP16_SIGNATURE_NCM0;
|
||||
ndp16->wLength = 16;
|
||||
ndp16->wNextNdpIndex = 0;
|
||||
|
||||
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 0];
|
||||
ndp16_datagram->wDatagramIndex = 16;
|
||||
ndp16_datagram->wDatagramLength = buflen;
|
||||
|
||||
ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 1];
|
||||
ndp16_datagram->wDatagramIndex = 0;
|
||||
ndp16_datagram->wDatagramLength = 0;
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", nth16->wBlockLength);
|
||||
|
||||
usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkout_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkout, g_cdc_ncm_tx_buffer, nth16->wBlockLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
return usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||
{
|
||||
(void)cdc_ncm_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
|
||||
{
|
||||
(void)cdc_ncm_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver cdc_ncm_class_driver = {
|
||||
.driver_name = "cdc_ncm",
|
||||
.connect = usbh_cdc_ncm_connect,
|
||||
.disconnect = usbh_cdc_ncm_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_CDC,
|
||||
.bInterfaceSubClass = CDC_NETWORK_CONTROL_MODEL,
|
||||
.bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE,
|
||||
.id_table = NULL,
|
||||
.class_driver = &cdc_ncm_class_driver
|
||||
};
|
||||
54
class/cdc/usbh_cdc_ncm.h
Normal file
54
class/cdc/usbh_cdc_ncm.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_CDC_NCM_H
|
||||
#define USBH_CDC_NCM_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
struct usbh_cdc_ncm {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* Interrupt IN endpoint */
|
||||
struct usbh_urb bulkout_urb; /* Bulk out endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN endpoint */
|
||||
struct usbh_urb intin_urb; /* Interrupt IN endpoint */
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
|
||||
struct cdc_ncm_ntb_parameters ntb_param;
|
||||
uint16_t bulkin_sequence;
|
||||
uint16_t bulkout_sequence;
|
||||
|
||||
uint8_t mac[6];
|
||||
bool connect_status;
|
||||
uint16_t max_segment_size;
|
||||
uint32_t speed[2];
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class);
|
||||
|
||||
void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class);
|
||||
void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
|
||||
|
||||
uint8_t *usbh_cdc_ncm_get_eth_txbuf(void);
|
||||
int usbh_cdc_ncm_eth_output(uint32_t buflen);
|
||||
void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_CDC_NCM_H */
|
||||
@@ -169,14 +169,14 @@
|
||||
#define HID_LOCAL_ITEM_DELIMITER_PREFIX 0xa8 /* Delimiter */
|
||||
|
||||
/* Modifier Keys (HID 8.3) */
|
||||
#define HID_MODIFER_LCTRL (1 << 0) /* Left Ctrl */
|
||||
#define HID_MODIFER_LSHIFT (1 << 1) /* Left Shift */
|
||||
#define HID_MODIFER_LALT (1 << 2) /* Left Alt */
|
||||
#define HID_MODIFER_LGUI (1 << 3) /* Left GUI */
|
||||
#define HID_MODIFER_RCTRL (1 << 4) /* Right Ctrl */
|
||||
#define HID_MODIFER_RSHIFT (1 << 5) /* Right Shift */
|
||||
#define HID_MODIFER_RALT (1 << 6) /* Right Alt */
|
||||
#define HID_MODIFER_RGUI (1 << 7) /* Right GUI */
|
||||
#define HID_MODIFIER_LCTRL (1 << 0) /* Left Ctrl */
|
||||
#define HID_MODIFIER_LSHIFT (1 << 1) /* Left Shift */
|
||||
#define HID_MODIFIER_LALT (1 << 2) /* Left Alt */
|
||||
#define HID_MODIFIER_LGUI (1 << 3) /* Left GUI */
|
||||
#define HID_MODIFIER_RCTRL (1 << 4) /* Right Ctrl */
|
||||
#define HID_MODIFIER_RSHIFT (1 << 5) /* Right Shift */
|
||||
#define HID_MODIFIER_RALT (1 << 6) /* Right Alt */
|
||||
#define HID_MODIFIER_RGUI (1 << 7) /* Right GUI */
|
||||
|
||||
/* Keyboard output report (1 byte) (HID B.1) */
|
||||
#define HID_KBD_OUTPUT_REPORT_NUMLOCK (1 << 0)
|
||||
@@ -191,11 +191,11 @@
|
||||
#define HID_MOUSE_INPUT_REPORT_BUTTON3 (1 << 2)
|
||||
#define HID_MOUSE_INPUT_REPORT_BUTTON_MASK (7)
|
||||
|
||||
#define HID_MOUSE_INPUT_BUTTON_LEFT (1 << 0)
|
||||
#define HID_MOUSE_INPUT_BUTTON_RIGHT (1 << 1)
|
||||
#define HID_MOUSE_INPUT_BUTTON_MIDDLE (1 << 2)
|
||||
#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3)
|
||||
#define HID_MOUSE_INPUT_BUTTON_FORWARD (1 << 4)
|
||||
#define HID_MOUSE_INPUT_BUTTON_LEFT (1 << 0)
|
||||
#define HID_MOUSE_INPUT_BUTTON_RIGHT (1 << 1)
|
||||
#define HID_MOUSE_INPUT_BUTTON_MIDDLE (1 << 2)
|
||||
#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3)
|
||||
#define HID_MOUSE_INPUT_BUTTON_FORWARD (1 << 4)
|
||||
|
||||
/* Joystick input report (4 bytes) (HID D.1) */
|
||||
#define HID_JS_INPUT_REPORT_HATSWITCH_SHIFT (0)
|
||||
@@ -241,14 +241,14 @@
|
||||
#define HID_DESKTOP_USAGE_UNDEFINED 0x00 /* Undefined */
|
||||
#define HID_DESKTOP_USAGE_POINTER 0x01 /* Pointer */
|
||||
#define HID_DESKTOP_USAGE_MOUSE 0x02 /* Mouse */
|
||||
/* 0x03 Reserved */
|
||||
/* 0x03 Reserved */
|
||||
#define HID_DESKTOP_USAGE_JOYSTICK 0x04 /* Joystick */
|
||||
#define HID_DESKTOP_USAGE_GAMEPAD 0x05 /* Game Pad */
|
||||
#define HID_DESKTOP_USAGE_KEYBOARD 0x06 /* Keyboard */
|
||||
#define HID_DESKTOP_USAGE_KEYPAD 0x07 /* Keypad */
|
||||
#define HID_DESKTOP_USAGE_MULTIAXIS 0x08 /* Multi-axis Controller */
|
||||
#define HID_DESKTOP_USAGE_TABLET 0x09 /* Tablet PC System Controls */
|
||||
/* 0x0a-2f Reserved */
|
||||
/* 0x0a-2f Reserved */
|
||||
#define HID_DESKTOP_USAGE_X 0x30 /* X */
|
||||
#define HID_DESKTOP_USAGE_Y 0x31 /* Y */
|
||||
#define HID_DESKTOP_USAGE_Z 0x32 /* Z */
|
||||
@@ -264,7 +264,7 @@
|
||||
#define HID_DESKTOP_USAGE_MOTION 0x3c /* Motion Wakeup */
|
||||
#define HID_DESKTOP_USAGE_START 0x3d /* Start */
|
||||
#define HID_DESKTOP_USAGE_SELECT 0x3e /* Select */
|
||||
/* 0x3f Reserved */
|
||||
/* 0x3f Reserved */
|
||||
#define HID_DESKTOP_USAGE_VX 0x40 /* Vx */
|
||||
#define HID_DESKTOP_USAGE_VY 0x41 /* Vy */
|
||||
#define HID_DESKTOP_USAGE_VZ 0x42 /* Vz */
|
||||
@@ -274,7 +274,7 @@
|
||||
#define HID_DESKTOP_USAGE_VNO 0x46 /* Vno */
|
||||
#define HID_DESKTOP_USAGE_FEATURE 0x47 /* Feature Notification */
|
||||
#define HID_DESKTOP_USAGE_RESOLUTION 0x48 /* Resolution Multiplier */
|
||||
/* 0x49-7f Reserved */
|
||||
/* 0x49-7f Reserved */
|
||||
#define HID_DESKTOP_USAGE_CONTROL 0x80 /* System Control */
|
||||
#define HID_DESKTOP_USAGE_POWERDOWN 0x81 /* System Power Down */
|
||||
#define HID_DESKTOP_USAGE_SLEEP 0x82 /* System Sleep */
|
||||
@@ -295,7 +295,7 @@
|
||||
#define HID_DESKTOP_USAGE_DPAD_DOWN 0x91 /* D-pad Down */
|
||||
#define HID_DESKTOP_USAGE_DPAD_RIGHT 0x92 /* D-pad Right */
|
||||
#define HID_DESKTOP_USAGE_DPAD_LEFT 0x93 /* D-pad Left */
|
||||
/* 0x94-9f Reserved */
|
||||
/* 0x94-9f Reserved */
|
||||
#define HID_DESKTOP_USAGE_DOCK 0xa0 /* System Dock */
|
||||
#define HID_DESKTOP_USAGE_UNDOCK 0xa1 /* System Undock */
|
||||
#define HID_DESKTOP_USAGE_SETUP 0xa2 /* System Setup */
|
||||
@@ -305,7 +305,7 @@
|
||||
#define HID_DESKTOP_USAGE_APP_DEBUG_BREAK 0xa6 /* Application Debugger Break */
|
||||
#define HID_DESKTOP_USAGE_MUTE 0xa7 /* System Speaker Mute */
|
||||
#define HID_DESKTOP_USAGE_HIBERNATE 0xa8 /* System Hibernate */
|
||||
/* 0xa9-af Reserved */
|
||||
/* 0xa9-af Reserved */
|
||||
#define HID_DESKTOP_USAGE_DISPLAY_INVERT 0xb0 /* System Display Invert */
|
||||
#define HID_DESKTOP_USAGE_DISPALY_INTERNAL 0xb1 /* System Display Internal */
|
||||
#define HID_DESKTOP_USAGE_DISPLAY_EXTERNAL 0xb2 /* System Display External */
|
||||
@@ -314,7 +314,7 @@
|
||||
#define HID_DESKTOP_USAGE_DISPLAY_TOGGLE 0xb5 /* System Display Toggle Int/Ext */
|
||||
#define HID_DESKTOP_USAGE_DISPLAY_SWAP 0xb6 /* System Display Swap */
|
||||
#define HID_DESKTOP_USAGE_ 0xb7 /* System Display LCD Autoscale */
|
||||
/* 0xb8-ffff Reserved */
|
||||
/* 0xb8-ffff Reserved */
|
||||
|
||||
/* Keyboard usage IDs (HuT 10) */
|
||||
#define HID_KBD_USAGE_NONE 0x00 /* Reserved (no event indicated) */
|
||||
@@ -529,16 +529,16 @@
|
||||
|
||||
/* HID Report Definitions */
|
||||
struct usb_hid_class_subdescriptor {
|
||||
uint8_t bDescriptorType;/* Class descriptor type (See 7.1) */
|
||||
uint16_t wDescriptorLength;/* Size of the report descriptor */
|
||||
uint8_t bDescriptorType; /* Class descriptor type (See 7.1) */
|
||||
uint16_t wDescriptorLength; /* Size of the report descriptor */
|
||||
} __PACKED;
|
||||
|
||||
struct usb_hid_descriptor {
|
||||
uint8_t bLength; /* Size of the HID descriptor */
|
||||
uint8_t bDescriptorType;/* HID descriptor type */
|
||||
uint16_t bcdHID;/* HID class specification release */
|
||||
uint8_t bCountryCode;/* Country code */
|
||||
uint8_t bNumDescriptors;/* Number of descriptors (>=1) */
|
||||
uint8_t bLength; /* Size of the HID descriptor */
|
||||
uint8_t bDescriptorType; /* HID descriptor type */
|
||||
uint16_t bcdHID; /* HID class specification release */
|
||||
uint8_t bCountryCode; /* Country code */
|
||||
uint8_t bNumDescriptors; /* Number of descriptors (>=1) */
|
||||
|
||||
/*
|
||||
* Specification says at least one Class Descriptor needs to
|
||||
@@ -550,36 +550,120 @@ struct usb_hid_descriptor {
|
||||
/* Standard Reports *********************************************************/
|
||||
|
||||
/* Keyboard input report (8 bytes) (HID B.1) */
|
||||
struct usb_hid_kbd_report
|
||||
{
|
||||
uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */
|
||||
uint8_t reserved;
|
||||
uint8_t key[6]; /* Keycode 1-6 */
|
||||
struct usb_hid_kbd_report {
|
||||
uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */
|
||||
uint8_t reserved;
|
||||
uint8_t key[6]; /* Keycode 1-6 */
|
||||
};
|
||||
|
||||
/* Keyboard output report (1 byte) (HID B.1),
|
||||
* see USBHID_KBDOUT_* definitions
|
||||
* see HID_KBD_OUTPUT_* definitions
|
||||
*/
|
||||
|
||||
/* Mouse input report (HID B.2) */
|
||||
struct usb_hid_mouse_report
|
||||
{
|
||||
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
|
||||
uint8_t xdisp; /* X displacement */
|
||||
uint8_t ydisp; /* y displacement */
|
||||
struct usb_hid_mouse_report {
|
||||
uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
|
||||
int8_t xdisp; /* X displacement */
|
||||
int8_t ydisp; /* y displacement */
|
||||
/* Device specific additional bytes may follow */
|
||||
#ifdef CONFIG_INPUT_MOUSE_WHEEL
|
||||
uint8_t wdisp; /* Wheel displacement */
|
||||
#endif
|
||||
uint8_t wdisp; /* Wheel displacement */
|
||||
};
|
||||
|
||||
/* Joystick input report (1 bytes) (HID D.1) */
|
||||
struct usb_hid_js_report
|
||||
{
|
||||
uint8_t xpos; /* X position */
|
||||
uint8_t ypos; /* X position */
|
||||
uint8_t buttons; /* See USBHID_JSIN_* definitions */
|
||||
uint8_t throttle; /* Throttle */
|
||||
struct usb_hid_js_report {
|
||||
int8_t xpos; /* X position */
|
||||
int8_t ypos; /* X position */
|
||||
uint8_t buttons; /* See USBHID_JSIN_* definitions */
|
||||
uint8_t throttle; /* Throttle */
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
#define HID_MOUSE_DESCRIPTOR_LEN (9 + 9 + 7)
|
||||
|
||||
#define HID_MOUSE_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, int_ep, wMaxPacketSize, bInterval) \
|
||||
0x09, /* bLength: Interface Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber: Number of Interface */ \
|
||||
0x00, /* bAlternateSetting: Alternate setting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
0x03, /* bInterfaceClass: HID */ \
|
||||
bInterfaceSubClass, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
|
||||
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
|
||||
0x00, /* iInterface: Index of string descriptor */ \
|
||||
0x09, /* bLength: HID Descriptor size */ \
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */ \
|
||||
0x11, /* bcdHID: HID Class Spec release number */ \
|
||||
0x01, \
|
||||
0x00, /* bCountryCode: Hardware target country */ \
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ \
|
||||
0x22, /* bDescriptorType */ \
|
||||
WBVAL(wItemLength), /* wItemLength: Total length of Report descriptor */ \
|
||||
0x07, /* bLength: Endpoint Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
|
||||
int_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
|
||||
0x03, /* bmAttributes: Interrupt endpoint */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
|
||||
bInterval /* bInterval: Polling Interval */
|
||||
|
||||
#define HID_KEYBOARD_DESCRIPTOR_LEN (9 + 9 + 7)
|
||||
|
||||
#define HID_KEYBOARD_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, int_ep, wMaxPacketSize, bInterval) \
|
||||
0x09, /* bLength: Interface Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber: Number of Interface */ \
|
||||
0x00, /* bAlternateSetting: Alternate setting */ \
|
||||
0x01, /* bNumEndpoints */ \
|
||||
0x03, /* bInterfaceClass: HID */ \
|
||||
bInterfaceSubClass, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
|
||||
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
|
||||
0x00, /* iInterface: Index of string descriptor */ \
|
||||
0x09, /* bLength: HID Descriptor size */ \
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */ \
|
||||
0x11, /* bcdHID: HID Class Spec release number */ \
|
||||
0x01, \
|
||||
0x00, /* bCountryCode: Hardware target country */ \
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ \
|
||||
0x22, /* bDescriptorType */ \
|
||||
WBVAL(wItemLength), /* wItemLength: Total length of Report descriptor */ \
|
||||
0x07, /* bLength: Endpoint Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
|
||||
int_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
|
||||
0x03, /* bmAttributes: Interrupt endpoint */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
|
||||
bInterval /* bInterval: Polling Interval */
|
||||
|
||||
#define HID_CUSTOM_INOUT_DESCRIPTOR_LEN (9 + 9 + 7 + 7)
|
||||
|
||||
#define HID_CUSTOM_INOUT_DESCRIPTOR_INIT(bInterfaceNumber, bInterfaceSubClass, wItemLength, in_ep, out_ep,wMaxPacketSize, bInterval) \
|
||||
0x09, /* bLength: Interface Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber: Number of Interface */ \
|
||||
0x00, /* bAlternateSetting: Alternate setting */ \
|
||||
0x02, /* bNumEndpoints */ \
|
||||
0x03, /* bInterfaceClass: HID */ \
|
||||
bInterfaceSubClass, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ \
|
||||
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ \
|
||||
0x00, /* iInterface: Index of string descriptor */ \
|
||||
0x09, /* bLength: HID Descriptor size */ \
|
||||
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */ \
|
||||
0x11, /* bcdHID: HID Class Spec release number */ \
|
||||
0x01, \
|
||||
0x00, /* bCountryCode: Hardware target country */ \
|
||||
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ \
|
||||
0x22, /* bDescriptorType */ \
|
||||
WBVAL(wItemLength), /* wItemLength: Total length of Report descriptor */ \
|
||||
0x07, /* bLength: Endpoint Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
|
||||
in_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
|
||||
0x03, /* bmAttributes: Interrupt endpoint */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
|
||||
bInterval, /* bInterval: Polling Interval */ \
|
||||
0x07, /* bLength: Endpoint Descriptor size */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ \
|
||||
out_ep, /* bEndpointAddress: Endpoint Address (IN) */ \
|
||||
0x03, /* bmAttributes: Interrupt endpoint */ \
|
||||
WBVAL(wMaxPacketSize), /* wMaxPacketSize: x Byte max */ \
|
||||
bInterval /* bInterval: Polling Interval */
|
||||
// clang-format on
|
||||
|
||||
#endif /* USB_HID_H */
|
||||
|
||||
@@ -50,6 +50,8 @@ static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_p
|
||||
|
||||
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
intf->class_interface_handler = hid_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
@@ -60,30 +62,65 @@ struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *
|
||||
return intf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Appendix G: HID Request Support Requirements
|
||||
*
|
||||
* The following table enumerates the requests that need to be supported by various types of HID class devices.
|
||||
* Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
|
||||
* ------------------------------------------------------------------------------------------
|
||||
* Boot Mouse Required Optional Optional Optional Required Required
|
||||
* Non-Boot Mouse Required Optional Optional Optional Optional Optional
|
||||
* Boot Keyboard Required Optional Required Required Required Required
|
||||
* Non-Boot Keybrd Required Optional Required Required Optional Optional
|
||||
* Other Device Required Optional Optional Optional Optional Optional
|
||||
*/
|
||||
|
||||
__WEAK void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
(void)report_type;
|
||||
(*data[0]) = 0;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK uint8_t usbd_hid_get_protocol(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_hid_set_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint32_t report_len)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
(void)report_type;
|
||||
(void)report;
|
||||
(void)report_len;
|
||||
}
|
||||
|
||||
__WEAK void usbd_hid_set_idle(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t duration)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)report_id;
|
||||
(void)duration;
|
||||
}
|
||||
|
||||
__WEAK void usbd_hid_set_protocol(uint8_t busid, uint8_t intf, uint8_t protocol)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
(void)protocol;
|
||||
}
|
||||
@@ -15,10 +15,6 @@ extern "C" {
|
||||
/* Init hid interface driver */
|
||||
struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len);
|
||||
|
||||
/* Register desc api */
|
||||
void usbd_hid_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc);
|
||||
void usbd_hid_report_descriptor_register(uint8_t busid, uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
|
||||
|
||||
/* Setup request command callback api */
|
||||
void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len);
|
||||
uint8_t usbd_hid_get_idle(uint8_t busid, uint8_t intf, uint8_t report_id);
|
||||
|
||||
@@ -12,18 +12,26 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/input%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /** Length offset */
|
||||
#define DESC_bDescriptorType 1 /** Descriptor type offset */
|
||||
|
||||
/* interface descriptor field offsets */
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[CONFIG_USBHOST_MAX_HID_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_hid *usbh_hid_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid));
|
||||
g_hid_class[devno].minor = devno;
|
||||
return &g_hid_class[devno];
|
||||
@@ -34,36 +42,40 @@ static struct usbh_hid *usbh_hid_class_alloc(void)
|
||||
|
||||
static void usbh_hid_class_free(struct usbh_hid *hid_class)
|
||||
{
|
||||
int devno = hid_class->minor;
|
||||
uint8_t devno = hid_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(hid_class, 0, sizeof(struct usbh_hid));
|
||||
}
|
||||
|
||||
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usb_setup_packet *setup = hid_class->hport->setup;
|
||||
int ret;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 128;
|
||||
setup->wLength = buflen;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf, ret - 8);
|
||||
return ret;
|
||||
return usbh_control_transfer(hid_class->hport, setup, buffer);
|
||||
}
|
||||
|
||||
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration)
|
||||
{
|
||||
struct usb_setup_packet *setup = hid_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = HID_REQUEST_SET_IDLE;
|
||||
@@ -76,26 +88,36 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur
|
||||
|
||||
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = hid_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = HID_REQUEST_GET_IDLE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf);
|
||||
if (ret < 0) {
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf, 1);
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
|
||||
{
|
||||
struct usb_setup_packet *setup = hid_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = HID_REQUEST_SET_PROTOCOL;
|
||||
@@ -106,10 +128,79 @@ int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
|
||||
return usbh_control_transfer(hid_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
int usbh_hid_get_protocol(struct usbh_hid *hid_class, uint8_t *protocol)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = HID_REQUEST_GET_PROTOCOL;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = hid_class->intf;
|
||||
setup->wLength = 1;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(protocol, g_hid_buf[hid_class->minor], ret - 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = HID_REQUEST_SET_REPORT;
|
||||
setup->wValue = (uint16_t)(((uint32_t)report_type << 8U) | (uint32_t)report_id);
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = buflen;
|
||||
|
||||
return usbh_control_transfer(hid_class->hport, setup, buffer);
|
||||
}
|
||||
|
||||
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!hid_class || !hid_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = hid_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = HID_REQUEST_GET_REPORT;
|
||||
setup->wValue = (uint16_t)(((uint32_t)report_type << 8U) | (uint32_t)report_id);
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = buflen;
|
||||
|
||||
ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf[hid_class->minor]);
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint8_t cur_iface = 0xff;
|
||||
uint8_t *p;
|
||||
bool found = false;
|
||||
|
||||
struct usbh_hid *hid_class = usbh_hid_class_alloc();
|
||||
if (hid_class == NULL) {
|
||||
@@ -122,6 +213,42 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
hport->config.intf[intf].priv = hid_class;
|
||||
|
||||
p = hport->raw_config_desc;
|
||||
while (p[DESC_bLength]) {
|
||||
switch (p[DESC_bDescriptorType]) {
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
cur_iface = p[INTF_DESC_bInterfaceNumber];
|
||||
if (cur_iface == intf) {
|
||||
hid_class->protocol = p[7];
|
||||
struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)(p + 9);
|
||||
|
||||
if (desc->bDescriptorType != HID_DESCRIPTOR_TYPE_HID) {
|
||||
USB_LOG_ERR("HID descriptor not found\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (desc->subdesc[0].bDescriptorType != HID_DESCRIPTOR_TYPE_HID_REPORT) {
|
||||
USB_LOG_ERR("HID report descriptor not found\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
hid_class->report_size = desc->subdesc[0].wDescriptorLength;
|
||||
found = true;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* skip to next descriptor */
|
||||
p += p[DESC_bLength];
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
USB_LOG_ERR("HID interface not found\r\n");
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
found:
|
||||
// /* 0x0 = boot protocol, 0x1 = report protocol */
|
||||
// ret = usbh_hid_set_protocol(hid_class, 0x1);
|
||||
// if (ret < 0) {
|
||||
@@ -133,7 +260,8 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
USB_LOG_WRN("Do not support set idle\r\n");
|
||||
}
|
||||
|
||||
ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc);
|
||||
/* We read report desc but do nothing (because of too much memory usage for parsing report desc, parsed by users) */
|
||||
ret = usbh_hid_get_report_descriptor(hid_class, g_hid_buf[hid_class->minor], MIN(sizeof(g_hid_buf[hid_class->minor]), hid_class->report_size));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -183,10 +311,12 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
__WEAK void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
(void)hid_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
(void)hid_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver hid_class_driver = {
|
||||
@@ -197,10 +327,9 @@ const struct usbh_class_driver hid_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_HID,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_HID,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = NULL,
|
||||
.class_driver = &hid_class_driver
|
||||
};
|
||||
|
||||
@@ -15,17 +15,26 @@ struct usbh_hid {
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
struct usbh_urb intout_urb; /* INTR OUT urb */
|
||||
|
||||
uint8_t report_desc[128];
|
||||
uint16_t report_size;
|
||||
|
||||
uint8_t protocol;
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer, uint32_t buflen);
|
||||
int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration);
|
||||
int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer);
|
||||
int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol);
|
||||
int usbh_hid_get_protocol(struct usbh_hid *hid_class, uint8_t *protocol);
|
||||
int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
|
||||
int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen);
|
||||
|
||||
void usbh_hid_run(struct usbh_hid *hid_class);
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class);
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
|
||||
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
|
||||
|
||||
#define HUB_MAX_DEPTH 5
|
||||
|
||||
#define HUB_SUBCLASS 0x00
|
||||
#define HUB_PROTOCOL_STT 0x01
|
||||
#define HUB_PROTOCOL_MTT 0x02
|
||||
|
||||
/* Hub class requests */
|
||||
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
|
||||
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
|
||||
@@ -27,23 +33,31 @@
|
||||
#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
|
||||
|
||||
/* Port features */
|
||||
#define HUB_PORT_FEATURE_CONNECTION (0x00)
|
||||
#define HUB_PORT_FEATURE_ENABLE (0x01)
|
||||
#define HUB_PORT_FEATURE_SUSPEND (0x02)
|
||||
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
|
||||
#define HUB_PORT_FEATURE_RESET (0x04)
|
||||
#define HUB_PORT_FEATURE_L1 (0x05)
|
||||
#define HUB_PORT_FEATURE_POWER (0x08)
|
||||
#define HUB_PORT_FEATURE_LOWSPEED (0x09)
|
||||
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
|
||||
#define HUB_PORT_FEATURE_CONNECTION (0x00)
|
||||
#define HUB_PORT_FEATURE_ENABLE (0x01)
|
||||
#define HUB_PORT_FEATURE_SUSPEND (0x02)
|
||||
#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
|
||||
#define HUB_PORT_FEATURE_RESET (0x04)
|
||||
#define HUB_PORT_FEATURE_L1 (0x05) /* USB 2.0 only */
|
||||
|
||||
#define HUB_PORT_FEATURE_POWER (0x08) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_POWER_SS (0x09) /* USB 3.0 only */
|
||||
/* This is a bit tricky because HUB_PORT_FEATURE_POWER_SS and
|
||||
HUB_PORT_FEATURE_LOWSPEED share the same bit. */
|
||||
#define HUB_PORT_FEATURE_LOWSPEED (0x09) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_TEST (0x0b) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_INDICATOR (0x0c) /* USB 2.0 only */
|
||||
|
||||
/* Port status change (wPortChange) */
|
||||
#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
|
||||
#define HUB_PORT_FEATURE_C_ENABLE (0x11)
|
||||
#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
|
||||
#define HUB_PORT_FEATURE_C_ENABLE (0x11) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_C_SUSPEND (0x12) /* USB 2.0 only */
|
||||
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
|
||||
#define HUB_PORT_FEATURE_C_RESET (0x14)
|
||||
#define HUB_PORT_FEATURE_TEST (0x15)
|
||||
#define HUB_PORT_FEATURE_INDICATOR (0x16)
|
||||
#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
|
||||
#define HUB_PORT_FEATURE_C_BH_RESET (0x15) /* USB 3.0 only */
|
||||
#define HUB_PORT_FEATURE_C_LINK_STATE (0x16) /* USB 3.0 only */
|
||||
#define HUB_PORT_FEATURE_C_CONFIG_ERR (0x17) /* USB 3.0 only */
|
||||
|
||||
/* Hub status */
|
||||
#define HUB_STATUS_LOCALPOWER (1 << 0)
|
||||
@@ -56,23 +70,42 @@
|
||||
/* Hub port status */
|
||||
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
|
||||
#define HUB_PORT_STATUS_ENABLE (1 << 1)
|
||||
#define HUB_PORT_STATUS_SUSPEND (1 << 2)
|
||||
#define HUB_PORT_STATUS_SUSPEND (1 << 2) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
|
||||
#define HUB_PORT_STATUS_RESET (1 << 4)
|
||||
#define HUB_PORT_STATUS_L1 (1 << 5)
|
||||
#define HUB_PORT_STATUS_POWER (1 << 8)
|
||||
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
|
||||
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
|
||||
#define HUB_PORT_STATUS_TEST (1 << 11)
|
||||
#define HUB_PORT_STATUS_INDICATOR (1 << 12)
|
||||
#define HUB_PORT_STATUS_L1 (1 << 5) /* USB 2.0 only */
|
||||
|
||||
/* Port Link State (PORT_LINK_STATE), USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_LS_U0 (0x00 << 5)
|
||||
#define HUB_PORT_STATUS_LS_U1 (0x01 << 5)
|
||||
#define HUB_PORT_STATUS_LS_U2 (0x02 << 5)
|
||||
#define HUB_PORT_STATUS_LS_U3 (0x03 << 5)
|
||||
#define HUB_PORT_STATUS_LS_SS_DISABLED (0x04 << 5)
|
||||
#define HUB_PORT_STATUS_LS_RX_DETECT (0x05 << 5)
|
||||
#define HUB_PORT_STATUS_LS_SS_INACTIVE (0x06 << 5)
|
||||
#define HUB_PORT_STATUS_LS_POLLING (0x07 << 5)
|
||||
#define HUB_PORT_STATUS_LS_RECOVERY (0x08 << 5)
|
||||
#define HUB_PORT_STATUS_LS_HOT_RESET (0x09 << 5)
|
||||
#define HUB_PORT_STATUS_LS_COMP_MOD (0x0a << 5)
|
||||
#define HUB_PORT_STATUS_LS_LOOPBACK (0x0b << 5)
|
||||
|
||||
#define HUB_PORT_STATUS_POWER (1 << 8)
|
||||
#define HUB_PORT_STATUS_POWER_SS (1 << 9) /* USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_TEST (1 << 11) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_INDICATOR (1 << 12) /* USB 2.0 only */
|
||||
|
||||
/* Hub port status change */
|
||||
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
|
||||
#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
|
||||
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
|
||||
#define HUB_PORT_STATUS_C_ENABLE (1 << 1) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_C_SUSPEND (1 << 2) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
|
||||
#define HUB_PORT_STATUS_C_RESET (1 << 4)
|
||||
#define HUB_PORT_STATUS_C_L1 (1 << 5)
|
||||
#define HUB_PORT_STATUS_C_L1 (1 << 5) /* USB 2.0 only */
|
||||
#define HUB_PORT_STATUS_C_BH_RESET (1 << 5) /* USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_C_PORTLINK (1 << 6) /* USB 3.0 only */
|
||||
#define HUB_PORT_STATUS_C_CONFIGERR (1 << 7) /* USB 3.0 only */
|
||||
|
||||
/* Hub characteristics */
|
||||
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
|
||||
@@ -106,6 +139,21 @@ struct usb_hub_descriptor {
|
||||
|
||||
#define USB_SIZEOF_HUB_DESC 9
|
||||
|
||||
/* Super speed Hub descriptor */
|
||||
struct usb_hub_ss_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bNbrPorts;
|
||||
uint16_t wHubCharacteristics;
|
||||
uint8_t bPwrOn2PwrGood;
|
||||
uint8_t bHubContrCurrent;
|
||||
uint8_t bHubHdrDecLat;
|
||||
uint16_t wHubDelay;
|
||||
uint8_t DeviceRemovable;
|
||||
} __PACKED;
|
||||
|
||||
#define USB_SIZEOF_HUB_SS_DESC 11
|
||||
|
||||
/* Hub status */
|
||||
struct hub_status {
|
||||
uint16_t wPortStatus;
|
||||
|
||||
@@ -22,29 +22,22 @@
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][USB_ALIGN_UP(1, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
extern int usbh_free_devaddr(struct usbh_hubport *hport);
|
||||
extern int usbh_enumerate(struct usbh_hubport *hport);
|
||||
extern void usbh_hubport_release(struct usbh_hubport *hport);
|
||||
|
||||
static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
|
||||
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
struct usbh_hubport *usbh_get_roothub_port(unsigned int port)
|
||||
{
|
||||
return &roothub.child[port - 1];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_hub *usbh_hub_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
|
||||
g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
|
||||
return &g_hub_class[devno];
|
||||
@@ -55,16 +48,14 @@ static struct usbh_hub *usbh_hub_class_alloc(void)
|
||||
|
||||
static void usbh_hub_class_free(struct usbh_hub *hub_class)
|
||||
{
|
||||
int devno = hub_class->index - EXTHUB_FIRST_INDEX;
|
||||
uint8_t devno = hub_class->index - EXTHUB_FIRST_INDEX;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(hub_class, 0, sizeof(struct usbh_hub));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -74,15 +65,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
|
||||
/* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
|
||||
and we havn't handle the difference here */
|
||||
if ((hub->parent->speed == USB_SPEED_SUPER) ||
|
||||
(hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
|
||||
} else {
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
|
||||
}
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
|
||||
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_HUB_DESC;
|
||||
@@ -91,11 +74,11 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
|
||||
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
|
||||
return ret;
|
||||
}
|
||||
#if 0
|
||||
static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
|
||||
static int _usbh_hub_get_hub_ss_descriptor(struct usbh_hub *hub, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
@@ -103,20 +86,20 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
|
||||
setup = hub->parent->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = HUB_REQUEST_GET_STATUS;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 2;
|
||||
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||
setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf);
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = USB_SIZEOF_HUB_SS_DESC;
|
||||
|
||||
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(buffer, g_hub_buf, 2);
|
||||
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_SS_DESC);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
{
|
||||
@@ -169,6 +152,7 @@ static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t f
|
||||
return usbh_control_transfer(hub->parent, setup, NULL);
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
@@ -184,9 +168,10 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
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)
|
||||
{
|
||||
(void)length;
|
||||
|
||||
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -1;
|
||||
@@ -206,6 +191,29 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_hub_ss_descriptor(struct usb_hub_ss_descriptor *desc, uint16_t length)
|
||||
{
|
||||
(void)length;
|
||||
|
||||
if (desc->bLength < USB_SIZEOF_HUB_SS_DESC) {
|
||||
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
|
||||
return -1;
|
||||
} else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB3) {
|
||||
USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
|
||||
return -2;
|
||||
} else {
|
||||
USB_LOG_RAW("SuperSpeed Hub Descriptor:\r\n");
|
||||
USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
|
||||
USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
|
||||
USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
|
||||
USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
|
||||
USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
|
||||
USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
|
||||
USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
|
||||
@@ -262,6 +270,7 @@ int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
{
|
||||
struct usb_setup_packet roothub_setup;
|
||||
@@ -280,23 +289,6 @@ static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hubport_release(struct usbh_hubport *child)
|
||||
{
|
||||
if (child->connected) {
|
||||
child->connected = false;
|
||||
usbh_free_devaddr(child);
|
||||
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
|
||||
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
|
||||
CLASS_DISCONNECT(child, i);
|
||||
}
|
||||
}
|
||||
child->config.config_desc.bNumInterfaces = 0;
|
||||
usbh_kill_urb(&child->ep0_urb);
|
||||
usb_osal_mutex_delete(child->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_USBHOST_MAX_EXTHUBS > 0
|
||||
static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
{
|
||||
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||
@@ -304,11 +296,21 @@ static void hub_int_complete_callback(void *arg, int nbytes)
|
||||
if (nbytes > 0) {
|
||||
usbh_hub_thread_wakeup(hub);
|
||||
} else if (nbytes == -USB_ERR_NAK) {
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
/* Restart timer to submit urb again */
|
||||
USB_LOG_DBG("Restart timer\r\n");
|
||||
usb_osal_timer_start(hub->int_timer);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
static void hub_int_timeout(void *arg)
|
||||
{
|
||||
struct usbh_hub *hub = (struct usbh_hub *)arg;
|
||||
|
||||
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
}
|
||||
|
||||
static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
@@ -324,22 +326,65 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
hub->hub_addr = hport->dev_addr;
|
||||
hub->parent = hport;
|
||||
hub->bus = hport->bus;
|
||||
hub->speed = hport->speed;
|
||||
|
||||
hport->self = hub;
|
||||
hport->config.intf[intf].priv = hub;
|
||||
|
||||
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
if (hport->depth > HUB_MAX_DEPTH) {
|
||||
USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
|
||||
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
|
||||
/*
|
||||
* Super-Speed hubs need to know their depth to be able to
|
||||
* parse the bits of the route-string that correspond to
|
||||
* their downstream port number.
|
||||
*
|
||||
*/
|
||||
if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
|
||||
ret = usbh_hub_set_depth(hub, hport->depth - 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Unable to set hub depth \r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
/* Get hub descriptor. */
|
||||
if (hport->speed == USB_SPEED_SUPER) {
|
||||
ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
|
||||
hub->nports = hub->hub_ss_desc.bNbrPorts;
|
||||
hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
|
||||
hub->tt_think = 0U;
|
||||
} else {
|
||||
ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
|
||||
hub->nports = hub->hub_desc.bNbrPorts;
|
||||
hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
|
||||
hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hub->child[port].port = port + 1;
|
||||
hub->child[port].parent = hub;
|
||||
hub->child[port].bus = hport->bus;
|
||||
}
|
||||
|
||||
if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
|
||||
hub->ismtt = 1;
|
||||
} else {
|
||||
hub->ismtt = 0;
|
||||
}
|
||||
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(hub->intin, ep_desc);
|
||||
@@ -347,28 +392,16 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hport->speed == USB_SPEED_SUPER) {
|
||||
uint16_t depth = 0;
|
||||
struct usbh_hubport *parent = hport->parent->parent;
|
||||
while (parent) {
|
||||
depth++;
|
||||
parent = parent->parent->parent;
|
||||
}
|
||||
|
||||
ret = usbh_hub_set_depth(hub, depth);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
usb_osal_msleep(hub->powerdelay);
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
|
||||
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
|
||||
if (ret < 0) {
|
||||
@@ -379,13 +412,16 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
hub->connected = true;
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
|
||||
|
||||
usb_slist_add_tail(&hub->bus->hub_list, &hub->list);
|
||||
|
||||
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
|
||||
usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
|
||||
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0);
|
||||
if (hub->int_timer == NULL) {
|
||||
USB_LOG_ERR("No memory to alloc int_timer\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
usb_osal_timer_start(hub->int_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -401,7 +437,11 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
usbh_kill_urb(&hub->intin_urb);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
if (hub->int_timer) {
|
||||
usb_osal_timer_delete(hub->int_timer);
|
||||
}
|
||||
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
child = &hub->child[port];
|
||||
usbh_hubport_release(child);
|
||||
child->parent = NULL;
|
||||
@@ -409,7 +449,6 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usb_slist_remove(&hub->bus->hub_list, &hub->list);
|
||||
}
|
||||
|
||||
usbh_hub_class_free(hub);
|
||||
@@ -418,38 +457,28 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usbh_hubport_enumerate_thread(void *argument)
|
||||
{
|
||||
struct usbh_hubport *child = (struct usbh_hubport *)argument;
|
||||
|
||||
if (usbh_enumerate(child) < 0) {
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
|
||||
}
|
||||
usb_osal_thread_delete(NULL);
|
||||
}
|
||||
|
||||
static void usbh_hub_events(struct usbh_hub *hub)
|
||||
{
|
||||
struct usbh_hubport *child;
|
||||
struct hub_port_status port_status;
|
||||
uint8_t portchange_index;
|
||||
uint16_t portchange_index;
|
||||
uint16_t portstatus;
|
||||
uint16_t portchange;
|
||||
uint16_t mask;
|
||||
uint16_t feat;
|
||||
uint8_t speed;
|
||||
int ret;
|
||||
size_t flags;
|
||||
|
||||
if (!hub->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
portchange_index = hub->int_buffer[0];
|
||||
hub->int_buffer[0] &= ~portchange_index;
|
||||
flags = usb_osal_enter_critical_section();
|
||||
memcpy(&portchange_index, hub->int_buffer, 2);
|
||||
usb_osal_leave_critical_section(flags);
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
|
||||
|
||||
if (!(portchange_index & (1 << (port + 1)))) {
|
||||
@@ -555,29 +584,24 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
}
|
||||
}
|
||||
|
||||
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
|
||||
speed = USB_SPEED_HIGH;
|
||||
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
|
||||
speed = USB_SPEED_LOW;
|
||||
}
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
else {
|
||||
extern uint8_t usbh_get_port_speed(struct usbh_hub * hub, const uint8_t port);
|
||||
|
||||
/* USB3.0 speed cannot get from portstatus, checkout port speed instead */
|
||||
uint8_t super_speed = usbh_get_port_speed(hub, port + 1);
|
||||
if (super_speed > USB_SPEED_HIGH) {
|
||||
/* assert that when using USB 3.0 ports, attached device must also be USB 3.0 speed */
|
||||
speed = super_speed;
|
||||
/*
|
||||
* Figure out device speed. This is a bit tricky because
|
||||
* HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
|
||||
*/
|
||||
if (portstatus & HUB_PORT_STATUS_POWER) {
|
||||
if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
|
||||
speed = USB_SPEED_HIGH;
|
||||
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
|
||||
speed = USB_SPEED_LOW;
|
||||
} else {
|
||||
speed = USB_SPEED_FULL;
|
||||
}
|
||||
} else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
|
||||
speed = USB_SPEED_SUPER;
|
||||
} else {
|
||||
USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
else {
|
||||
speed = USB_SPEED_FULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
child = &hub->child[port];
|
||||
/** release child sources first */
|
||||
@@ -585,6 +609,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
|
||||
memset(child, 0, sizeof(struct usbh_hubport));
|
||||
child->parent = hub;
|
||||
child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
|
||||
child->connected = true;
|
||||
child->port = port + 1;
|
||||
child->speed = speed;
|
||||
@@ -593,8 +618,11 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
|
||||
USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
|
||||
|
||||
/* create disposable thread to enumerate device on current hport, do not block hub thread */
|
||||
usb_osal_thread_create("usbh_enum", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hubport_enumerate_thread, (void *)child);
|
||||
if (usbh_enumerate(child) < 0) {
|
||||
/** release child sources */
|
||||
usbh_hubport_release(child);
|
||||
USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
|
||||
}
|
||||
} else {
|
||||
child = &hub->child[port];
|
||||
/** release child sources */
|
||||
@@ -616,16 +644,16 @@ static void usbh_hub_events(struct usbh_hub *hub)
|
||||
|
||||
/* Start next hub int transfer */
|
||||
if (!hub->is_roothub && hub->connected) {
|
||||
usbh_submit_urb(&hub->intin_urb);
|
||||
usb_osal_timer_start(hub->int_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbh_hub_thread(void *argument)
|
||||
static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
struct usbh_hub *hub;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_bus *bus = (struct usbh_bus *)argument;
|
||||
struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
|
||||
usb_hc_init(bus);
|
||||
while (1) {
|
||||
@@ -645,6 +673,17 @@ void usbh_hub_thread_wakeup(struct usbh_hub *hub)
|
||||
int usbh_hub_initialize(struct usbh_bus *bus)
|
||||
{
|
||||
char thread_name[32] = { 0 };
|
||||
struct usbh_hub *hub;
|
||||
|
||||
hub = &bus->hcd.roothub;
|
||||
hub->connected = true;
|
||||
hub->index = 1;
|
||||
hub->is_roothub = true;
|
||||
hub->parent = NULL;
|
||||
hub->hub_addr = 1;
|
||||
hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
|
||||
hub->int_buffer = bus->hcd.roothub_intbuf;
|
||||
hub->bus = bus;
|
||||
|
||||
bus->hub_mq = usb_osal_mq_create(7);
|
||||
if (bus->hub_mq == NULL) {
|
||||
@@ -663,21 +702,17 @@ int usbh_hub_initialize(struct usbh_bus *bus)
|
||||
|
||||
int usbh_hub_deinitialize(struct usbh_bus *bus)
|
||||
{
|
||||
usb_slist_t *hub_list;
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_hub *hub;
|
||||
size_t flags;
|
||||
|
||||
flags = usb_osal_enter_critical_section();
|
||||
|
||||
usb_slist_for_each(hub_list, &bus->hub_list)
|
||||
{
|
||||
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
|
||||
hub = &bus->hcd.roothub;
|
||||
for (uint8_t port = 0; port < hub->nports; port++) {
|
||||
hport = &hub->child[port];
|
||||
|
||||
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
|
||||
hport = &hub->child[port];
|
||||
|
||||
usbh_hubport_release(hport);
|
||||
}
|
||||
usbh_hubport_release(hport);
|
||||
}
|
||||
|
||||
usb_hc_deinit(bus);
|
||||
@@ -699,11 +734,10 @@ const struct usbh_class_driver hub_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = USB_DEVICE_CLASS_HUB,
|
||||
.subclass = 0,
|
||||
.protocol = 0,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_HUB,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.id_table = NULL,
|
||||
.class_driver = &hub_class_driver
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
|
||||
struct usbh_hub;
|
||||
|
||||
#define USBH_HUB_MAX_PORTS 4
|
||||
/* Maximum size of an interrupt IN transfer */
|
||||
#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
|
||||
USB_MEM_ALIGNX struct CBW cbw;
|
||||
USB_MEM_ALIGNX struct CSW csw;
|
||||
|
||||
bool readonly;
|
||||
USB_MEM_ALIGNX bool readonly;
|
||||
bool popup;
|
||||
uint8_t sKey; /* Sense key */
|
||||
uint8_t ASC; /* Additional Sense Code */
|
||||
@@ -50,11 +50,14 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
|
||||
usb_osal_mq_t usbd_msc_mq;
|
||||
usb_osal_thread_t usbd_msc_thread;
|
||||
uint32_t nbytes;
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
uint32_t event;
|
||||
uint32_t nbytes;
|
||||
#endif
|
||||
} g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbdev_msc_thread(void *argument);
|
||||
static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
#endif
|
||||
|
||||
static void usdb_msc_set_max_lun(uint8_t busid)
|
||||
@@ -94,21 +97,25 @@ static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb
|
||||
|
||||
void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_INIT:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
|
||||
if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
|
||||
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_mq\r\n");
|
||||
}
|
||||
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)busid);
|
||||
g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)(uint32_t)busid);
|
||||
if (g_usbd_msc[busid].usbd_msc_thread == NULL) {
|
||||
USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_thread\r\n");
|
||||
}
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
g_usbd_msc[busid].event = 0;
|
||||
#endif
|
||||
break;
|
||||
case USBD_EVENT_DEINIT:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
if (g_usbd_msc[busid].usbd_msc_mq) {
|
||||
usb_osal_mq_delete(g_usbd_msc[busid].usbd_msc_mq);
|
||||
}
|
||||
@@ -500,6 +507,9 @@ static bool SCSI_readCapacity10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
@@ -522,9 +532,12 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
return false;
|
||||
}
|
||||
g_usbd_msc[busid].stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||
return true;
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
g_usbd_msc[busid].event = MSC_DATA_IN;
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead(busid);
|
||||
#endif
|
||||
@@ -532,6 +545,9 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
|
||||
static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
@@ -554,9 +570,12 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
return false;
|
||||
}
|
||||
g_usbd_msc[busid].stage = MSC_DATA_IN;
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||
return true;
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
g_usbd_msc[busid].event = MSC_DATA_IN;
|
||||
return true;
|
||||
#else
|
||||
return SCSI_processRead(busid);
|
||||
#endif
|
||||
@@ -565,6 +584,10 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
@@ -594,6 +617,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint32_t data_len = 0;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
|
||||
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
|
||||
return false;
|
||||
@@ -803,6 +830,8 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
|
||||
|
||||
void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
|
||||
switch (g_usbd_msc[busid].stage) {
|
||||
case MSC_READ_CBW:
|
||||
if (SCSI_CBWDecode(busid, nbytes) == false) {
|
||||
@@ -815,9 +844,12 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
||||
case SCSI_CMD_WRITE10:
|
||||
case SCSI_CMD_WRITE12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
g_usbd_msc[busid].nbytes = nbytes;
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
g_usbd_msc[busid].nbytes = nbytes;
|
||||
g_usbd_msc[busid].event = MSC_DATA_OUT;
|
||||
#else
|
||||
if (SCSI_processWrite(busid, nbytes) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
@@ -835,13 +867,18 @@ void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
|
||||
void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
switch (g_usbd_msc[busid].stage) {
|
||||
case MSC_DATA_IN:
|
||||
switch (g_usbd_msc[busid].cbw.CB[0]) {
|
||||
case SCSI_CMD_READ10:
|
||||
case SCSI_CMD_READ12:
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
g_usbd_msc[busid].event = MSC_DATA_IN;
|
||||
#else
|
||||
if (SCSI_processRead(busid) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
@@ -870,19 +907,41 @@ void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_MSC_THREAD
|
||||
static void usbdev_msc_thread(void *argument)
|
||||
#if defined(CONFIG_USBDEV_MSC_THREAD)
|
||||
static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
uintptr_t event;
|
||||
int ret;
|
||||
uint8_t busid = (uint8_t)argument;
|
||||
uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
|
||||
while (1) {
|
||||
ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
USB_LOG_DBG("%d\r\n", event);
|
||||
USB_LOG_DBG("event:%d\r\n", event);
|
||||
if (event == MSC_DATA_OUT) {
|
||||
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
} else if (event == MSC_DATA_IN) {
|
||||
if (SCSI_processRead(busid) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(CONFIG_USBDEV_MSC_POLLING)
|
||||
void usbd_msc_polling(uint8_t busid)
|
||||
{
|
||||
uint8_t event;
|
||||
|
||||
event = g_usbd_msc[busid].event;
|
||||
|
||||
if (event != 0) {
|
||||
g_usbd_msc[busid].event = 0;
|
||||
USB_LOG_DBG("event:%d\r\n", event);
|
||||
if (event == MSC_DATA_OUT) {
|
||||
if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
|
||||
usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
|
||||
@@ -918,9 +977,10 @@ struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *
|
||||
for (uint8_t i = 0u; i <= g_usbd_msc[busid].max_lun; i++) {
|
||||
usbd_msc_get_cap(busid, i, &g_usbd_msc[busid].scsi_blk_nbr[i], &g_usbd_msc[busid].scsi_blk_size[i]);
|
||||
|
||||
if (g_usbd_msc[busid].scsi_blk_size[i] > CONFIG_USBDEV_MSC_MAX_BUFSIZE) {
|
||||
USB_LOG_ERR("msc block buffer overflow\r\n");
|
||||
return NULL;
|
||||
if (CONFIG_USBDEV_MSC_MAX_BUFSIZE % g_usbd_msc[busid].scsi_blk_size[i]) {
|
||||
USB_LOG_ERR("CONFIG_USBDEV_MSC_MAX_BUFSIZE must be a multiple of block size\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +992,38 @@ void usbd_msc_set_readonly(uint8_t busid, bool readonly)
|
||||
g_usbd_msc[busid].readonly = readonly;
|
||||
}
|
||||
|
||||
bool usbd_msc_set_popup(uint8_t busid)
|
||||
bool usbd_msc_get_popup(uint8_t busid)
|
||||
{
|
||||
return g_usbd_msc[busid].popup;
|
||||
}
|
||||
|
||||
__WEAK void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||
{
|
||||
(void)busid;
|
||||
(void)lun;
|
||||
|
||||
*block_num = 0;
|
||||
*block_size = 0;
|
||||
}
|
||||
|
||||
__WEAK int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
(void)busid;
|
||||
(void)lun;
|
||||
(void)sector;
|
||||
(void)buffer;
|
||||
(void)length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
(void)busid;
|
||||
(void)lun;
|
||||
(void)sector;
|
||||
(void)buffer;
|
||||
(void)length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -23,7 +23,9 @@ int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *b
|
||||
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
|
||||
|
||||
void usbd_msc_set_readonly(uint8_t busid, bool readonly);
|
||||
bool usbd_msc_set_popup(uint8_t busid);
|
||||
bool usbd_msc_get_popup(uint8_t busid);
|
||||
|
||||
void usbd_msc_polling(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -13,7 +13,12 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/sd%c"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
|
||||
#ifndef CONFIG_USBHOST_MSC_READY_CHECK_TIMES
|
||||
#define CONFIG_USBHOST_MSC_READY_CHECK_TIMES 10
|
||||
#endif
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_cbw_csw[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[CONFIG_USBHOST_MAX_MSC_CLASS][USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_msc g_msc_class[CONFIG_USBHOST_MAX_MSC_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
@@ -21,11 +26,11 @@ static struct usbh_msc_modeswitch_config *g_msc_modeswitch_config = NULL;
|
||||
|
||||
static struct usbh_msc *usbh_msc_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_MSC_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_msc_class[devno], 0, sizeof(struct usbh_msc));
|
||||
g_msc_class[devno].sdchar = 'a' + devno;
|
||||
return &g_msc_class[devno];
|
||||
@@ -36,17 +41,22 @@ static struct usbh_msc *usbh_msc_class_alloc(void)
|
||||
|
||||
static void usbh_msc_class_free(struct usbh_msc *msc_class)
|
||||
{
|
||||
int devno = msc_class->sdchar - 'a';
|
||||
uint8_t devno = msc_class->sdchar - 'a';
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(msc_class, 0, sizeof(struct usbh_msc));
|
||||
}
|
||||
|
||||
static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
|
||||
{
|
||||
struct usb_setup_packet *setup = msc_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!msc_class || !msc_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = msc_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = MSC_REQUEST_GET_MAX_LUN;
|
||||
@@ -80,6 +90,8 @@ static void usbh_msc_cbw_dump(struct CBW *cbw)
|
||||
|
||||
static void usbh_msc_csw_dump(struct CSW *csw)
|
||||
{
|
||||
(void)csw;
|
||||
|
||||
USB_LOG_DBG("CSW:\r\n");
|
||||
USB_LOG_DBG(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
|
||||
USB_LOG_DBG(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
|
||||
@@ -113,44 +125,44 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
|
||||
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer, uint32_t timeout)
|
||||
{
|
||||
int nbytes;
|
||||
|
||||
usbh_msc_cbw_dump(cbw);
|
||||
|
||||
/* Send the CBW */
|
||||
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, timeout);
|
||||
if (nbytes < 0) {
|
||||
USB_LOG_ERR("cbw transfer error\r\n");
|
||||
USB_LOG_ERR("cbw transfer error: %d\r\n", nbytes);
|
||||
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);
|
||||
nbytes = usbh_msc_bulk_out_transfer(msc_class, buffer, cbw->dDataLength, timeout);
|
||||
} else if (cbw->CB[0] == SCSI_CMD_READCAPACITY10) {
|
||||
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, timeout);
|
||||
if (nbytes >= 0) {
|
||||
/* Save the capacity information */
|
||||
msc_class->blocknum = GET_BE32(&buffer[0]) + 1;
|
||||
msc_class->blocksize = GET_BE32(&buffer[4]);
|
||||
}
|
||||
} else {
|
||||
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
nbytes = usbh_msc_bulk_in_transfer(msc_class, buffer, cbw->dDataLength, timeout);
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
USB_LOG_ERR("msc data transfer error\r\n");
|
||||
USB_LOG_ERR("msc data transfer error: %d\r\n", nbytes);
|
||||
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);
|
||||
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, timeout);
|
||||
if (nbytes < 0) {
|
||||
USB_LOG_ERR("csw transfer error\r\n");
|
||||
USB_LOG_ERR("csw transfer error: %d\r\n", nbytes);
|
||||
goto __err_exit;
|
||||
}
|
||||
|
||||
@@ -175,14 +187,14 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
|
||||
cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], NULL, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
|
||||
@@ -190,7 +202,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
@@ -200,7 +212,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
|
||||
cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
|
||||
cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
||||
@@ -208,7 +220,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
@@ -218,7 +230,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
||||
cbw->CB[0] = SCSI_CMD_INQUIRY;
|
||||
cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
@@ -226,7 +238,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
@@ -235,7 +247,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
|
||||
cbw->CB[0] = SCSI_CMD_READCAPACITY10;
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, g_msc_buf);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], g_msc_buf[msc_class->sdchar - 'a'], CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t *message)
|
||||
@@ -243,18 +255,18 @@ static inline void usbh_msc_modeswitch(struct usbh_msc *msc_class, const uint8_t
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
|
||||
memcpy(g_msc_buf, message, 31);
|
||||
memcpy(g_msc_cbw_csw[msc_class->sdchar - 'a'], message, 31);
|
||||
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, NULL);
|
||||
usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], NULL, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
struct usbh_msc *msc_class = usbh_msc_class_alloc();
|
||||
if (msc_class == NULL) {
|
||||
@@ -267,12 +279,17 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
hport->config.intf[intf].priv = msc_class;
|
||||
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
|
||||
ret = usbh_msc_get_maxlun(msc_class, g_msc_buf[msc_class->sdchar - 'a']);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
if (ret == -USB_ERR_STALL) {
|
||||
USB_LOG_WRN("Device does not support multiple LUNs\r\n");
|
||||
g_msc_buf[msc_class->sdchar - 'a'][0] = 0;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
|
||||
USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[msc_class->sdchar - 'a'][0] + 1);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
@@ -301,34 +318,6 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_testunitready(msc_class);
|
||||
if (ret < 0) {
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msc_class->blocksize > 0) {
|
||||
USB_LOG_INFO("Capacity info:\r\n");
|
||||
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
|
||||
} else {
|
||||
USB_LOG_ERR("Invalid block size\r\n");
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
|
||||
|
||||
USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
@@ -363,13 +352,52 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_msc_scsi_init(struct usbh_msc *msc_class)
|
||||
{
|
||||
int ret;
|
||||
uint16_t cnt;
|
||||
|
||||
cnt = 0;
|
||||
while (usbh_msc_scsi_testunitready(msc_class) < 0) {
|
||||
USB_LOG_WRN("Device not ready, try again...\r\n");
|
||||
ret = usbh_msc_scsi_requestsense(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_testunitready\r\n");
|
||||
}
|
||||
cnt++;
|
||||
if (cnt > CONFIG_USBHOST_MSC_READY_CHECK_TIMES) {
|
||||
return -USB_ERR_NODEV;
|
||||
}
|
||||
}
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (msc_class->blocksize > 0) {
|
||||
USB_LOG_INFO("Capacity info:\r\n");
|
||||
USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
|
||||
} else {
|
||||
USB_LOG_ERR("Invalid block size\r\n");
|
||||
return -USB_ERR_RANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
|
||||
{
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
@@ -380,7 +408,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con
|
||||
SET_BE32(&cbw->CB[2], start_sector);
|
||||
SET_BE16(&cbw->CB[7], nsectors);
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
|
||||
@@ -388,7 +416,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
|
||||
struct CBW *cbw;
|
||||
|
||||
/* Construct the CBW */
|
||||
cbw = (struct CBW *)g_msc_buf;
|
||||
cbw = (struct CBW *)g_msc_cbw_csw[msc_class->sdchar - 'a'];
|
||||
memset(cbw, 0, USB_SIZEOF_MSC_CBW);
|
||||
cbw->dSignature = MSC_CBW_Signature;
|
||||
|
||||
@@ -400,7 +428,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons
|
||||
SET_BE32(&cbw->CB[2], start_sector);
|
||||
SET_BE16(&cbw->CB[7], nsectors);
|
||||
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_buf, (uint8_t *)buffer);
|
||||
return usbh_bulk_cbw_csw_xfer(msc_class, cbw, (struct CSW *)g_msc_cbw_csw[msc_class->sdchar - 'a'], (uint8_t *)buffer, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||
}
|
||||
|
||||
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
||||
@@ -414,10 +442,12 @@ void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config)
|
||||
|
||||
__WEAK void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
(void)msc_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
(void)msc_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver msc_class_driver = {
|
||||
@@ -428,10 +458,9 @@ const struct usbh_class_driver msc_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_MASS_STORAGE,
|
||||
.subclass = MSC_SUBCLASS_SCSI,
|
||||
.protocol = MSC_PROTOCOL_BULK_ONLY,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_MASS_STORAGE,
|
||||
.bInterfaceSubClass = MSC_SUBCLASS_SCSI,
|
||||
.bInterfaceProtocol = MSC_PROTOCOL_BULK_ONLY,
|
||||
.id_table = NULL,
|
||||
.class_driver = &msc_class_driver
|
||||
};
|
||||
|
||||
@@ -20,6 +20,8 @@ struct usbh_msc {
|
||||
uint8_t sdchar;
|
||||
uint32_t blocknum; /* Number of blocks on the USB mass storage device */
|
||||
uint16_t blocksize; /* Block size of USB mass storage device */
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct usbh_msc_modeswitch_config {
|
||||
@@ -30,6 +32,7 @@ struct usbh_msc_modeswitch_config {
|
||||
};
|
||||
|
||||
void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config);
|
||||
int usbh_msc_scsi_init(struct usbh_msc *msc_class);
|
||||
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);
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_xxx *usbh_xxx_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CUSTOM_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_xxx_class[devno], 0, sizeof(struct usbh_xxx));
|
||||
g_xxx_class[devno].minor = devno;
|
||||
return &g_xxx_class[devno];
|
||||
@@ -24,10 +24,10 @@ static struct usbh_xxx *usbh_xxx_class_alloc(void)
|
||||
|
||||
static void usbh_xxx_class_free(struct usbh_xxx *xxx_class)
|
||||
{
|
||||
int devno = xxx_class->minor;
|
||||
uint8_t devno = xxx_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(xxx_class, 0, sizeof(struct usbh_xxx));
|
||||
}
|
||||
@@ -89,10 +89,9 @@ static const struct usbh_class_driver xxx_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = 0,
|
||||
.subclass = 0,
|
||||
.protocol = 0,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = 0,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.id_table = NULL,
|
||||
.class_driver = &xxx_class_driver
|
||||
};
|
||||
|
||||
@@ -12,6 +12,8 @@ struct usbh_xxx {
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
void usbh_xxx_run(struct usbh_xxx *xxx_class);
|
||||
|
||||
195
class/vendor/net/usbh_asix.c
vendored
195
class/vendor/net/usbh_asix.c
vendored
@@ -14,12 +14,12 @@
|
||||
#define DEV_FORMAT "/dev/asix"
|
||||
|
||||
static struct usbh_asix g_asix_class;
|
||||
#define CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE (1514U + 8)
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[CONFIG_USBHOST_ASIX_ETH_MAX_SEGSZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[16];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[32];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_rx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_tx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_inttx_buffer[USB_ALIGN_UP(16, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_asix_buf[USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
#define ETH_ALEN 6
|
||||
|
||||
@@ -56,9 +56,14 @@ static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
|
||||
void *data,
|
||||
uint16_t size)
|
||||
{
|
||||
struct usb_setup_packet *setup = asix_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!asix_class || !asix_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = asix_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = cmd;
|
||||
setup->wValue = value;
|
||||
@@ -66,7 +71,7 @@ static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
|
||||
setup->wLength = size;
|
||||
|
||||
ret = usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
|
||||
if (ret < 0) {
|
||||
if (ret < 8) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(data, g_asix_buf, ret - 8);
|
||||
@@ -81,7 +86,12 @@ static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
|
||||
void *data,
|
||||
uint16_t size)
|
||||
{
|
||||
struct usb_setup_packet *setup = asix_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!asix_class || !asix_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = asix_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = cmd;
|
||||
@@ -89,9 +99,12 @@ static int usbh_asix_write_cmd(struct usbh_asix *asix_class,
|
||||
setup->wIndex = index;
|
||||
setup->wLength = size;
|
||||
|
||||
memcpy(g_asix_buf, data, size);
|
||||
|
||||
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
|
||||
if (data && size) {
|
||||
memcpy(g_asix_buf, data, size);
|
||||
return usbh_control_transfer(asix_class->hport, setup, g_asix_buf);
|
||||
} else {
|
||||
return usbh_control_transfer(asix_class->hport, setup, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbh_asix_mdio_write(struct usbh_asix *asix_class, int phy_id, int loc, int val)
|
||||
@@ -263,6 +276,15 @@ static int usbh_asix_write_gpio(struct usbh_asix *asix_class, uint16_t value, in
|
||||
static void usbh_asix_set_multicast(struct usbh_asix *asix_class)
|
||||
{
|
||||
uint16_t rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_AM;
|
||||
#if CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE == 4096
|
||||
rx_ctl |= AX_RX_CTL_MFB_4096;
|
||||
#elif CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE == 8192
|
||||
rx_ctl |= AX_RX_CTL_MFB_8192;
|
||||
#elif CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE == 16384
|
||||
rx_ctl |= AX_RX_CTL_MFB_16384;
|
||||
#else
|
||||
rx_ctl |= AX_RX_CTL_MFB_2048;
|
||||
#endif
|
||||
const uint8_t multi_filter[] = { 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40 };
|
||||
|
||||
usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_MULTI_FILTER, 0, 0, (uint8_t *)multi_filter, AX_MCAST_FILTER_SIZE);
|
||||
@@ -358,7 +380,7 @@ static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, 0, NULL);
|
||||
ret = usbh_asix_write_cmd(asix_class, AX_CMD_SW_PHY_SELECT, asix_class->embd_phy | AX_PHYSEL_SSEN, 0, NULL, 0);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Select PHY #1 failed: %d\r\n", ret);
|
||||
goto out;
|
||||
@@ -422,7 +444,7 @@ static int usbh_ax88772a_hw_reset(struct usbh_asix *asix_class)
|
||||
|
||||
ret = usbh_asix_write_cmd(asix_class, AX_CMD_WRITE_IPG0,
|
||||
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
|
||||
AX88772_IPG2_DEFAULT, 0, NULL);
|
||||
AX88772_IPG2_DEFAULT, NULL, 0);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Write IPG,IPG1,IPG2 failed: %d\r\n", ret);
|
||||
goto out;
|
||||
@@ -589,7 +611,7 @@ static int usbh_asix_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
USB_LOG_INFO("Init %s done\r\n", asix_class->name);
|
||||
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register ASIX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_asix_run(asix_class);
|
||||
@@ -649,16 +671,20 @@ int usbh_asix_get_connect_status(struct usbh_asix *asix_class)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usbh_asix_rx_thread(void *argument)
|
||||
void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
uint32_t g_asix_rx_length;
|
||||
int ret;
|
||||
err_t err;
|
||||
uint16_t len;
|
||||
uint16_t len_crc;
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
uint32_t data_offset;
|
||||
#if CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
uint32_t transfer_size = CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE;
|
||||
#else
|
||||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
USB_LOG_INFO("Create asix rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
@@ -674,11 +700,12 @@ find_class:
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(128);
|
||||
}
|
||||
|
||||
g_asix_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize), USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
usbh_bulk_urb_fill(&g_asix_class.bulkin_urb, g_asix_class.hport, g_asix_class.bulkin, &g_asix_rx_buffer[g_asix_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_asix_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
@@ -686,31 +713,44 @@ find_class:
|
||||
|
||||
g_asix_rx_length += g_asix_class.bulkin_urb.actual_length;
|
||||
|
||||
if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize)) {
|
||||
len = ((uint16_t)g_asix_rx_buffer[0] | ((uint16_t)(g_asix_rx_buffer[1]) << 8)) & 0x7ff;
|
||||
len_crc = g_asix_rx_buffer[2] | ((uint16_t)(g_asix_rx_buffer[3]) << 8);
|
||||
|
||||
if (len != (~len_crc & 0x7ff)) {
|
||||
USB_LOG_ERR("asix rx header error\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A transfer is complete because last packet is a short packet.
|
||||
* Short packet is not zero, match g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize).
|
||||
* Short packet is zero, check if g_asix_class.bulkin_urb.actual_length < transfer_size, for example transfer is complete with size is 1024 < 2048.
|
||||
*/
|
||||
if (g_asix_rx_length % USB_GET_MAXPACKETSIZE(g_asix_class.bulkin->wMaxPacketSize) ||
|
||||
(g_asix_class.bulkin_urb.actual_length < transfer_size)) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len);
|
||||
g_asix_rx_length = 0;
|
||||
data_offset = 0;
|
||||
while (g_asix_rx_length > 0) {
|
||||
len = ((uint16_t)g_asix_rx_buffer[data_offset + 0] | ((uint16_t)(g_asix_rx_buffer[data_offset + 1]) << 8)) & 0x7ff;
|
||||
len_crc = g_asix_rx_buffer[data_offset + 2] | ((uint16_t)(g_asix_rx_buffer[data_offset + 3]) << 8);
|
||||
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
if (len != (~len_crc & 0x7ff)) {
|
||||
USB_LOG_ERR("rx header error\r\n");
|
||||
g_asix_rx_length = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t *buf = (uint8_t *)&g_asix_rx_buffer[data_offset + 4];
|
||||
usbh_asix_eth_input(buf, len);
|
||||
g_asix_rx_length -= (len + 4);
|
||||
data_offset += (len + 4);
|
||||
|
||||
if (g_asix_rx_length < 4) {
|
||||
g_asix_rx_length = 0;
|
||||
}
|
||||
} else {
|
||||
g_asix_rx_length = 0;
|
||||
USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n");
|
||||
}
|
||||
} else {
|
||||
#if CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
if (g_asix_rx_length == CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
|
||||
#else
|
||||
if ((g_asix_rx_length + (16 * 1024)) > CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
@@ -720,78 +760,67 @@ delete:
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
uint8_t *usbh_asix_get_eth_txbuf(void)
|
||||
{
|
||||
return &g_asix_tx_buffer[4];
|
||||
}
|
||||
|
||||
int usbh_asix_eth_output(uint32_t buflen)
|
||||
{
|
||||
int ret;
|
||||
struct pbuf *q;
|
||||
uint16_t actual_len;
|
||||
uint8_t *buffer = &g_asix_tx_buffer[4];
|
||||
|
||||
if (g_asix_class.connect_status == false) {
|
||||
return ERR_BUF;
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
g_asix_tx_buffer[0] = p->tot_len & 0xff;
|
||||
g_asix_tx_buffer[1] = (p->tot_len >> 8) & 0xff;
|
||||
g_asix_tx_buffer[0] = buflen & 0xff;
|
||||
g_asix_tx_buffer[1] = (buflen >> 8) & 0xff;
|
||||
g_asix_tx_buffer[2] = ~g_asix_tx_buffer[0];
|
||||
g_asix_tx_buffer[3] = ~g_asix_tx_buffer[1];
|
||||
|
||||
if (!(p->tot_len + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
|
||||
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 8);
|
||||
g_asix_tx_buffer[p->tot_len + 4 + 0] = 0x00;
|
||||
g_asix_tx_buffer[p->tot_len + 4 + 1] = 0x00;
|
||||
g_asix_tx_buffer[p->tot_len + 4 + 2] = 0xff;
|
||||
g_asix_tx_buffer[p->tot_len + 4 + 3] = 0xff;
|
||||
actual_len = p->tot_len + 8;
|
||||
if (!(buflen + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
|
||||
USB_LOG_DBG("txlen:%d\r\n", buflen + 8);
|
||||
g_asix_tx_buffer[buflen + 4 + 0] = 0x00;
|
||||
g_asix_tx_buffer[buflen + 4 + 1] = 0x00;
|
||||
g_asix_tx_buffer[buflen + 4 + 2] = 0xff;
|
||||
g_asix_tx_buffer[buflen + 4 + 3] = 0xff;
|
||||
actual_len = buflen + 8;
|
||||
} else {
|
||||
USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4);
|
||||
actual_len = p->tot_len + 4;
|
||||
USB_LOG_DBG("txlen:%d\r\n", buflen + 4);
|
||||
actual_len = buflen + 4;
|
||||
}
|
||||
|
||||
usbh_bulk_urb_fill(&g_asix_class.bulkout_urb, g_asix_class.hport, g_asix_class.bulkout, g_asix_tx_buffer, actual_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_asix_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
return usbh_submit_urb(&g_asix_class.bulkout_urb);
|
||||
}
|
||||
|
||||
__WEAK void usbh_asix_run(struct usbh_asix *asix_class)
|
||||
{
|
||||
(void)asix_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_asix_stop(struct usbh_asix *asix_class)
|
||||
{
|
||||
(void)asix_class;
|
||||
}
|
||||
|
||||
static const uint16_t asix_id_table[][2] = {
|
||||
{ 0x0B95, 0x772B },
|
||||
{ 0x0B95, 0x7720 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct usbh_class_driver asix_class_driver = {
|
||||
.driver_name = "asix",
|
||||
.connect = usbh_asix_connect,
|
||||
.disconnect = usbh_asix_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info ax88772b_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x0B95,
|
||||
.pid = 0x772B,
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info asix_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = asix_id_table,
|
||||
.class_driver = &asix_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info ax88772_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x0B95,
|
||||
.pid = 0x7720,
|
||||
.class_driver = &asix_class_driver
|
||||
};
|
||||
};
|
||||
13
class/vendor/net/usbh_asix.h
vendored
13
class/vendor/net/usbh_asix.h
vendored
@@ -6,9 +6,6 @@
|
||||
#ifndef USBH_ASIX_H
|
||||
#define USBH_ASIX_H
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
|
||||
|
||||
#define AX_CMD_SET_SW_MII 0x06
|
||||
@@ -156,9 +153,7 @@ struct usbh_asix {
|
||||
bool connect_status;
|
||||
uint8_t mac[6];
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gateway;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -170,8 +165,10 @@ int usbh_asix_get_connect_status(struct usbh_asix *asix_class);
|
||||
void usbh_asix_run(struct usbh_asix *asix_class);
|
||||
void usbh_asix_stop(struct usbh_asix *asix_class);
|
||||
|
||||
void usbh_asix_rx_thread(void *argument);
|
||||
err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p);
|
||||
uint8_t *usbh_asix_get_eth_txbuf(void);
|
||||
int usbh_asix_eth_output(uint32_t buflen);
|
||||
void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
2281
class/vendor/net/usbh_rtl8152.c
vendored
Normal file
2281
class/vendor/net/usbh_rtl8152.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
68
class/vendor/net/usbh_rtl8152.h
vendored
Normal file
68
class/vendor/net/usbh_rtl8152.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_RTL8152_H
|
||||
#define USBH_RTL8152_H
|
||||
|
||||
struct usbh_rtl8152 {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
struct usbh_urb intin_urb;
|
||||
|
||||
uint8_t intf;
|
||||
|
||||
uint8_t mac[6];
|
||||
bool connect_status;
|
||||
uint32_t speed[2];
|
||||
|
||||
uint8_t version;
|
||||
uint8_t eee_adv;
|
||||
uint8_t eee_en;
|
||||
uint8_t supports_gmii;
|
||||
uint16_t min_mtu;
|
||||
uint16_t max_mtu;
|
||||
uint16_t ocp_base;
|
||||
uint32_t saved_wolopts;
|
||||
uint32_t rx_buf_sz;
|
||||
|
||||
struct rtl_ops {
|
||||
void (*init)(struct usbh_rtl8152 *tp);
|
||||
int (*enable)(struct usbh_rtl8152 *tp);
|
||||
void (*disable)(struct usbh_rtl8152 *tp);
|
||||
void (*up)(struct usbh_rtl8152 *tp);
|
||||
void (*down)(struct usbh_rtl8152 *tp);
|
||||
void (*unload)(struct usbh_rtl8152 *tp);
|
||||
bool (*in_nway)(struct usbh_rtl8152 *tp);
|
||||
void (*hw_phy_cfg)(struct usbh_rtl8152 *tp);
|
||||
void (*autosuspend_en)(struct usbh_rtl8152 *tp, bool enable);
|
||||
void (*change_mtu)(struct usbh_rtl8152 *tp);
|
||||
} rtl_ops;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_rtl8152_get_connect_status(struct usbh_rtl8152 *rtl8152_class);
|
||||
|
||||
void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class);
|
||||
void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class);
|
||||
|
||||
uint8_t *usbh_rtl8152_get_eth_txbuf(void);
|
||||
int usbh_rtl8152_eth_output(uint32_t buflen);
|
||||
void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_RTL8152_H */
|
||||
60
class/vendor/serial/usbh_ch34x.c
vendored
60
class/vendor/serial/usbh_ch34x.c
vendored
@@ -8,7 +8,7 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ch34x_buf[64];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ch34x_buf[USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
|
||||
|
||||
@@ -17,11 +17,11 @@ static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_ch34x_class[devno], 0, sizeof(struct usbh_ch34x));
|
||||
g_ch34x_class[devno].minor = devno;
|
||||
return &g_ch34x_class[devno];
|
||||
@@ -32,10 +32,10 @@ static struct usbh_ch34x *usbh_ch34x_class_alloc(void)
|
||||
|
||||
static void usbh_ch34x_class_free(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
int devno = ch34x_class->minor;
|
||||
uint8_t devno = ch34x_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(ch34x_class, 0, sizeof(struct usbh_ch34x));
|
||||
}
|
||||
@@ -90,9 +90,14 @@ static int usbh_ch34x_get_baudrate_div(uint32_t baudrate, uint8_t *factor, uint8
|
||||
|
||||
static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!ch34x_class || !ch34x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ch34x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = CH34X_READ_VERSION;
|
||||
setup->wValue = 0;
|
||||
@@ -110,7 +115,12 @@ static int usbh_ch34x_get_version(struct usbh_ch34x *ch34x_class)
|
||||
|
||||
static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!ch34x_class || !ch34x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ch34x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = CH34X_WRITE_REG;
|
||||
@@ -123,12 +133,17 @@ static int usbh_ch34x_flow_ctrl(struct usbh_ch34x *ch34x_class)
|
||||
|
||||
int usbh_ch34x_set_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
uint16_t reg_value = 0;
|
||||
uint16_t value = 0;
|
||||
uint8_t factor = 0;
|
||||
uint8_t divisor = 0;
|
||||
|
||||
if (!ch34x_class || !ch34x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ch34x_class->hport->setup;
|
||||
|
||||
memcpy((uint8_t *)&ch34x_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||
|
||||
/* refer to https://github.com/WCHSoftGroup/ch341ser_linux/blob/main/driver/ch341.c */
|
||||
@@ -197,7 +212,12 @@ int usbh_ch34x_get_line_coding(struct usbh_ch34x *ch34x_class, struct cdc_line_c
|
||||
|
||||
int usbh_ch34x_set_line_state(struct usbh_ch34x *ch34x_class, bool dtr, bool rts)
|
||||
{
|
||||
struct usb_setup_packet *setup = ch34x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!ch34x_class || !ch34x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ch34x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = CH34X_MODEM_CTRL;
|
||||
@@ -329,12 +349,19 @@ int usbh_ch34x_bulk_out_transfer(struct usbh_ch34x *ch34x_class, uint8_t *buffer
|
||||
|
||||
__WEAK void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
(void)ch34x_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
|
||||
{
|
||||
(void)ch34x_class;
|
||||
}
|
||||
|
||||
static const uint16_t ch34x_id_table[][2] = {
|
||||
{ 0x1A86, 0x7523 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct usbh_class_driver ch34x_class_driver = {
|
||||
.driver_name = "ch34x",
|
||||
.connect = usbh_ch34x_connect,
|
||||
@@ -342,11 +369,10 @@ const struct usbh_class_driver ch34x_class_driver = {
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0xff,
|
||||
.protocol = 0xff,
|
||||
.vid = 0x1A86,
|
||||
.pid = 0x7523,
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = ch34x_id_table,
|
||||
.class_driver = &ch34x_class_driver
|
||||
};
|
||||
2
class/vendor/serial/usbh_ch34x.h
vendored
2
class/vendor/serial/usbh_ch34x.h
vendored
@@ -51,6 +51,8 @@ struct usbh_ch34x {
|
||||
|
||||
uint8_t intf;
|
||||
uint8_t minor;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
76
class/vendor/serial/usbh_cp210x.c
vendored
76
class/vendor/serial/usbh_cp210x.c
vendored
@@ -8,20 +8,20 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[64];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cp210x_buf[USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_CP210X_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_CP210X_CLASS 1
|
||||
|
||||
static struct usbh_cp210x g_cp210x_class[CONFIG_USBHOST_MAX_CP210X_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_CP210X_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_cp210x_class[devno], 0, sizeof(struct usbh_cp210x));
|
||||
g_cp210x_class[devno].minor = devno;
|
||||
return &g_cp210x_class[devno];
|
||||
@@ -32,17 +32,22 @@ static struct usbh_cp210x *usbh_cp210x_class_alloc(void)
|
||||
|
||||
static void usbh_cp210x_class_free(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
int devno = cp210x_class->minor;
|
||||
uint8_t devno = cp210x_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(cp210x_class, 0, sizeof(struct usbh_cp210x));
|
||||
}
|
||||
|
||||
static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cp210x_class || !cp210x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cp210x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CP210X_IFC_ENABLE;
|
||||
@@ -55,7 +60,12 @@ static int usbh_cp210x_enable(struct usbh_cp210x *cp210x_class)
|
||||
|
||||
static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cp210x_class || !cp210x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cp210x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CP210X_SET_FLOW;
|
||||
@@ -70,7 +80,12 @@ static int usbh_cp210x_set_flow(struct usbh_cp210x *cp210x_class)
|
||||
|
||||
static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cp210x_class || !cp210x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cp210x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CP210X_SET_CHARS;
|
||||
@@ -87,7 +102,12 @@ static int usbh_cp210x_set_chars(struct usbh_cp210x *cp210x_class)
|
||||
|
||||
static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t baudrate)
|
||||
{
|
||||
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!cp210x_class || !cp210x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cp210x_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CP210X_SET_BAUDRATE;
|
||||
@@ -101,9 +121,14 @@ static int usbh_cp210x_set_baudrate(struct usbh_cp210x *cp210x_class, uint32_t b
|
||||
|
||||
static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t databits, uint8_t parity, uint8_t stopbits)
|
||||
{
|
||||
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
uint16_t value;
|
||||
|
||||
if (!cp210x_class || !cp210x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cp210x_class->hport->setup;
|
||||
|
||||
value = ((databits & 0x0F) << 8) | ((parity & 0x0f) << 4) | ((stopbits & 0x03) << 0);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
@@ -117,9 +142,14 @@ static int usbh_cp210x_set_data_format(struct usbh_cp210x *cp210x_class, uint8_t
|
||||
|
||||
static int usbh_cp210x_set_mhs(struct usbh_cp210x *cp210x_class, uint8_t dtr, uint8_t rts, uint8_t dtr_mask, uint8_t rts_mask)
|
||||
{
|
||||
struct usb_setup_packet *setup = cp210x_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
uint16_t value;
|
||||
|
||||
if (!cp210x_class || !cp210x_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = cp210x_class->hport->setup;
|
||||
|
||||
value = ((dtr & 0x01) << 0) | ((rts & 0x01) << 1) | ((dtr_mask & 0x01) << 8) | ((rts_mask & 0x01) << 9);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
@@ -268,12 +298,19 @@ int usbh_cp210x_bulk_out_transfer(struct usbh_cp210x *cp210x_class, uint8_t *buf
|
||||
|
||||
__WEAK void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
(void)cp210x_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
|
||||
{
|
||||
(void)cp210x_class;
|
||||
}
|
||||
|
||||
static const uint16_t cp210x_id_table[][2] = {
|
||||
{ 0x10C4, 0xEA60 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct usbh_class_driver cp210x_class_driver = {
|
||||
.driver_name = "cp210x",
|
||||
.connect = usbh_cp210x_connect,
|
||||
@@ -281,11 +318,10 @@ const struct usbh_class_driver cp210x_class_driver = {
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0xff,
|
||||
.protocol = 0xff,
|
||||
.vid = 0x10C4,
|
||||
.pid = 0xEA60,
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = cp210x_id_table,
|
||||
.class_driver = &cp210x_class_driver
|
||||
};
|
||||
10
class/vendor/serial/usbh_cp210x.h
vendored
10
class/vendor/serial/usbh_cp210x.h
vendored
@@ -17,7 +17,7 @@
|
||||
#define CP210X_SET_BREAK 0x05
|
||||
#define CP210X_IMM_CHAR 0x06
|
||||
#define CP210X_SET_MHS 0x07 // Set DTR, RTS
|
||||
#define CP210X_GET_MDMSTS 0x08
|
||||
#define CP210X_GET_MDMSTS 0x08
|
||||
#define CP210X_SET_XON 0x09
|
||||
#define CP210X_SET_XOFF 0x0A
|
||||
#define CP210X_SET_EVENTMASK 0x0B
|
||||
@@ -33,9 +33,9 @@
|
||||
#define CP210X_EMBED_EVENTS 0x15
|
||||
#define CP210X_GET_EVENTSTATE 0x16
|
||||
#define CP210X_SET_CHARS 0x19
|
||||
#define CP210X_GET_BAUDRATE 0x1D
|
||||
#define CP210X_GET_BAUDRATE 0x1D
|
||||
#define CP210X_SET_BAUDRATE 0x1E // Set baudrate
|
||||
#define CP210X_VENDOR_SPECIFIC 0xFF
|
||||
#define CP210X_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
struct usbh_cp210x {
|
||||
struct usbh_hubport *hport;
|
||||
@@ -45,9 +45,11 @@ struct usbh_cp210x {
|
||||
struct usbh_urb bulkin_urb;
|
||||
|
||||
struct cdc_line_coding line_coding;
|
||||
|
||||
|
||||
uint8_t intf;
|
||||
uint8_t minor;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
270
class/vendor/serial/usbh_ftdi.c
vendored
270
class/vendor/serial/usbh_ftdi.c
vendored
@@ -8,20 +8,39 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[64];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_ftdi_buf[USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_FTDI_CLASS 4
|
||||
#define CONFIG_USBHOST_MAX_FTDI_CLASS 1
|
||||
|
||||
static struct usbh_ftdi g_ftdi_class[CONFIG_USBHOST_MAX_FTDI_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static const char *ftdi_chip_name[] = {
|
||||
[SIO] = "SIO", /* the serial part of FT8U100AX */
|
||||
[FT232A] = "FT232A",
|
||||
[FT232B] = "FT232B",
|
||||
[FT2232C] = "FT2232C/D",
|
||||
[FT232R] = "FT232R",
|
||||
[FT232H] = "FT232H",
|
||||
[FT2232H] = "FT2232H",
|
||||
[FT4232H] = "FT4232H",
|
||||
[FT4232HA] = "FT4232HA",
|
||||
[FT232HP] = "FT232HP",
|
||||
[FT233HP] = "FT233HP",
|
||||
[FT2232HP] = "FT2232HP",
|
||||
[FT2233HP] = "FT2233HP",
|
||||
[FT4232HP] = "FT4232HP",
|
||||
[FT4233HP] = "FT4233HP",
|
||||
[FTX] = "FT-X",
|
||||
};
|
||||
|
||||
static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_FTDI_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_ftdi_class[devno], 0, sizeof(struct usbh_ftdi));
|
||||
g_ftdi_class[devno].minor = devno;
|
||||
return &g_ftdi_class[devno];
|
||||
@@ -32,46 +51,90 @@ static struct usbh_ftdi *usbh_ftdi_class_alloc(void)
|
||||
|
||||
static void usbh_ftdi_class_free(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
int devno = ftdi_class->minor;
|
||||
uint8_t devno = ftdi_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(ftdi_class, 0, sizeof(struct usbh_ftdi));
|
||||
}
|
||||
|
||||
static void usbh_ftdi_caculate_baudrate(uint32_t *itdf_divisor, uint32_t actual_baudrate)
|
||||
{
|
||||
#define FTDI_USB_CLK 48000000
|
||||
int baudrate;
|
||||
uint8_t frac[] = { 0, 8, 4, 2, 6, 10, 12, 14 };
|
||||
/*
|
||||
* Divide positive or negative dividend by positive or negative divisor
|
||||
* and round to closest integer. Result is undefined for negative
|
||||
* divisors if the dividend variable type is unsigned and for negative
|
||||
* dividends if the divisor variable type is unsigned.
|
||||
*/
|
||||
#define DIV_ROUND_CLOSEST(x, divisor) ( \
|
||||
{ \
|
||||
typeof(x) __x = x; \
|
||||
typeof(divisor) __d = divisor; \
|
||||
(((typeof(x))-1) > 0 || \
|
||||
((typeof(divisor))-1) > 0 || \
|
||||
(((__x) > 0) == ((__d) > 0))) ? \
|
||||
(((__x) + ((__d) / 2)) / (__d)) : \
|
||||
(((__x) - ((__d) / 2)) / (__d)); \
|
||||
})
|
||||
|
||||
if (actual_baudrate == 2000000) {
|
||||
*itdf_divisor = 0x01;
|
||||
} else if (actual_baudrate == 3000000) {
|
||||
*itdf_divisor = 0x00;
|
||||
} else {
|
||||
baudrate = actual_baudrate;
|
||||
if (baudrate > 100000 && baudrate < 12000000) {
|
||||
baudrate = (baudrate / 100000) + 100000;
|
||||
}
|
||||
int divisor = FTDI_USB_CLK / baudrate;
|
||||
int frac_bits = 0;
|
||||
for (int i = 0; i < sizeof(frac) / sizeof(frac[0]); i++) {
|
||||
if ((divisor & 0xF) == frac[i]) {
|
||||
frac_bits = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
divisor >>= 4;
|
||||
divisor &= 0x3FFF;
|
||||
*itdf_divisor = (divisor << 14) | (frac_bits << 8);
|
||||
}
|
||||
static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, int base)
|
||||
{
|
||||
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
|
||||
uint32_t divisor;
|
||||
/* divisor shifted 3 bits to the left */
|
||||
int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud);
|
||||
divisor = divisor3 >> 3;
|
||||
divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14;
|
||||
/* Deal with special cases for highest baud rates. */
|
||||
if (divisor == 1) /* 1.0 */
|
||||
divisor = 0;
|
||||
else if (divisor == 0x4001) /* 1.5 */
|
||||
divisor = 1;
|
||||
return divisor;
|
||||
}
|
||||
|
||||
static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud)
|
||||
{
|
||||
return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
|
||||
}
|
||||
|
||||
static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, int base)
|
||||
{
|
||||
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
|
||||
uint32_t divisor;
|
||||
int divisor3;
|
||||
|
||||
/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
|
||||
divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud);
|
||||
|
||||
divisor = divisor3 >> 3;
|
||||
divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14;
|
||||
/* Deal with special cases for highest baud rates. */
|
||||
if (divisor == 1) /* 1.0 */
|
||||
divisor = 0;
|
||||
else if (divisor == 0x4001) /* 1.5 */
|
||||
divisor = 1;
|
||||
/*
|
||||
* Set this bit to turn off a divide by 2.5 on baud rate generator
|
||||
* This enables baud rates up to 12Mbaud but cannot reach below 1200
|
||||
* baud with this bit set
|
||||
*/
|
||||
divisor |= 0x00020000;
|
||||
return divisor;
|
||||
}
|
||||
|
||||
static uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud)
|
||||
{
|
||||
return ftdi_2232h_baud_base_to_divisor(baud, 120000000);
|
||||
}
|
||||
|
||||
int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_RESET_REQUEST;
|
||||
@@ -84,7 +147,12 @@ int usbh_ftdi_reset(struct usbh_ftdi *ftdi_class)
|
||||
|
||||
static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||
{
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_SET_MODEM_CTRL_REQUEST;
|
||||
@@ -97,14 +165,36 @@ static int usbh_ftdi_set_modem(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||
|
||||
static int usbh_ftdi_set_baudrate(struct usbh_ftdi *ftdi_class, uint32_t baudrate)
|
||||
{
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
uint32_t itdf_divisor;
|
||||
struct usb_setup_packet *setup;
|
||||
uint32_t div_value;
|
||||
uint16_t value;
|
||||
uint8_t baudrate_high;
|
||||
|
||||
usbh_ftdi_caculate_baudrate(&itdf_divisor, baudrate);
|
||||
value = itdf_divisor & 0xFFFF;
|
||||
baudrate_high = (itdf_divisor >> 16) & 0xff;
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
switch (ftdi_class->chip_type) {
|
||||
case FT232B:
|
||||
case FT2232C:
|
||||
case FT232R:
|
||||
if (baudrate > 3000000) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
div_value = ftdi_232bm_baud_to_divisor(baudrate);
|
||||
break;
|
||||
default:
|
||||
if ((baudrate <= 12000000) && (baudrate >= 1200)) {
|
||||
div_value = ftdi_2232h_baud_to_divisor(baudrate);
|
||||
} else {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
value = div_value & 0xFFFF;
|
||||
baudrate_high = (div_value >> 16) & 0xff;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_SET_BAUDRATE_REQUEST;
|
||||
@@ -120,13 +210,18 @@ static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t datab
|
||||
/**
|
||||
* D0-D7 databits BITS_7=7, BITS_8=8
|
||||
* D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4
|
||||
* D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2
|
||||
* D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2
|
||||
* D14 BREAK_OFF=0, BREAK_ON=1
|
||||
**/
|
||||
struct usb_setup_packet *setup;
|
||||
uint16_t value;
|
||||
|
||||
uint16_t value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f);
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
value = ((isbreak & 0x01) << 14) | ((stopbits & 0x03) << 11) | ((parity & 0x0f) << 8) | (databits & 0x0f);
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_SET_DATA_REQUEST;
|
||||
@@ -139,7 +234,12 @@ static int usbh_ftdi_set_data_format(struct usbh_ftdi *ftdi_class, uint8_t datab
|
||||
|
||||
static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||
{
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_SET_LATENCY_TIMER_REQUEST;
|
||||
@@ -152,7 +252,12 @@ static int usbh_ftdi_set_latency_timer(struct usbh_ftdi *ftdi_class, uint16_t va
|
||||
|
||||
static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||
{
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_SET_FLOW_CTRL_REQUEST;
|
||||
@@ -165,9 +270,14 @@ static int usbh_ftdi_set_flow_ctrl(struct usbh_ftdi *ftdi_class, uint16_t value)
|
||||
|
||||
static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = ftdi_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!ftdi_class || !ftdi_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = ftdi_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = SIO_POLL_MODEM_STATUS_REQUEST;
|
||||
setup->wValue = 0x0000;
|
||||
@@ -185,7 +295,11 @@ static int usbh_ftdi_read_modem_status(struct usbh_ftdi *ftdi_class)
|
||||
int usbh_ftdi_set_line_coding(struct usbh_ftdi *ftdi_class, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
memcpy((uint8_t *)&ftdi_class->line_coding, line_coding, sizeof(struct cdc_line_coding));
|
||||
usbh_ftdi_set_baudrate(ftdi_class, line_coding->dwDTERate);
|
||||
|
||||
int ret = usbh_ftdi_set_baudrate(ftdi_class, line_coding->dwDTERate);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return usbh_ftdi_set_data_format(ftdi_class, line_coding->bDataBits, line_coding->bParityType, line_coding->bCharFormat, 0);
|
||||
}
|
||||
|
||||
@@ -218,6 +332,7 @@ static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
uint16_t version;
|
||||
|
||||
struct usbh_ftdi *ftdi_class = usbh_ftdi_class_alloc();
|
||||
if (ftdi_class == NULL) {
|
||||
@@ -230,6 +345,34 @@ static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
hport->config.intf[intf].priv = ftdi_class;
|
||||
|
||||
version = hport->device_desc.bcdDevice;
|
||||
|
||||
switch (version) {
|
||||
case 0x400:
|
||||
ftdi_class->chip_type = FT232B;
|
||||
case 0x500:
|
||||
ftdi_class->chip_type = FT2232C;
|
||||
break;
|
||||
case 0x600:
|
||||
ftdi_class->chip_type = FT232R;
|
||||
break;
|
||||
case 0x700:
|
||||
ftdi_class->chip_type = FT2232H;
|
||||
break;
|
||||
case 0x800:
|
||||
ftdi_class->chip_type = FT4232H;
|
||||
break;
|
||||
case 0x900:
|
||||
ftdi_class->chip_type = FT232H;
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_LOG_ERR("Unknown FTDI chip version:%04x\r\n", version);
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
|
||||
USB_LOG_INFO("FTDI chip name:%s\r\n", ftdi_chip_name[ftdi_class->chip_type]);
|
||||
|
||||
usbh_ftdi_reset(ftdi_class);
|
||||
usbh_ftdi_set_flow_ctrl(ftdi_class, SIO_DISABLE_FLOW_CTRL);
|
||||
usbh_ftdi_set_latency_timer(ftdi_class, 0x10);
|
||||
@@ -335,34 +478,31 @@ int usbh_ftdi_bulk_out_transfer(struct usbh_ftdi *ftdi_class, uint8_t *buffer, u
|
||||
|
||||
__WEAK void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
(void)ftdi_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
|
||||
{
|
||||
(void)ftdi_class;
|
||||
}
|
||||
|
||||
static const uint16_t ftdi_id_table[][2] = {
|
||||
{ 0x0403, 0x6001 },
|
||||
{ 0x0403, 0x6010 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct usbh_class_driver ftdi_class_driver = {
|
||||
.driver_name = "ftdi",
|
||||
.connect = usbh_ftdi_connect,
|
||||
.disconnect = usbh_ftdi_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info ftdi1_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0xff,
|
||||
.protocol = 0xff,
|
||||
.vid = 0x0403,
|
||||
.pid = 0x6001,
|
||||
.class_driver = &ftdi_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info ftdi2_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0xff,
|
||||
.protocol = 0xff,
|
||||
.vid = 0x0403,
|
||||
.pid = 0x6010,
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = ftdi_id_table,
|
||||
.class_driver = &ftdi_class_driver
|
||||
};
|
||||
22
class/vendor/serial/usbh_ftdi.h
vendored
22
class/vendor/serial/usbh_ftdi.h
vendored
@@ -39,6 +39,25 @@
|
||||
|
||||
#define SIO_RTS_CTS_HS (0x1 << 8)
|
||||
|
||||
enum ftdi_chip_type {
|
||||
SIO,
|
||||
FT232A,
|
||||
FT232B,
|
||||
FT2232C,
|
||||
FT232R,
|
||||
FT232H,
|
||||
FT2232H,
|
||||
FT4232H,
|
||||
FT4232HA,
|
||||
FT232HP,
|
||||
FT233HP,
|
||||
FT2232HP,
|
||||
FT2233HP,
|
||||
FT4232HP,
|
||||
FT4233HP,
|
||||
FTX,
|
||||
};
|
||||
|
||||
struct usbh_ftdi {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
@@ -51,6 +70,9 @@ struct usbh_ftdi {
|
||||
uint8_t intf;
|
||||
uint8_t minor;
|
||||
uint8_t modem_status[2];
|
||||
enum ftdi_chip_type chip_type;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
448
class/vendor/serial/usbh_pl2303.c
vendored
Normal file
448
class/vendor/serial/usbh_pl2303.c
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
* Copyright (c) 2024, Derek Konigsberg
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_pl2303.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_pl2303"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/ttyUSB%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_pl2303_buf[USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
#define CONFIG_USBHOST_MAX_PL2303_CLASS 1
|
||||
|
||||
#define UT_WRITE_VENDOR_DEVICE (USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
|
||||
#define UT_READ_VENDOR_DEVICE (USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE)
|
||||
|
||||
static struct usbh_pl2303 g_pl2303_class[CONFIG_USBHOST_MAX_PL2303_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_pl2303 *usbh_pl2303_class_alloc(void)
|
||||
{
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_PL2303_CLASS; devno++) {
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_pl2303_class[devno], 0, sizeof(struct usbh_pl2303));
|
||||
g_pl2303_class[devno].minor = devno;
|
||||
return &g_pl2303_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_pl2303_class_free(struct usbh_pl2303 *pl2303_class)
|
||||
{
|
||||
uint8_t devno = pl2303_class->minor;
|
||||
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(pl2303_class, 0, sizeof(struct usbh_pl2303));
|
||||
}
|
||||
|
||||
static int usbh_pl2303_get_chiptype(struct usbh_pl2303 *pl2303_class)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (pl2303_class->hport->device_desc.bcdDevice) {
|
||||
case 0x0300:
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HX;
|
||||
/* or TA, that is HX with external crystal */
|
||||
break;
|
||||
case 0x0400:
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HXD;
|
||||
/* or EA, that is HXD with ESD protection */
|
||||
/* or RA, that has internal voltage level converter that works only up to 1Mbaud (!) */
|
||||
break;
|
||||
case 0x0500:
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HXD;
|
||||
/* in fact it's TB, that is HXD with external crystal */
|
||||
break;
|
||||
default:
|
||||
/* NOTE: I have no info about the bcdDevice for the base PL2303 (up to 1.2Mbaud,
|
||||
only fixed rates) and for PL2303SA (8-pin chip, up to 115200 baud */
|
||||
/* Determine the chip type. This algorithm is taken from Linux. */
|
||||
if (pl2303_class->hport->device_desc.bDeviceClass == 0x02) {
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303;
|
||||
} else if (pl2303_class->hport->device_desc.bMaxPacketSize0 == 0x40) {
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HX;
|
||||
} else {
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The new chip revision PL2303HXN is only compatible with the new
|
||||
* PLCOM_SET_REQUEST_PL2303HXN command. Issuing the old command
|
||||
* PLCOM_SET_REQUEST to the new chip raises an error. Thus, PL2303HX
|
||||
* and PL2303HXN can be distinguished by issuing an old-style request
|
||||
* (on a status register) to the new chip and checking the error.
|
||||
*/
|
||||
if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HX) {
|
||||
struct usb_setup_packet *setup = pl2303_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = UT_READ_VENDOR_DEVICE;
|
||||
setup->bRequest = PL2303_SET_REQUEST;
|
||||
setup->wValue = PL2303_STATUS_REG_PL2303HX;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 1;
|
||||
|
||||
ret = usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
|
||||
if (ret == -USB_ERR_STALL) {
|
||||
pl2303_class->chiptype = USBH_PL2303_TYPE_PL2303HXN;
|
||||
ret = 0;
|
||||
} else if (ret < 0) {
|
||||
USB_LOG_WRN("Error checking chip type: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
switch (pl2303_class->chiptype) {
|
||||
case USBH_PL2303_TYPE_PL2303:
|
||||
USB_LOG_INFO("chiptype = 2303\r\n");
|
||||
break;
|
||||
case USBH_PL2303_TYPE_PL2303HX:
|
||||
USB_LOG_INFO("chiptype = 2303HX/TA\r\n");
|
||||
break;
|
||||
case USBH_PL2303_TYPE_PL2303HXN:
|
||||
USB_LOG_INFO("chiptype = 2303HXN\r\n");
|
||||
break;
|
||||
case USBH_PL2303_TYPE_PL2303HXD:
|
||||
USB_LOG_INFO("chiptype = 2303HXD/TB/RA/EA\r\n");
|
||||
break;
|
||||
default:
|
||||
USB_LOG_INFO("chiptype = [%d]\r\n", pl2303_class->chiptype);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_pl2303_do(struct usbh_pl2303 *pl2303_class,
|
||||
uint8_t req_type, uint8_t request, uint16_t value, uint16_t index,
|
||||
uint16_t length)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!pl2303_class || !pl2303_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = pl2303_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = req_type;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = value;
|
||||
setup->wIndex = index;
|
||||
setup->wLength = length;
|
||||
|
||||
return usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
|
||||
}
|
||||
|
||||
int usbh_pl2303_set_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!pl2303_class || !pl2303_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = pl2303_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = pl2303_class->intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
memcpy(g_pl2303_buf, line_coding, sizeof(struct cdc_line_coding));
|
||||
|
||||
return usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
|
||||
}
|
||||
|
||||
int usbh_pl2303_get_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!pl2303_class || !pl2303_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = pl2303_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = pl2303_class->intf;
|
||||
setup->wLength = 7;
|
||||
|
||||
ret = usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(line_coding, g_pl2303_buf, sizeof(struct cdc_line_coding));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_pl2303_set_line_state(struct usbh_pl2303 *pl2303_class, bool dtr, bool rts)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!pl2303_class || !pl2303_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = pl2303_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
|
||||
setup->wValue = (dtr << 0) | (rts << 1);
|
||||
setup->wIndex = pl2303_class->intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
return usbh_control_transfer(pl2303_class->hport, setup, NULL);
|
||||
}
|
||||
|
||||
static int usbh_pl2303_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_pl2303 *pl2303_class = usbh_pl2303_class_alloc();
|
||||
if (pl2303_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc pl2303_class\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
pl2303_class->hport = hport;
|
||||
pl2303_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = pl2303_class;
|
||||
|
||||
do {
|
||||
ret = usbh_pl2303_get_chiptype(pl2303_class);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Startup reset sequence, if necessary for the chip type */
|
||||
if (pl2303_class->chiptype != USBH_PL2303_TYPE_PL2303HXN) {
|
||||
struct usb_setup_packet *setup = pl2303_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = UT_WRITE_VENDOR_DEVICE;
|
||||
setup->bRequest = PL2303_SET_REQUEST;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = pl2303_class->intf;
|
||||
setup->wLength = 0;
|
||||
|
||||
ret = usbh_control_transfer(pl2303_class->hport, setup, g_pl2303_buf);
|
||||
if (ret < 0) {
|
||||
USB_LOG_WRN("Initialization reset failed: %d\r\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303) {
|
||||
/* HX variants seem to lock up after a clear stall request. */
|
||||
/*
|
||||
* The FreeBSD code sets the stall flags on the in and out pipes
|
||||
* here. Have no idea exactly how to do this, or if it is necessary.
|
||||
* May just leave this code unwritten until test hardware is available.
|
||||
*/
|
||||
} else if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HX || pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HXD) {
|
||||
/* Reset upstream data pipes */
|
||||
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 8, 0, 0);
|
||||
if (ret < 0) {
|
||||
USB_LOG_WRN("Could not reset upstream data pipes (8,0): %d\r\n", ret);
|
||||
break;
|
||||
}
|
||||
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 9, 0, 0);
|
||||
if (ret < 0) {
|
||||
USB_LOG_WRN("Could not reset upstream data pipes (9,0): %d\r\n", ret);
|
||||
break;
|
||||
}
|
||||
} else if (pl2303_class->chiptype == USBH_PL2303_TYPE_PL2303HXN) {
|
||||
/* Reset upstream data pipes */
|
||||
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST_PL2303HXN, 0x07, 0x03, 0);
|
||||
if (ret < 0) {
|
||||
USB_LOG_WRN("Could not reset upstream data pipes (7,3): %d\r\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final device initialization, if necessary for the chip type */
|
||||
if (pl2303_class->chiptype != USBH_PL2303_TYPE_PL2303HXN) {
|
||||
if (usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x0404, 0, 0) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8383, 0, 1) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x0404, 1, 0) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8484, 0, 1) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_READ_VENDOR_DEVICE, PL2303_SET_REQUEST, 0x8383, 0, 1) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 0, 1, 0) < 0 ||
|
||||
usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 1, 0, 0) < 0) {
|
||||
USB_LOG_WRN("Could not complete init sequence\r\n");
|
||||
ret = -USB_ERR_INVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pl2303_class->chiptype != USBH_PL2303_TYPE_PL2303) {
|
||||
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 2, 0x44, 0);
|
||||
} else {
|
||||
ret = usbh_pl2303_do(pl2303_class, UT_WRITE_VENDOR_DEVICE, PL2303_SET_REQUEST, 2, 0x24, 0);
|
||||
}
|
||||
if (ret < 0) {
|
||||
USB_LOG_WRN("Could not complete final init request: %d\r\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("Failed to initialize PL2303 device: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
continue;
|
||||
} else {
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(pl2303_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(pl2303_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, pl2303_class->minor);
|
||||
|
||||
USB_LOG_INFO("Register PL2303 Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
#if 0
|
||||
USB_LOG_INFO("Test pl2303 rx and tx and rx for 5 times, baudrate is 115200\r\n");
|
||||
|
||||
struct cdc_line_coding linecoding;
|
||||
uint8_t count = 5;
|
||||
|
||||
linecoding.dwDTERate = 115200;
|
||||
linecoding.bDataBits = 8;
|
||||
linecoding.bParityType = 0;
|
||||
linecoding.bCharFormat = 0;
|
||||
usbh_pl2303_set_line_coding(pl2303_class, &linecoding);
|
||||
usbh_pl2303_set_line_state(pl2303_class, true, false);
|
||||
|
||||
memset(g_pl2303_buf, 'a', sizeof(g_pl2303_buf));
|
||||
ret = usbh_pl2303_bulk_out_transfer(pl2303_class, g_pl2303_buf, sizeof(g_pl2303_buf), 0xfffffff);
|
||||
USB_LOG_RAW("out ret:%d\r\n", ret);
|
||||
while (count--) {
|
||||
ret = usbh_pl2303_bulk_in_transfer(pl2303_class, g_pl2303_buf, sizeof(g_pl2303_buf), 0xfffffff);
|
||||
USB_LOG_RAW("in ret:%d\r\n", ret);
|
||||
if (ret > 0) {
|
||||
for (uint32_t i = 0; i < ret; i++) {
|
||||
USB_LOG_RAW("%02x ", g_pl2303_buf[i]);
|
||||
}
|
||||
}
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
usbh_pl2303_run(pl2303_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_pl2303_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_pl2303 *pl2303_class = (struct usbh_pl2303 *)hport->config.intf[intf].priv;
|
||||
|
||||
if (pl2303_class) {
|
||||
if (pl2303_class->bulkin) {
|
||||
usbh_kill_urb(&pl2303_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (pl2303_class->bulkout) {
|
||||
usbh_kill_urb(&pl2303_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister PL2303 Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_pl2303_stop(pl2303_class);
|
||||
}
|
||||
|
||||
usbh_pl2303_class_free(pl2303_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_pl2303_bulk_in_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &pl2303_class->bulkin_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &pl2303_class->bulkout_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class)
|
||||
{
|
||||
(void)pl2303_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
|
||||
{
|
||||
(void)pl2303_class;
|
||||
}
|
||||
|
||||
static const uint16_t pl2303_id_table[][2] = {
|
||||
{ 0x067B, 0x2303 }, // PL2303 Serial (ATEN/IOGEAR UC232A)
|
||||
{ 0x067B, 0x23A3 }, // PL2303HXN Serial, type GC
|
||||
{ 0x067B, 0x23B3 }, // PL2303HXN Serial, type GB
|
||||
{ 0x067B, 0x23C3 }, // PL2303HXN Serial, type GT
|
||||
{ 0x067B, 0x23D3 }, // PL2303HXN Serial, type GL
|
||||
{ 0x067B, 0x23E3 }, // PL2303HXN Serial, type GE
|
||||
{ 0x067B, 0x23F3 }, // PL2303HXN Serial, type GS
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct usbh_class_driver pl2303_class_driver = {
|
||||
.driver_name = "pl2303",
|
||||
.connect = usbh_pl2303_connect,
|
||||
.disconnect = usbh_pl2303_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info pl2303_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = pl2303_id_table,
|
||||
.class_driver = &pl2303_class_driver
|
||||
};
|
||||
62
class/vendor/serial/usbh_pl2303.h
vendored
Normal file
62
class/vendor/serial/usbh_pl2303.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_PL2303_H
|
||||
#define USBH_PL2303_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#define PL2303_SET_REQUEST 0x01
|
||||
#define PL2303_SET_REQUEST_PL2303HXN 0x80
|
||||
#define PL2303_SET_CRTSCTS 0x41
|
||||
#define PL2303_SET_CRTSCTS_PL2303X 0x61
|
||||
#define PL2303_SET_CRTSCTS_PL2303HXN 0xFA
|
||||
#define PL2303_CLEAR_CRTSCTS_PL2303HXN 0xFF
|
||||
#define PL2303_CRTSCTS_REG_PL2303HXN 0x0A
|
||||
#define PL2303_STATUS_REG_PL2303HX 0x8080
|
||||
|
||||
/* Different PL2303 IC types */
|
||||
#define USBH_PL2303_TYPE_UNKNOWN 0
|
||||
#define USBH_PL2303_TYPE_PL2303 1
|
||||
#define USBH_PL2303_TYPE_PL2303HX 2
|
||||
#define USBH_PL2303_TYPE_PL2303HXD 3
|
||||
#define USBH_PL2303_TYPE_PL2303HXN 4
|
||||
|
||||
struct usbh_pl2303 {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
|
||||
struct cdc_line_coding linecoding;
|
||||
|
||||
uint8_t intf;
|
||||
uint8_t minor;
|
||||
uint8_t chiptype;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_pl2303_set_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding);
|
||||
int usbh_pl2303_get_line_coding(struct usbh_pl2303 *pl2303_class, struct cdc_line_coding *line_coding);
|
||||
int usbh_pl2303_set_line_state(struct usbh_pl2303 *pl2303_class, bool dtr, bool rts);
|
||||
|
||||
int usbh_pl2303_bulk_in_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
int usbh_pl2303_bulk_out_transfer(struct usbh_pl2303 *pl2303_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||
|
||||
void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class);
|
||||
void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_PL2303_H */
|
||||
6
class/vendor/wifi/README.md
vendored
Normal file
6
class/vendor/wifi/README.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# BL616 USB WIFI
|
||||
|
||||
Usbwifi firmware please contact bouffalolab. You can purchase a module in the following ways:
|
||||
|
||||
- https://iot.mi.com/moduleBrowser.html
|
||||
- https://docs.ai-thinker.com/ai_m61
|
||||
512
class/vendor/wifi/usbh_bl616.c
vendored
Normal file
512
class/vendor/wifi/usbh_bl616.c
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_bl616.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_bl616"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/wifi/bl616"
|
||||
|
||||
#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
|
||||
#define ARR_ELE_6(e) (e)[0], (e)[1], (e)[2], (e)[3], (e)[4], (e)[5]
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bl616_tx_buffer[2048 + 512];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bl616_rx_buffer[2048 + 512];
|
||||
|
||||
static struct usbh_bl616 g_bl616_class;
|
||||
|
||||
static const char *auth_to_str(uint8_t auth)
|
||||
{
|
||||
const char *table[RNM_WIFI_AUTH_MAX] = {
|
||||
[RNM_WIFI_AUTH_UNKNOWN] = "UNKNOWN",
|
||||
[RNM_WIFI_AUTH_OPEN] = "OPEN",
|
||||
[RNM_WIFI_AUTH_WEP] = "WEP",
|
||||
[RNM_WIFI_AUTH_WPA_PSK] = "WPA-PSK",
|
||||
[RNM_WIFI_AUTH_WPA2_PSK] = "WPA2-PSK",
|
||||
[RNM_WIFI_AUTH_WPA_WPA2_PSK] = "WPA2-PSK/WPA-PSK",
|
||||
[RNM_WIFI_AUTH_WPA_ENTERPRISE] = "WPA-ENT",
|
||||
[RNM_WIFI_AUTH_WPA3_SAE] = "WPA3-SAE",
|
||||
[RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE] = "WPA2-PSK/WPA3-SAE",
|
||||
};
|
||||
if (auth < RNM_WIFI_AUTH_MAX)
|
||||
return table[auth];
|
||||
else
|
||||
return table[RNM_WIFI_AUTH_UNKNOWN];
|
||||
}
|
||||
|
||||
static const char *cipher_to_str(uint8_t cipher)
|
||||
{
|
||||
const char *table[RNM_WIFI_CIPHER_MAX] = {
|
||||
[RNM_WIFI_CIPHER_UNKNOWN] = "UNKNOWN",
|
||||
[RNM_WIFI_CIPHER_NONE] = "NONE",
|
||||
[RNM_WIFI_CIPHER_WEP] = "WEP",
|
||||
[RNM_WIFI_CIPHER_AES] = "AES",
|
||||
[RNM_WIFI_CIPHER_TKIP] = "TKIP",
|
||||
[RNM_WIFI_CIPHER_TKIP_AES] = "TKIP/AES",
|
||||
};
|
||||
if (cipher < RNM_WIFI_CIPHER_MAX)
|
||||
return table[cipher];
|
||||
else
|
||||
return table[RNM_WIFI_CIPHER_UNKNOWN];
|
||||
}
|
||||
|
||||
static int parse_get_mac_rsp_msg(struct usbh_bl616 *bl616_class, void *buf, int buf_len)
|
||||
{
|
||||
usb_data_t *usb_hdr = buf;
|
||||
rnm_mac_addr_ind_msg_t *rsp = buf + sizeof(usb_data_t);
|
||||
|
||||
if (buf_len != sizeof(usb_data_t) + sizeof(rnm_mac_addr_ind_msg_t)) {
|
||||
return -1;
|
||||
}
|
||||
if (usb_hdr->type != USBWIFI_DATA_TYPE_CMD || usb_hdr->length != sizeof(rnm_mac_addr_ind_msg_t)) {
|
||||
return -1;
|
||||
}
|
||||
if (rsp->hdr.cmd != BFLB_CMD_GET_MAC_ADDR || !(rsp->hdr.flags & RNM_MSG_FLAG_ACK)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(bl616_class->sta_mac, rsp->sta_mac, 6);
|
||||
memcpy(bl616_class->ap_mac, rsp->ap_mac, 6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_bl616_bulk_in_transfer(struct usbh_bl616 *bl616_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &bl616_class->bulkin_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, bl616_class->hport, bl616_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_bulk_out_transfer(struct usbh_bl616 *bl616_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_urb *urb = &bl616_class->bulkout_urb;
|
||||
|
||||
usbh_bulk_urb_fill(urb, bl616_class->hport, bl616_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_get_wifi_mac(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
int ret;
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *rnm_msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(rnm_msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
rnm_msg->cmd = BFLB_CMD_GET_MAC_ADDR;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
ret = usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usbh_bl616_bulk_in_transfer(bl616_class, g_bl616_rx_buffer, sizeof(g_bl616_rx_buffer), 500);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = parse_get_mac_rsp_msg(bl616_class, g_bl616_rx_buffer, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_wifi_open(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_HELLO;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
static int usbh_bl616_wifi_close(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_UNLOAD_DRV;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_wifi_sta_connect(const char *ssid,
|
||||
const int ssid_len,
|
||||
const char *password,
|
||||
const int pwd_len)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_sta_connect_msg_t *msg = (rnm_sta_connect_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_sta_connect_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_sta_connect_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->hdr.cmd = BFLB_CMD_STA_CONNECT;
|
||||
msg->hdr.msg_id = 0x0001;
|
||||
msg->hdr.session_id = 0x0002;
|
||||
msg->ssid_len = ssid_len;
|
||||
memcpy(msg->ssid, ssid, ssid_len);
|
||||
if (password) {
|
||||
memcpy(msg->password, password, pwd_len);
|
||||
}
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_sta_connect_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_wifi_sta_disconnect(void)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_STA_DISCONNECT;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_get_wifi_scan_result(void)
|
||||
{
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_SCAN_RESULTS;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
return usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
}
|
||||
|
||||
int usbh_bl616_wifi_scan(void)
|
||||
{
|
||||
int ret;
|
||||
uint32_t msg_len;
|
||||
usb_data_t *usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
rnm_base_msg_t *msg = (rnm_base_msg_t *)(g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
memset(msg, 0, sizeof(rnm_base_msg_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_CMD;
|
||||
usb_hdr->length = sizeof(rnm_base_msg_t);
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
msg->cmd = BFLB_CMD_SCAN;
|
||||
|
||||
msg_len = sizeof(usb_data_t) + sizeof(rnm_base_msg_t);
|
||||
|
||||
ret = usbh_bl616_bulk_out_transfer(&g_bl616_class, g_bl616_tx_buffer, msg_len, 500);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
usb_osal_msleep(500);
|
||||
return usbh_bl616_get_wifi_scan_result();
|
||||
}
|
||||
|
||||
static int usbh_bl616_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_bl616 *bl616_class = &g_bl616_class;
|
||||
|
||||
memset(bl616_class, 0, sizeof(struct usbh_bl616));
|
||||
|
||||
bl616_class->hport = hport;
|
||||
bl616_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = bl616_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(bl616_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(bl616_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
usbh_bl616_get_wifi_mac(bl616_class);
|
||||
usbh_bl616_wifi_close(bl616_class);
|
||||
usbh_bl616_wifi_open(bl616_class);
|
||||
|
||||
USB_LOG_INFO("BL616 WIFI STA MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
bl616_class->sta_mac[0],
|
||||
bl616_class->sta_mac[1],
|
||||
bl616_class->sta_mac[2],
|
||||
bl616_class->sta_mac[3],
|
||||
bl616_class->sta_mac[4],
|
||||
bl616_class->sta_mac[5]);
|
||||
|
||||
USB_LOG_INFO("BL616 WIFI AP MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
bl616_class->ap_mac[0],
|
||||
bl616_class->ap_mac[1],
|
||||
bl616_class->ap_mac[2],
|
||||
bl616_class->ap_mac[3],
|
||||
bl616_class->ap_mac[4],
|
||||
bl616_class->ap_mac[5]);
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_bl616_run(bl616_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bl616_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_bl616 *bl616_class = (struct usbh_bl616 *)hport->config.intf[intf].priv;
|
||||
|
||||
if (bl616_class) {
|
||||
if (bl616_class->bulkin) {
|
||||
usbh_kill_urb(&bl616_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (bl616_class->bulkout) {
|
||||
usbh_kill_urb(&bl616_class->bulkout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_bl616_stop(bl616_class);
|
||||
}
|
||||
|
||||
memset(bl616_class, 0, sizeof(struct usbh_bl616));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_bl616_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
int ret;
|
||||
usb_data_t *usb_hdr;
|
||||
rnm_base_msg_t *msg;
|
||||
rnm_sta_ip_update_ind_msg_t *ipmsg;
|
||||
rnm_scan_ind_msg_t *scanmsg;
|
||||
uint8_t *data;
|
||||
|
||||
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
USB_LOG_INFO("Create bl616 wifi rx thread\r\n");
|
||||
|
||||
while (1) {
|
||||
ret = usbh_bl616_bulk_in_transfer(&g_bl616_class, g_bl616_rx_buffer, sizeof(g_bl616_rx_buffer), USB_OSAL_WAITING_FOREVER);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
usb_hdr = (usb_data_t *)g_bl616_rx_buffer;
|
||||
|
||||
if (usb_hdr->type == USBWIFI_DATA_TYPE_CMD) {
|
||||
msg = (rnm_base_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
|
||||
switch (msg->cmd) {
|
||||
case BFLB_CMD_STA_CONNECTED_IND:
|
||||
USB_LOG_INFO("AP connected\n");
|
||||
g_bl616_class.connect_status = true;
|
||||
usbh_bl616_sta_connect_callback();
|
||||
|
||||
break;
|
||||
case BFLB_CMD_STA_DISCONNECTED_IND:
|
||||
if (g_bl616_class.connect_status == true) {
|
||||
g_bl616_class.connect_status = false;
|
||||
USB_LOG_INFO("AP disconnected\n");
|
||||
usbh_bl616_sta_disconnect_callback();
|
||||
}
|
||||
break;
|
||||
case BFLB_CMD_STA_IP_UPDATE_IND:
|
||||
ipmsg = (rnm_sta_ip_update_ind_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
|
||||
USB_LOG_INFO("WIFI IP update\r\n");
|
||||
USB_LOG_INFO("WIFI IPv4 Address : %d:%d:%d:%d\r\n",
|
||||
ipmsg->ip4_addr[0],
|
||||
ipmsg->ip4_addr[1],
|
||||
ipmsg->ip4_addr[2],
|
||||
ipmsg->ip4_addr[3]);
|
||||
USB_LOG_INFO("WIFI IPv4 Mask : %d:%d:%d:%d\r\n",
|
||||
ipmsg->ip4_mask[0],
|
||||
ipmsg->ip4_mask[1],
|
||||
ipmsg->ip4_mask[2],
|
||||
ipmsg->ip4_mask[3]);
|
||||
USB_LOG_INFO("WIFI IPv4 Gateway : %d:%d:%d:%d\r\n\r\n",
|
||||
ipmsg->ip4_gw[0],
|
||||
ipmsg->ip4_gw[1],
|
||||
ipmsg->ip4_gw[2],
|
||||
ipmsg->ip4_gw[3]);
|
||||
|
||||
g_bl616_class.mode = BL_MODE_STA;
|
||||
usbh_bl616_sta_update_ip(ipmsg->ip4_addr, ipmsg->ip4_mask, ipmsg->ip4_gw);
|
||||
break;
|
||||
case BFLB_CMD_SCAN_RESULTS:
|
||||
scanmsg = (rnm_scan_ind_msg_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
USB_LOG_INFO("WIFI scan result:\r\n");
|
||||
for (uint32_t i = 0; i < scanmsg->num; ++i) {
|
||||
struct bf1b_wifi_scan_record *r = &scanmsg->records[i];
|
||||
USB_LOG_INFO("BSSID " MAC_FMT ", channel %u, rssi %d, auth %s, cipher %s, SSID %s\r\n",
|
||||
ARR_ELE_6(r->bssid), r->channel, r->rssi,
|
||||
auth_to_str(r->auth_mode), cipher_to_str(r->cipher), r->ssid);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (usb_hdr->type == USBWIFI_DATA_TYPE_PKT) {
|
||||
data = (uint8_t *)(g_bl616_rx_buffer + usb_hdr->payload_offset);
|
||||
usbh_bl616_eth_input(data, usb_hdr->length);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
USB_LOG_INFO("Delete bl616 wifi rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
}
|
||||
|
||||
uint8_t *usbh_bl616_get_eth_txbuf(void)
|
||||
{
|
||||
return (g_bl616_tx_buffer + sizeof(usb_data_t));
|
||||
}
|
||||
|
||||
int usbh_bl616_eth_output(uint32_t buflen)
|
||||
{
|
||||
usb_data_t *usb_hdr;
|
||||
uint32_t txlen;
|
||||
|
||||
if (g_bl616_class.connect_status == false) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
usb_hdr = (usb_data_t *)g_bl616_tx_buffer;
|
||||
memset(usb_hdr, 0, sizeof(usb_data_t));
|
||||
|
||||
usb_hdr->type = USBWIFI_DATA_TYPE_PKT;
|
||||
usb_hdr->length = buflen;
|
||||
usb_hdr->payload_offset = sizeof(usb_data_t);
|
||||
|
||||
txlen = buflen + sizeof(usb_data_t);
|
||||
if (!(txlen % USB_GET_MAXPACKETSIZE(g_bl616_class.bulkout->wMaxPacketSize))) {
|
||||
txlen += 1;
|
||||
}
|
||||
USB_LOG_DBG("txlen:%d\r\n", txlen);
|
||||
|
||||
usbh_bulk_urb_fill(&g_bl616_class.bulkout_urb, g_bl616_class.hport, g_bl616_class.bulkout, g_bl616_tx_buffer, txlen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
return usbh_submit_urb(&g_bl616_class.bulkout_urb);
|
||||
}
|
||||
|
||||
int wifi_sta_connect(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
USB_LOG_ERR("Usage: %s <ssid> <password>\r\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
usbh_bl616_wifi_sta_connect(argv[1], strlen(argv[1]), argv[2], strlen(argv[2]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_scan(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
usbh_bl616_wifi_scan();
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bl616_run(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
(void)bl616_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bl616_stop(struct usbh_bl616 *bl616_class)
|
||||
{
|
||||
(void)bl616_class;
|
||||
}
|
||||
|
||||
static const uint16_t bl616_id_table[][2] = {
|
||||
{ 0x349b, 0x616f },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct usbh_class_driver bl616_class_driver = {
|
||||
.driver_name = "bl616_wifi",
|
||||
.connect = usbh_bl616_connect,
|
||||
.disconnect = usbh_bl616_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info bl616_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = bl616_id_table,
|
||||
.class_driver = &bl616_class_driver
|
||||
};
|
||||
220
class/vendor/wifi/usbh_bl616.h
vendored
Normal file
220
class/vendor/wifi/usbh_bl616.h
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_BL616_H
|
||||
#define USBH_BL616_H
|
||||
|
||||
#define USBWIFI_DATA_TYPE_CMD 0xA55A
|
||||
#define USBWIFI_DATA_TYPE_PKT 0x6996
|
||||
|
||||
#define USB_DATA_FLAG_AP_PKT (1u << 0)
|
||||
|
||||
typedef enum {
|
||||
BFLB_CMD_REBOOT = 0,
|
||||
BFLB_CMD_RESET,
|
||||
BFLB_CMD_HELLO,
|
||||
BFLB_CMD_PING,
|
||||
|
||||
BFLB_CMD_GET_MAC_ADDR,
|
||||
|
||||
// Scan
|
||||
BFLB_CMD_SCAN,
|
||||
BFLB_CMD_SCAN_RESULTS,
|
||||
|
||||
// STA
|
||||
BFLB_CMD_STA_CONNECT,
|
||||
BFLB_CMD_STA_DISCONNECT,
|
||||
BFLB_CMD_STA_CONNECTED_IND,
|
||||
BFLB_CMD_STA_DISCONNECTED_IND,
|
||||
BFLB_CMD_STA_IP_UPDATE_IND,
|
||||
BFLB_CMD_STA_SET_AUTO_RECONNECT,
|
||||
BFLB_CMD_STA_GET_LINK_STATUS,
|
||||
|
||||
// AP
|
||||
BFLB_CMD_AP_START,
|
||||
BFLB_CMD_AP_STOP,
|
||||
BFLB_CMD_AP_STARTED_IND,
|
||||
BFLB_CMD_AP_STOPPED_IND,
|
||||
BFLB_CMD_AP_GET_STA_LIST,
|
||||
|
||||
// Monitor
|
||||
BFLB_CMD_MONITOR_START,
|
||||
BFLB_CMD_MONITOR_STOP,
|
||||
BFLB_CMD_MONITOR_SET_CHANNEL,
|
||||
BFLB_CMD_MONITOR_GET_CHANNEL,
|
||||
|
||||
BFLB_CMD_SET_LPM_MODE,
|
||||
|
||||
// OTA
|
||||
BFLB_CMD_GET_DEV_VERSION,
|
||||
BFLB_CMD_OTA,
|
||||
|
||||
BFLB_CMD_EXT,
|
||||
|
||||
BFLB_CMD_USER_EXT,
|
||||
BFLB_CMD_UNLOAD_DRV,
|
||||
|
||||
BFLB_CMD_MAX,
|
||||
} bflb_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
STATUS_OK,
|
||||
STATUS_NOMEM = 128,
|
||||
STATUS_INVALID_INPUT,
|
||||
STATUS_INVALID_MODE,
|
||||
STATUS_ERR_UNSPECIFIED,
|
||||
STATUS_NOT_IMPLEMENTED,
|
||||
} cmd_status_t;
|
||||
|
||||
typedef enum {
|
||||
RNM_WIFI_AUTH_UNKNOWN = 0,
|
||||
RNM_WIFI_AUTH_OPEN,
|
||||
RNM_WIFI_AUTH_WEP,
|
||||
RNM_WIFI_AUTH_WPA_PSK,
|
||||
RNM_WIFI_AUTH_WPA2_PSK,
|
||||
RNM_WIFI_AUTH_WPA_WPA2_PSK,
|
||||
RNM_WIFI_AUTH_WPA_ENTERPRISE,
|
||||
RNM_WIFI_AUTH_WPA3_SAE,
|
||||
RNM_WIFI_AUTH_WPA2_PSK_WPA3_SAE,
|
||||
RNM_WIFI_AUTH_MAX,
|
||||
} rnm_wifi_auth_mode_t;
|
||||
|
||||
typedef enum {
|
||||
RNM_WIFI_CIPHER_UNKNOWN = 0,
|
||||
RNM_WIFI_CIPHER_NONE,
|
||||
RNM_WIFI_CIPHER_WEP,
|
||||
RNM_WIFI_CIPHER_AES,
|
||||
RNM_WIFI_CIPHER_TKIP,
|
||||
RNM_WIFI_CIPHER_TKIP_AES,
|
||||
RNM_WIFI_CIPHER_MAX,
|
||||
} rnm_wifi_cipher_t;
|
||||
|
||||
/* common header */
|
||||
typedef struct {
|
||||
uint16_t cmd;
|
||||
// flag ACK is used by server to indicate a response to client
|
||||
#define RNM_MSG_FLAG_ACK (1 << 0)
|
||||
// flag TRANSPARENT is never transfered to peer but used locally
|
||||
#define RNM_MSG_FLAG_TRANSPARENT (1 << 1)
|
||||
// flag ASYNC is used by server to notify client events such as STA_CONNECTED
|
||||
#define RNM_MSG_FLAG_ASYNC (1 << 2)
|
||||
uint16_t flags;
|
||||
uint16_t status;
|
||||
uint16_t msg_id;
|
||||
uint16_t session_id;
|
||||
uint16_t msg_id_replying;
|
||||
} rnm_base_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
} rnm_ack_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint8_t sta_mac[6];
|
||||
uint8_t ap_mac[6];
|
||||
} rnm_mac_addr_ind_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint16_t ssid_len;
|
||||
uint8_t ssid[32];
|
||||
uint8_t password[64];
|
||||
} rnm_sta_connect_msg_t;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint8_t ip4_addr[4];
|
||||
uint8_t ip4_mask[4];
|
||||
uint8_t ip4_gw[4];
|
||||
uint8_t ip4_dns1[4];
|
||||
uint8_t ip4_dns2[4];
|
||||
uint8_t gw_mac[6];
|
||||
} rnm_sta_ip_update_ind_msg_t;
|
||||
|
||||
struct bf1b_wifi_scan_record {
|
||||
uint8_t bssid[6];
|
||||
// TODO use compressed SSID encoding to save room
|
||||
uint8_t ssid[32 + 1];
|
||||
uint16_t channel;
|
||||
int8_t rssi;
|
||||
uint8_t auth_mode;
|
||||
uint8_t cipher;
|
||||
} __PACKED;
|
||||
|
||||
typedef struct {
|
||||
rnm_base_msg_t hdr;
|
||||
uint16_t num;
|
||||
struct bf1b_wifi_scan_record records[];
|
||||
} rnm_scan_ind_msg_t;
|
||||
|
||||
typedef enum {
|
||||
BL_MODE_NONE,
|
||||
BL_MODE_STA, // card is STA
|
||||
BL_MODE_AP, // card is AP
|
||||
BL_MODE_STA_AP, // card is STA&AP
|
||||
BL_MODE_SNIFFER, // card is sniffer
|
||||
BL_MODE_MAX,
|
||||
} bl_wifi_mode_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint16_t flags;
|
||||
uint16_t payload_offset;
|
||||
uint32_t rsvd[8];
|
||||
uint8_t payload[];
|
||||
} __attribute__((aligned(4))) usb_data_t;
|
||||
|
||||
struct usbh_bl616 {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
|
||||
struct usbh_urb bulkout_urb;
|
||||
struct usbh_urb bulkin_urb;
|
||||
|
||||
uint8_t intf;
|
||||
|
||||
uint8_t sta_mac[6];
|
||||
uint8_t ap_mac[6];
|
||||
uint8_t mode;
|
||||
bool connect_status;
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_bl616_wifi_sta_connect(const char *ssid,
|
||||
const int ssid_len,
|
||||
const char *password,
|
||||
const int pwd_len);
|
||||
|
||||
int usbh_bl616_wifi_sta_disconnect(void);
|
||||
int usbh_bl616_wifi_scan(void);
|
||||
|
||||
void usbh_bl616_sta_connect_callback(void);
|
||||
void usbh_bl616_sta_disconnect_callback(void);
|
||||
void usbh_bl616_sta_update_ip(uint8_t ip4_addr[4], uint8_t ip4_mask[4], uint8_t ip4_gw[4]);
|
||||
|
||||
uint8_t *usbh_bl616_get_eth_txbuf(void);
|
||||
int usbh_bl616_eth_output(uint32_t buflen);
|
||||
void usbh_bl616_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_bl616_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
|
||||
void usbh_bl616_run(struct usbh_bl616 *bl616_class);
|
||||
void usbh_bl616_stop(struct usbh_bl616 *bl616_class);
|
||||
|
||||
int wifi_sta_connect(int argc, char **argv);
|
||||
int wifi_scan(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_BL616_H */
|
||||
228
class/vendor/xbox/usbh_xbox.c
vendored
Normal file
228
class/vendor/xbox/usbh_xbox.c
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Till Harbaum
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_xbox.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/xbox%d"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_xbox_buf[128];
|
||||
|
||||
static struct usbh_xbox g_xbox_class[CONFIG_USBHOST_MAX_XBOX_CLASS];
|
||||
static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_xbox *usbh_xbox_class_alloc(void)
|
||||
{
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_XBOX_CLASS; devno++) {
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_xbox_class[devno], 0, sizeof(struct usbh_xbox));
|
||||
g_xbox_class[devno].minor = devno;
|
||||
return &g_xbox_class[devno];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usbh_xbox_class_free(struct usbh_xbox *xbox_class)
|
||||
{
|
||||
uint8_t devno = xbox_class->minor;
|
||||
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(xbox_class, 0, sizeof(struct usbh_xbox));
|
||||
}
|
||||
|
||||
int usbh_xbox_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
|
||||
struct usbh_xbox *xbox_class = usbh_xbox_class_alloc();
|
||||
if (xbox_class == NULL) {
|
||||
USB_LOG_ERR("Fail to alloc xbox_class\r\n");
|
||||
return -USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
xbox_class->hport = hport;
|
||||
xbox_class->intf = intf;
|
||||
|
||||
hport->config.intf[intf].priv = xbox_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(xbox_class->intin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(xbox_class->intout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, xbox_class->minor);
|
||||
|
||||
USB_LOG_INFO("Register XBOX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
|
||||
usbh_xbox_run(xbox_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_xbox_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_xbox *xbox_class = (struct usbh_xbox *)hport->config.intf[intf].priv;
|
||||
|
||||
if (xbox_class) {
|
||||
if (xbox_class->intin) {
|
||||
usbh_kill_urb(&xbox_class->intin_urb);
|
||||
}
|
||||
|
||||
if (xbox_class->intout) {
|
||||
usbh_kill_urb(&xbox_class->intout_urb);
|
||||
}
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister XBOX Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_xbox_stop(xbox_class);
|
||||
}
|
||||
|
||||
usbh_xbox_class_free(xbox_class);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__WEAK void usbh_xbox_run(struct usbh_xbox *xbox_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_xbox_stop(struct usbh_xbox *xbox_class)
|
||||
{
|
||||
}
|
||||
|
||||
const struct usbh_class_driver xbox_class_driver = {
|
||||
.driver_name = "xbox",
|
||||
.connect = usbh_xbox_connect,
|
||||
.disconnect = usbh_xbox_disconnect
|
||||
};
|
||||
|
||||
static const uint16_t xbox_id_table[][2] = {
|
||||
{ 0x0079, 0x18d4 }, // GPD Win 2 X-Box Controller
|
||||
{ 0x03eb, 0xff01 }, // Wooting One (Legacy)
|
||||
{ 0x03eb, 0xff02 }, // Wooting Two (Legacy)
|
||||
{ 0x044f, 0xb326 }, // Thrustmaster Gamepad GP XID
|
||||
{ 0x045e, 0x028e }, // Microsoft X-Box 360 pad
|
||||
{ 0x045e, 0x028f }, // Microsoft X-Box 360 pad v2
|
||||
{ 0x046d, 0xc21d }, // Logitech Gamepad F310
|
||||
{ 0x046d, 0xc21e }, // Logitech Gamepad F510
|
||||
{ 0x046d, 0xc21f }, // Logitech Gamepad F710
|
||||
{ 0x046d, 0xc242 }, // Logitech Chillstream Controller
|
||||
{ 0x046d, 0xcaa3 }, // Logitech DriveFx Racing Wheel
|
||||
{ 0x056e, 0x2004 }, // Elecom JC-U3613M
|
||||
{ 0x06a3, 0xf51a }, // Saitek P3600
|
||||
{ 0x0738, 0x4716 }, // Mad Catz Wired Xbox 360 Controller
|
||||
{ 0x0738, 0x4718 }, // Mad Catz Street Fighter IV FightStick SE
|
||||
{ 0x0738, 0x4726 }, // Mad Catz Xbox 360 Controller
|
||||
{ 0x0738, 0x4736 }, // Mad Catz MicroCon Gamepad
|
||||
{ 0x0738, 0x4740 }, // Mad Catz Beat Pad
|
||||
{ 0x0738, 0x9871 }, // Mad Catz Portable Drum
|
||||
{ 0x0738, 0xb726 }, // Mad Catz Xbox controller - MW2
|
||||
{ 0x0738, 0xbeef }, // Mad Catz JOYTECH NEO SE Advanced GamePad
|
||||
{ 0x0738, 0xcb02 }, // Saitek Cyborg Rumble Pad - PC/Xbox 360
|
||||
{ 0x0738, 0xcb03 }, // Saitek P3200 Rumble Pad - PC/Xbox 360
|
||||
{ 0x0738, 0xcb29 }, // Saitek Aviator Stick AV8R02
|
||||
{ 0x0738, 0xf738 }, // Super SFIV FightStick TE S
|
||||
{ 0x07ff, 0xffff }, // Mad Catz GamePad
|
||||
{ 0x0e6f, 0x0113 }, // Afterglow AX.1 Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x011f }, // Rock Candy Gamepad Wired Controller
|
||||
{ 0x0e6f, 0x0131 }, // PDP EA Sports Controller
|
||||
{ 0x0e6f, 0x0133 }, // Xbox 360 Wired Controller
|
||||
{ 0x0e6f, 0x0201 }, // Pelican PL-3601 'TSZ' Wired Xbox 360 Controller
|
||||
{ 0x0e6f, 0x0213 }, // Afterglow Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x021f }, // Rock Candy Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x0301 }, // Logic3 Controller
|
||||
{ 0x0e6f, 0x0401 }, // Logic3 Controller
|
||||
{ 0x0e6f, 0x0413 }, // Afterglow AX.1 Gamepad for Xbox 360
|
||||
{ 0x0e6f, 0x0501 }, // PDP Xbox 360 Controller
|
||||
{ 0x0e6f, 0xf900 }, // PDP Afterglow AX.1
|
||||
{ 0x0f0d, 0x000a }, // Hori Co. DOA4 FightStick
|
||||
{ 0x0f0d, 0x000c }, // Hori PadEX Turbo
|
||||
{ 0x1038, 0x1430 }, // SteelSeries Stratus Duo
|
||||
{ 0x1038, 0x1431 }, // SteelSeries Stratus Duo
|
||||
{ 0x11c9, 0x55f0 }, // Nacon GC-100XF
|
||||
{ 0x1209, 0x2882 }, // Ardwiino Controller
|
||||
{ 0x12ab, 0x0301 }, // PDP AFTERGLOW AX.1
|
||||
{ 0x1430, 0x4748 }, // RedOctane Guitar Hero X-plorer
|
||||
{ 0x1430, 0xf801 }, // RedOctane Controller
|
||||
{ 0x146b, 0x0601 }, // BigBen Interactive XBOX 360 Controller
|
||||
{ 0x1532, 0x0037 }, // Razer Sabertooth
|
||||
{ 0x15e4, 0x3f00 }, // Power A Mini Pro Elite
|
||||
{ 0x15e4, 0x3f0a }, // Xbox Airflo wired controller
|
||||
{ 0x15e4, 0x3f10 }, // Batarang Xbox 360 controller
|
||||
{ 0x162e, 0xbeef }, // Joytech Neo-Se Take2
|
||||
{ 0x1689, 0xfd00 }, // Razer Onza Tournament Edition
|
||||
{ 0x1689, 0xfd01 }, // Razer Onza Classic Edition
|
||||
{ 0x1689, 0xfe00 }, // Razer Sabertooth
|
||||
{ 0x1949, 0x041a }, // Amazon Game Controller
|
||||
{ 0x1bad, 0x0002 }, // Harmonix Rock Band Guitar
|
||||
{ 0x1bad, 0xf016 }, // Mad Catz Xbox 360 Controller
|
||||
{ 0x1bad, 0xf021 }, // Mad Cats Ghost Recon FS GamePad
|
||||
{ 0x1bad, 0xf023 }, // MLG Pro Circuit Controller (Xbox)
|
||||
{ 0x1bad, 0xf025 }, // Mad Catz Call Of Duty
|
||||
{ 0x1bad, 0xf027 }, // Mad Catz FPS Pro
|
||||
{ 0x1bad, 0xf028 }, // Street Fighter IV FightPad
|
||||
{ 0x1bad, 0xf030 }, // Mad Catz Xbox 360 MC2 MicroCon Racing Wheel
|
||||
{ 0x1bad, 0xf036 }, // Mad Catz MicroCon GamePad Pro
|
||||
{ 0x1bad, 0xf038 }, // Street Fighter IV FightStick TE
|
||||
{ 0x1bad, 0xf501 }, // HoriPad EX2 Turbo
|
||||
{ 0x1bad, 0xf506 }, // Hori Real Arcade Pro.EX Premium VLX
|
||||
{ 0x1bad, 0xf900 }, // Harmonix Xbox 360 Controller
|
||||
{ 0x1bad, 0xf901 }, // Gamestop Xbox 360 Controller
|
||||
{ 0x1bad, 0xf903 }, // Tron Xbox 360 controller
|
||||
{ 0x1bad, 0xf904 }, // PDP Versus Fighting Pad
|
||||
{ 0x1bad, 0xfa01 }, // MadCatz GamePad
|
||||
{ 0x1bad, 0xfd00 }, // Razer Onza TE
|
||||
{ 0x1bad, 0xfd01 }, // Razer Onza
|
||||
{ 0x20d6, 0x2001 }, // BDA Xbox Series X Wired Controller
|
||||
{ 0x20d6, 0x281f }, // PowerA Wired Controller For Xbox 360
|
||||
{ 0x24c6, 0x5300 }, // PowerA MINI PROEX Controller
|
||||
{ 0x24c6, 0x5303 }, // Xbox Airflo wired controller
|
||||
{ 0x24c6, 0x530a }, // Xbox 360 Pro EX Controller
|
||||
{ 0x24c6, 0x531a }, // PowerA Pro Ex
|
||||
{ 0x24c6, 0x5397 }, // FUS1ON Tournament Controller
|
||||
{ 0x24c6, 0x5500 }, // Hori XBOX 360 EX 2 with Turbo
|
||||
{ 0x24c6, 0x5501 }, // Hori Real Arcade Pro VX-SA
|
||||
{ 0x24c6, 0x5506 }, // Hori SOULCALIBUR V Stick
|
||||
{ 0x24c6, 0x550d }, // Hori GEM Xbox controller
|
||||
{ 0x24c6, 0x5b00 }, // ThrustMaster Ferrari 458 Racing Wheel
|
||||
{ 0x24c6, 0x5b02 }, // Thrustmaster, Inc. GPX Controller
|
||||
{ 0x24c6, 0x5b03 }, // Thrustmaster Ferrari 458 Racing Wheel
|
||||
{ 0x24c6, 0x5d04 }, // Razer Sabertooth
|
||||
{ 0x24c6, 0xfafe }, // Rock Candy Gamepad for Xbox 360
|
||||
{ 0x2563, 0x058d }, // OneXPlayer Gamepad
|
||||
{ 0x2dc8, 0x3106 }, // 8BitDo Ultimate Wireless / Pro 2 Wired Controller
|
||||
{ 0x2dc8, 0x3109 }, // 8BitDo Ultimate Wireless Bluetooth
|
||||
{ 0x31e3, 0x1100 }, // Wooting One
|
||||
{ 0x31e3, 0x1200 }, // Wooting Two
|
||||
{ 0x31e3, 0x1210 }, // Wooting Lekker
|
||||
{ 0x31e3, 0x1220 }, // Wooting Two HE
|
||||
{ 0x31e3, 0x1230 }, // Wooting Two HE (ARM)
|
||||
{ 0x31e3, 0x1300 }, // Wooting 60HE (AVR)
|
||||
{ 0x31e3, 0x1310 }, // Wooting 60HE (ARM)
|
||||
{ 0x3285, 0x0607 }, // Nacon GC-100
|
||||
{ 0x413d, 0x2104 }, // Black Shark Green Ghost Gamepad
|
||||
{ 0x0000, 0x0000 } // end of list
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_VEND_SPECIFIC,
|
||||
.bInterfaceSubClass = 0x5d,
|
||||
.bInterfaceProtocol = 0x01,
|
||||
.id_table = xbox_id_table,
|
||||
.class_driver = &xbox_class_driver
|
||||
};
|
||||
31
class/vendor/xbox/usbh_xbox.h
vendored
Normal file
31
class/vendor/xbox/usbh_xbox.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Till Harbaum
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_XBOX_H
|
||||
#define USBH_XBOX_H
|
||||
|
||||
struct usbh_xbox {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */
|
||||
struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
struct usbh_urb intout_urb; /* INTR OUT urb */
|
||||
|
||||
uint8_t intf; /* interface number */
|
||||
uint8_t minor;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usbh_xbox_run(struct usbh_xbox *xbox_class);
|
||||
void usbh_xbox_stop(struct usbh_xbox *xbox_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_XBOX_H */
|
||||
@@ -806,14 +806,15 @@ struct video_still_probe_and_commit_controls {
|
||||
struct video_cs_if_vc_header_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdVDC;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint16_t bcdUVC;
|
||||
uint16_t wTotalLength;
|
||||
uint32_t dwClockFrequency;
|
||||
uint8_t bInCollection;
|
||||
uint8_t baInterfaceNr[];
|
||||
} __PACKED;
|
||||
|
||||
#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (11 + n)
|
||||
#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (12 + n)
|
||||
|
||||
struct video_cs_if_vc_input_terminal_descriptor {
|
||||
uint8_t bLength;
|
||||
@@ -860,6 +861,22 @@ struct video_cs_if_vc_output_terminal_descriptor {
|
||||
|
||||
#define VIDEO_SIZEOF_VC_OUTPUT_TERMINAL_DESC 9
|
||||
|
||||
struct video_cs_if_vc_extension_unit_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bUnitID;
|
||||
uint8_t guidExtensionCode[16];
|
||||
uint8_t bNumControls;
|
||||
uint8_t bNrInPins;
|
||||
// uint8_t baSourceID[];
|
||||
uint8_t bControlSize;
|
||||
// uint8_t bmControls[]
|
||||
uint8_t iExtension;
|
||||
} __PACKED;
|
||||
|
||||
#define VIDEO_SIZEOF_VC_EXTENSION_UNIT_DESC(p, n) (24 + p + n)
|
||||
|
||||
struct video_cs_ep_vc_ep_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
@@ -922,7 +939,7 @@ struct video_cs_if_vs_frame_uncompressed_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFormatIndex;
|
||||
uint8_t bFrameIndex;
|
||||
uint8_t bmCapabilities;
|
||||
uint16_t wWidth;
|
||||
uint16_t wHeight;
|
||||
@@ -931,10 +948,10 @@ struct video_cs_if_vs_frame_uncompressed_descriptor {
|
||||
uint32_t dwMaxVideoFrameBufferSize;
|
||||
uint32_t dwDefaultFrameInterval;
|
||||
uint8_t bFrameIntervalType;
|
||||
uint32_t dwFrameInterval;
|
||||
uint32_t dwFrameInterval[];
|
||||
} __PACKED;
|
||||
|
||||
#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC 30
|
||||
#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC(n) (26 + 4 * (n))
|
||||
|
||||
struct video_cs_if_vs_format_mjpeg_descriptor {
|
||||
uint8_t bLength;
|
||||
@@ -956,7 +973,7 @@ struct video_cs_if_vs_frame_mjpeg_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFormatIndex;
|
||||
uint8_t bFrameIndex;
|
||||
uint8_t bmCapabilities;
|
||||
uint16_t wWidth;
|
||||
uint16_t wHeight;
|
||||
@@ -965,11 +982,48 @@ struct video_cs_if_vs_frame_mjpeg_descriptor {
|
||||
uint32_t dwMaxVideoFrameBufferSize;
|
||||
uint32_t dwDefaultFrameInterval;
|
||||
uint8_t bFrameIntervalType;
|
||||
uint32_t dwFrameInterval1;
|
||||
uint32_t dwFrameInterval2;
|
||||
uint32_t dwFrameInterval[];
|
||||
} __PACKED;
|
||||
|
||||
#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + n)
|
||||
#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + 4 * (n))
|
||||
|
||||
/* H264 Payload - 3.1.1. H264 Video Format Descriptor */
|
||||
struct video_cs_if_vs_format_h26x_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFormatIndex;
|
||||
uint8_t bNumFrameDescriptors;
|
||||
uint8_t guidFormat[16];
|
||||
uint8_t bBitsPerPixel;
|
||||
uint8_t bDefaultFrameIndex;
|
||||
uint8_t bAspectRatioX;
|
||||
uint8_t bAspectRatioY;
|
||||
uint8_t bmInterfaceFlags;
|
||||
uint8_t bCopyProtect;
|
||||
uint8_t bVariableSize;
|
||||
} __PACKED;
|
||||
|
||||
#define VIDEO_SIZEOF_VS_FORMAT_H264_DESC 28
|
||||
|
||||
/* H264 Payload - 3.1.2. H264 Video Frame Descriptor */
|
||||
struct video_cs_if_vs_frame_h26x_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFrameIndex;
|
||||
uint8_t bmCapabilities;
|
||||
uint16_t wWidth;
|
||||
uint16_t wHeight;
|
||||
uint32_t dwMinBitRate;
|
||||
uint32_t dwMaxBitRate;
|
||||
uint32_t dwDefaultFrameInterval;
|
||||
uint8_t bFrameIntervalType;
|
||||
uint32_t dwBytesPerLine;
|
||||
uint32_t dwFrameInterval[];
|
||||
} __PACKED;
|
||||
|
||||
#define VIDEO_SIZEOF_VS_FRAME_H264_DESC(n) (26 + 4 * (n))
|
||||
|
||||
struct video_cs_if_vs_colorformat_descriptor {
|
||||
uint8_t bLength;
|
||||
@@ -1041,74 +1095,145 @@ struct video_autoexposure_mode {
|
||||
|
||||
#define VIDEO_GUID_YUY2 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
|
||||
#define VIDEO_GUID_NV12 0x4E, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
|
||||
#define VIDEO_GUID_NV21 0x4E, 0x56, 0x32, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
|
||||
#define VIDEO_GUID_M420 0x4D, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
|
||||
#define VIDEO_GUID_I420 0x49, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
|
||||
#define VIDEO_GUID_H264 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
|
||||
|
||||
#define VIDEO_VC_TERMINAL_LEN (13 + 18 + 12 + 9)
|
||||
|
||||
/*Length of template descriptor: 81 bytes*/
|
||||
#define VIDEO_VC_DESCRIPTOR_LEN (8 + 9 + VIDEO_VC_TERMINAL_LEN + 7 + 5)
|
||||
#define VIDEO_VC_NOEP_DESCRIPTOR_LEN (8 + 9 + VIDEO_VC_TERMINAL_LEN)
|
||||
|
||||
// clang-format off
|
||||
#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bNumEndpoints, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
|
||||
/* Interface Association Descriptor */ \
|
||||
0x08, \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
|
||||
bFirstInterface, \
|
||||
0x02, \
|
||||
USB_DEVICE_CLASS_VIDEO, \
|
||||
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
|
||||
0x00, \
|
||||
0x00, \
|
||||
/* VideoControl Interface Descriptor */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
0x00, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
bNumEndpoints, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
|
||||
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
|
||||
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
|
||||
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
|
||||
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ \
|
||||
/*Class-specific VideoControl Interface Descriptor */ \
|
||||
0x0d, /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
|
||||
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
|
||||
WBVAL(wTotalLength), /* wTotalLength */ \
|
||||
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
|
||||
0x01, /* bInCollection : Number of streaming interfaces. */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ \
|
||||
/* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
|
||||
0x12, \
|
||||
0x24, \
|
||||
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
|
||||
0x01, /* bTerminalID */ \
|
||||
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
|
||||
0x00, /* bAssocTerminal */ \
|
||||
0x00, /* iTerminal */ \
|
||||
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
|
||||
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
|
||||
WBVAL(0x0000), /* wOcularFocalLength */ \
|
||||
0x03, /* bControlSize */ \
|
||||
0x00, 0x00, 0x00, /* bmControls */ \
|
||||
0x0c, \
|
||||
0x24, \
|
||||
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
|
||||
0x02, /* bUnitID */ \
|
||||
0x01, /* bSourceID */ \
|
||||
0x00, 0x00, /* wMaxMultiplier */ \
|
||||
0x02, /* bControlSize */ \
|
||||
0x00, 0x00, /* bmControls */ \
|
||||
0x00, /* iProcessing */ \
|
||||
0x00, /* bmVideoStandards */ \
|
||||
0x09, \
|
||||
0x24, \
|
||||
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
|
||||
0x03, /* bTerminalID */ \
|
||||
WBVAL(VIDEO_TT_STREAMING), \
|
||||
0x00, /* bAssocTerminal */ \
|
||||
0x02, /* bSourceID */ \
|
||||
0x00 /* iTerminal */
|
||||
#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bEndpointAddress, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
|
||||
/* Interface Association Descriptor */ \
|
||||
0x08, \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
|
||||
bFirstInterface, \
|
||||
0x02, \
|
||||
USB_DEVICE_CLASS_VIDEO, \
|
||||
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
|
||||
0x00, \
|
||||
0x00, /* VideoControl Interface Descriptor */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
0x00, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x01, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
|
||||
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
|
||||
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
|
||||
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
|
||||
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ /*Class-specific VideoControl Interface Descriptor */ \
|
||||
0x0d, /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
|
||||
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
|
||||
WBVAL(wTotalLength), /* wTotalLength */ \
|
||||
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
|
||||
0x01, /* bInCollection : Number of streaming interfaces. */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
|
||||
0x12, \
|
||||
0x24, \
|
||||
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
|
||||
0x01, /* bTerminalID */ \
|
||||
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
|
||||
0x00, /* bAssocTerminal */ \
|
||||
0x00, /* iTerminal */ \
|
||||
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
|
||||
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
|
||||
WBVAL(0x0000), /* wOcularFocalLength */ \
|
||||
0x03, /* bControlSize */ \
|
||||
0x00, 0x00, 0x00, /* bmControls */ \
|
||||
0x0c, \
|
||||
0x24, \
|
||||
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
|
||||
0x02, /* bUnitID */ \
|
||||
0x01, /* bSourceID */ \
|
||||
0x00, 0x00, /* wMaxMultiplier */ \
|
||||
0x02, /* bControlSize */ \
|
||||
0x00, 0x00, /* bmControls */ \
|
||||
0x00, /* iProcessing */ \
|
||||
0x00, /* bmVideoStandards */ \
|
||||
0x09, \
|
||||
0x24, \
|
||||
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
|
||||
0x03, /* bTerminalID */ \
|
||||
WBVAL(VIDEO_TT_STREAMING), \
|
||||
0x00, /* bAssocTerminal */ \
|
||||
0x02, /* bSourceID */ \
|
||||
0x00, /* iTerminal */ \
|
||||
0x07, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
|
||||
bEndpointAddress, /* bEndpointAddress */ \
|
||||
0x03, /* bmAttributes */ \
|
||||
0x10, 0x00, /* wMaxPacketSize */ \
|
||||
0x08, /* bInterval */ \
|
||||
/* Class-specific VC Interrupt Endpoint Descriptor */ \
|
||||
0x05, 0x25, 0x03, 0x10, 0x00
|
||||
|
||||
#define VIDEO_VC_NOEP_DESCRIPTOR_INIT(bFirstInterface, bEndpointAddress, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
|
||||
/* Interface Association Descriptor */ \
|
||||
0x08, \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
|
||||
bFirstInterface, \
|
||||
0x02, \
|
||||
USB_DEVICE_CLASS_VIDEO, \
|
||||
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
|
||||
0x00, \
|
||||
0x00, /* VideoControl Interface Descriptor */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
|
||||
0x00, /* bInterfaceNumber */ \
|
||||
0x00, /* bAlternateSetting */ \
|
||||
0x00, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
|
||||
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
|
||||
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
|
||||
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
|
||||
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ /*Class-specific VideoControl Interface Descriptor */ \
|
||||
0x0d, /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
|
||||
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
|
||||
WBVAL(wTotalLength), /* wTotalLength */ \
|
||||
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
|
||||
0x01, /* bInCollection : Number of streaming interfaces. */ \
|
||||
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
|
||||
0x12, \
|
||||
0x24, \
|
||||
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
|
||||
0x01, /* bTerminalID */ \
|
||||
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
|
||||
0x00, /* bAssocTerminal */ \
|
||||
0x00, /* iTerminal */ \
|
||||
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
|
||||
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
|
||||
WBVAL(0x0000), /* wOcularFocalLength */ \
|
||||
0x03, /* bControlSize */ \
|
||||
0x00, 0x00, 0x00, /* bmControls */ \
|
||||
0x0c, \
|
||||
0x24, \
|
||||
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
|
||||
0x02, /* bUnitID */ \
|
||||
0x01, /* bSourceID */ \
|
||||
0x00, 0x00, /* wMaxMultiplier */ \
|
||||
0x02, /* bControlSize */ \
|
||||
0x00, 0x00, /* bmControls */ \
|
||||
0x00, /* iProcessing */ \
|
||||
0x00, /* bmVideoStandards */ \
|
||||
0x09, \
|
||||
0x24, \
|
||||
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
|
||||
0x03, /* bTerminalID */ \
|
||||
WBVAL(VIDEO_TT_STREAMING), \
|
||||
0x00, /* bAssocTerminal */ \
|
||||
0x02, /* bSourceID */ \
|
||||
0x00 /* iTerminal */ \
|
||||
|
||||
#define VIDEO_VS_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints) \
|
||||
/* Video Streaming (VS) Interface Descriptor */ \
|
||||
0x09, /* bLength */ \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType : INTERFACE */ \
|
||||
bInterfaceNumber, /* bInterfaceNumber: Index of this interface */ \
|
||||
bAlternateSetting, /* bAlternateSetting: Index of this alternate setting */ \
|
||||
@@ -1118,21 +1243,37 @@ struct video_autoexposure_mode {
|
||||
0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
|
||||
0x00 /* iInterface : unused */
|
||||
|
||||
#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
|
||||
/*Class-specific VideoStream Header Descriptor (Input) */ \
|
||||
0x0d + PP_NARG(__VA_ARGS__), \
|
||||
0x24, \
|
||||
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
|
||||
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
|
||||
WBVAL(wTotalLength), \
|
||||
bEndpointAddress, \
|
||||
0x00, /* bmInfo : No dynamic format change supported. */ \
|
||||
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
|
||||
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
|
||||
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
|
||||
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
|
||||
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
|
||||
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
|
||||
#define VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
|
||||
/*Class-specific VideoStream Header Descriptor (Input) */ \
|
||||
0x0d + PP_NARG(__VA_ARGS__), \
|
||||
0x24, \
|
||||
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
|
||||
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
|
||||
WBVAL(wTotalLength), \
|
||||
bEndpointAddress, \
|
||||
0x00, /* bmInfo : No dynamic format change supported. */ \
|
||||
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
|
||||
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
|
||||
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
|
||||
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
|
||||
0x01, /* bControlSize : Size of the bmaControls field */ \
|
||||
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
|
||||
|
||||
#define VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
|
||||
/*Class-specific VideoStream Header Descriptor (Input) */ \
|
||||
0x0d + PP_NARG(__VA_ARGS__), \
|
||||
0x24, \
|
||||
VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_SUBTYPE, \
|
||||
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
|
||||
WBVAL(wTotalLength), \
|
||||
bEndpointAddress, \
|
||||
0x00, /* bmInfo : No dynamic format change supported. */ \
|
||||
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
|
||||
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
|
||||
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
|
||||
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
|
||||
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
|
||||
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
|
||||
|
||||
#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat) \
|
||||
/*Payload Format(UNCOMPRESSED) Descriptor */ \
|
||||
@@ -1142,7 +1283,7 @@ struct video_autoexposure_mode {
|
||||
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
|
||||
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
|
||||
GUIDFormat, /* GUID Format YUY2 {32595559-0000-0010-8000-00AA00389B71} */ \
|
||||
0x0c, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
|
||||
0x10, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
|
||||
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
|
||||
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
|
||||
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
|
||||
@@ -1150,8 +1291,8 @@ struct video_autoexposure_mode {
|
||||
0x00 /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */
|
||||
|
||||
#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
|
||||
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwFrameInterval) \
|
||||
0x1e, \
|
||||
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
|
||||
0x1a + PP_NARG(__VA_ARGS__), \
|
||||
0x24, \
|
||||
VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, \
|
||||
bFrameIndex, \
|
||||
@@ -1161,13 +1302,13 @@ struct video_autoexposure_mode {
|
||||
DBVAL(dwMinBitRate), \
|
||||
DBVAL(dwMaxBitRate), \
|
||||
DBVAL(dwMaxVideoFrameBufferSize), \
|
||||
DBVAL(dwDefaultFrameInterval), \
|
||||
0x01, \
|
||||
DBVAL(dwFrameInterval)
|
||||
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
|
||||
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
|
||||
__VA_ARGS__
|
||||
|
||||
#define VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
|
||||
/*Payload Format(MJPEG) Descriptor */ \
|
||||
0x0b, /* bLength */ \
|
||||
0x0b, /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
0x06, /* bDescriptorSubType : VS_FORMAT_MJPEG subtype */ \
|
||||
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
|
||||
@@ -1181,7 +1322,7 @@ struct video_autoexposure_mode {
|
||||
|
||||
#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
|
||||
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
|
||||
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
|
||||
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_MJPEG */ \
|
||||
bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
|
||||
@@ -1194,5 +1335,46 @@ struct video_autoexposure_mode {
|
||||
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
|
||||
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
|
||||
__VA_ARGS__
|
||||
|
||||
#define VIDEO_VS_FORMAT_H264_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
|
||||
/*Payload Format(H.264) Descriptor */ \
|
||||
0x1c, /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VS_FORMAT_FRAME_BASED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FORMAT_FRAME_BASED subtype */\
|
||||
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
|
||||
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
|
||||
VIDEO_GUID_H264, \
|
||||
0x00, /* bmFlags : Uses fixed size samples.. */ \
|
||||
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
|
||||
0x00, /* bAspectRatioX : Non-interlaced stream – not required. */ \
|
||||
0x00, /* bAspectRatioY : Non-interlaced stream – not required. */ \
|
||||
0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
|
||||
0x00, /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */ \
|
||||
0x00 /* Variable size: False */
|
||||
|
||||
#define VIDEO_VS_FRAME_H264_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
|
||||
dwDefaultFrameInterval, bFrameIntervalType, ...) \
|
||||
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VS_FRAME_FRAME_BASED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_BASED */ \
|
||||
bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
|
||||
0x00, /* bmCapabilities : Still images using capture method 0 are supported at this frame setting.D1: Fixed frame-rate. */ \
|
||||
WBVAL(wWidth), /* wWidth (2bytes): Width of frame is 128 pixels. */ \
|
||||
WBVAL(wHeight), /* wHeight (2bytes): Height of frame is 64 pixels. */ \
|
||||
DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \
|
||||
DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \
|
||||
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
|
||||
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
|
||||
DBVAL(0x00), /* dwBytesPerLine (4bytes) */ \
|
||||
__VA_ARGS__
|
||||
|
||||
#define VIDEO_VS_COLOR_MATCHING_DESCRIPTOR_INIT() \
|
||||
0x06, /* bLength */ \
|
||||
0x24, /* bDescriptorType : CS_INTERFACE */ \
|
||||
VIDEO_VS_COLORFORMAT_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_COLORFORMAT */ \
|
||||
0x01, /* bColorPrimaries */ \
|
||||
0x01, /* bTransferCharacteristics */ \
|
||||
0x04 /* bMatrixCoefficients */
|
||||
|
||||
// clang-format on
|
||||
#endif /*USB_VIDEO_H */
|
||||
@@ -18,12 +18,28 @@ struct usbd_video_priv {
|
||||
uint8_t power_mode;
|
||||
uint8_t error_code;
|
||||
struct video_entity_info info[3];
|
||||
uint8_t *ep_buf0;
|
||||
uint8_t *ep_buf1;
|
||||
bool ep_buf0_ready;
|
||||
bool ep_buf1_ready;
|
||||
uint32_t ep_buf0_len;
|
||||
uint32_t ep_buf1_len;
|
||||
uint8_t ep_buf_idx;
|
||||
bool stream_finish;
|
||||
uint32_t max_packets;
|
||||
uint8_t *stream_buf;
|
||||
uint32_t stream_len;
|
||||
uint32_t stream_offset;
|
||||
uint8_t stream_frameid;
|
||||
uint32_t stream_headerlen;
|
||||
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
|
||||
|
||||
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||
|
||||
(void)busid;
|
||||
|
||||
switch (control_selector) {
|
||||
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
@@ -295,8 +311,7 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
|
||||
case VIDEO_PU_BRIGHTNESS_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
case VIDEO_REQUEST_SET_CUR: {
|
||||
uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
|
||||
USB_LOG_INFO("Video set brightness:%d\r\n", wBrightness);
|
||||
//uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
|
||||
} break;
|
||||
case VIDEO_REQUEST_GET_CUR: {
|
||||
uint16_t wBrightness = 0x0080;
|
||||
@@ -670,7 +685,7 @@ static int video_class_interface_request_handler(uint8_t busid, struct usb_setup
|
||||
} else {
|
||||
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
|
||||
}
|
||||
} else if (intf_num == 1) { /* Video Stream Inteface */
|
||||
} else if (intf_num == 1) { /* Video Stream Inteface */
|
||||
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
|
||||
}
|
||||
return -1;
|
||||
@@ -699,7 +714,7 @@ static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
{
|
||||
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
|
||||
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
|
||||
@@ -736,9 +751,47 @@ void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameIn
|
||||
g_usbd_video[busid].commit.bPreferedVersion = 0;
|
||||
g_usbd_video[busid].commit.bMinVersion = 0;
|
||||
g_usbd_video[busid].commit.bMaxVersion = 0;
|
||||
|
||||
g_usbd_video[busid].stream_frameid = 0;
|
||||
g_usbd_video[busid].stream_headerlen = 2;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
|
||||
static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
|
||||
{
|
||||
struct video_payload_header *header;
|
||||
uint32_t len;
|
||||
uint32_t offset;
|
||||
|
||||
len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
|
||||
offset = 0;
|
||||
while (len > 0) {
|
||||
header = (struct video_payload_header *)&ep_buf[offset];
|
||||
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
|
||||
header->headerInfoUnion.bmheaderInfo = 0;
|
||||
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
|
||||
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
|
||||
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
|
||||
|
||||
uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
|
||||
|
||||
usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
|
||||
&g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
|
||||
len2);
|
||||
|
||||
g_usbd_video[busid].stream_offset += len2;
|
||||
len -= len2;
|
||||
offset += (len2 + g_usbd_video[busid].stream_headerlen);
|
||||
|
||||
if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
|
||||
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(uint8_t busid,
|
||||
struct usbd_interface *intf,
|
||||
uint32_t dwFrameInterval,
|
||||
uint32_t dwMaxVideoFrameSize,
|
||||
uint32_t dwMaxPayloadTransferSize)
|
||||
@@ -762,28 +815,82 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
|
||||
return intf;
|
||||
}
|
||||
|
||||
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
|
||||
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
|
||||
{
|
||||
uint32_t packets;
|
||||
uint32_t last_packet_size;
|
||||
uint32_t picture_pos = 0;
|
||||
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
||||
uint32_t remain;
|
||||
|
||||
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
|
||||
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
|
||||
|
||||
for (size_t i = 0; i < packets; i++) {
|
||||
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||
if (i == (packets - 1)) {
|
||||
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
|
||||
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||
} else {
|
||||
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
|
||||
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
|
||||
if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */
|
||||
g_usbd_video[busid].ep_buf0_ready = false;
|
||||
g_usbd_video[busid].ep_buf_idx = 1;
|
||||
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
|
||||
} else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */
|
||||
g_usbd_video[busid].ep_buf1_ready = false;
|
||||
g_usbd_video[busid].ep_buf_idx = 0;
|
||||
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
|
||||
} else {
|
||||
if (g_usbd_video[busid].stream_finish) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
uvc_header[1] ^= 1;
|
||||
*out_len = (input_len + 2 * packets);
|
||||
return packets;
|
||||
|
||||
if (!g_usbd_video[busid].ep_buf0_ready) {
|
||||
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
|
||||
if (remain == 0) {
|
||||
g_usbd_video[busid].stream_frameid ^= 1;
|
||||
g_usbd_video[busid].stream_finish = true;
|
||||
} else {
|
||||
g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
|
||||
g_usbd_video[busid].ep_buf0_ready = true;
|
||||
if (!g_usbd_video[busid].ep_buf1_ready) {
|
||||
g_usbd_video[busid].ep_buf_idx = 0;
|
||||
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_usbd_video[busid].ep_buf1_ready) {
|
||||
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
|
||||
if (remain == 0) {
|
||||
g_usbd_video[busid].stream_frameid ^= 1;
|
||||
g_usbd_video[busid].stream_finish = true;
|
||||
} else {
|
||||
g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
|
||||
g_usbd_video[busid].ep_buf1_ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
|
||||
{
|
||||
if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_usbd_video[busid].ep_buf0 = ep_buf0;
|
||||
g_usbd_video[busid].ep_buf1 = ep_buf1;
|
||||
g_usbd_video[busid].ep_buf0_ready = false;
|
||||
g_usbd_video[busid].ep_buf1_ready = false;
|
||||
g_usbd_video[busid].ep_buf_idx = 0;
|
||||
g_usbd_video[busid].stream_finish = false;
|
||||
g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
|
||||
g_usbd_video[busid].stream_buf = stream_buf;
|
||||
g_usbd_video[busid].stream_len = stream_len;
|
||||
g_usbd_video[busid].stream_offset = 0;
|
||||
|
||||
usbd_video_stream_split_transfer(busid, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_video_open(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
}
|
||||
|
||||
__WEAK void usbd_video_close(uint8_t busid, uint8_t intf)
|
||||
{
|
||||
(void)busid;
|
||||
(void)intf;
|
||||
}
|
||||
@@ -20,7 +20,9 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
|
||||
|
||||
void usbd_video_open(uint8_t busid, uint8_t intf);
|
||||
void usbd_video_close(uint8_t busid, uint8_t intf);
|
||||
uint32_t usbd_video_mjpeg_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
||||
|
||||
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep);
|
||||
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
|
||||
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[128];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[USB_ALIGN_UP(128, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static const char *format_type[] = { "uncompressed", "mjpeg" };
|
||||
|
||||
@@ -34,11 +34,11 @@ static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_video *usbh_video_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
|
||||
g_video_class[devno].minor = devno;
|
||||
return &g_video_class[devno];
|
||||
@@ -49,20 +49,25 @@ static struct usbh_video *usbh_video_class_alloc(void)
|
||||
|
||||
static void usbh_video_class_free(struct usbh_video *video_class)
|
||||
{
|
||||
int devno = video_class->minor;
|
||||
uint8_t devno = video_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
}
|
||||
|
||||
int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
uint8_t retry;
|
||||
|
||||
if (!video_class || !video_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = video_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = cs << 8;
|
||||
@@ -91,9 +96,14 @@ int usbh_video_get(struct usbh_video *video_class, uint8_t request, uint8_t intf
|
||||
|
||||
int usbh_video_set(struct usbh_video *video_class, uint8_t request, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret;
|
||||
|
||||
if (!video_class || !video_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = video_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = request;
|
||||
setup->wValue = cs << 8;
|
||||
@@ -136,7 +146,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
uint16_t wHeight,
|
||||
uint8_t altsetting)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
uint8_t mult;
|
||||
uint16_t mps;
|
||||
@@ -146,6 +156,11 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
uint8_t frameidx = 0;
|
||||
uint8_t step;
|
||||
|
||||
if (!video_class || !video_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = video_class->hport->setup;
|
||||
|
||||
if (video_class->is_opened) {
|
||||
return 0;
|
||||
}
|
||||
@@ -180,7 +195,7 @@ int usbh_video_open(struct usbh_video *video_class,
|
||||
* Get MIN request (probe)
|
||||
* Get CUR request (probe)
|
||||
* Set CUR request (commit)
|
||||
*
|
||||
*
|
||||
*/
|
||||
step = 0;
|
||||
ret = usbh_videostreaming_get_cur_probe(video_class);
|
||||
@@ -265,9 +280,14 @@ errout:
|
||||
|
||||
int usbh_video_close(struct usbh_video *video_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = video_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
|
||||
if (!video_class || !video_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = video_class->hport->setup;
|
||||
|
||||
USB_LOG_INFO("Close video device\r\n");
|
||||
|
||||
video_class->is_opened = false;
|
||||
@@ -300,12 +320,12 @@ void usbh_video_list_info(struct usbh_video *video_class)
|
||||
uint16_t mps;
|
||||
|
||||
USB_LOG_INFO("============= Video device information ===================\r\n");
|
||||
USB_LOG_INFO("bcdVDC:%04x\r\n", video_class->bcdVDC);
|
||||
USB_LOG_INFO("Num of altsettings:%u\r\n", video_class->num_of_intf_altsettings);
|
||||
USB_LOG_RAW("bcdVDC:%04x\r\n", video_class->bcdVDC);
|
||||
USB_LOG_RAW("Num of altsettings:%u\r\n", video_class->num_of_intf_altsettings);
|
||||
|
||||
for (uint8_t i = 0; i < video_class->num_of_intf_altsettings; i++) {
|
||||
if (i == 0) {
|
||||
USB_LOG_INFO("Ingore altsetting 0\r\n");
|
||||
USB_LOG_RAW("Ingore altsetting 0\r\n");
|
||||
continue;
|
||||
}
|
||||
ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
|
||||
@@ -313,7 +333,7 @@ void usbh_video_list_info(struct usbh_video *video_class)
|
||||
mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
|
||||
mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
|
||||
|
||||
USB_LOG_INFO("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
USB_LOG_RAW("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
i,
|
||||
ep_desc->bEndpointAddress,
|
||||
ep_desc->bmAttributes,
|
||||
@@ -322,15 +342,15 @@ void usbh_video_list_info(struct usbh_video *video_class)
|
||||
mult);
|
||||
}
|
||||
|
||||
USB_LOG_INFO("bNumFormats:%u\r\n", video_class->num_of_formats);
|
||||
USB_LOG_RAW("bNumFormats:%u\r\n", video_class->num_of_formats);
|
||||
for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
|
||||
USB_LOG_INFO(" FormatIndex:%u\r\n", i + 1);
|
||||
USB_LOG_INFO(" FormatType:%s\r\n", format_type[video_class->format[i].format_type]);
|
||||
USB_LOG_INFO(" bNumFrames:%u\r\n", video_class->format[i].num_of_frames);
|
||||
USB_LOG_INFO(" Resolution:\r\n");
|
||||
USB_LOG_RAW(" FormatIndex:%u\r\n", i + 1);
|
||||
USB_LOG_RAW(" FormatType:%s\r\n", format_type[video_class->format[i].format_type]);
|
||||
USB_LOG_RAW(" bNumFrames:%u\r\n", video_class->format[i].num_of_frames);
|
||||
USB_LOG_RAW(" Resolution:\r\n");
|
||||
for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) {
|
||||
USB_LOG_INFO(" FrameIndex:%u\r\n", j + 1);
|
||||
USB_LOG_INFO(" wWidth: %d, wHeight: %d\r\n",
|
||||
USB_LOG_RAW(" FrameIndex:%u\r\n", j + 1);
|
||||
USB_LOG_RAW(" wWidth: %d, wHeight: %d\r\n",
|
||||
video_class->format[i].frame[j].wWidth,
|
||||
video_class->format[i].frame[j].wHeight);
|
||||
}
|
||||
@@ -475,20 +495,26 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
(void)video_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
(void)video_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
||||
@@ -505,20 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VIDEO,
|
||||
.subclass = VIDEO_SC_VIDEOCONTROL,
|
||||
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL,
|
||||
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.id_table = NULL,
|
||||
.class_driver = &video_ctrl_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VIDEO,
|
||||
.subclass = VIDEO_SC_VIDEOSTREAMING,
|
||||
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING,
|
||||
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.id_table = NULL,
|
||||
.class_driver = &video_streaming_class_driver
|
||||
};
|
||||
|
||||
@@ -22,12 +22,19 @@ struct usbh_video_format {
|
||||
uint8_t num_of_frames;
|
||||
};
|
||||
|
||||
struct usbh_videoframe {
|
||||
uint8_t *frame_buf;
|
||||
uint32_t frame_bufsize;
|
||||
uint32_t frame_format;
|
||||
uint32_t frame_size;
|
||||
};
|
||||
|
||||
struct usbh_videostreaming {
|
||||
struct usbh_videoframe *frame;
|
||||
uint32_t frame_format;
|
||||
uint32_t bufoffset;
|
||||
uint32_t buflen;
|
||||
uint16_t width;
|
||||
uint16_t heigth;
|
||||
void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
|
||||
uint16_t height;
|
||||
};
|
||||
|
||||
struct usbh_video {
|
||||
@@ -48,6 +55,8 @@ struct usbh_video {
|
||||
uint8_t num_of_intf_altsettings;
|
||||
uint8_t num_of_formats;
|
||||
struct usbh_video_format format[3];
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -17,26 +17,14 @@ static struct usbd_endpoint rndis_ep_data[3];
|
||||
#define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
|
||||
#define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define RNDIS_MAX_PACKET_SIZE 512
|
||||
#else
|
||||
#define RNDIS_MAX_PACKET_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USB_HS
|
||||
#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */
|
||||
#else
|
||||
#define RNDIS_LINK_SPEED 480000000 /* Link baudrate (480Mbit/s for USB-HS) */
|
||||
#endif
|
||||
|
||||
/* Device data structure */
|
||||
struct usbd_rndis_priv {
|
||||
uint32_t drv_version;
|
||||
uint32_t link_status;
|
||||
uint32_t speed;
|
||||
uint32_t net_filter;
|
||||
usb_eth_stat_t eth_state;
|
||||
rndis_state_t init_state;
|
||||
bool set_rsp_get;
|
||||
uint8_t mac[6];
|
||||
} g_usbd_rndis;
|
||||
|
||||
@@ -45,14 +33,22 @@ struct usbd_rndis_priv {
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
|
||||
#if CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE < 1580
|
||||
#undef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
|
||||
#endif
|
||||
|
||||
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];
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
#endif
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[USB_ALIGN_UP(CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[USB_ALIGN_UP(8, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
volatile uint8_t *g_rndis_rx_data_buffer;
|
||||
volatile uint32_t g_rndis_rx_data_length;
|
||||
volatile uint32_t g_rndis_rx_total_length;
|
||||
volatile uint32_t g_rndis_tx_data_length;
|
||||
|
||||
/* RNDIS options list */
|
||||
@@ -110,11 +106,17 @@ static void rndis_notify_rsp(void)
|
||||
|
||||
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
(void)busid;
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
||||
g_usbd_rndis.set_rsp_get = true;
|
||||
|
||||
rndis_encapsulated_cmd_handler(*data, setup->wLength);
|
||||
break;
|
||||
case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
|
||||
g_usbd_rndis.set_rsp_get = false;
|
||||
|
||||
*data = rndis_encapsulated_resp_buffer;
|
||||
*len = ((rndis_generic_msg_t *)rndis_encapsulated_resp_buffer)->MessageLength;
|
||||
break;
|
||||
@@ -160,6 +162,8 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
|
||||
rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
|
||||
rndis_initialize_cmplt_t *resp;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
||||
@@ -169,8 +173,8 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
|
||||
resp->Medium = RNDIS_MEDIUM_802_3;
|
||||
resp->MaxPacketsPerTransfer = 1;
|
||||
resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + sizeof(rndis_data_packet_t);
|
||||
resp->MaxPacketsPerTransfer = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE / 1580;
|
||||
resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE;
|
||||
resp->PacketAlignmentFactor = 0;
|
||||
resp->AfListOffset = 0;
|
||||
resp->AfListSize = 0;
|
||||
@@ -185,6 +189,9 @@ static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_halt_msg_t *resp;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageLength = 0;
|
||||
|
||||
@@ -200,6 +207,8 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
uint8_t *infomation_buffer;
|
||||
uint32_t infomation_len = 0;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
resp->RequestId = cmd->RequestId;
|
||||
@@ -225,7 +234,7 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||||
RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE);
|
||||
RNDIS_INQUIRY_PUT_LE32(0x05DC); /* mtu 1500 */
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_VENDOR_ID:
|
||||
@@ -250,7 +259,12 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_LINK_SPEED:
|
||||
RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
|
||||
if (usbd_get_ep_mps(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr) > 64) {
|
||||
RNDIS_INQUIRY_PUT_LE32(480000000 / 100);
|
||||
} else {
|
||||
RNDIS_INQUIRY_PUT_LE32(12000000 / 100);
|
||||
}
|
||||
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
@@ -258,11 +272,11 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE);
|
||||
RNDIS_INQUIRY_PUT_LE32(0x0616); /* 1514 + 44 */
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
|
||||
RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIA_STATE_CONNECTED);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
@@ -341,6 +355,8 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
rndis_set_cmplt_t *resp;
|
||||
rndis_config_parameter_t *param;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_SET_CMPLT;
|
||||
@@ -397,6 +413,9 @@ static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
||||
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
rndis_reset_cmplt_t *resp;
|
||||
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||
resp->MessageLength = sizeof(rndis_reset_cmplt_t);
|
||||
@@ -415,6 +434,8 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
|
||||
rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
|
||||
rndis_keepalive_cmplt_t *resp;
|
||||
|
||||
(void)len;
|
||||
|
||||
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
||||
@@ -428,15 +449,20 @@ static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
|
||||
|
||||
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
(void)busid;
|
||||
(void)arg;
|
||||
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
g_rndis_rx_data_length = 0;
|
||||
g_rndis_tx_data_length = 0;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -448,10 +474,12 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
||||
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
||||
if ((hdr->MessageType != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
|
||||
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_rx_data_buffer;
|
||||
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
|
||||
usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -459,24 +487,59 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
|
||||
g_rndis_rx_data_length = hdr->DataLength;
|
||||
|
||||
usbd_rndis_data_recv_done();
|
||||
usbd_rndis_data_recv_done(g_rndis_rx_data_length);
|
||||
}
|
||||
|
||||
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
|
||||
(void)busid;
|
||||
|
||||
if ((nbytes % usbd_get_ep_mps(0, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(0, ep, NULL, 0);
|
||||
} else {
|
||||
usbd_rndis_data_send_done(g_rndis_tx_data_length);
|
||||
g_rndis_tx_data_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
(void)busid;
|
||||
(void)ep;
|
||||
(void)nbytes;
|
||||
|
||||
//USB_LOG_DBG("len:%d\r\n", nbytes);
|
||||
}
|
||||
|
||||
int usbd_rndis_start_write(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (g_rndis_tx_data_length > 0) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
g_rndis_tx_data_length = len;
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
|
||||
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, buf, len);
|
||||
}
|
||||
|
||||
int usbd_rndis_start_read(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
g_rndis_rx_data_buffer = buf;
|
||||
g_rndis_rx_total_length = len;
|
||||
g_rndis_rx_data_length = 0;
|
||||
return usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, buf, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#include <lwip/pbuf.h>
|
||||
|
||||
@@ -489,15 +552,14 @@ struct pbuf *usbd_rndis_eth_rx(void)
|
||||
}
|
||||
p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
return NULL;
|
||||
}
|
||||
memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
|
||||
usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
|
||||
p->len = g_rndis_rx_data_length;
|
||||
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
|
||||
g_rndis_rx_data_length = 0;
|
||||
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
|
||||
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -507,8 +569,8 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||
return 0;
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (g_rndis_tx_data_length > 0) {
|
||||
@@ -521,7 +583,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
|
||||
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
usb_memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
@@ -533,10 +595,7 @@ int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = p->tot_len;
|
||||
|
||||
g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
|
||||
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
|
||||
return usbd_rndis_start_write(g_rndis_tx_buffer, sizeof(rndis_data_packet_t) + p->tot_len);
|
||||
}
|
||||
#endif
|
||||
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
@@ -548,7 +607,6 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
|
||||
g_usbd_rndis.drv_version = 0x0001;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
g_usbd_rndis.speed = RNDIS_LINK_SPEED;
|
||||
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
|
||||
@@ -568,3 +626,42 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
int usbd_rndis_set_connect(bool connect)
|
||||
{
|
||||
if (!usb_device_is_configured(0)) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if(g_usbd_rndis.set_rsp_get)
|
||||
return -USB_ERR_BUSY;
|
||||
|
||||
rndis_indicate_status_t *resp;
|
||||
|
||||
resp = ((rndis_indicate_status_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
|
||||
resp->MessageLength = sizeof(rndis_indicate_status_t);
|
||||
if(connect) {
|
||||
resp->Status = RNDIS_STATUS_MEDIA_CONNECT;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
} else {
|
||||
resp->Status = RNDIS_STATUS_MEDIA_DISCONNECT;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
}
|
||||
resp->StatusBufferLength = 0;
|
||||
resp->StatusBufferOffset = 0;
|
||||
|
||||
rndis_notify_rsp();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbd_rndis_data_recv_done(uint32_t len)
|
||||
{
|
||||
(void)len;
|
||||
}
|
||||
|
||||
__WEAK void usbd_rndis_data_send_done(uint32_t len)
|
||||
{
|
||||
(void)len;
|
||||
}
|
||||
@@ -18,7 +18,12 @@ 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);
|
||||
int usbd_rndis_set_connect(bool connect);
|
||||
|
||||
void usbd_rndis_data_recv_done(uint32_t len);
|
||||
void usbd_rndis_data_send_done(uint32_t len);
|
||||
int usbd_rndis_start_write(uint8_t *buf, uint32_t len);
|
||||
int usbd_rndis_start_read(uint8_t *buf, uint32_t len);
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
struct pbuf *usbd_rndis_eth_rx(void);
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
static struct usbh_bluetooth g_bluetooth_class;
|
||||
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[USB_ALIGN_UP(CONFIG_USBHOST_BLUETOOTH_TX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[USB_ALIGN_UP(CONFIG_USBHOST_BLUETOOTH_RX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
#else
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[1 + 256];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[1 + 256];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[USB_ALIGN_UP(256, CONFIG_USB_ALIGN_SIZE)];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[USB_ALIGN_UP(256, CONFIG_USB_ALIGN_SIZE)];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[USB_ALIGN_UP(CONFIG_USBHOST_BLUETOOTH_TX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[USB_ALIGN_UP(CONFIG_USBHOST_BLUETOOTH_RX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
#endif
|
||||
|
||||
static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
@@ -96,7 +96,7 @@ static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
USB_LOG_INFO("Bluetooth select altsetting 0\r\n");
|
||||
#endif
|
||||
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT);
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_bluetooth_run(bluetooth_class);
|
||||
return ret;
|
||||
@@ -189,7 +189,7 @@ int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_bluetooth_hci_rx_thread(void *argument)
|
||||
void usbh_bluetooth_hci_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
int ret;
|
||||
uint32_t ep_mps;
|
||||
@@ -224,7 +224,7 @@ void usbh_bluetooth_hci_rx_thread(void *argument)
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete :
|
||||
delete :
|
||||
USB_LOG_INFO("Delete hc acl rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
@@ -234,7 +234,12 @@ delete :
|
||||
static int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||
struct usb_setup_packet *setup = bluetooth_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!bluetooth_class || !bluetooth_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = bluetooth_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = 0x00;
|
||||
@@ -266,7 +271,7 @@ int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_bluetooth_hci_evt_rx_thread(void *argument)
|
||||
void usbh_bluetooth_hci_evt_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
int ret;
|
||||
uint32_t ep_mps;
|
||||
@@ -309,13 +314,13 @@ void usbh_bluetooth_hci_evt_rx_thread(void *argument)
|
||||
usb_osal_msleep(interval);
|
||||
}
|
||||
// clang-format off
|
||||
delete :
|
||||
delete :
|
||||
USB_LOG_INFO("Delete hc event rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void usbh_bluetooth_hci_acl_rx_thread(void *argument)
|
||||
void usbh_bluetooth_hci_acl_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
int ret;
|
||||
uint32_t ep_mps;
|
||||
@@ -351,7 +356,7 @@ void usbh_bluetooth_hci_acl_rx_thread(void *argument)
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete :
|
||||
delete :
|
||||
USB_LOG_INFO("Delete hc acl rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
@@ -360,14 +365,18 @@ delete :
|
||||
|
||||
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
|
||||
{
|
||||
(void)bluetooth_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
|
||||
{
|
||||
(void)bluetooth_class;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver bluetooth_class_driver = {
|
||||
@@ -377,23 +386,26 @@ static const struct usbh_class_driver bluetooth_class_driver = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
static const uint16_t bluetooth_id_table[][2] = {
|
||||
{ 0x2fe3, 0x000c },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.vid = 0x2fe3,
|
||||
.pid = 0x000c,
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0x00,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.id_table = bluetooth_id_table,
|
||||
.class_driver = &bluetooth_class_driver
|
||||
};
|
||||
#else
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_WIRELESS,
|
||||
.subclass = 0x01,
|
||||
.protocol = 0x01,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
|
||||
.bInterfaceSubClass = 0x01,
|
||||
.bInterfaceProtocol = 0x01,
|
||||
.id_table = NULL,
|
||||
.class_driver = &bluetooth_class_driver
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,8 @@ struct usbh_bluetooth {
|
||||
struct usbh_urb *isoout_urb; /* Bulk OUT urb */
|
||||
uint8_t num_of_intf_altsettings;
|
||||
#endif
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -38,10 +40,10 @@ extern "C" {
|
||||
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
|
||||
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
void usbh_bluetooth_hci_rx_thread(void *argument);
|
||||
void usbh_bluetooth_hci_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
#else
|
||||
void usbh_bluetooth_hci_evt_rx_thread(void *argument);
|
||||
void usbh_bluetooth_hci_acl_rx_thread(void *argument);
|
||||
void usbh_bluetooth_hci_evt_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
void usbh_bluetooth_hci_acl_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
#endif
|
||||
|
||||
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);
|
||||
|
||||
@@ -13,23 +13,20 @@
|
||||
|
||||
#define DEV_FORMAT "/dev/rndis"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[512];
|
||||
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
|
||||
|
||||
/* 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 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE, CONFIG_USB_ALIGN_SIZE)];
|
||||
// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[USB_ALIGN_UP(16, CONFIG_USB_ALIGN_SIZE)];
|
||||
|
||||
static struct usbh_rndis g_rndis_class;
|
||||
|
||||
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
(void)rndis_class;
|
||||
// int ret;
|
||||
// struct usbh_urb *urb = &rndis_class->intin_urb;
|
||||
|
||||
@@ -44,11 +41,16 @@ static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||
|
||||
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_initialize_msg_t *cmd;
|
||||
rndis_initialize_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_initialize_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_INITIALIZE_MSG;
|
||||
@@ -78,7 +80,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
setup->wLength = sizeof(g_rndis_buf);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
@@ -86,16 +88,26 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer;
|
||||
rndis_class->max_transfer_size = resp->MaxTransferSize;
|
||||
USB_LOG_INFO("MaxPacketsPerTransfer:%u\r\n", (unsigned int)resp->MaxPacketsPerTransfer);
|
||||
USB_LOG_INFO("MaxTransferSize:%u\r\n", (unsigned int)resp->MaxTransferSize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_query_msg_t *cmd;
|
||||
rndis_query_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_query_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_QUERY_MSG;
|
||||
@@ -126,7 +138,7 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
setup->wLength = sizeof(g_rndis_buf);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
@@ -142,11 +154,16 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid,
|
||||
|
||||
static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_set_msg_t *cmd;
|
||||
rndis_set_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_set_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_SET_MSG;
|
||||
@@ -178,7 +195,7 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
setup->wLength = sizeof(g_rndis_buf);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
@@ -209,11 +226,16 @@ int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup = rndis_class->hport->setup;
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_keepalive_msg_t *cmd;
|
||||
rndis_keepalive_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_keepalive_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
|
||||
@@ -240,7 +262,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
setup->wLength = sizeof(g_rndis_buf);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
@@ -256,8 +278,8 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint32_t *oid_support_list;
|
||||
unsigned int oid = 0;
|
||||
unsigned int oid_num = 0;
|
||||
uint32_t oid = 0;
|
||||
uint32_t oid_num = 0;
|
||||
uint32_t data_len;
|
||||
uint8_t tmp_buffer[512];
|
||||
uint8_t data[32];
|
||||
@@ -297,7 +319,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
oid_num = (data_len / 4);
|
||||
USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%d\r\n", oid_num);
|
||||
USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%u\r\n", (unsigned int)oid_num);
|
||||
|
||||
oid_support_list = (uint32_t *)tmp_buffer;
|
||||
|
||||
@@ -358,21 +380,21 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", oid);
|
||||
USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", (unsigned int)oid);
|
||||
continue;
|
||||
}
|
||||
USB_LOG_INFO("rndis query iod:%08x success\r\n", oid);
|
||||
USB_LOG_INFO("rndis query iod:%08x success\r\n", (unsigned int)oid);
|
||||
}
|
||||
|
||||
uint32_t packet_filter = 0x0f;
|
||||
usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
|
||||
ret = usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_GEN_CURRENT_PACKET_FILTER success\r\n");
|
||||
|
||||
uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
|
||||
usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
|
||||
ret = usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -386,13 +408,13 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
rndis_class->mac[4],
|
||||
rndis_class->mac[5]);
|
||||
|
||||
memcpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_run(rndis_class);
|
||||
return ret;
|
||||
query_errorout:
|
||||
USB_LOG_ERR("rndis query iod:%08x error\r\n", oid);
|
||||
USB_LOG_ERR("rndis query iod:%08x error\r\n", (unsigned int)oid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -426,17 +448,20 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_rndis_rx_thread(void *argument)
|
||||
void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
|
||||
{
|
||||
uint32_t g_rndis_rx_length;
|
||||
uint32_t pmg_offset;
|
||||
uint32_t payload_offset;
|
||||
int ret;
|
||||
err_t err;
|
||||
struct pbuf *p, *q;
|
||||
uint32_t pmg_offset;
|
||||
rndis_data_packet_t *pmsg;
|
||||
rndis_data_packet_t temp;
|
||||
struct netif *netif = (struct netif *)argument;
|
||||
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
uint32_t transfer_size = CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE;
|
||||
#else
|
||||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
(void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
|
||||
|
||||
USB_LOG_INFO("Create rndis rx thread\r\n");
|
||||
// clang-format off
|
||||
@@ -453,52 +478,65 @@ find_class:
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(128);
|
||||
}
|
||||
|
||||
g_rndis_rx_length = 0;
|
||||
while (1) {
|
||||
g_rndis_rx_length = 0;
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, g_rndis_rx_buffer, CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, &g_rndis_rx_buffer[g_rndis_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_rndis_rx_length = g_rndis_class.bulkin_urb.actual_length;
|
||||
pmg_offset = 0;
|
||||
while (g_rndis_rx_length > 0) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
|
||||
g_rndis_rx_length += g_rndis_class.bulkin_urb.actual_length;
|
||||
|
||||
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
|
||||
/* A transfer is complete because last packet is a short packet.
|
||||
* Short packet is not zero, match g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize).
|
||||
* Short packet cannot be zero.
|
||||
*/
|
||||
if (g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize)) {
|
||||
pmg_offset = 0;
|
||||
|
||||
/* Not word-aligned case */
|
||||
if (pmg_offset & 0x3) {
|
||||
memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
|
||||
pmsg = &temp;
|
||||
}
|
||||
uint32_t total_len = g_rndis_rx_length;
|
||||
|
||||
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
||||
p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
payload_offset = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset + payload_offset);
|
||||
memcpy(q->payload, src, q->len);
|
||||
payload_offset += q->len;
|
||||
}
|
||||
while (g_rndis_rx_length > 0) {
|
||||
USB_LOG_DBG("rxlen:%u\r\n", (unsigned int)g_rndis_rx_length);
|
||||
|
||||
err = netif->input(p, netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
|
||||
|
||||
/* Not word-aligned case */
|
||||
if (pmg_offset & 0x3) {
|
||||
usb_memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
|
||||
pmsg = &temp;
|
||||
}
|
||||
|
||||
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
||||
uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
|
||||
|
||||
usbh_rndis_eth_input(buf, pmsg->DataLength);
|
||||
pmg_offset += pmsg->MessageLength;
|
||||
g_rndis_rx_length -= pmsg->MessageLength;
|
||||
|
||||
/* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
|
||||
if (g_rndis_rx_length < 4) {
|
||||
g_rndis_rx_length = 0;
|
||||
}
|
||||
} else {
|
||||
USB_LOG_ERR("offset:%u,remain:%u,total:%u\r\n", (unsigned int)pmg_offset, (unsigned int)g_rndis_rx_length, (unsigned int)total_len);
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
|
||||
USB_LOG_ERR("Error rndis packet message\r\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
if (g_rndis_rx_length == CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
||||
#else
|
||||
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
} else {
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("Error rndis packet message\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,53 +548,48 @@ delete:
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
uint8_t *usbh_rndis_get_eth_txbuf(void)
|
||||
{
|
||||
return (g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
}
|
||||
|
||||
int usbh_rndis_eth_output(uint32_t buflen)
|
||||
{
|
||||
int ret;
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
uint32_t len;
|
||||
|
||||
if (g_rndis_class.connect_status == false) {
|
||||
return ERR_BUF;
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + buflen;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = p->tot_len;
|
||||
|
||||
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
hdr->DataLength = buflen;
|
||||
|
||||
len = hdr->MessageLength;
|
||||
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
|
||||
if (!(hdr->MessageLength % g_rndis_class.bulkout->wMaxPacketSize)) {
|
||||
hdr->MessageLength += 1;
|
||||
if (!(len % g_rndis_class.bulkout->wMaxPacketSize)) {
|
||||
len += 1;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", hdr->MessageLength);
|
||||
USB_LOG_DBG("txlen:%d\r\n", len);
|
||||
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, hdr->MessageLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
return usbh_submit_urb(&g_rndis_class.bulkout_urb);
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
(void)rndis_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
(void)rndis_class;
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver rndis_class_driver = {
|
||||
@@ -567,10 +600,9 @@ static const struct usbh_class_driver rndis_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_WIRELESS,
|
||||
.subclass = 0x01,
|
||||
.protocol = 0x03,
|
||||
.vid = 0x00,
|
||||
.pid = 0x00,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
|
||||
.bInterfaceSubClass = 0x01,
|
||||
.bInterfaceProtocol = 0x03,
|
||||
.id_table = NULL,
|
||||
.class_driver = &rndis_class_driver
|
||||
};
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
struct usbh_rndis {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
@@ -25,14 +22,15 @@ struct usbh_rndis {
|
||||
uint8_t minor;
|
||||
|
||||
uint32_t request_id;
|
||||
uint32_t tx_offset;
|
||||
uint32_t max_transfer_pkts; /* max packets in one transfer */
|
||||
uint32_t max_transfer_size; /* max size in one transfer */
|
||||
|
||||
uint32_t link_speed;
|
||||
bool connect_status;
|
||||
uint8_t mac[6];
|
||||
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gateway;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -45,8 +43,10 @@ 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);
|
||||
uint8_t *usbh_rndis_get_eth_txbuf(void);
|
||||
int usbh_rndis_eth_output(uint32_t buflen);
|
||||
void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -33,14 +33,21 @@ int usb_dc_deinit(uint8_t busid);
|
||||
*/
|
||||
int usbd_set_address(uint8_t busid, const uint8_t addr);
|
||||
|
||||
/**
|
||||
* @brief Set remote wakeup feature
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usbd_set_remote_wakeup(uint8_t busid);
|
||||
|
||||
/**
|
||||
* @brief Get USB device speed
|
||||
*
|
||||
* @param[in] port port index
|
||||
* @param[in] busid bus index
|
||||
*
|
||||
* @return port speed, USB_SPEED_LOW or USB_SPEED_FULL or USB_SPEED_HIGH
|
||||
*/
|
||||
uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port);
|
||||
uint8_t usbd_get_port_speed(uint8_t busid);
|
||||
|
||||
/**
|
||||
* @brief configure and enable endpoint.
|
||||
@@ -129,7 +136,12 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
|
||||
*/
|
||||
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len);
|
||||
|
||||
/* usb dcd irq callback */
|
||||
/* usb dcd irq callback, called by user */
|
||||
|
||||
/**
|
||||
* @brief Usb sof irq callback.
|
||||
*/
|
||||
void usbd_event_sof_handler(uint8_t busid);
|
||||
|
||||
/**
|
||||
* @brief Usb connect irq callback.
|
||||
@@ -178,6 +190,18 @@ void usbd_event_ep_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyte
|
||||
*/
|
||||
void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||
|
||||
#ifdef CONFIG_USBDEV_TEST_MODE
|
||||
/**
|
||||
* @brief Usb execute test mode
|
||||
* @param[in] busid device busid
|
||||
* @param[in] test_mode usb test mode
|
||||
*/
|
||||
void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode);
|
||||
#endif
|
||||
|
||||
/* called by user */
|
||||
void USBD_IRQHandler(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
19
common/usb_dcache.h
Normal file
19
common/usb_dcache.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_DCACHE_H
|
||||
#define USB_DCACHE_H
|
||||
|
||||
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||
#if CONFIG_USB_ALIGN_SIZE % 32
|
||||
#error "CONFIG_USB_ALIGN_SIZE must be multiple of 32"
|
||||
#endif
|
||||
#else
|
||||
#define usb_dcache_clean(addr, size)
|
||||
#define usb_dcache_invalidate(addr, size)
|
||||
#define usb_dcache_flush(addr, size)
|
||||
#endif
|
||||
|
||||
#endif /* USB_DCACHE_H */
|
||||
@@ -34,6 +34,10 @@
|
||||
/**< maximum packet size (MPS) for EP 0 */
|
||||
#define USB_CTRL_EP_MPS 64
|
||||
|
||||
/**< maximum packet size (MPS) for bulk EP */
|
||||
#define USB_BULK_EP_MPS_HS 512
|
||||
#define USB_BULK_EP_MPS_FS 64
|
||||
|
||||
/* USB PID Types */
|
||||
#define USB_PID_OUT (0x01) /* Tokens */
|
||||
#define USB_PID_IN (0x09)
|
||||
@@ -538,7 +542,7 @@ struct usb_msosv2_subset_function_descriptor {
|
||||
} __PACKED;
|
||||
|
||||
struct usb_msosv2_descriptor {
|
||||
uint8_t *compat_id;
|
||||
const uint8_t *compat_id;
|
||||
uint16_t compat_id_len;
|
||||
uint8_t vendor_code;
|
||||
};
|
||||
@@ -610,14 +614,14 @@ struct usb_webusb_url_descriptor {
|
||||
char URL[];
|
||||
} __PACKED;
|
||||
|
||||
struct usb_webusb_url_ex_descriptor {
|
||||
struct usb_webusb_descriptor {
|
||||
uint8_t vendor_code;
|
||||
uint8_t *string;
|
||||
const uint8_t *string;
|
||||
uint32_t string_len;
|
||||
} __PACKED;
|
||||
|
||||
struct usb_bos_descriptor {
|
||||
uint8_t *string;
|
||||
const uint8_t *string;
|
||||
uint32_t string_len;
|
||||
};
|
||||
|
||||
@@ -660,6 +664,27 @@ struct usb_desc_header {
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
|
||||
|
||||
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bNumConfigurations) \
|
||||
0x0A, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, /* bDescriptorType */ \
|
||||
WBVAL(bcdUSB), /* bcdUSB */ \
|
||||
bDeviceClass, /* bDeviceClass */ \
|
||||
bDeviceSubClass, /* bDeviceSubClass */ \
|
||||
bDeviceProtocol, /* bDeviceProtocol */ \
|
||||
0x40, /* bMaxPacketSize */ \
|
||||
bNumConfigurations, /* bNumConfigurations */ \
|
||||
0x00 /* bReserved */
|
||||
|
||||
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
|
||||
0x09, /* bLength */ \
|
||||
USB_DESCRIPTOR_TYPE_OTHER_SPEED, /* bDescriptorType */ \
|
||||
WBVAL(wTotalLength), /* wTotalLength */ \
|
||||
bNumInterfaces, /* bNumInterfaces */ \
|
||||
bConfigurationValue, /* bConfigurationValue */ \
|
||||
0x00, /* iConfiguration */ \
|
||||
bmAttributes, /* bmAttributes */ \
|
||||
USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
|
||||
|
||||
#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints, \
|
||||
bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
|
||||
0x09, /* bLength */ \
|
||||
|
||||
@@ -34,10 +34,12 @@ struct usbh_iso_frame_packet {
|
||||
* Structure containing the USB Urb configuration.
|
||||
*/
|
||||
struct usbh_urb {
|
||||
usb_slist_t list;
|
||||
void *hcpriv;
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *ep;
|
||||
uint8_t data_toggle;
|
||||
uint8_t interval;
|
||||
struct usb_setup_packet *setup;
|
||||
uint8_t *transfer_buffer;
|
||||
uint32_t transfer_buffer_length;
|
||||
@@ -106,6 +108,9 @@ int usbh_submit_urb(struct usbh_urb *urb);
|
||||
*/
|
||||
int usbh_kill_urb(struct usbh_urb *urb);
|
||||
|
||||
/* called by user */
|
||||
void USBH_IRQHandler(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -75,11 +75,57 @@
|
||||
|
||||
#define USB_LOG_RAW(...) CONFIG_USB_PRINTF(__VA_ARGS__)
|
||||
|
||||
void usb_assert(const char *filename, int linenum);
|
||||
#define USB_ASSERT(f) \
|
||||
do { \
|
||||
if (!(f)) \
|
||||
usb_assert(__FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#ifndef CONFIG_USB_ASSERT_DISABLE
|
||||
#define USB_ASSERT(f) \
|
||||
do { \
|
||||
if (!(f)) { \
|
||||
USB_LOG_ERR("ASSERT FAIL [%s] @ %s:%d\r\n", #f, __FILE__, __LINE__); \
|
||||
while (1) { \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define USB_ASSERT_MSG(f, fmt, ...) \
|
||||
do { \
|
||||
if (!(f)) { \
|
||||
USB_LOG_ERR("ASSERT FAIL [%s] @ %s:%d\r\n", #f, __FILE__, __LINE__); \
|
||||
USB_LOG_ERR(fmt "\r\n", ##__VA_ARGS__); \
|
||||
while (1) { \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
#else
|
||||
#define USB_ASSERT(f) {}
|
||||
#define USB_ASSERT_MSG(f, fmt, ...) {}
|
||||
#endif
|
||||
|
||||
#define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
static inline void usb_hexdump(const void *ptr, uint32_t buflen)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)ptr;
|
||||
unsigned int i, j;
|
||||
|
||||
(void)buf;
|
||||
|
||||
for (i = 0; i < buflen; i += 16) {
|
||||
CONFIG_USB_PRINTF("%08x:", i);
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen) {
|
||||
if ((j % 8) == 0) {
|
||||
CONFIG_USB_PRINTF(" ");
|
||||
}
|
||||
|
||||
CONFIG_USB_PRINTF("%02X ", buf[i + j]);
|
||||
} else
|
||||
CONFIG_USB_PRINTF(" ");
|
||||
CONFIG_USB_PRINTF(" ");
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen)
|
||||
CONFIG_USB_PRINTF("%c", ___is_print(buf[i + j]) ? buf[i + j] : '.');
|
||||
CONFIG_USB_PRINTF("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USB_LOG_H */
|
||||
|
||||
96
common/usb_memcpy.h
Normal file
96
common/usb_memcpy.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_MEMCPY_H
|
||||
#define USB_MEMCPY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define ALIGN_UP_DWORD(x) ((uint32_t)(uintptr_t)(x) & (sizeof(uint32_t) - 1))
|
||||
|
||||
static inline void dword2array(char *addr, uint32_t w)
|
||||
{
|
||||
addr[0] = w;
|
||||
addr[1] = w >> 8;
|
||||
addr[2] = w >> 16;
|
||||
addr[3] = w >> 24;
|
||||
}
|
||||
|
||||
static inline void *usb_memcpy(void *s1, const void *s2, size_t n)
|
||||
{
|
||||
char *b1 = (char *)s1;
|
||||
const char *b2 = (const char *)s2;
|
||||
uint32_t *w1;
|
||||
const uint32_t *w2;
|
||||
|
||||
if (ALIGN_UP_DWORD(b1) == ALIGN_UP_DWORD(b2)) {
|
||||
while (ALIGN_UP_DWORD(b1) != 0 && n > 0) {
|
||||
*b1++ = *b2++;
|
||||
--n;
|
||||
}
|
||||
|
||||
w1 = (uint32_t *)b1;
|
||||
w2 = (const uint32_t *)b2;
|
||||
|
||||
while (n >= 4 * sizeof(uint32_t)) {
|
||||
*w1++ = *w2++;
|
||||
*w1++ = *w2++;
|
||||
*w1++ = *w2++;
|
||||
*w1++ = *w2++;
|
||||
n -= 4 * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
while (n >= sizeof(uint32_t)) {
|
||||
*w1++ = *w2++;
|
||||
n -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
b1 = (char *)w1;
|
||||
b2 = (const char *)w2;
|
||||
|
||||
while (n--) {
|
||||
*b1++ = *b2++;
|
||||
}
|
||||
} else {
|
||||
while (n > 0 && ALIGN_UP_DWORD(b2) != 0) {
|
||||
*b1++ = *b2++;
|
||||
--n;
|
||||
}
|
||||
|
||||
w2 = (const uint32_t *)b2;
|
||||
|
||||
while (n >= 4 * sizeof(uint32_t)) {
|
||||
dword2array(b1, *w2++);
|
||||
b1 += sizeof(uint32_t);
|
||||
dword2array(b1, *w2++);
|
||||
b1 += sizeof(uint32_t);
|
||||
dword2array(b1, *w2++);
|
||||
b1 += sizeof(uint32_t);
|
||||
dword2array(b1, *w2++);
|
||||
b1 += sizeof(uint32_t);
|
||||
n -= 4 * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
while (n >= sizeof(uint32_t)) {
|
||||
dword2array(b1, *w2++);
|
||||
b1 += sizeof(uint32_t);
|
||||
n -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
b2 = (const char *)w2;
|
||||
|
||||
while (n--) {
|
||||
*b1++ = *b2++;
|
||||
}
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USB_MEMCPY_DISABLE
|
||||
#define memcpy usb_memcpy
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,18 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __INCLUDE_NUTTX_CONFIG_H
|
||||
#define CONFIG_USB_OSAL_THREAD_SET_ARGV int argc, char **argv
|
||||
#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)strtoul(argv[1], NULL, 16))
|
||||
#elif defined(__ZEPHYR__)
|
||||
#define CONFIG_USB_OSAL_THREAD_SET_ARGV void *p1, void *p2, void *p3
|
||||
#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)p1)
|
||||
#else
|
||||
#define CONFIG_USB_OSAL_THREAD_SET_ARGV void *argument
|
||||
#define CONFIG_USB_OSAL_THREAD_GET_ARGV ((uintptr_t)argument)
|
||||
#endif
|
||||
|
||||
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
|
||||
|
||||
@@ -15,7 +27,15 @@ typedef void *usb_osal_thread_t;
|
||||
typedef void *usb_osal_sem_t;
|
||||
typedef void *usb_osal_mutex_t;
|
||||
typedef void *usb_osal_mq_t;
|
||||
typedef void (*usb_thread_entry_t)(void *argument);
|
||||
typedef void (*usb_thread_entry_t)(CONFIG_USB_OSAL_THREAD_SET_ARGV);
|
||||
typedef void (*usb_timer_handler_t)(void *argument);
|
||||
struct usb_osal_timer {
|
||||
usb_timer_handler_t handler;
|
||||
void *argument;
|
||||
bool is_period;
|
||||
uint32_t timeout_ms;
|
||||
void *timer;
|
||||
};
|
||||
|
||||
/*
|
||||
* Task with smaller priority value indicates higher task priority
|
||||
@@ -39,9 +59,17 @@ void usb_osal_mq_delete(usb_osal_mq_t mq);
|
||||
int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr);
|
||||
int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout);
|
||||
|
||||
struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period);
|
||||
void usb_osal_timer_delete(struct usb_osal_timer *timer);
|
||||
void usb_osal_timer_start(struct usb_osal_timer *timer);
|
||||
void usb_osal_timer_stop(struct usb_osal_timer *timer);
|
||||
|
||||
size_t usb_osal_enter_critical_section(void);
|
||||
void usb_osal_leave_critical_section(size_t flag);
|
||||
|
||||
void usb_osal_msleep(uint32_t delay);
|
||||
|
||||
void *usb_osal_malloc(size_t size);
|
||||
void usb_osal_free(void *ptr);
|
||||
|
||||
#endif /* USB_OSAL_H */
|
||||
|
||||
41
common/usb_otg.h
Normal file
41
common/usb_otg.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_OTG_H
|
||||
#define USB_OTG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief usb otg controller hardware or gpio id simulator init.
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usb_otg_init(uint8_t busid);
|
||||
/**
|
||||
* @brief usb otg controller hardware or gpio id simulator deinit.
|
||||
*
|
||||
* @return On success will return 0, and others indicate fail.
|
||||
*/
|
||||
int usb_otg_deinit(uint8_t busid);
|
||||
/**
|
||||
* @brief get current role mode.
|
||||
*
|
||||
* @return return USBOTG_MODE_HOST or USBOTG_MODE_DEVICE.
|
||||
*/
|
||||
uint8_t usbotg_get_current_mode(uint8_t busid);
|
||||
|
||||
/* called by user */
|
||||
void USBOTG_IRQHandler(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USB_OTG_H */
|
||||
@@ -206,5 +206,14 @@
|
||||
#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
|
||||
|
||||
#define USB_ALIGN_UP(size, align) (((size) + (align)-1) & ~((align)-1))
|
||||
#define USB_ALIGN_DOWN(size, align) ((size) & ~((align)-1))
|
||||
|
||||
#ifndef usb_phyaddr2ramaddr
|
||||
#define usb_phyaddr2ramaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
#ifndef usb_ramaddr2phyaddr
|
||||
#define usb_ramaddr2phyaddr(addr) (addr)
|
||||
#endif
|
||||
|
||||
#endif /* USB_UTIL_H */
|
||||
|
||||
21
common/usb_version.h
Normal file
21
common/usb_version.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USB_VERSION_H
|
||||
#define USB_VERSION_H
|
||||
|
||||
#ifdef CHERRYUSB_VERSION
|
||||
#warning "Please do not define CHERRYUSB_VERSION in usb_config.h"
|
||||
#undef CHERRYUSB_VERSION
|
||||
#endif
|
||||
#ifdef CHERRYUSB_VERSION_STR
|
||||
#warning "Please do not define CHERRYUSB_VERSION_STR in usb_config.h"
|
||||
#undef CHERRYUSB_VERSION_STR
|
||||
#endif
|
||||
|
||||
#define CHERRYUSB_VERSION 0x010500
|
||||
#define CHERRYUSB_VERSION_STR "v1.5.0"
|
||||
|
||||
#endif
|
||||
557
core/usbd_core.c
557
core/usbd_core.c
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,8 @@ extern "C" {
|
||||
#include "usb_list.h"
|
||||
#include "usb_log.h"
|
||||
#include "usb_dc.h"
|
||||
#include "usb_memcpy.h"
|
||||
#include "usb_version.h"
|
||||
|
||||
enum usbd_event_type {
|
||||
/* USB DCD IRQ */
|
||||
@@ -43,6 +45,12 @@ enum usbd_event_type {
|
||||
USBD_EVENT_UNKNOWN
|
||||
};
|
||||
|
||||
#define USBD_EP0_STATE_SETUP 0
|
||||
#define USBD_EP0_STATE_IN_DATA 1
|
||||
#define USBD_EP0_STATE_OUT_DATA 2
|
||||
#define USBD_EP0_STATE_IN_STATUS 3
|
||||
#define USBD_EP0_STATE_OUT_STATUS 4
|
||||
|
||||
typedef int (*usbd_request_handler)(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
|
||||
typedef void (*usbd_endpoint_callback)(uint8_t busid, uint8_t ep, uint32_t nbytes);
|
||||
typedef void (*usbd_notify_handler)(uint8_t busid, uint8_t event, void *arg);
|
||||
@@ -67,16 +75,16 @@ struct usb_descriptor {
|
||||
const uint8_t *(*config_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*device_quality_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*other_speed_descriptor_callback)(uint8_t speed);
|
||||
const uint8_t *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
|
||||
const char *(*string_descriptor_callback)(uint8_t speed, uint8_t index);
|
||||
const struct usb_msosv1_descriptor *msosv1_descriptor;
|
||||
const struct usb_msosv2_descriptor *msosv2_descriptor;
|
||||
const struct usb_webusb_url_ex_descriptor *webusb_url_descriptor;
|
||||
const struct usb_webusb_descriptor *webusb_url_descriptor;
|
||||
const struct usb_bos_descriptor *bos_descriptor;
|
||||
};
|
||||
|
||||
struct usbd_bus {
|
||||
uint8_t busid;
|
||||
uint32_t reg_base;
|
||||
uintptr_t reg_base;
|
||||
};
|
||||
|
||||
extern struct usbd_bus g_usbdev_bus[];
|
||||
@@ -92,13 +100,20 @@ void usbd_desc_register(uint8_t busid, const uint8_t *desc);
|
||||
void usbd_msosv1_desc_register(uint8_t busid, struct usb_msosv1_descriptor *desc);
|
||||
void usbd_msosv2_desc_register(uint8_t busid, struct usb_msosv2_descriptor *desc);
|
||||
void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc);
|
||||
void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc);
|
||||
#endif
|
||||
|
||||
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf);
|
||||
void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
|
||||
|
||||
uint16_t usbd_get_ep_mps(uint8_t busid, uint8_t ep);
|
||||
uint8_t usbd_get_ep_mult(uint8_t busid, uint8_t ep);
|
||||
bool usb_device_is_configured(uint8_t busid);
|
||||
int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
|
||||
bool usb_device_is_suspend(uint8_t busid);
|
||||
int usbd_send_remote_wakeup(uint8_t busid);
|
||||
uint8_t usbd_get_ep0_next_state(uint8_t busid);
|
||||
|
||||
int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
|
||||
int usbd_deinitialize(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
1032
core/usbh_core.c
1032
core/usbh_core.c
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,9 @@
|
||||
#include "usb_hc.h"
|
||||
#include "usb_osal.h"
|
||||
#include "usbh_hub.h"
|
||||
#include "usb_memcpy.h"
|
||||
#include "usb_dcache.h"
|
||||
#include "usb_version.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -30,6 +33,7 @@ extern "C" {
|
||||
#define USB_CLASS_MATCH_INTF_CLASS 0x0004
|
||||
#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
|
||||
#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
|
||||
#define USB_CLASS_MATCH_VID_PID (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT)
|
||||
|
||||
#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
|
||||
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
|
||||
@@ -39,28 +43,29 @@ extern "C" {
|
||||
#elif defined(__GNUC__)
|
||||
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
|
||||
#pragma section = "usbh_class_info"
|
||||
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#pragma section = ".usbh_class_info"
|
||||
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
|
||||
#endif
|
||||
|
||||
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? interval : (1 << (interval - 1)))
|
||||
|
||||
#define USBH_EP_INIT(ep, ep_desc) \
|
||||
do { \
|
||||
ep = ep_desc; \
|
||||
USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \
|
||||
ep_desc->bEndpointAddress, \
|
||||
USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes), \
|
||||
ep_desc->bmAttributes, \
|
||||
USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \
|
||||
ep_desc->bInterval, \
|
||||
USB_GET_MULT(ep_desc->bmAttributes)); \
|
||||
USB_GET_MULT(ep_desc->wMaxPacketSize)); \
|
||||
} while (0)
|
||||
|
||||
struct usbh_class_info {
|
||||
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
|
||||
uint8_t class; /* Base device class code */
|
||||
uint8_t subclass; /* Sub-class, depends on base class. Eg. */
|
||||
uint8_t protocol; /* Protocol, depends on base class. Eg. */
|
||||
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
|
||||
uint16_t pid; /* Product ID (for vendor/product specific devices) */
|
||||
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
|
||||
uint8_t bInterfaceClass; /* Base device class code */
|
||||
uint8_t bInterfaceSubClass; /* Sub-class, depends on base class. Eg. */
|
||||
uint8_t bInterfaceProtocol; /* Protocol, depends on base class. Eg. */
|
||||
const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
|
||||
const struct usbh_class_driver *class_driver;
|
||||
};
|
||||
|
||||
@@ -98,6 +103,9 @@ struct usbh_hubport {
|
||||
uint8_t port; /* Hub port index */
|
||||
uint8_t dev_addr; /* device address */
|
||||
uint8_t speed; /* device speed */
|
||||
uint8_t depth; /* distance from root hub */
|
||||
uint8_t route; /* route string */
|
||||
uint8_t slot_id; /* slot id */
|
||||
struct usb_device_descriptor device_desc;
|
||||
struct usbh_configuration config;
|
||||
const char *iManufacturer;
|
||||
@@ -106,28 +114,32 @@ struct usbh_hubport {
|
||||
uint8_t *raw_config_desc;
|
||||
struct usb_setup_packet *setup;
|
||||
struct usbh_hub *parent;
|
||||
struct usbh_hub *self; /* if this hubport is a hub */
|
||||
struct usbh_bus *bus;
|
||||
#ifdef CONFIG_USBHOST_XHCI
|
||||
uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */
|
||||
#endif
|
||||
struct usb_endpoint_descriptor ep0;
|
||||
struct usbh_urb ep0_urb;
|
||||
usb_osal_mutex_t mutex;
|
||||
};
|
||||
|
||||
struct usbh_hub {
|
||||
usb_slist_t list;
|
||||
bool connected;
|
||||
bool is_roothub;
|
||||
uint8_t index;
|
||||
uint8_t hub_addr;
|
||||
struct usb_hub_descriptor hub_desc;
|
||||
uint8_t speed;
|
||||
uint8_t nports;
|
||||
uint8_t powerdelay;
|
||||
uint8_t tt_think;
|
||||
bool ismtt;
|
||||
struct usb_hub_descriptor hub_desc; /* USB 2.0 only */
|
||||
struct usb_hub_ss_descriptor hub_ss_desc; /* USB 3.0 only */
|
||||
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
|
||||
struct usbh_hubport *parent;
|
||||
struct usbh_bus *bus;
|
||||
struct usb_endpoint_descriptor *intin;
|
||||
struct usbh_urb intin_urb;
|
||||
uint8_t *int_buffer;
|
||||
struct usb_osal_timer *int_timer;
|
||||
};
|
||||
|
||||
struct usbh_devaddr_map {
|
||||
@@ -143,9 +155,9 @@ struct usbh_devaddr_map {
|
||||
};
|
||||
|
||||
struct usbh_hcd {
|
||||
uint32_t reg_base;
|
||||
uintptr_t reg_base;
|
||||
uint8_t hcd_id;
|
||||
uint8_t roothub_intbuf[1];
|
||||
uint8_t roothub_intbuf[2]; /* at most 15 roothub ports */
|
||||
struct usbh_hub roothub;
|
||||
};
|
||||
|
||||
@@ -156,7 +168,6 @@ struct usbh_bus {
|
||||
struct usbh_devaddr_map devgen;
|
||||
usb_osal_thread_t hub_thread;
|
||||
usb_osal_mq_t hub_mq;
|
||||
usb_slist_t hub_list;
|
||||
};
|
||||
|
||||
static inline void usbh_control_urb_fill(struct usbh_urb *urb,
|
||||
@@ -214,6 +225,7 @@ static inline void usbh_int_urb_fill(struct usbh_urb *urb,
|
||||
urb->timeout = timeout;
|
||||
urb->complete = complete;
|
||||
urb->arg = arg;
|
||||
urb->interval = USBH_GET_URB_INTERVAL(ep->bInterval, hport->speed);
|
||||
}
|
||||
|
||||
extern struct usbh_bus g_usbhost_bus[];
|
||||
@@ -235,11 +247,11 @@ int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *s
|
||||
|
||||
/**
|
||||
* @brief Retrieves a USB string descriptor from a specific hub port.
|
||||
*
|
||||
*
|
||||
* This function is responsible for retrieving the USB string descriptor
|
||||
* with the specified index from the USB device connected to the given hub port.
|
||||
* The retrieved descriptor is stored in the output buffer provided.
|
||||
*
|
||||
*
|
||||
* @param hport Pointer to the USB hub port structure.
|
||||
* @param index Index of the string descriptor to retrieve.
|
||||
* @param output Pointer to the buffer where the retrieved descriptor will be stored.
|
||||
@@ -249,11 +261,11 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
|
||||
|
||||
/**
|
||||
* @brief Sets the alternate setting for a USB interface on a specific hub port.
|
||||
*
|
||||
*
|
||||
* This function is responsible for setting the alternate setting of the
|
||||
* specified USB interface on the USB device connected to the given hub port.
|
||||
* The interface and alternate setting are identified by the respective parameters.
|
||||
*
|
||||
*
|
||||
* @param hport Pointer to the USB hub port structure.
|
||||
* @param intf Interface number to set the alternate setting for.
|
||||
* @param altsetting Alternate setting value to set for the interface.
|
||||
@@ -261,9 +273,10 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
|
||||
*/
|
||||
int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
|
||||
|
||||
int usbh_initialize(uint8_t busid, uint32_t reg_base);
|
||||
int usbh_initialize(uint8_t busid, uintptr_t reg_base);
|
||||
int usbh_deinitialize(uint8_t busid);
|
||||
void *usbh_find_class_instance(const char *devname);
|
||||
struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port);
|
||||
|
||||
int lsusb(int argc, char **argv);
|
||||
|
||||
|
||||
137
core/usbotg_core.c
Normal file
137
core/usbotg_core.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbotg_core.h"
|
||||
|
||||
struct usbotg_core_priv {
|
||||
uint8_t busid;
|
||||
uint32_t reg_base;
|
||||
usb_osal_sem_t change_sem;
|
||||
usb_osal_thread_t change_thread;
|
||||
bool usbh_initialized;
|
||||
bool usbd_initialized;
|
||||
int (*usbh_initialize)(uint8_t busid, uint32_t reg_base);
|
||||
int (*usbd_initialize)(uint8_t busid, uint32_t reg_base);
|
||||
} g_usbotg_core[CONFIG_USBHOST_MAX_BUS];
|
||||
|
||||
static void usbotg_host_initialize(uint8_t busid)
|
||||
{
|
||||
if (g_usbotg_core[busid].usbd_initialized) {
|
||||
g_usbotg_core[busid].usbd_initialized = false;
|
||||
usbd_deinitialize(busid);
|
||||
}
|
||||
if (g_usbotg_core[busid].usbh_initialize && !g_usbotg_core[busid].usbh_initialized) {
|
||||
g_usbotg_core[busid].usbh_initialized = true;
|
||||
g_usbotg_core[busid].usbh_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbotg_device_initialize(uint8_t busid)
|
||||
{
|
||||
if (g_usbotg_core[busid].usbh_initialized) {
|
||||
g_usbotg_core[busid].usbh_initialized = false;
|
||||
usbh_deinitialize(busid);
|
||||
}
|
||||
if (g_usbotg_core[busid].usbd_initialize && !g_usbotg_core[busid].usbd_initialize) {
|
||||
g_usbotg_core[busid].usbd_initialized = true;
|
||||
g_usbotg_core[busid].usbd_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbotg_rolechange_thread(void *argument)
|
||||
{
|
||||
uint8_t busid = (uint8_t)(uintptr_t)argument;
|
||||
|
||||
usb_otg_init(busid);
|
||||
|
||||
while (1) {
|
||||
if (usb_osal_sem_take(g_usbotg_core[busid].change_sem, USB_OSAL_WAITING_FOREVER) == 0) {
|
||||
if (usbotg_get_current_mode(busid) == USBOTG_MODE_HOST) {
|
||||
usbotg_host_initialize(busid);
|
||||
} else if (usbotg_get_current_mode(busid) == USBOTG_MODE_DEVICE) {
|
||||
usbotg_device_initialize(busid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usbotg_initialize(uint8_t otg_mode, uint8_t busid, uint32_t reg_base,
|
||||
int (*usbh_initialize)(uint8_t busid, uint32_t reg_base),
|
||||
int (*usbd_initialize)(uint8_t busid, uint32_t reg_base))
|
||||
{
|
||||
char thread_name[32] = { 0 };
|
||||
|
||||
if (busid >= CONFIG_USBHOST_MAX_BUS) {
|
||||
USB_LOG_ERR("bus overflow\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
g_usbotg_core[busid].busid = busid;
|
||||
g_usbotg_core[busid].reg_base = reg_base;
|
||||
g_usbotg_core[busid].usbh_initialize = usbh_initialize;
|
||||
g_usbotg_core[busid].usbd_initialize = usbd_initialize;
|
||||
|
||||
if (otg_mode == USBOTG_MODE_OTG) {
|
||||
g_usbotg_core[busid].change_sem = usb_osal_sem_create(0);
|
||||
if (g_usbotg_core[busid].change_sem == NULL) {
|
||||
USB_LOG_ERR("Failed to create change_sem\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(thread_name, 32, "usbotg%u", busid);
|
||||
g_usbotg_core[busid].change_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbotg_rolechange_thread, (void *)(uintptr_t)busid);
|
||||
if (g_usbotg_core[busid].change_thread == NULL) {
|
||||
USB_LOG_ERR("Failed to create usbotg thread\r\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (otg_mode == USBOTG_MODE_HOST) {
|
||||
usbotg_host_initialize(busid);
|
||||
} else if (otg_mode == USBOTG_MODE_DEVICE) {
|
||||
usbotg_device_initialize(busid);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbotg_deinitialize(uint8_t busid, uint32_t reg_base)
|
||||
{
|
||||
if (g_usbotg_core[busid].usbd_initialized) {
|
||||
g_usbotg_core[busid].usbd_initialized = false;
|
||||
usbd_deinitialize(busid);
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].usbh_initialized) {
|
||||
g_usbotg_core[busid].usbh_initialized = false;
|
||||
usbh_deinitialize(busid);
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].change_sem) {
|
||||
usb_otg_deinit(busid);
|
||||
usb_osal_sem_delete(g_usbotg_core[busid].change_sem);
|
||||
}
|
||||
|
||||
if (g_usbotg_core[busid].change_thread) {
|
||||
usb_osal_thread_delete(g_usbotg_core[busid].change_thread);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usbotg_trigger_role_change(uint8_t busid)
|
||||
{
|
||||
usb_osal_sem_give(g_usbotg_core[busid].change_sem);
|
||||
}
|
||||
|
||||
void USBOTG_IRQHandler(uint8_t busid)
|
||||
{
|
||||
if (usbotg_get_current_mode(busid) == USBOTG_MODE_HOST) {
|
||||
USBH_IRQHandler(busid);
|
||||
} else if (usbotg_get_current_mode(busid) == USBOTG_MODE_DEVICE) {
|
||||
USBD_IRQHandler(busid);
|
||||
}
|
||||
}
|
||||
34
core/usbotg_core.h
Normal file
34
core/usbotg_core.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBOTG_CORE_H
|
||||
#define USBOTG_CORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USBOTG_MODE_UNKNOWN 0
|
||||
#define USBOTG_MODE_OTG 1
|
||||
#define USBOTG_MODE_HOST 2
|
||||
#define USBOTG_MODE_DEVICE 3
|
||||
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usb_otg.h"
|
||||
|
||||
int usbotg_initialize(uint8_t otg_mode, uint8_t busid, uint32_t reg_base,
|
||||
int (*usbh_initialize)(uint8_t busid, uint32_t reg_base),
|
||||
int (*usbd_initialize)(uint8_t busid, uint32_t reg_base));
|
||||
int usbotg_deinitialize(uint8_t busid, uint32_t reg_base);
|
||||
|
||||
/* called by user */
|
||||
void usbotg_trigger_role_change(uint8_t busid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBOTG_CORE_H */
|
||||
BIN
demo/CherryUSB.h264
Normal file
BIN
demo/CherryUSB.h264
Normal file
Binary file not shown.
BIN
demo/CherryUSB.jpg
Normal file
BIN
demo/CherryUSB.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
1
demo/CherryUSB_64x48.YUYV
Normal file
1
demo/CherryUSB_64x48.YUYV
Normal file
File diff suppressed because one or more lines are too long
BIN
demo/adb/cherryadb.png
Normal file
BIN
demo/adb/cherryadb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user