usbd_rndis.c 21 KB

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