usbd_rndis.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. * Copyright (c) 2022, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbd_core.h"
  7. #include "usbd_rndis.h"
  8. #include "rndis_protocol.h"
  9. #define RNDIS_OUT_EP_IDX 0
  10. #define RNDIS_IN_EP_IDX 1
  11. #define RNDIS_INT_EP_IDX 2
  12. /* Describe EndPoints configuration */
  13. static struct usbd_endpoint rndis_ep_data[3];
  14. #define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
  15. #define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
  16. /* Device data structure */
  17. struct usbd_rndis_priv {
  18. uint32_t drv_version;
  19. uint32_t link_status;
  20. uint32_t net_filter;
  21. usb_eth_stat_t eth_state;
  22. rndis_state_t init_state;
  23. uint8_t mac[6];
  24. } g_usbd_rndis;
  25. #if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
  26. #undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
  27. #define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
  28. #endif
  29. #if CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE < 1580
  30. #undef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
  31. #define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
  32. #endif
  33. static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
  34. static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
  35. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
  36. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
  37. volatile uint8_t *g_rndis_rx_data_buffer;
  38. volatile uint32_t g_rndis_rx_data_length;
  39. volatile uint32_t g_rndis_tx_data_length;
  40. /* RNDIS options list */
  41. const uint32_t oid_supported_list[] = {
  42. /* General OIDs */
  43. OID_GEN_SUPPORTED_LIST,
  44. OID_GEN_HARDWARE_STATUS,
  45. OID_GEN_MEDIA_SUPPORTED,
  46. OID_GEN_MEDIA_IN_USE,
  47. OID_GEN_MAXIMUM_FRAME_SIZE,
  48. OID_GEN_LINK_SPEED,
  49. OID_GEN_TRANSMIT_BLOCK_SIZE,
  50. OID_GEN_RECEIVE_BLOCK_SIZE,
  51. OID_GEN_VENDOR_ID,
  52. OID_GEN_VENDOR_DESCRIPTION,
  53. OID_GEN_VENDOR_DRIVER_VERSION,
  54. OID_GEN_CURRENT_PACKET_FILTER,
  55. OID_GEN_MAXIMUM_TOTAL_SIZE,
  56. OID_GEN_MEDIA_CONNECT_STATUS,
  57. OID_GEN_PHYSICAL_MEDIUM,
  58. /* General Statistic OIDs */
  59. OID_GEN_XMIT_OK,
  60. OID_GEN_RCV_OK,
  61. OID_GEN_XMIT_ERROR,
  62. OID_GEN_RCV_ERROR,
  63. OID_GEN_RCV_NO_BUFFER,
  64. /* Please configure us */
  65. OID_GEN_RNDIS_CONFIG_PARAMETER,
  66. /* 802.3 OIDs */
  67. OID_802_3_PERMANENT_ADDRESS,
  68. OID_802_3_CURRENT_ADDRESS,
  69. OID_802_3_MULTICAST_LIST,
  70. OID_802_3_MAXIMUM_LIST_SIZE,
  71. /* 802.3 Statistic OIDs */
  72. OID_802_3_RCV_ERROR_ALIGNMENT,
  73. OID_802_3_XMIT_ONE_COLLISION,
  74. OID_802_3_XMIT_MORE_COLLISIONS,
  75. OID_802_3_MAC_OPTIONS,
  76. };
  77. static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
  78. static void rndis_notify_rsp(void)
  79. {
  80. memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
  81. NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
  82. usbd_ep_start_write(0, rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
  83. }
  84. static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  85. {
  86. switch (setup->bRequest) {
  87. case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
  88. rndis_encapsulated_cmd_handler(*data, setup->wLength);
  89. break;
  90. case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
  91. *data = rndis_encapsulated_resp_buffer;
  92. *len = ((rndis_generic_msg_t *)rndis_encapsulated_resp_buffer)->MessageLength;
  93. break;
  94. default:
  95. return -1;
  96. }
  97. return 0;
  98. }
  99. static int rndis_init_cmd_handler(uint8_t *data, uint32_t len);
  100. static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len);
  101. static int rndis_query_cmd_handler(uint8_t *data, uint32_t len);
  102. static int rndis_set_cmd_handler(uint8_t *data, uint32_t len);
  103. static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len);
  104. static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len);
  105. static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len)
  106. {
  107. switch (((rndis_generic_msg_t *)data)->MessageType) {
  108. case REMOTE_NDIS_INITIALIZE_MSG:
  109. return rndis_init_cmd_handler(data, len);
  110. case REMOTE_NDIS_HALT_MSG:
  111. return rndis_halt_cmd_handler(data, len);
  112. case REMOTE_NDIS_QUERY_MSG:
  113. return rndis_query_cmd_handler(data, len);
  114. case REMOTE_NDIS_SET_MSG:
  115. return rndis_set_cmd_handler(data, len);
  116. case REMOTE_NDIS_RESET_MSG:
  117. return rndis_reset_cmd_handler(data, len);
  118. case REMOTE_NDIS_KEEPALIVE_MSG:
  119. return rndis_keepalive_cmd_handler(data, len);
  120. default:
  121. break;
  122. }
  123. return -1;
  124. }
  125. static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
  126. {
  127. rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
  128. rndis_initialize_cmplt_t *resp;
  129. resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
  130. resp->RequestId = cmd->RequestId;
  131. resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
  132. resp->MessageLength = sizeof(rndis_initialize_cmplt_t);
  133. resp->MajorVersion = RNDIS_MAJOR_VERSION;
  134. resp->MinorVersion = RNDIS_MINOR_VERSION;
  135. resp->Status = RNDIS_STATUS_SUCCESS;
  136. resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
  137. resp->Medium = RNDIS_MEDIUM_802_3;
  138. resp->MaxPacketsPerTransfer = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE / 1580;
  139. resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE;
  140. resp->PacketAlignmentFactor = 0;
  141. resp->AfListOffset = 0;
  142. resp->AfListSize = 0;
  143. g_usbd_rndis.init_state = rndis_initialized;
  144. rndis_notify_rsp();
  145. return 0;
  146. }
  147. static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
  148. {
  149. rndis_halt_msg_t *resp;
  150. resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
  151. resp->MessageLength = 0;
  152. g_usbd_rndis.init_state = rndis_uninitialized;
  153. return 0;
  154. }
  155. static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
  156. {
  157. rndis_query_msg_t *cmd = (rndis_query_msg_t *)data;
  158. rndis_query_cmplt_t *resp;
  159. uint8_t *infomation_buffer;
  160. uint32_t infomation_len = 0;
  161. resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
  162. resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
  163. resp->RequestId = cmd->RequestId;
  164. resp->InformationBufferOffset = sizeof(rndis_query_cmplt_t) - sizeof(rndis_generic_msg_t);
  165. resp->Status = RNDIS_STATUS_SUCCESS;
  166. infomation_buffer = (uint8_t *)resp + sizeof(rndis_query_cmplt_t);
  167. switch (cmd->Oid) {
  168. case OID_GEN_SUPPORTED_LIST:
  169. RNDIS_INQUIRY_PUT(oid_supported_list, sizeof(oid_supported_list));
  170. infomation_len = sizeof(oid_supported_list);
  171. break;
  172. case OID_GEN_HARDWARE_STATUS:
  173. RNDIS_INQUIRY_PUT_LE32(NDIS_HW_STS_READY);
  174. infomation_len = 4;
  175. break;
  176. case OID_GEN_MEDIA_SUPPORTED:
  177. case OID_GEN_MEDIA_IN_USE:
  178. RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
  179. infomation_len = 4;
  180. break;
  181. case OID_GEN_MAXIMUM_FRAME_SIZE:
  182. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  183. case OID_GEN_RECEIVE_BLOCK_SIZE:
  184. RNDIS_INQUIRY_PUT_LE32(0x05DC); /* mtu 1500 */
  185. infomation_len = 4;
  186. break;
  187. case OID_GEN_VENDOR_ID:
  188. RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_VENDOR_ID);
  189. infomation_len = 4;
  190. break;
  191. case OID_GEN_VENDOR_DRIVER_VERSION:
  192. RNDIS_INQUIRY_PUT_LE32(0x0001);
  193. infomation_len = 4;
  194. break;
  195. case OID_GEN_VENDOR_DESCRIPTION:
  196. RNDIS_INQUIRY_PUT(CONFIG_USBDEV_RNDIS_VENDOR_DESC, strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC));
  197. infomation_len = (strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC) + 1);
  198. break;
  199. case OID_802_3_CURRENT_ADDRESS:
  200. case OID_802_3_PERMANENT_ADDRESS:
  201. RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
  202. infomation_len = 6;
  203. break;
  204. case OID_GEN_PHYSICAL_MEDIUM:
  205. RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
  206. infomation_len = 4;
  207. break;
  208. case OID_GEN_LINK_SPEED:
  209. if (usbd_get_ep_mps(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr) > 64) {
  210. RNDIS_INQUIRY_PUT_LE32(480000000 / 100);
  211. } else {
  212. RNDIS_INQUIRY_PUT_LE32(12000000 / 100);
  213. }
  214. infomation_len = 4;
  215. break;
  216. case OID_GEN_CURRENT_PACKET_FILTER:
  217. RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
  218. infomation_len = 4;
  219. break;
  220. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  221. RNDIS_INQUIRY_PUT_LE32(0x0616); /* 1514 + 44 */
  222. infomation_len = 4;
  223. break;
  224. case OID_GEN_MEDIA_CONNECT_STATUS:
  225. RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
  226. infomation_len = 4;
  227. break;
  228. case OID_GEN_RNDIS_CONFIG_PARAMETER:
  229. RNDIS_INQUIRY_PUT_LE32(0);
  230. infomation_len = 4;
  231. break;
  232. case OID_802_3_MAXIMUM_LIST_SIZE:
  233. RNDIS_INQUIRY_PUT_LE32(1); /* one address */
  234. infomation_len = 4;
  235. break;
  236. case OID_802_3_MULTICAST_LIST:
  237. //RNDIS_INQUIRY_PUT_LE32(0xE0000000); /* 224.0.0.0 */
  238. resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
  239. RNDIS_INQUIRY_PUT_LE32(0);
  240. infomation_len = 4;
  241. break;
  242. case OID_802_3_MAC_OPTIONS:
  243. // infomation_len = 0;
  244. resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
  245. RNDIS_INQUIRY_PUT_LE32(0);
  246. infomation_len = 4;
  247. break;
  248. case OID_GEN_MAC_OPTIONS:
  249. RNDIS_INQUIRY_PUT_LE32(0);
  250. infomation_len = 4;
  251. break;
  252. case OID_802_3_RCV_ERROR_ALIGNMENT:
  253. RNDIS_INQUIRY_PUT_LE32(0);
  254. infomation_len = 4;
  255. break;
  256. case OID_802_3_XMIT_ONE_COLLISION:
  257. RNDIS_INQUIRY_PUT_LE32(0);
  258. infomation_len = 4;
  259. break;
  260. case OID_802_3_XMIT_MORE_COLLISIONS:
  261. RNDIS_INQUIRY_PUT_LE32(0);
  262. infomation_len = 4;
  263. break;
  264. case OID_GEN_XMIT_OK:
  265. RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
  266. infomation_len = 4;
  267. break;
  268. case OID_GEN_RCV_OK:
  269. RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
  270. infomation_len = 4;
  271. break;
  272. case OID_GEN_RCV_ERROR:
  273. RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
  274. infomation_len = 4;
  275. break;
  276. case OID_GEN_XMIT_ERROR:
  277. RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
  278. infomation_len = 4;
  279. break;
  280. case OID_GEN_RCV_NO_BUFFER:
  281. RNDIS_INQUIRY_PUT_LE32(0);
  282. infomation_len = 4;
  283. break;
  284. default:
  285. resp->Status = RNDIS_STATUS_FAILURE;
  286. infomation_len = 0;
  287. USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
  288. break;
  289. }
  290. resp->MessageLength = sizeof(rndis_query_cmplt_t) + infomation_len;
  291. resp->InformationBufferLength = infomation_len;
  292. rndis_notify_rsp();
  293. return 0;
  294. }
  295. static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
  296. {
  297. rndis_set_msg_t *cmd = (rndis_set_msg_t *)data;
  298. rndis_set_cmplt_t *resp;
  299. rndis_config_parameter_t *param;
  300. resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
  301. resp->RequestId = cmd->RequestId;
  302. resp->MessageType = REMOTE_NDIS_SET_CMPLT;
  303. resp->MessageLength = sizeof(rndis_set_cmplt_t);
  304. resp->Status = RNDIS_STATUS_SUCCESS;
  305. switch (cmd->Oid) {
  306. case OID_GEN_RNDIS_CONFIG_PARAMETER:
  307. param = (rndis_config_parameter_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
  308. USB_LOG_WRN("RNDIS cfg param: NameOfs=%d, NameLen=%d, ValueOfs=%d, ValueLen=%d\r\n",
  309. param->ParameterNameOffset, param->ParameterNameLength,
  310. param->ParameterValueOffset, param->ParameterValueLength);
  311. break;
  312. case OID_GEN_CURRENT_PACKET_FILTER:
  313. if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
  314. USB_LOG_WRN("PACKET_FILTER!\r\n");
  315. resp->Status = RNDIS_STATUS_INVALID_DATA;
  316. } else {
  317. uint32_t *filter;
  318. /* Parameter starts at offset buf_offset of the req_id field */
  319. filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
  320. //g_usbd_rndis.net_filter = param->ParameterNameOffset;
  321. g_usbd_rndis.net_filter = *(uint32_t *)filter;
  322. if (g_usbd_rndis.net_filter) {
  323. g_usbd_rndis.init_state = rndis_data_initialized;
  324. } else {
  325. g_usbd_rndis.init_state = rndis_initialized;
  326. }
  327. }
  328. break;
  329. case OID_GEN_CURRENT_LOOKAHEAD:
  330. break;
  331. case OID_GEN_PROTOCOL_OPTIONS:
  332. break;
  333. case OID_802_3_MULTICAST_LIST:
  334. break;
  335. case OID_PNP_ADD_WAKE_UP_PATTERN:
  336. case OID_PNP_REMOVE_WAKE_UP_PATTERN:
  337. case OID_PNP_ENABLE_WAKE_UP:
  338. default:
  339. resp->Status = RNDIS_STATUS_FAILURE;
  340. USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
  341. break;
  342. }
  343. rndis_notify_rsp();
  344. return 0;
  345. }
  346. static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
  347. {
  348. // rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
  349. rndis_reset_cmplt_t *resp;
  350. resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
  351. resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
  352. resp->MessageLength = sizeof(rndis_reset_cmplt_t);
  353. resp->Status = RNDIS_STATUS_SUCCESS;
  354. resp->AddressingReset = 1;
  355. g_usbd_rndis.init_state = rndis_uninitialized;
  356. rndis_notify_rsp();
  357. return 0;
  358. }
  359. static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
  360. {
  361. rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
  362. rndis_keepalive_cmplt_t *resp;
  363. resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
  364. resp->RequestId = cmd->RequestId;
  365. resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
  366. resp->MessageLength = sizeof(rndis_keepalive_cmplt_t);
  367. resp->Status = RNDIS_STATUS_SUCCESS;
  368. rndis_notify_rsp();
  369. return 0;
  370. }
  371. static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
  372. {
  373. switch (event) {
  374. case USBD_EVENT_RESET:
  375. g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
  376. break;
  377. case USBD_EVENT_CONFIGURED:
  378. g_rndis_rx_data_length = 0;
  379. g_rndis_tx_data_length = 0;
  380. g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
  381. usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
  382. break;
  383. default:
  384. break;
  385. }
  386. }
  387. void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  388. {
  389. rndis_data_packet_t *hdr;
  390. hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
  391. g_rndis_rx_data_buffer = g_rndis_rx_buffer;
  392. if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
  393. usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
  394. return;
  395. }
  396. /* Point to the payload and update the message length */
  397. g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
  398. g_rndis_rx_data_length = hdr->DataLength;
  399. usbd_rndis_data_recv_done();
  400. }
  401. void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  402. {
  403. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  404. /* send zlp */
  405. usbd_ep_start_write(0, ep, NULL, 0);
  406. } else {
  407. g_rndis_tx_data_length = 0;
  408. }
  409. }
  410. void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  411. {
  412. //USB_LOG_DBG("len:%d\r\n", nbytes);
  413. }
  414. #ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
  415. #include <lwip/pbuf.h>
  416. struct pbuf *usbd_rndis_eth_rx(void)
  417. {
  418. struct pbuf *p;
  419. if (g_rndis_rx_data_length == 0) {
  420. return NULL;
  421. }
  422. p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
  423. if (p == NULL) {
  424. return NULL;
  425. }
  426. usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
  427. p->len = g_rndis_rx_data_length;
  428. USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
  429. g_rndis_rx_data_length = 0;
  430. usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
  431. return p;
  432. }
  433. int usbd_rndis_eth_tx(struct pbuf *p)
  434. {
  435. struct pbuf *q;
  436. uint8_t *buffer;
  437. rndis_data_packet_t *hdr;
  438. if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
  439. return -USB_ERR_NOTCONN;
  440. }
  441. if (g_rndis_tx_data_length > 0) {
  442. return -USB_ERR_BUSY;
  443. }
  444. if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
  445. p->tot_len = sizeof(g_rndis_tx_buffer);
  446. }
  447. buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
  448. for (q = p; q != NULL; q = q->next) {
  449. usb_memcpy(buffer, q->payload, q->len);
  450. buffer += q->len;
  451. }
  452. hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
  453. memset(hdr, 0, sizeof(rndis_data_packet_t));
  454. hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
  455. hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
  456. hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
  457. hdr->DataLength = p->tot_len;
  458. g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
  459. USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
  460. return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
  461. }
  462. #endif
  463. struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
  464. const uint8_t out_ep,
  465. const uint8_t in_ep,
  466. const uint8_t int_ep, uint8_t mac[6])
  467. {
  468. memcpy(g_usbd_rndis.mac, mac, 6);
  469. g_usbd_rndis.drv_version = 0x0001;
  470. g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
  471. rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
  472. rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
  473. rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr = in_ep;
  474. rndis_ep_data[RNDIS_IN_EP_IDX].ep_cb = rndis_bulk_in;
  475. rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
  476. rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
  477. usbd_add_endpoint(0, &rndis_ep_data[RNDIS_OUT_EP_IDX]);
  478. usbd_add_endpoint(0, &rndis_ep_data[RNDIS_IN_EP_IDX]);
  479. usbd_add_endpoint(0, &rndis_ep_data[RNDIS_INT_EP_IDX]);
  480. intf->class_interface_handler = rndis_class_interface_request_handler;
  481. intf->class_endpoint_handler = NULL;
  482. intf->vendor_handler = NULL;
  483. intf->notify_handler = rndis_notify_handler;
  484. return intf;
  485. }