usbh_lwip.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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 larger than 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. usbh_lwip_eth_output_common(p, usbh_cdc_ecm_get_eth_txbuf());
  102. ret = usbh_cdc_ecm_eth_output(p->tot_len);
  103. if (ret < 0) {
  104. return -RT_ERROR;
  105. } else {
  106. return RT_EOK;
  107. }
  108. }
  109. void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen)
  110. {
  111. usbh_lwip_eth_input_common(g_cdc_ecm_dev.netif, buf, buflen);
  112. }
  113. void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
  114. {
  115. memset(&g_cdc_ecm_dev, 0, sizeof(struct eth_device));
  116. g_cdc_ecm_dev.parent.control = rt_usbh_cdc_ecm_control;
  117. g_cdc_ecm_dev.eth_rx = NULL;
  118. g_cdc_ecm_dev.eth_tx = rt_usbh_cdc_ecm_eth_tx;
  119. g_cdc_ecm_dev.parent.user_data = cdc_ecm_class;
  120. eth_device_init(&g_cdc_ecm_dev, "u0");
  121. eth_device_linkchange(&g_cdc_ecm_dev, RT_TRUE);
  122. usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL);
  123. }
  124. void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
  125. {
  126. eth_device_deinit(&g_cdc_ecm_dev);
  127. }
  128. #endif
  129. #ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
  130. #include "usbh_rndis.h"
  131. static struct eth_device g_rndis_dev;
  132. static rt_timer_t keep_timer = RT_NULL;
  133. static void rndis_dev_keepalive_timeout(void *parameter)
  134. {
  135. struct usbh_rndis *rndis_class = (struct usbh_rndis *)parameter;
  136. usbh_rndis_keepalive(rndis_class);
  137. }
  138. static void timer_init(struct usbh_rndis *rndis_class)
  139. {
  140. keep_timer = rt_timer_create("keep",
  141. rndis_dev_keepalive_timeout,
  142. rndis_class,
  143. 5000,
  144. RT_TIMER_FLAG_PERIODIC |
  145. RT_TIMER_FLAG_SOFT_TIMER);
  146. rt_timer_start(keep_timer);
  147. }
  148. static rt_err_t rt_usbh_rndis_control(rt_device_t dev, int cmd, void *args)
  149. {
  150. struct usbh_rndis *rndis_class = (struct usbh_rndis *)dev->user_data;
  151. switch (cmd) {
  152. case NIOCTL_GADDR:
  153. /* get mac address */
  154. if (args)
  155. rt_memcpy(args, rndis_class->mac, 6);
  156. else
  157. return -RT_ERROR;
  158. break;
  159. default:
  160. break;
  161. }
  162. return RT_EOK;
  163. }
  164. static rt_err_t rt_usbh_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
  165. {
  166. int ret;
  167. usbh_lwip_eth_output_common(p, usbh_rndis_get_eth_txbuf());
  168. ret = usbh_rndis_eth_output(p->tot_len);
  169. if (ret < 0) {
  170. return -RT_ERROR;
  171. } else {
  172. return RT_EOK;
  173. }
  174. }
  175. void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
  176. {
  177. usbh_lwip_eth_input_common(g_rndis_dev.netif, buf, buflen);
  178. }
  179. void usbh_rndis_run(struct usbh_rndis *rndis_class)
  180. {
  181. memset(&g_rndis_dev, 0, sizeof(struct eth_device));
  182. g_rndis_dev.parent.control = rt_usbh_rndis_control;
  183. g_rndis_dev.eth_rx = NULL;
  184. g_rndis_dev.eth_tx = rt_usbh_rndis_eth_tx;
  185. g_rndis_dev.parent.user_data = rndis_class;
  186. eth_device_init(&g_rndis_dev, "u2");
  187. eth_device_linkchange(&g_rndis_dev, RT_TRUE);
  188. usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
  189. //timer_init(rndis_class);
  190. }
  191. void usbh_rndis_stop(struct usbh_rndis *rndis_class)
  192. {
  193. eth_device_deinit(&g_rndis_dev);
  194. // rt_timer_stop(keep_timer);
  195. // rt_timer_delete(keep_timer);
  196. }
  197. #endif
  198. #ifdef CONFIG_USBHOST_PLATFORM_CDC_NCM
  199. #include "usbh_cdc_ncm.h"
  200. static struct eth_device g_cdc_ncm_dev;
  201. static rt_err_t rt_usbh_cdc_ncm_control(rt_device_t dev, int cmd, void *args)
  202. {
  203. struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)dev->user_data;
  204. switch (cmd) {
  205. case NIOCTL_GADDR:
  206. /* get mac address */
  207. if (args)
  208. rt_memcpy(args, cdc_ncm_class->mac, 6);
  209. else
  210. return -RT_ERROR;
  211. break;
  212. default:
  213. break;
  214. }
  215. return RT_EOK;
  216. }
  217. static rt_err_t rt_usbh_cdc_ncm_eth_tx(rt_device_t dev, struct pbuf *p)
  218. {
  219. int ret;
  220. usbh_lwip_eth_output_common(p, usbh_cdc_ncm_get_eth_txbuf());
  221. ret = usbh_cdc_ncm_eth_output(p->tot_len);
  222. if (ret < 0) {
  223. return -RT_ERROR;
  224. } else {
  225. return RT_EOK;
  226. }
  227. }
  228. void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen)
  229. {
  230. usbh_lwip_eth_input_common(g_cdc_ncm_dev.netif, buf, buflen);
  231. }
  232. void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
  233. {
  234. memset(&g_cdc_ncm_dev, 0, sizeof(struct eth_device));
  235. g_cdc_ncm_dev.parent.control = rt_usbh_cdc_ncm_control;
  236. g_cdc_ncm_dev.eth_rx = NULL;
  237. g_cdc_ncm_dev.eth_tx = rt_usbh_cdc_ncm_eth_tx;
  238. g_cdc_ncm_dev.parent.user_data = cdc_ncm_class;
  239. eth_device_init(&g_cdc_ncm_dev, "u1");
  240. eth_device_linkchange(&g_cdc_ncm_dev, RT_TRUE);
  241. usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, NULL);
  242. }
  243. void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
  244. {
  245. eth_device_deinit(&g_cdc_ncm_dev);
  246. }
  247. #endif
  248. #ifdef CONFIG_USBHOST_PLATFORM_ASIX
  249. #include "usbh_asix.h"
  250. static struct eth_device g_asix_dev;
  251. static rt_err_t rt_usbh_asix_control(rt_device_t dev, int cmd, void *args)
  252. {
  253. struct usbh_asix *asix_class = (struct usbh_asix *)dev->user_data;
  254. switch (cmd) {
  255. case NIOCTL_GADDR:
  256. /* get mac address */
  257. if (args)
  258. rt_memcpy(args, asix_class->mac, 6);
  259. else
  260. return -RT_ERROR;
  261. break;
  262. default:
  263. break;
  264. }
  265. return RT_EOK;
  266. }
  267. static rt_err_t rt_usbh_asix_eth_tx(rt_device_t dev, struct pbuf *p)
  268. {
  269. int ret;
  270. usbh_lwip_eth_output_common(p, usbh_asix_get_eth_txbuf());
  271. ret = usbh_asix_eth_output(p->tot_len);
  272. if (ret < 0) {
  273. return -RT_ERROR;
  274. } else {
  275. return RT_EOK;
  276. }
  277. }
  278. void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen)
  279. {
  280. usbh_lwip_eth_input_common(g_asix_dev.netif, buf, buflen);
  281. }
  282. void usbh_asix_run(struct usbh_asix *asix_class)
  283. {
  284. memset(&g_asix_dev, 0, sizeof(struct eth_device));
  285. g_asix_dev.parent.control = rt_usbh_asix_control;
  286. g_asix_dev.eth_rx = NULL;
  287. g_asix_dev.eth_tx = rt_usbh_asix_eth_tx;
  288. g_asix_dev.parent.user_data = asix_class;
  289. eth_device_init(&g_asix_dev, "u3");
  290. eth_device_linkchange(&g_asix_dev, RT_TRUE);
  291. usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, NULL);
  292. }
  293. void usbh_asix_stop(struct usbh_asix *asix_class)
  294. {
  295. eth_device_deinit(&g_asix_dev);
  296. }
  297. #endif
  298. #ifdef CONFIG_USBHOST_PLATFORM_RTL8152
  299. #include "usbh_rtl8152.h"
  300. static struct eth_device g_rtl8152_dev;
  301. static rt_err_t rt_usbh_rtl8152_control(rt_device_t dev, int cmd, void *args)
  302. {
  303. struct usbh_rtl8152 *rtl8152_class = (struct usbh_rtl8152 *)dev->user_data;
  304. switch (cmd) {
  305. case NIOCTL_GADDR:
  306. /* get mac address */
  307. if (args)
  308. rt_memcpy(args, rtl8152_class->mac, 6);
  309. else
  310. return -RT_ERROR;
  311. break;
  312. default:
  313. break;
  314. }
  315. return RT_EOK;
  316. }
  317. static rt_err_t rt_usbh_rtl8152_eth_tx(rt_device_t dev, struct pbuf *p)
  318. {
  319. int ret;
  320. usbh_lwip_eth_output_common(p, usbh_rtl8152_get_eth_txbuf());
  321. ret = usbh_rtl8152_eth_output(p->tot_len);
  322. if (ret < 0) {
  323. return -RT_ERROR;
  324. } else {
  325. return RT_EOK;
  326. }
  327. }
  328. void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen)
  329. {
  330. usbh_lwip_eth_input_common(g_rtl8152_dev.netif, buf, buflen);
  331. }
  332. void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
  333. {
  334. memset(&g_rtl8152_dev, 0, sizeof(struct eth_device));
  335. g_rtl8152_dev.parent.control = rt_usbh_rtl8152_control;
  336. g_rtl8152_dev.eth_rx = NULL;
  337. g_rtl8152_dev.eth_tx = rt_usbh_rtl8152_eth_tx;
  338. g_rtl8152_dev.parent.user_data = rtl8152_class;
  339. eth_device_init(&g_rtl8152_dev, "u4");
  340. eth_device_linkchange(&g_rtl8152_dev, RT_TRUE);
  341. usb_osal_thread_create("usbh_rtl8152_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rtl8152_rx_thread, NULL);
  342. }
  343. void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
  344. {
  345. eth_device_deinit(&g_rtl8152_dev);
  346. }
  347. #endif