1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define LOG_LEVEL CONFIG_USB_DEVICE_NETWORK_LOG_LEVEL
8 #include <logging/log.h>
9 LOG_MODULE_REGISTER(usb_rndis);
10
11 /* Enable verbose debug printing extra hexdumps */
12 #define VERBOSE_DEBUG 0
13
14 #include <init.h>
15
16 #include <net/ethernet.h>
17 #include <net_private.h>
18
19 #include <usb/usb_device.h>
20 #include <usb/class/usb_cdc.h>
21 #include <os_desc.h>
22
23 #include "netusb.h"
24 #include "function_rndis.h"
25
26 /* RNDIS handling */
27 #define CFG_RNDIS_TX_BUF_COUNT 5
28 #define CFG_RNDIS_TX_BUF_SIZE 512
29 NET_BUF_POOL_DEFINE(rndis_tx_pool, CFG_RNDIS_TX_BUF_COUNT,
30 CFG_RNDIS_TX_BUF_SIZE, 0, NULL);
31 static struct k_fifo rndis_tx_queue;
32
33 /* Serialize RNDIS command queue for later processing */
34 #define CFG_RNDIS_CMD_BUF_COUNT 2
35 #define CFG_RNDIS_CMD_BUF_SIZE CONFIG_USB_REQUEST_BUFFER_SIZE
36 NET_BUF_POOL_DEFINE(rndis_cmd_pool, CFG_RNDIS_CMD_BUF_COUNT,
37 CFG_RNDIS_CMD_BUF_SIZE, 0, NULL);
38 static struct k_fifo rndis_cmd_queue;
39
40 /*
41 * Stack for cmd thread
42 */
43 static K_KERNEL_STACK_DEFINE(cmd_stack, 2048);
44 static struct k_thread cmd_thread_data;
45
46 struct usb_rndis_config {
47 struct usb_association_descriptor iad;
48 struct usb_if_descriptor if0;
49 struct cdc_header_descriptor if0_header;
50 struct cdc_cm_descriptor if0_cm;
51 struct cdc_acm_descriptor if0_acm;
52 struct cdc_union_descriptor if0_union;
53 struct usb_ep_descriptor if0_int_ep;
54
55 struct usb_if_descriptor if1;
56 struct usb_ep_descriptor if1_in_ep;
57 struct usb_ep_descriptor if1_out_ep;
58 } __packed;
59
60 USBD_CLASS_DESCR_DEFINE(primary, 0) struct usb_rndis_config rndis_cfg = {
61 .iad = {
62 .bLength = sizeof(struct usb_association_descriptor),
63 .bDescriptorType = USB_DESC_INTERFACE_ASSOC,
64 .bFirstInterface = 0,
65 .bInterfaceCount = 0x02,
66 .bFunctionClass = USB_BCC_CDC_CONTROL,
67 .bFunctionSubClass = 6,
68 .bFunctionProtocol = 0,
69 .iFunction = 0,
70 },
71 /* Interface descriptor 0 */
72 /* CDC Communication interface */
73 .if0 = {
74 .bLength = sizeof(struct usb_if_descriptor),
75 .bDescriptorType = USB_DESC_INTERFACE,
76 .bInterfaceNumber = 0,
77 .bAlternateSetting = 0,
78 .bNumEndpoints = 1,
79 .bInterfaceClass = USB_BCC_CDC_CONTROL,
80 .bInterfaceSubClass = ACM_SUBCLASS,
81 .bInterfaceProtocol = ACM_VENDOR_PROTOCOL,
82 .iInterface = 0,
83 },
84 /* Header Functional Descriptor */
85 .if0_header = {
86 .bFunctionLength = sizeof(struct cdc_header_descriptor),
87 .bDescriptorType = USB_DESC_CS_INTERFACE,
88 .bDescriptorSubtype = HEADER_FUNC_DESC,
89 .bcdCDC = sys_cpu_to_le16(USB_SRN_1_1),
90 },
91 /* Call Management Functional Descriptor */
92 .if0_cm = {
93 .bFunctionLength = sizeof(struct cdc_cm_descriptor),
94 .bDescriptorType = USB_DESC_CS_INTERFACE,
95 .bDescriptorSubtype = CALL_MANAGEMENT_FUNC_DESC,
96 .bmCapabilities = 0x00,
97 .bDataInterface = 1,
98 },
99 /* ACM Functional Descriptor */
100 .if0_acm = {
101 .bFunctionLength = sizeof(struct cdc_acm_descriptor),
102 .bDescriptorType = USB_DESC_CS_INTERFACE,
103 .bDescriptorSubtype = ACM_FUNC_DESC,
104 /* Device supports the request combination of:
105 * Set_Line_Coding,
106 * Set_Control_Line_State,
107 * Get_Line_Coding
108 * and the notification Serial_State
109 */
110 .bmCapabilities = 0x00,
111 },
112 /* Union Functional Descriptor */
113 .if0_union = {
114 .bFunctionLength = sizeof(struct cdc_union_descriptor),
115 .bDescriptorType = USB_DESC_CS_INTERFACE,
116 .bDescriptorSubtype = UNION_FUNC_DESC,
117 .bControlInterface = 0,
118 .bSubordinateInterface0 = 1,
119 },
120 /* Notification EP Descriptor */
121 .if0_int_ep = {
122 .bLength = sizeof(struct usb_ep_descriptor),
123 .bDescriptorType = USB_DESC_ENDPOINT,
124 .bEndpointAddress = RNDIS_INT_EP_ADDR,
125 .bmAttributes = USB_DC_EP_INTERRUPT,
126 .wMaxPacketSize =
127 sys_cpu_to_le16(CONFIG_RNDIS_INTERRUPT_EP_MPS),
128 .bInterval = 0x09,
129 },
130
131 /* Interface descriptor 1 */
132 /* CDC Data Interface */
133 .if1 = {
134 .bLength = sizeof(struct usb_if_descriptor),
135 .bDescriptorType = USB_DESC_INTERFACE,
136 .bInterfaceNumber = 1,
137 .bAlternateSetting = 0,
138 .bNumEndpoints = 2,
139 .bInterfaceClass = USB_BCC_CDC_DATA,
140 .bInterfaceSubClass = 0,
141 .bInterfaceProtocol = 0,
142 .iInterface = 0,
143 },
144 /* Data Endpoint IN */
145 .if1_in_ep = {
146 .bLength = sizeof(struct usb_ep_descriptor),
147 .bDescriptorType = USB_DESC_ENDPOINT,
148 .bEndpointAddress = RNDIS_IN_EP_ADDR,
149 .bmAttributes = USB_DC_EP_BULK,
150 .wMaxPacketSize =
151 sys_cpu_to_le16(CONFIG_RNDIS_BULK_EP_MPS),
152 .bInterval = 0x00,
153 },
154 /* Data Endpoint OUT */
155 .if1_out_ep = {
156 .bLength = sizeof(struct usb_ep_descriptor),
157 .bDescriptorType = USB_DESC_ENDPOINT,
158 .bEndpointAddress = RNDIS_OUT_EP_ADDR,
159 .bmAttributes = USB_DC_EP_BULK,
160 .wMaxPacketSize =
161 sys_cpu_to_le16(CONFIG_RNDIS_BULK_EP_MPS),
162 .bInterval = 0x00,
163 },
164 };
165
166 /*
167 * TLV structure is used for data encapsulation parsing
168 */
169 struct tlv {
170 uint32_t type;
171 uint32_t len;
172 uint8_t data[];
173 } __packed;
174
175 static struct __rndis {
176 uint32_t net_filter;
177
178 enum {
179 UNINITIALIZED,
180 INITIALIZED,
181 } state;
182
183 struct net_pkt *in_pkt; /* Pointer to pkt assembling at the moment */
184 int in_pkt_len; /* Packet length to be assembled */
185 int skip_bytes; /* In case of low memory, skip bytes */
186
187 uint16_t mtu;
188 uint16_t speed; /* TODO: Calculate right speed */
189
190 /* Statistics */
191 uint32_t rx_err;
192 uint32_t tx_err;
193 uint32_t rx_no_buf;
194
195 atomic_t notify_count;
196
197 uint8_t mac[6];
198 uint8_t media_status;
199 } rndis = {
200 .mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 },
201 .mtu = 1500, /* Ethernet frame */
202 .media_status = RNDIS_OBJECT_ID_MEDIA_DISCONNECTED,
203 .state = UNINITIALIZED,
204 .skip_bytes = 0,
205 .speed = 0,
206 };
207
208 static uint8_t manufacturer[] = CONFIG_USB_DEVICE_MANUFACTURER;
209 static uint32_t drv_version = 1U;
210
211 static uint8_t tx_buf[NET_ETH_MAX_FRAME_SIZE +
212 sizeof(struct rndis_payload_packet)];
213
214 static uint32_t object_id_supported[] = {
215 RNDIS_OBJECT_ID_GEN_SUPP_LIST,
216 RNDIS_OBJECT_ID_GEN_HW_STATUS,
217 RNDIS_OBJECT_ID_GEN_SUPP_MEDIA,
218 RNDIS_OBJECT_ID_GEN_IN_USE_MEDIA,
219
220 RNDIS_OBJECT_ID_GEN_MAX_FRAME_SIZE,
221 RNDIS_OBJECT_ID_GEN_LINK_SPEED,
222 RNDIS_OBJECT_ID_GEN_BLOCK_TX_SIZE,
223 RNDIS_OBJECT_ID_GEN_BLOCK_RX_SIZE,
224
225 RNDIS_OBJECT_ID_GEN_VENDOR_ID,
226 RNDIS_OBJECT_ID_GEN_VENDOR_DESC,
227 RNDIS_OBJECT_ID_GEN_VENDOR_DRV_VER,
228
229 RNDIS_OBJECT_ID_GEN_PKT_FILTER,
230 RNDIS_OBJECT_ID_GEN_MAX_TOTAL_SIZE,
231 RNDIS_OBJECT_ID_GEN_CONN_MEDIA_STATUS,
232 RNDIS_OBJECT_ID_GEN_PHYSICAL_MEDIUM,
233 #if defined(USE_RNDIS_STATISTICS)
234 /* Using RNDIS statistics puts heavy load on
235 * USB bus, disable it for now
236 */
237 RNDIS_OBJECT_ID_GEN_TRANSMIT_OK,
238 RNDIS_OBJECT_ID_GEN_RECEIVE_OK,
239 RNDIS_OBJECT_ID_GEN_TRANSMIT_ERROR,
240 RNDIS_OBJECT_ID_GEN_RECEIVE_ERROR,
241 RNDIS_OBJECT_ID_GEN_RECEIVE_NO_BUF,
242 #endif /* USE_RNDIS_STATISTICS */
243 RNDIS_OBJECT_ID_802_3_PERMANENT_ADDRESS,
244 RNDIS_OBJECT_ID_802_3_CURR_ADDRESS,
245 RNDIS_OBJECT_ID_802_3_MCAST_LIST,
246 RNDIS_OBJECT_ID_802_3_MAX_LIST_SIZE,
247 RNDIS_OBJECT_ID_802_3_MAC_OPTIONS,
248 };
249
250 #define RNDIS_INT_EP_IDX 0
251 #define RNDIS_OUT_EP_IDX 1
252 #define RNDIS_IN_EP_IDX 2
253
254 static void rndis_bulk_out(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status);
255
256 static struct usb_ep_cfg_data rndis_ep_data[] = {
257 {
258 .ep_cb = usb_transfer_ep_callback,
259 .ep_addr = RNDIS_INT_EP_ADDR
260 },
261 {
262 .ep_cb = rndis_bulk_out,
263 .ep_addr = RNDIS_OUT_EP_ADDR
264 },
265 {
266 .ep_cb = usb_transfer_ep_callback,
267 .ep_addr = RNDIS_IN_EP_ADDR
268 },
269 };
270
parse_rndis_header(const uint8_t * buffer,uint32_t buf_len)271 static int parse_rndis_header(const uint8_t *buffer, uint32_t buf_len)
272 {
273 struct rndis_payload_packet *hdr = (void *)buffer;
274 uint32_t len;
275
276 if (buf_len < sizeof(*hdr)) {
277 LOG_ERR("Too small packet len %u", buf_len);
278 return -EINVAL;
279 }
280
281 if (hdr->type != sys_cpu_to_le32(RNDIS_DATA_PACKET)) {
282 LOG_ERR("Wrong data packet type 0x%x",
283 sys_le32_to_cpu(hdr->type));
284 return -EINVAL;
285 }
286
287 len = sys_le32_to_cpu(hdr->len);
288 /*
289 * Calculate additional offset since payload_offset is calculated
290 * from the start of itself ;)
291 */
292 if (len < sys_le32_to_cpu(hdr->payload_offset) +
293 sys_le32_to_cpu(hdr->payload_len) +
294 offsetof(struct rndis_payload_packet, payload_offset)) {
295 LOG_ERR("Incorrect RNDIS packet");
296 return -EINVAL;
297 }
298
299 LOG_DBG("Parsing packet: len %u payload offset %u payload len %u",
300 len, sys_le32_to_cpu(hdr->payload_offset),
301 sys_le32_to_cpu(hdr->payload_len));
302
303 return len;
304 }
305
rndis_clean(void)306 void rndis_clean(void)
307 {
308 LOG_DBG("");
309
310 if (rndis.in_pkt) {
311 net_pkt_unref(rndis.in_pkt);
312
313 rndis.in_pkt = NULL;
314 rndis.in_pkt_len = 0;
315 }
316
317 rndis.skip_bytes = 0;
318 }
319
rndis_bulk_out(uint8_t ep,enum usb_dc_ep_cb_status_code ep_status)320 static void rndis_bulk_out(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status)
321 {
322 uint8_t buffer[CONFIG_RNDIS_BULK_EP_MPS];
323 uint32_t hdr_offset = 0U;
324 uint32_t len, read;
325
326 usb_read(ep, NULL, 0, &len);
327
328 LOG_DBG("EP 0x%x status %d len %u", ep, ep_status, len);
329
330 if (len > CONFIG_RNDIS_BULK_EP_MPS) {
331 LOG_WRN("Limit read len %u to MPS %u", len,
332 CONFIG_RNDIS_BULK_EP_MPS);
333 len = CONFIG_RNDIS_BULK_EP_MPS;
334 }
335
336 usb_read(ep, buffer, len, &read);
337 if (len != read) {
338 LOG_ERR("Read %u instead of expected %u, skip the rest",
339 read, len);
340 rndis.skip_bytes = len - read;
341 return;
342 }
343
344 /* We already use frame keeping with len, warn here about
345 * receiving frame delimeter
346 */
347 if (len == 1U && !buffer[0]) {
348 LOG_DBG("Got frame delimeter, skip");
349 return;
350 }
351
352 /* Handle skip bytes */
353 if (rndis.skip_bytes) {
354 LOG_WRN("Skip %u bytes out of remaining %d bytes",
355 len, rndis.skip_bytes);
356
357 rndis.skip_bytes -= len;
358
359 if (rndis.skip_bytes < 0) {
360 LOG_ERR("Error skipping bytes");
361
362 rndis.skip_bytes = 0;
363 }
364
365 return;
366 }
367
368 /* Start new packet */
369 if (!rndis.in_pkt) {
370 struct net_pkt *pkt;
371
372 /* Append data only, skipping RNDIS header */
373 hdr_offset = sizeof(struct rndis_payload_packet);
374
375 rndis.in_pkt_len = parse_rndis_header(buffer, len);
376 if (rndis.in_pkt_len < 0) {
377 LOG_ERR("Error parsing RNDIS header");
378
379 rndis.rx_err++;
380 return;
381 }
382
383 pkt = net_pkt_alloc_with_buffer(netusb_net_iface(),
384 rndis.in_pkt_len,
385 AF_UNSPEC, 0, K_NO_WAIT);
386 if (!pkt) {
387 /* In case of low memory: skip the whole packet
388 * hoping to get buffers for later ones
389 */
390 rndis.skip_bytes = rndis.in_pkt_len - len;
391 rndis.rx_no_buf++;
392
393 LOG_ERR("Not enough pkt buffers, len %u, skip %u",
394 rndis.in_pkt_len, rndis.skip_bytes);
395
396 return;
397 }
398
399 rndis.in_pkt = pkt;
400 }
401
402 if (net_pkt_write(rndis.in_pkt,
403 buffer + hdr_offset, len - hdr_offset)) {
404 LOG_ERR("Error writing data to pkt: %p", rndis.in_pkt);
405 rndis_clean();
406 rndis.rx_err++;
407 return;
408 }
409
410 LOG_DBG("To assemble %d bytes, reading %u bytes",
411 rndis.in_pkt_len, len);
412
413 rndis.in_pkt_len -= len;
414 if (!rndis.in_pkt_len) {
415 LOG_DBG("Assembled full RNDIS packet");
416
417 if (VERBOSE_DEBUG) {
418 net_pkt_hexdump(rndis.in_pkt, ">");
419 }
420
421 /* Queue data to iface */
422 netusb_recv(rndis.in_pkt);
423
424 /* Start over for new packets */
425 rndis.in_pkt = NULL;
426 } else if (rndis.in_pkt_len < 0) {
427 LOG_ERR("Error assembling packet, drop and start over");
428 rndis_clean();
429 }
430 }
431
rndis_notify_cb(uint8_t ep,int size,void * priv)432 static void rndis_notify_cb(uint8_t ep, int size, void *priv)
433 {
434 LOG_DBG("ep %x size %u", ep, size);
435
436
437 atomic_dec(&rndis.notify_count);
438 }
439
rndis_queue_rsp(struct net_buf * rsp)440 static void rndis_queue_rsp(struct net_buf *rsp)
441 {
442 if (!k_fifo_is_empty(&rndis_tx_queue)) {
443 LOG_WRN("Transmit response queue is not empty");
444 }
445
446 LOG_DBG("Queued response pkt %p", rsp);
447
448 net_buf_put(&rndis_tx_queue, rsp);
449 }
450
451 /* Notify host about available data */
rndis_notify_rsp(void)452 static void rndis_notify_rsp(void)
453 {
454 static uint32_t buf[2] = {
455 sys_cpu_to_le32(0x01),
456 sys_cpu_to_le32(0x00)
457 };
458 int ret;
459
460 LOG_DBG("count %u", atomic_get(&rndis.notify_count));
461
462 if (atomic_get(&rndis.notify_count)) {
463 LOG_WRN("Notification is already sent");
464 return;
465 }
466
467 atomic_inc(&rndis.notify_count);
468
469 ret = usb_transfer(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr,
470 (uint8_t *)buf, sizeof(buf),
471 USB_TRANS_WRITE | USB_TRANS_NO_ZLP,
472 rndis_notify_cb, NULL);
473 if (ret < 0) {
474 LOG_ERR("Transfer failure, ret %d", ret);
475 }
476 }
477
rndis_init_handle(uint8_t * data,uint32_t len)478 static int rndis_init_handle(uint8_t *data, uint32_t len)
479 {
480 struct rndis_init_cmd *cmd = (void *)data;
481 struct rndis_init_cmd_complete *rsp;
482 struct net_buf *buf;
483
484 LOG_DBG("req_id 0x%x", cmd->req_id);
485
486 buf = net_buf_alloc(&rndis_tx_pool, K_NO_WAIT);
487 if (!buf) {
488 LOG_ERR("Cannot get free buffer");
489 return -ENOMEM;
490 }
491
492 rsp = net_buf_add(buf, sizeof(*rsp));
493 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_SUCCESS);
494 rsp->type = sys_cpu_to_le32(RNDIS_CMD_INITIALIZE_COMPLETE);
495 rsp->len = sys_cpu_to_le32(sizeof(*rsp));
496 rsp->req_id = cmd->req_id;
497
498 rsp->major_ver = sys_cpu_to_le32(RNDIS_MAJOR_VERSION);
499 rsp->minor_ver = sys_cpu_to_le32(RNDIS_MINOR_VERSION);
500
501 rsp->flags = sys_cpu_to_le32(RNDIS_FLAG_CONNECTIONLESS);
502 rsp->medium = sys_cpu_to_le32(RNDIS_MEDIUM_WIRED_ETHERNET);
503 rsp->max_packets = sys_cpu_to_le32(1);
504 rsp->max_transfer_size = sys_cpu_to_le32(rndis.mtu +
505 sizeof(struct net_eth_hdr) +
506 sizeof(struct
507 rndis_payload_packet));
508
509 rsp->pkt_align_factor = sys_cpu_to_le32(0);
510 (void)memset(rsp->__reserved, 0, sizeof(rsp->__reserved));
511
512 rndis.state = INITIALIZED;
513
514 rndis_queue_rsp(buf);
515
516 /* Nofity about ready reply */
517 rndis_notify_rsp();
518
519 return 0;
520 }
521
rndis_halt_handle(void)522 static int rndis_halt_handle(void)
523 {
524 LOG_DBG("");
525
526 rndis.state = UNINITIALIZED;
527
528 /* TODO: Stop networking */
529
530 return 0;
531 }
532
rndis_query_add_supp_list(struct net_buf * buf)533 static uint32_t rndis_query_add_supp_list(struct net_buf *buf)
534 {
535 for (int i = 0; i < ARRAY_SIZE(object_id_supported); i++) {
536 net_buf_add_le32(buf, object_id_supported[i]);
537 }
538
539 return sizeof(object_id_supported);
540 }
541
rndis_query_handle(uint8_t * data,uint32_t len)542 static int rndis_query_handle(uint8_t *data, uint32_t len)
543 {
544 struct rndis_query_cmd *cmd = (void *)data;
545 struct rndis_query_cmd_complete *rsp;
546 struct net_buf *buf;
547 uint32_t object_id, buf_len = 0U;
548
549 buf = net_buf_alloc(&rndis_tx_pool, K_NO_WAIT);
550 if (!buf) {
551 LOG_ERR("Cannot get free buffer");
552 return -ENOMEM;
553 }
554
555 object_id = sys_le32_to_cpu(cmd->object_id);
556
557 LOG_DBG("req_id 0x%x Object ID 0x%x buf_len %u buf_offset %u",
558 sys_le32_to_cpu(cmd->req_id),
559 object_id,
560 sys_le32_to_cpu(cmd->buf_len),
561 sys_le32_to_cpu(cmd->buf_offset));
562
563 rsp = net_buf_add(buf, sizeof(*rsp));
564 rsp->type = sys_cpu_to_le32(RNDIS_CMD_QUERY_COMPLETE);
565 rsp->req_id = cmd->req_id;
566
567 /* offset is from the beginning of the req_id field */
568 rsp->buf_offset = sys_cpu_to_le32(16);
569
570 switch (object_id) {
571 case RNDIS_OBJECT_ID_GEN_SUPP_LIST:
572 LOG_DBG("RNDIS_OBJECT_ID_GEN_SUPP_LIST");
573 rndis_query_add_supp_list(buf);
574 break;
575 case RNDIS_OBJECT_ID_GEN_PHYSICAL_MEDIUM:
576 LOG_DBG("RNDIS_OBJECT_ID_GEN_PHYSICAL_MEDIUM");
577 net_buf_add_le32(buf, RNDIS_PHYSICAL_MEDIUM_TYPE_UNSPECIFIED);
578 break;
579 case RNDIS_OBJECT_ID_GEN_MAX_FRAME_SIZE:
580 LOG_DBG("RNDIS_OBJECT_ID_GEN_MAX_FRAME_SIZE");
581 net_buf_add_le32(buf, rndis.mtu);
582 break;
583 case RNDIS_OBJECT_ID_GEN_LINK_SPEED:
584 LOG_DBG("RNDIS_OBJECT_ID_GEN_LINK_SPEED");
585 if (rndis.media_status == RNDIS_OBJECT_ID_MEDIA_DISCONNECTED) {
586 net_buf_add_le32(buf, 0);
587 } else {
588 net_buf_add_le32(buf, rndis.speed);
589 }
590 break;
591 case RNDIS_OBJECT_ID_GEN_CONN_MEDIA_STATUS:
592 LOG_DBG("RNDIS_OBJECT_ID_GEN_CONN_MEDIA_STATUS");
593 net_buf_add_le32(buf, rndis.media_status);
594 break;
595 case RNDIS_OBJECT_ID_GEN_MAX_TOTAL_SIZE:
596 LOG_DBG("RNDIS_OBJECT_ID_GEN_MAX_TOTAL_SIZE");
597 net_buf_add_le32(buf, RNDIS_GEN_MAX_TOTAL_SIZE);
598 break;
599
600 /* Statistics stuff */
601 case RNDIS_OBJECT_ID_GEN_TRANSMIT_ERROR:
602 LOG_DBG("RNDIS_OBJECT_ID_GEN_TRANSMIT_ERROR: %u", rndis.tx_err);
603 net_buf_add_le32(buf, rndis.tx_err);
604 break;
605 case RNDIS_OBJECT_ID_GEN_RECEIVE_ERROR:
606 LOG_DBG("RNDIS_OBJECT_ID_GEN_RECEIVE_ERROR: %u", rndis.rx_err);
607 net_buf_add_le32(buf, rndis.rx_err);
608 break;
609 case RNDIS_OBJECT_ID_GEN_RECEIVE_NO_BUF:
610 LOG_DBG("RNDIS_OBJECT_ID_GEN_RECEIVE_NO_BUF: %u",
611 rndis.rx_no_buf);
612 net_buf_add_le32(buf, rndis.rx_no_buf);
613 break;
614
615 /* IEEE 802.3 */
616 case RNDIS_OBJECT_ID_802_3_PERMANENT_ADDRESS:
617 LOG_DBG("RNDIS_OBJECT_ID_802_3_PERMANENT_ADDRESS");
618 memcpy(net_buf_add(buf, sizeof(rndis.mac)), rndis.mac,
619 sizeof(rndis.mac));
620 break;
621 case RNDIS_OBJECT_ID_802_3_CURR_ADDRESS:
622 LOG_DBG("RNDIS_OBJECT_ID_802_3_CURR_ADDRESS");
623 memcpy(net_buf_add(buf, sizeof(rndis.mac)), rndis.mac,
624 sizeof(rndis.mac));
625 break;
626 case RNDIS_OBJECT_ID_802_3_MCAST_LIST:
627 LOG_DBG("RNDIS_OBJECT_ID_802_3_MCAST_LIST");
628 net_buf_add_le32(buf, 0xE0000000); /* 224.0.0.0 */
629 break;
630 case RNDIS_OBJECT_ID_802_3_MAX_LIST_SIZE:
631 LOG_DBG("RNDIS_OBJECT_ID_802_3_MAX_LIST_SIZE");
632 net_buf_add_le32(buf, 1); /* one address */
633 break;
634
635 /* Vendor information */
636 case RNDIS_OBJECT_ID_GEN_VENDOR_ID:
637 LOG_DBG("RNDIS_OBJECT_ID_GEN_VENDOR_ID");
638 net_buf_add_le32(buf, CONFIG_USB_DEVICE_VID);
639 break;
640 case RNDIS_OBJECT_ID_GEN_VENDOR_DESC:
641 LOG_DBG("RNDIS_OBJECT_ID_GEN_VENDOR_DESC");
642 memcpy(net_buf_add(buf, sizeof(manufacturer) - 1), manufacturer,
643 sizeof(manufacturer) - 1);
644 break;
645 case RNDIS_OBJECT_ID_GEN_VENDOR_DRV_VER:
646 LOG_DBG("RNDIS_OBJECT_ID_GEN_VENDOR_DRV_VER");
647 net_buf_add_le32(buf, drv_version);
648 break;
649 default:
650 LOG_WRN("Unhandled query for Object ID 0x%x", object_id);
651 break;
652 }
653
654 buf_len = buf->len - sizeof(*rsp);
655
656 if (buf_len) {
657 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_SUCCESS);
658 } else {
659 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_NOT_SUPP);
660 }
661
662 /* Can be zero if object_id not handled / found */
663 rsp->buf_len = sys_cpu_to_le32(buf_len);
664
665 rsp->len = sys_cpu_to_le32(buf_len + sizeof(*rsp));
666
667 LOG_DBG("buf_len %u rsp->len %u buf->len %u",
668 buf_len, rsp->len, buf->len);
669
670 rndis_queue_rsp(buf);
671
672 /* Nofity about ready reply */
673 rndis_notify_rsp();
674
675 return 0;
676 }
677
rndis_set_handle(uint8_t * data,uint32_t len)678 static int rndis_set_handle(uint8_t *data, uint32_t len)
679 {
680 struct rndis_set_cmd *cmd = (void *)data;
681 struct rndis_set_cmd_complete *rsp;
682 struct net_buf *buf;
683 uint32_t object_id;
684 uint8_t *param;
685
686 if (len < sizeof(*cmd)) {
687 LOG_ERR("Packet is shorter then header");
688 return -EINVAL;
689 }
690
691 /* Parameter starts at offset buf_offset of the req_id field ;) */
692 param = (uint8_t *)&cmd->req_id + sys_le32_to_cpu(cmd->buf_offset);
693
694 if (len - ((uint32_t)param - (uint32_t)cmd) !=
695 sys_le32_to_cpu(cmd->buf_len)) {
696 LOG_ERR("Packet parsing error");
697 return -EINVAL;
698 }
699
700 buf = net_buf_alloc(&rndis_tx_pool, K_NO_WAIT);
701 if (!buf) {
702 LOG_ERR("Cannot get free buffer");
703 return -ENOMEM;
704 }
705
706 object_id = sys_le32_to_cpu(cmd->object_id);
707
708 LOG_DBG("req_id 0x%x Object ID 0x%x buf_len %u buf_offset %u",
709 sys_le32_to_cpu(cmd->req_id), object_id,
710 sys_le32_to_cpu(cmd->buf_len),
711 sys_le32_to_cpu(cmd->buf_offset));
712
713 rsp = net_buf_add(buf, sizeof(*rsp));
714 rsp->type = sys_cpu_to_le32(RNDIS_CMD_SET_COMPLETE);
715 rsp->len = sys_cpu_to_le32(sizeof(*rsp));
716 rsp->req_id = cmd->req_id; /* same endianness */
717
718 switch (object_id) {
719 case RNDIS_OBJECT_ID_GEN_PKT_FILTER:
720 if (sys_le32_to_cpu(cmd->buf_len) < sizeof(rndis.net_filter)) {
721 LOG_ERR("Packet is too small");
722 rsp->status = RNDIS_CMD_STATUS_INVALID_DATA;
723 break;
724 }
725
726 rndis.net_filter = sys_get_le32(param);
727 LOG_DBG("RNDIS_OBJECT_ID_GEN_PKT_FILTER 0x%x",
728 rndis.net_filter);
729 /* TODO: Start / Stop networking here */
730 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_SUCCESS);
731 break;
732 case RNDIS_OBJECT_ID_802_3_MCAST_LIST:
733 LOG_DBG("RNDIS_OBJECT_ID_802_3_MCAST_LIST");
734 /* ignore for now */
735 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_SUCCESS);
736 break;
737 default:
738 LOG_ERR("Unhandled object_id 0x%x", object_id);
739 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_NOT_SUPP);
740 break;
741 }
742
743 rndis_queue_rsp(buf);
744
745 /* Nofity about ready reply */
746 rndis_notify_rsp();
747
748 return 0;
749 }
750
rndis_reset_handle(uint8_t * data,uint32_t len)751 static int rndis_reset_handle(uint8_t *data, uint32_t len)
752 {
753 struct rndis_reset_cmd_complete *rsp;
754 struct net_buf *buf;
755
756 buf = net_buf_alloc(&rndis_tx_pool, K_NO_WAIT);
757 if (!buf) {
758 LOG_ERR("Cannot get free buffer");
759 return -ENOMEM;
760 }
761
762 LOG_DBG("");
763
764 rsp = net_buf_add(buf, sizeof(*rsp));
765 rsp->type = sys_cpu_to_le32(RNDIS_CMD_RESET_COMPLETE);
766 rsp->len = sys_cpu_to_le32(sizeof(*rsp));
767 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_SUCCESS);
768 rsp->addr_reset = sys_cpu_to_le32(1);
769
770 rndis_queue_rsp(buf);
771
772 /* Nofity about ready reply */
773 rndis_notify_rsp();
774
775 return 0;
776 }
777
rndis_keepalive_handle(uint8_t * data,uint32_t len)778 static int rndis_keepalive_handle(uint8_t *data, uint32_t len)
779 {
780 struct rndis_keepalive_cmd *cmd = (void *)data;
781 struct rndis_keepalive_cmd_complete *rsp;
782 struct net_buf *buf;
783
784 buf = net_buf_alloc(&rndis_tx_pool, K_NO_WAIT);
785 if (!buf) {
786 LOG_ERR("Cannot get free buffer");
787 return -ENOMEM;
788 }
789
790 LOG_DBG("");
791
792 rsp = net_buf_add(buf, sizeof(*rsp));
793 rsp->type = sys_cpu_to_le32(RNDIS_CMD_KEEPALIVE_COMPLETE);
794 rsp->len = sys_cpu_to_le32(sizeof(*rsp));
795 rsp->req_id = cmd->req_id; /* same order */
796 rsp->status = sys_cpu_to_le32(RNDIS_CMD_STATUS_SUCCESS);
797
798 rndis_queue_rsp(buf);
799
800 /* Nofity about ready reply */
801 rndis_notify_rsp();
802
803 return 0;
804 }
805
queue_encapsulated_cmd(uint8_t * data,uint32_t len)806 static int queue_encapsulated_cmd(uint8_t *data, uint32_t len)
807 {
808 struct net_buf *buf;
809
810 buf = net_buf_alloc(&rndis_cmd_pool, K_NO_WAIT);
811 if (!buf) {
812 LOG_ERR("Cannot get free buffer");
813 return -ENOMEM;
814 }
815
816 memcpy(net_buf_add(buf, len), data, len);
817
818 net_buf_put(&rndis_cmd_queue, buf);
819
820 LOG_DBG("queued buf %p", buf);
821
822 return 0;
823 }
824
handle_encapsulated_cmd(uint8_t * data,uint32_t len)825 static int handle_encapsulated_cmd(uint8_t *data, uint32_t len)
826 {
827 struct tlv *msg = (void *)data;
828
829 if (VERBOSE_DEBUG) {
830 net_hexdump("CMD >", data, len);
831 }
832
833 if (len != msg->len) {
834 LOG_WRN("Total len is different then command len %u %u",
835 len, msg->len);
836 /* TODO: need actions? */
837 }
838
839 LOG_DBG("RNDIS type 0x%x len %u total len %u",
840 msg->type, msg->len, len);
841
842 switch (msg->type) {
843 case RNDIS_CMD_INITIALIZE:
844 return rndis_init_handle(data, len);
845 case RNDIS_CMD_HALT:
846 return rndis_halt_handle();
847 case RNDIS_CMD_QUERY:
848 return rndis_query_handle(data, len);
849 case RNDIS_CMD_SET:
850 return rndis_set_handle(data, len);
851 case RNDIS_CMD_RESET:
852 return rndis_reset_handle(data, len);
853 case RNDIS_CMD_KEEPALIVE:
854 return rndis_keepalive_handle(data, len);
855 default:
856 LOG_ERR("Message 0x%x unhandled", msg->type);
857 return -ENOTSUP;
858 }
859
860 return 0;
861 }
862
handle_encapsulated_rsp(uint8_t ** data,uint32_t * len)863 static int handle_encapsulated_rsp(uint8_t **data, uint32_t *len)
864 {
865 struct net_buf *buf;
866
867 LOG_DBG("");
868
869 buf = net_buf_get(&rndis_tx_queue, K_NO_WAIT);
870 if (!buf) {
871 LOG_ERR("Error getting response buffer");
872 *len = 0U;
873 return -ENODATA;
874 }
875
876 if (VERBOSE_DEBUG) {
877 net_hexdump("RSP <", buf->data, buf->len);
878 }
879
880 memcpy(*data, buf->data, buf->len);
881 *len = buf->len;
882
883 net_buf_unref(buf);
884
885 return 0;
886 }
887
rndis_class_handler(struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)888 static int rndis_class_handler(struct usb_setup_packet *setup, int32_t *len,
889 uint8_t **data)
890 {
891 LOG_DBG("len %d req_type 0x%x req 0x%x enabled %u",
892 *len, setup->bmRequestType, setup->bRequest,
893 netusb_enabled());
894
895 if (!netusb_enabled()) {
896 LOG_ERR("interface disabled");
897 return -ENODEV;
898 }
899
900 if (usb_reqtype_is_to_device(setup)) {
901 if (setup->bRequest == CDC_SEND_ENC_CMD) {
902 /*
903 * Instead of handling here, queue
904 * handle_encapsulated_cmd(*data, *len);
905 */
906 return queue_encapsulated_cmd(*data, *len);
907 }
908 } else {
909 if (setup->bRequest == CDC_GET_ENC_RSP) {
910 return handle_encapsulated_rsp(data, len);
911 }
912 }
913
914 LOG_WRN("Unknown USB packet req 0x%x type 0x%x",
915 setup->bRequest, setup->bmRequestType);
916 return -ENOTSUP;
917 }
918
cmd_thread(void)919 static void cmd_thread(void)
920 {
921 LOG_INF("Command thread started");
922
923 while (true) {
924 struct net_buf *buf;
925
926 buf = net_buf_get(&rndis_cmd_queue, K_FOREVER);
927
928 LOG_DBG("got buf %p", buf);
929
930 handle_encapsulated_cmd(buf->data, buf->len);
931
932 net_buf_unref(buf);
933
934 k_yield();
935 }
936 }
937
938 /*
939 * RNDIS Send functions
940 */
941
rndis_hdr_add(uint8_t * buf,uint32_t len)942 static void rndis_hdr_add(uint8_t *buf, uint32_t len)
943 {
944 struct rndis_payload_packet *hdr = (void *)buf;
945 uint32_t offset = offsetof(struct rndis_payload_packet, payload_offset);
946
947 (void)memset(hdr, 0, sizeof(*hdr));
948
949 hdr->type = sys_cpu_to_le32(RNDIS_DATA_PACKET);
950 hdr->len = sys_cpu_to_le32(len + sizeof(*hdr));
951 hdr->payload_offset = sys_cpu_to_le32(sizeof(*hdr) - offset);
952 hdr->payload_len = sys_cpu_to_le32(len);
953
954 LOG_DBG("type %u len %u payload offset %u payload len %u",
955 hdr->type, hdr->len, hdr->payload_offset, hdr->payload_len);
956 }
957
rndis_send(struct net_pkt * pkt)958 static int rndis_send(struct net_pkt *pkt)
959 {
960 size_t len = net_pkt_get_len(pkt);
961 int ret;
962
963 LOG_DBG("send pkt %p len %u", pkt, len);
964
965 if (rndis.media_status == RNDIS_OBJECT_ID_MEDIA_DISCONNECTED) {
966 LOG_DBG("Media disconnected, drop pkt %p", pkt);
967 return -EPIPE;
968 }
969
970 if (VERBOSE_DEBUG) {
971 net_pkt_hexdump(pkt, "<");
972 }
973
974 if (len + sizeof(struct rndis_payload_packet) > sizeof(tx_buf)) {
975 LOG_WRN("Trying to send too large packet, drop");
976 return -ENOMEM;
977 }
978
979 rndis_hdr_add(tx_buf, len);
980
981 ret = net_pkt_read(pkt,
982 tx_buf + sizeof(struct rndis_payload_packet),
983 len);
984 if (ret < 0) {
985 return ret;
986 }
987
988 ret = usb_transfer_sync(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, tx_buf,
989 len + sizeof(struct rndis_payload_packet),
990 USB_TRANS_WRITE);
991 if (ret != len + sizeof(struct rndis_payload_packet)) {
992 LOG_ERR("Transfer failure");
993 return ret;
994 }
995
996 return 0;
997 }
998
999 #if defined(CONFIG_USB_DEVICE_OS_DESC)
1000 /* This string descriptor would be read the first time device is plugged in.
1001 * It is Microsoft extension called an OS String Descriptor
1002 */
1003 #define MSOS_STRING_LENGTH 18
1004 static struct string_desc {
1005 uint8_t bLength;
1006 uint8_t bDescriptorType;
1007 uint8_t bString[MSOS_STRING_LENGTH - 4];
1008 uint8_t bMS_VendorCode;
1009 uint8_t bPad;
1010 } __packed msosv1_string_descriptor = {
1011 .bLength = MSOS_STRING_LENGTH,
1012 .bDescriptorType = USB_DESC_STRING,
1013 /* Signature MSFT100 */
1014 .bString = {
1015 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00,
1016 '1', 0x00, '0', 0x00, '0', 0x00
1017 },
1018 .bMS_VendorCode = 0x03, /* Vendor Code, used for a control request */
1019 .bPad = 0x00, /* Padding byte for VendorCode look as UTF16 */
1020 };
1021
1022 static struct compat_id_desc {
1023 /* MS OS 1.0 Header Section */
1024 uint32_t dwLength;
1025 uint16_t bcdVersion;
1026 uint16_t wIndex;
1027 uint8_t bCount;
1028 uint8_t Reserved[7];
1029 /* MS OS 1.0 Function Section */
1030 struct compat_id_func {
1031 uint8_t bFirstInterfaceNumber;
1032 uint8_t Reserved1;
1033 uint8_t compatibleID[8];
1034 uint8_t subCompatibleID[8];
1035 uint8_t Reserved2[6];
1036 } __packed func[1];
1037 } __packed msosv1_compatid_descriptor = {
1038 .dwLength = sys_cpu_to_le32(40),
1039 .bcdVersion = sys_cpu_to_le16(0x0100),
1040 .wIndex = sys_cpu_to_le16(USB_OSDESC_EXTENDED_COMPAT_ID),
1041 .bCount = 0x01, /* One function section */
1042 .Reserved = {
1043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1044 },
1045
1046 .func = {
1047 {
1048 .bFirstInterfaceNumber = 0x00,
1049 .Reserved1 = 0x01,
1050 .compatibleID = {
1051 'R', 'N', 'D', 'I', 'S', 0x00, 0x00, 0x00
1052 },
1053 .subCompatibleID = {
1054 '5', '1', '6', '2', '0', '0', '1', 0x00
1055 },
1056 .Reserved2 = {
1057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1058 }
1059 },
1060 }
1061 };
1062
1063 static struct usb_os_descriptor os_desc = {
1064 .string = (uint8_t *)&msosv1_string_descriptor,
1065 .string_len = sizeof(msosv1_string_descriptor),
1066 .vendor_code = 0x03,
1067 .compat_id = (uint8_t *)&msosv1_compatid_descriptor,
1068 .compat_id_len = sizeof(msosv1_compatid_descriptor),
1069 };
1070 #endif /* CONFIG_USB_DEVICE_OS_DESC */
1071
rndis_init(const struct device * arg)1072 static int rndis_init(const struct device *arg)
1073 {
1074 ARG_UNUSED(arg);
1075
1076 LOG_DBG("RNDIS initialization");
1077
1078 /* Transmit queue init */
1079 k_fifo_init(&rndis_tx_queue);
1080 /* Command queue init */
1081 k_fifo_init(&rndis_cmd_queue);
1082
1083 /* Register MS OS Descriptor */
1084 usb_register_os_desc(&os_desc);
1085
1086 k_thread_create(&cmd_thread_data, cmd_stack,
1087 K_KERNEL_STACK_SIZEOF(cmd_stack),
1088 (k_thread_entry_t)cmd_thread,
1089 NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT);
1090
1091 k_thread_name_set(&cmd_thread_data, "usb_rndis");
1092
1093 return 0;
1094 }
1095
rndis_connect_media(bool status)1096 static int rndis_connect_media(bool status)
1097 {
1098 if (status) {
1099 rndis.media_status = RNDIS_OBJECT_ID_MEDIA_CONNECTED;
1100 } else {
1101 rndis.media_status = RNDIS_OBJECT_ID_MEDIA_DISCONNECTED;
1102 }
1103
1104 return 0;
1105 }
1106
1107 static struct netusb_function rndis_function = {
1108 .connect_media = rndis_connect_media,
1109 .send_pkt = rndis_send,
1110 };
1111
rndis_status_cb(struct usb_cfg_data * cfg,enum usb_dc_status_code status,const uint8_t * param)1112 static void rndis_status_cb(struct usb_cfg_data *cfg,
1113 enum usb_dc_status_code status,
1114 const uint8_t *param)
1115 {
1116 ARG_UNUSED(cfg);
1117
1118 /* Check the USB status and do needed action if required */
1119 switch (status) {
1120 case USB_DC_CONFIGURED:
1121 LOG_DBG("USB device configured");
1122 netusb_enable(&rndis_function);
1123 break;
1124
1125 case USB_DC_DISCONNECTED:
1126 LOG_DBG("USB device disconnected");
1127 netusb_disable();
1128 break;
1129
1130 case USB_DC_ERROR:
1131 case USB_DC_RESET:
1132 case USB_DC_CONNECTED:
1133 case USB_DC_SUSPEND:
1134 case USB_DC_RESUME:
1135 case USB_DC_INTERFACE:
1136 LOG_DBG("USB unhandlded state: %d", status);
1137 break;
1138
1139 case USB_DC_SOF:
1140 break;
1141
1142 case USB_DC_UNKNOWN:
1143 default:
1144 LOG_DBG("USB unknown state %d", status);
1145 break;
1146 }
1147 }
1148
netusb_interface_config(struct usb_desc_header * head,uint8_t bInterfaceNumber)1149 static void netusb_interface_config(struct usb_desc_header *head,
1150 uint8_t bInterfaceNumber)
1151 {
1152 ARG_UNUSED(head);
1153
1154 rndis_cfg.if0.bInterfaceNumber = bInterfaceNumber;
1155 rndis_cfg.if0_union.bControlInterface = bInterfaceNumber;
1156 rndis_cfg.if0_union.bSubordinateInterface0 = bInterfaceNumber + 1;
1157 rndis_cfg.if1.bInterfaceNumber = bInterfaceNumber + 1;
1158 rndis_cfg.iad.bFirstInterface = bInterfaceNumber;
1159 }
1160
1161 USBD_CFG_DATA_DEFINE(primary, netusb) struct usb_cfg_data netusb_config = {
1162 .usb_device_description = NULL,
1163 .interface_config = netusb_interface_config,
1164 .interface_descriptor = &rndis_cfg.if0,
1165 .cb_usb_status = rndis_status_cb,
1166 .interface = {
1167 .class_handler = rndis_class_handler,
1168 .custom_handler = NULL,
1169 .vendor_handler = NULL,
1170 },
1171 .num_endpoints = ARRAY_SIZE(rndis_ep_data),
1172 .endpoint = rndis_ep_data,
1173 };
1174
1175 /* Initialize this before eth_netusb device init */
1176 SYS_INIT(rndis_init, POST_KERNEL, 0);
1177