usbh_lwip.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "netif/etharp.h"
  7. #include "lwip/netif.h"
  8. #include "lwip/pbuf.h"
  9. #include "lwip/tcpip.h"
  10. #if LWIP_DHCP
  11. #include "lwip/dhcp.h"
  12. #include "lwip/prot/dhcp.h"
  13. #endif
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include <netif/ethernetif.h>
  17. #include "usbh_core.h"
  18. #include "lwip/opt.h"
  19. #ifndef RT_USING_LWIP212
  20. #error must enable RT_USING_LWIP212
  21. #endif
  22. #ifndef LWIP_NO_RX_THREAD
  23. #error must enable LWIP_NO_RX_THREAD, we do not use rtthread eth rx thread
  24. #endif
  25. #ifndef LWIP_NO_TX_THREAD
  26. #warning suggest you to enable LWIP_NO_TX_THREAD, we do not use rtthread eth tx thread
  27. #endif
  28. #if LWIP_TCPIP_CORE_LOCKING_INPUT != 1
  29. #warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread
  30. #endif
  31. #if LWIP_TCPIP_CORE_LOCKING != 1
  32. #error must set LWIP_TCPIP_CORE_LOCKING to 1
  33. #endif
  34. #if PBUF_POOL_BUFSIZE < 1600
  35. #error PBUF_POOL_BUFSIZE must be larger than 1600
  36. #endif
  37. #if RT_LWIP_TCPTHREAD_STACKSIZE < 2048
  38. #error RT_LWIP_TCPTHREAD_STACKSIZE must be >= 2048
  39. #endif
  40. // #define CONFIG_USBHOST_PLATFORM_CDC_ECM
  41. // #define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
  42. // #define CONFIG_USBHOST_PLATFORM_CDC_NCM
  43. // #define CONFIG_USBHOST_PLATFORM_ASIX
  44. // #define CONFIG_USBHOST_PLATFORM_RTL8152
  45. void usbh_lwip_eth_output_common(struct pbuf *p, uint8_t *buf)
  46. {
  47. struct pbuf *q;
  48. uint8_t *buffer;
  49. buffer = buf;
  50. for (q = p; q != NULL; q = q->next) {
  51. usb_memcpy(buffer, q->payload, q->len);
  52. buffer += q->len;
  53. }
  54. }
  55. void usbh_lwip_eth_input_common(struct netif *netif, uint8_t *buf, uint32_t len)
  56. {
  57. #if LWIP_TCPIP_CORE_LOCKING_INPUT
  58. pbuf_type type = PBUF_REF;
  59. #else
  60. pbuf_type type = PBUF_POOL;
  61. #endif
  62. err_t err;
  63. struct pbuf *p;
  64. p = pbuf_alloc(PBUF_RAW, len, type);
  65. if (p != NULL) {
  66. #if LWIP_TCPIP_CORE_LOCKING_INPUT
  67. p->payload = buf;
  68. #else
  69. usb_memcpy(p->payload, buf, len);
  70. #endif
  71. err = netif->input(p, netif);
  72. if (err != ERR_OK) {
  73. pbuf_free(p);
  74. }
  75. } else {
  76. USB_LOG_ERR("No memory to alloc pbuf\r\n");
  77. }
  78. }
  79. #ifdef CONFIG_USBHOST_PLATFORM_CDC_ECM
  80. #include "usbh_cdc_ecm.h"
  81. static struct eth_device g_cdc_ecm_dev;
  82. static rt_err_t rt_usbh_cdc_ecm_control(rt_device_t dev, int cmd, void *args)
  83. {
  84. struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)dev->user_data;
  85. switch (cmd) {
  86. case NIOCTL_GADDR:
  87. /* get mac address */
  88. if (args)
  89. rt_memcpy(args, cdc_ecm_class->mac, 6);
  90. else
  91. return -RT_ERROR;
  92. break;
  93. default:
  94. break;
  95. }
  96. return RT_EOK;
  97. }
  98. static rt_err_t rt_usbh_cdc_ecm_eth_tx(rt_device_t dev, struct pbuf *p)
  99. {
  100. int ret;
  101. (void)dev;
  102. usbh_lwip_eth_output_common(p, usbh_cdc_ecm_get_eth_txbuf());
  103. ret = usbh_cdc_ecm_eth_output(p->tot_len);
  104. if (ret < 0) {
  105. return -RT_ERROR;
  106. } else {
  107. return RT_EOK;
  108. }
  109. }
  110. void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen)
  111. {
  112. usbh_lwip_eth_input_common(g_cdc_ecm_dev.netif, buf, buflen);
  113. }
  114. void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
  115. {
  116. memset(&g_cdc_ecm_dev, 0, sizeof(struct eth_device));
  117. g_cdc_ecm_dev.parent.control = rt_usbh_cdc_ecm_control;
  118. g_cdc_ecm_dev.eth_rx = NULL;
  119. g_cdc_ecm_dev.eth_tx = rt_usbh_cdc_ecm_eth_tx;
  120. g_cdc_ecm_dev.parent.user_data = cdc_ecm_class;
  121. eth_device_init(&g_cdc_ecm_dev, "u0");
  122. eth_device_linkchange(&g_cdc_ecm_dev, RT_TRUE);
  123. usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL);
  124. }
  125. void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
  126. {
  127. (void)cdc_ecm_class;
  128. eth_device_deinit(&g_cdc_ecm_dev);
  129. }
  130. #endif
  131. #ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
  132. #include "usbh_rndis.h"
  133. static struct eth_device g_rndis_dev;
  134. static rt_timer_t keep_timer = RT_NULL;
  135. static void rndis_dev_keepalive_timeout(void *parameter)
  136. {
  137. struct usbh_rndis *rndis_class = (struct usbh_rndis *)parameter;
  138. usbh_rndis_keepalive(rndis_class);
  139. }
  140. static void timer_init(struct usbh_rndis *rndis_class)
  141. {
  142. keep_timer = rt_timer_create("keep",
  143. rndis_dev_keepalive_timeout,
  144. rndis_class,
  145. 5000,
  146. RT_TIMER_FLAG_PERIODIC |
  147. RT_TIMER_FLAG_SOFT_TIMER);
  148. rt_timer_start(keep_timer);
  149. }
  150. static rt_err_t rt_usbh_rndis_control(rt_device_t dev, int cmd, void *args)
  151. {
  152. struct usbh_rndis *rndis_class = (struct usbh_rndis *)dev->user_data;
  153. switch (cmd) {
  154. case NIOCTL_GADDR:
  155. /* get mac address */
  156. if (args)
  157. rt_memcpy(args, rndis_class->mac, 6);
  158. else
  159. return -RT_ERROR;
  160. break;
  161. default:
  162. break;
  163. }
  164. return RT_EOK;
  165. }
  166. static rt_err_t rt_usbh_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
  167. {
  168. int ret;
  169. (void)dev;
  170. usbh_lwip_eth_output_common(p, usbh_rndis_get_eth_txbuf());
  171. ret = usbh_rndis_eth_output(p->tot_len);
  172. if (ret < 0) {
  173. return -RT_ERROR;
  174. } else {
  175. return RT_EOK;
  176. }
  177. }
  178. void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
  179. {
  180. usbh_lwip_eth_input_common(g_rndis_dev.netif, buf, buflen);
  181. }
  182. void usbh_rndis_run(struct usbh_rndis *rndis_class)
  183. {
  184. memset(&g_rndis_dev, 0, sizeof(struct eth_device));
  185. g_rndis_dev.parent.control = rt_usbh_rndis_control;
  186. g_rndis_dev.eth_rx = NULL;
  187. g_rndis_dev.eth_tx = rt_usbh_rndis_eth_tx;
  188. g_rndis_dev.parent.user_data = rndis_class;
  189. eth_device_init(&g_rndis_dev, "u2");
  190. eth_device_linkchange(&g_rndis_dev, RT_TRUE);
  191. usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
  192. //timer_init(rndis_class);
  193. }
  194. void usbh_rndis_stop(struct usbh_rndis *rndis_class)
  195. {
  196. (void)rndis_class;
  197. eth_device_deinit(&g_rndis_dev);
  198. // rt_timer_stop(keep_timer);
  199. // rt_timer_delete(keep_timer);
  200. }
  201. #endif
  202. #ifdef CONFIG_USBHOST_PLATFORM_CDC_NCM
  203. #include "usbh_cdc_ncm.h"
  204. static struct eth_device g_cdc_ncm_dev;
  205. static rt_err_t rt_usbh_cdc_ncm_control(rt_device_t dev, int cmd, void *args)
  206. {
  207. struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)dev->user_data;
  208. switch (cmd) {
  209. case NIOCTL_GADDR:
  210. /* get mac address */
  211. if (args)
  212. rt_memcpy(args, cdc_ncm_class->mac, 6);
  213. else
  214. return -RT_ERROR;
  215. break;
  216. default:
  217. break;
  218. }
  219. return RT_EOK;
  220. }
  221. static rt_err_t rt_usbh_cdc_ncm_eth_tx(rt_device_t dev, struct pbuf *p)
  222. {
  223. int ret;
  224. (void)dev;
  225. usbh_lwip_eth_output_common(p, usbh_cdc_ncm_get_eth_txbuf());
  226. ret = usbh_cdc_ncm_eth_output(p->tot_len);
  227. if (ret < 0) {
  228. return -RT_ERROR;
  229. } else {
  230. return RT_EOK;
  231. }
  232. }
  233. void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen)
  234. {
  235. usbh_lwip_eth_input_common(g_cdc_ncm_dev.netif, buf, buflen);
  236. }
  237. void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
  238. {
  239. memset(&g_cdc_ncm_dev, 0, sizeof(struct eth_device));
  240. g_cdc_ncm_dev.parent.control = rt_usbh_cdc_ncm_control;
  241. g_cdc_ncm_dev.eth_rx = NULL;
  242. g_cdc_ncm_dev.eth_tx = rt_usbh_cdc_ncm_eth_tx;
  243. g_cdc_ncm_dev.parent.user_data = cdc_ncm_class;
  244. eth_device_init(&g_cdc_ncm_dev, "u1");
  245. eth_device_linkchange(&g_cdc_ncm_dev, RT_TRUE);
  246. usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, NULL);
  247. }
  248. void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
  249. {
  250. (void)cdc_ncm_class;
  251. eth_device_deinit(&g_cdc_ncm_dev);
  252. }
  253. #endif
  254. #ifdef CONFIG_USBHOST_PLATFORM_ASIX
  255. #include "usbh_asix.h"
  256. static struct eth_device g_asix_dev;
  257. static rt_err_t rt_usbh_asix_control(rt_device_t dev, int cmd, void *args)
  258. {
  259. struct usbh_asix *asix_class = (struct usbh_asix *)dev->user_data;
  260. switch (cmd) {
  261. case NIOCTL_GADDR:
  262. /* get mac address */
  263. if (args)
  264. rt_memcpy(args, asix_class->mac, 6);
  265. else
  266. return -RT_ERROR;
  267. break;
  268. default:
  269. break;
  270. }
  271. return RT_EOK;
  272. }
  273. static rt_err_t rt_usbh_asix_eth_tx(rt_device_t dev, struct pbuf *p)
  274. {
  275. int ret;
  276. (void)dev;
  277. usbh_lwip_eth_output_common(p, usbh_asix_get_eth_txbuf());
  278. ret = usbh_asix_eth_output(p->tot_len);
  279. if (ret < 0) {
  280. return -RT_ERROR;
  281. } else {
  282. return RT_EOK;
  283. }
  284. }
  285. void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen)
  286. {
  287. usbh_lwip_eth_input_common(g_asix_dev.netif, buf, buflen);
  288. }
  289. void usbh_asix_run(struct usbh_asix *asix_class)
  290. {
  291. memset(&g_asix_dev, 0, sizeof(struct eth_device));
  292. g_asix_dev.parent.control = rt_usbh_asix_control;
  293. g_asix_dev.eth_rx = NULL;
  294. g_asix_dev.eth_tx = rt_usbh_asix_eth_tx;
  295. g_asix_dev.parent.user_data = asix_class;
  296. eth_device_init(&g_asix_dev, "u3");
  297. eth_device_linkchange(&g_asix_dev, RT_TRUE);
  298. usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, NULL);
  299. }
  300. void usbh_asix_stop(struct usbh_asix *asix_class)
  301. {
  302. (void)asix_class;
  303. eth_device_deinit(&g_asix_dev);
  304. }
  305. #endif
  306. #ifdef CONFIG_USBHOST_PLATFORM_RTL8152
  307. #include "usbh_rtl8152.h"
  308. static struct eth_device g_rtl8152_dev;
  309. static rt_err_t rt_usbh_rtl8152_control(rt_device_t dev, int cmd, void *args)
  310. {
  311. struct usbh_rtl8152 *rtl8152_class = (struct usbh_rtl8152 *)dev->user_data;
  312. switch (cmd) {
  313. case NIOCTL_GADDR:
  314. /* get mac address */
  315. if (args)
  316. rt_memcpy(args, rtl8152_class->mac, 6);
  317. else
  318. return -RT_ERROR;
  319. break;
  320. default:
  321. break;
  322. }
  323. return RT_EOK;
  324. }
  325. static rt_err_t rt_usbh_rtl8152_eth_tx(rt_device_t dev, struct pbuf *p)
  326. {
  327. int ret;
  328. (void)dev;
  329. usbh_lwip_eth_output_common(p, usbh_rtl8152_get_eth_txbuf());
  330. ret = usbh_rtl8152_eth_output(p->tot_len);
  331. if (ret < 0) {
  332. return -RT_ERROR;
  333. } else {
  334. return RT_EOK;
  335. }
  336. }
  337. void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen)
  338. {
  339. usbh_lwip_eth_input_common(g_rtl8152_dev.netif, buf, buflen);
  340. }
  341. void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
  342. {
  343. memset(&g_rtl8152_dev, 0, sizeof(struct eth_device));
  344. g_rtl8152_dev.parent.control = rt_usbh_rtl8152_control;
  345. g_rtl8152_dev.eth_rx = NULL;
  346. g_rtl8152_dev.eth_tx = rt_usbh_rtl8152_eth_tx;
  347. g_rtl8152_dev.parent.user_data = rtl8152_class;
  348. eth_device_init(&g_rtl8152_dev, "u4");
  349. eth_device_linkchange(&g_rtl8152_dev, RT_TRUE);
  350. usb_osal_thread_create("usbh_rtl8152_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rtl8152_rx_thread, NULL);
  351. }
  352. void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
  353. {
  354. (void)rtl8152_class;
  355. eth_device_deinit(&g_rtl8152_dev);
  356. }
  357. #endif