1/* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2016-2019. All rights reserved.
3 * Description: LiteOS USB Driver RNDIS Protocol
4 * Author: huangjieliang
5 * Create: 2016-07-13
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28/* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36
37#include <lwip/netifapi.h>
38#include "gadget/f_ether.h"
39#include "gadget/rndis.h"
40#include "gadget/composite.h"
41#include "implementation/global_implementation.h"
42#include "controller/usb_device/dwc_otg_pcd.h"
43#include "controller/usb_device/dwc_otg_pcd_intr.h"
44#include "net/usb_eth_drv.h"
45
46#ifdef __cplusplus
47#if __cplusplus
48extern "C" {
49#endif /* __cplusplus */
50#endif /* __cplusplus */
51
52const struct netif *g_ether_usb0;
53
54/* device driver structure definition */
55
56static const driver_t g_fethernet_driver_t =
57{
58  .name     = "fethernet",
59  .methods  = NULL,
60  .size     = 0
61};
62
63/* private device class information */
64
65static devclass_t g_fethernet_devclass;
66DRIVER_MODULE(fethernet, simple, g_fethernet_driver_t, g_fethernet_devclass, usbdev_rndis_initialize, 0);
67
68#define DEIVICE_VENDOR_ID    0x0525
69#define DEIVICE_PRODUCT_ID   0xa4a2
70
71#define ETHER_NCONFIGS       1
72#define ETHER_CONFIGID       0
73#define ETHER_NINTERFACES    2
74#define ETHER_NSTRIDS        5
75#define ETHER_NUM_EPS        3
76
77#define RNDIS_STRING_ID_LEN      4
78#define RNDIS_STRING_PID_LEN     44
79#define RNDIS_VERSION_STRING_LEN 62
80#define RNDIS_STRING_LEN         58
81#define RNDIS_TYPE_LEN           40
82
83static const char g_rndis_string_id[RNDIS_STRING_ID_LEN] =
84{
85  RNDIS_STRING_ID_LEN, UDESC_STRING, 0x09, 0x04
86};
87
88static const char g_rndis_string_pid[RNDIS_STRING_PID_LEN] =
89{
90  RNDIS_STRING_PID_LEN, UDESC_STRING, 'R', 0, 'N', 0, 'D', 0, 'I',
91  0, 'S', 0, '/', 0, 'E', 0, 't', 0, 'h', 0, 'e', 0, 'r', 0, 'n',
92  0, 'e', 0, 't', 0, ' ', 0, 'G', 0, 'a', 0, 'd', 0, 'g', 0, 'e',
93  0, 't', 0
94};
95
96static const char g_version_string[RNDIS_VERSION_STRING_LEN] =
97{
98  RNDIS_VERSION_STRING_LEN, UDESC_STRING, 0x4c, 0x00, 0x69, 0x00,
99  0x6e, 0x00, 0x75, 0x00, 0x78, 0x00, 0x20, 0x00, 0x33, 0x00, 0x2e,
100  0x00, 0x31, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x30, 0x00,
101  0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x20,
102  0x00, 0x64, 0x00, 0x77, 0x00, 0x63, 0x00, 0x5f, 0x00, 0x6f, 0x00,
103  0x74, 0x00, 0x67, 0x00, 0x5f, 0x00, 0x70, 0x00, 0x63, 0x00, 0x64,
104  0x00
105};
106
107static const char g_rndis_string[RNDIS_STRING_LEN] =
108{
109  RNDIS_STRING_LEN, UDESC_STRING, 0x52, 0x00, 0x4e, 0x00, 0x44, 0x00,
110  0x49, 0x00, 0x53, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d,
111  0x00, 0x6d, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x63, 0x00,
112  0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73,
113  0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00,
114  0x72, 0x00, 0x6f, 0x00, 0x6c, 0x00
115};
116
117static const char g_rndis_type_string[RNDIS_TYPE_LEN] =
118{
119  RNDIS_TYPE_LEN, UDESC_STRING, 0x52, 0x00, 0x4e, 0x00, 0x44, 0x00,
120  0x49, 0x00, 0x53, 0x00, 0x20, 0x00, 0x45, 0x00, 0x74, 0x00, 0x68,
121  0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00,
122  0x20, 0x00, 0x44, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00
123};
124
125static const struct usb_device_descriptor g_fether_device_desc =
126{
127  .bLength            = sizeof(struct usb_device_descriptor),
128  .bDescriptorType    = UDESC_DEVICE,
129  HSETW(.bcdUSB,      UD_BCD_USB),         /* USB version */
130  .bDeviceClass       = UDCLASS_COMM,
131  .bDeviceSubClass    = 0,
132  .bDeviceProtocol    = 0,
133  .bMaxPacketSize     = UD_USB_MPS,
134  HSETW(.idVendor,    DEIVICE_VENDOR_ID),  /* vendor */
135  HSETW(.idProduct,   DEIVICE_PRODUCT_ID), /* product */
136  HSETW(.bcdDevice,   0x0318),             /* device version */
137  .iManufacturer      = 1,
138  .iProduct           = 2,
139  .iSerialNumber      = 0,
140  .bNumConfigurations = 1,
141};
142
143static struct usbd_string g_fether_device_strings[] =
144{
145  {0, g_rndis_string_id},
146  {1, g_version_string},
147  {2, g_rndis_string_pid},
148  {4, g_rndis_string},
149  {5, g_rndis_type_string},
150  USBD_DEVICE_STRINGS_END
151};
152
153
154static inline int is_multicast_eth_addr(const uint8_t *addr)
155{
156  return (0x01 & addr[0]);
157}
158
159uint8_t eth_set_hwaddr(struct netif *usb_netif, uint8_t *addr, uint8_t len)
160{
161  errno_t err;
162
163  if (is_multicast_eth_addr(addr))
164    {
165      usb_err("config a multicast mac address, please check!\n");
166      return 1;
167    }
168
169  if (len != NETIF_MAX_HWADDR_LEN)
170    {
171      usb_err("config wrong mac address len=%u\n", len);
172      return 1;
173    }
174
175  err = memcpy_s(usb_netif->hwaddr, NETIF_MAX_HWADDR_LEN, addr, len);
176  if (err != EOK)
177    {
178      usb_err("memcpy_s fail, err:%d\n", err);
179      return 1;
180    }
181
182  return 0;
183}
184
185void eth_random_addr(uint8_t *addr)
186{
187  uint32_t rand_val;
188  uint32_t nowclocks;
189
190  msleep(200);
191  nowclocks = hi_sched_clock() & 0xffffffff;  /* Get low 32-bit value */
192  srand(nowclocks);
193  rand_val = (uint32_t)rand();
194  addr[0]  = rand_val & 0xff;
195  addr[1]  = (rand_val >> 8) & 0xff;
196  addr[2]  = (rand_val >> 16) & 0xff;
197  addr[3]  = (rand_val >> 24) & 0xff;
198
199  msleep(200);
200  nowclocks = hi_sched_clock() & 0xffffffff;  /* Get low 32-bit value */
201  srand(nowclocks);
202  rand_val = (uint32_t)rand();
203  addr[4]  = rand_val & 0xff;
204  addr[5]  = (rand_val >> 8) & 0xff;
205  addr[0] &= 0xfe;  /* clear multicast bit */
206  addr[0] |= 0x02;  /* set local assignment bit (IEEE802) */
207}
208
209static void eth_tx(struct netif *usb_netif, struct pbuf *p)
210{
211  struct los_eth_driver *sc = (struct los_eth_driver *)usb_netif->state;
212  struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
213  struct pbuf *q;
214  int sg_len = 0;
215
216  for (q = p; q != NULL; q = q->next)
217    {
218      sg_list[sg_len].buf = (UINTPTR)q->payload;
219      sg_list[sg_len++].len = q->len;
220    }
221
222  rndis_tx(sc, sg_list, sg_len, p->tot_len, (UINTPTR)p);
223}
224
225void eth_rx(struct los_eth_driver *sc, const struct usbdev_req_s *req)
226{
227  struct netif *usb_netif = &sc->ac_if;
228  uint32_t total_len      = req->xfrd - RNDIS_PACKET_HDR_SIZE;
229  struct pbuf *p;
230
231  if (total_len > MAX_ETH_MSG)
232    {
233      total_len = MAX_ETH_MSG;
234    }
235
236  p = pbuf_alloc(PBUF_RAW, (uint16_t)(total_len + ETH_PAD_SIZE), PBUF_RAM);
237  if (p == NULL)
238    {
239      usb_err("eth_drv_recv : pbuf_alloc failed\n");
240      return;
241    }
242
243#if ETH_PAD_SIZE
244  (void)pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
245#endif
246
247  (void)memcpy_s(p->payload, total_len, &req->buf[RNDIS_PACKET_HDR_SIZE], total_len);
248
249#if ETH_PAD_SIZE
250  (void)pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
251#endif
252
253  driverif_input(usb_netif, p);
254}
255
256#if PF_PKT_SUPPORT
257static void eth_drv_config(struct netif *usb_netif, uint32_t cflags, uint8_t set_bit)
258{
259  LWIP_UNUSED_ARG(usb_netif);
260  LWIP_UNUSED_ARG(cflags);
261  LWIP_UNUSED_ARG(set_bit);
262
263  /* Nothing to be done for now */
264
265}
266#endif
267
268void netdev_register(struct los_eth_driver *sc)
269{
270  struct netif *usb_netif = &sc->ac_if;
271  ip4_addr_t ipaddr, netmask, gw;
272  uint8_t dev_addr[NETIF_MAX_HWADDR_LEN];
273  err_t ret;
274
275  IP4_ADDR(&gw, 10, 67, 233, 1);
276  IP4_ADDR(&ipaddr, 10, 67, 233, 3);
277  IP4_ADDR(&netmask, 255, 255, 255, 0);
278
279  usb_netif->state           = sc;
280  usb_netif->drv_send        = eth_tx;
281  usb_netif->drv_set_hwaddr  = eth_set_hwaddr;
282  usb_netif->link_layer_type = ETHERNET_DRIVER_IF;
283  usb_netif->hwaddr_len      = NETIF_MAX_HWADDR_LEN;
284
285#if PF_PKT_SUPPORT
286  usb_netif->drv_config = eth_drv_config;
287#endif
288
289#if LWIP_NETIF_ETHTOOL
290  usb_netif->ethtool_ops = NULL;
291#endif
292
293  eth_random_addr(dev_addr);
294  (void)memcpy_s(usb_netif->hwaddr, NETIF_MAX_HWADDR_LEN, dev_addr, NETIF_MAX_HWADDR_LEN);
295
296  ret = netifapi_netif_add(usb_netif, &ipaddr, &netmask, &gw);
297  if (ret)
298    {
299      usb_err("%s %d, add netif failed, ret:%d\n", __FUNCTION__, __LINE__, ret);
300      return;
301    }
302
303  (void)netifapi_netif_set_link_down(usb_netif);
304
305  g_ether_usb0 = usb_netif;
306}
307
308void netdev_unregister(struct los_eth_driver *sc)
309{
310  struct netif *usb_netif = &sc->ac_if;
311
312  if (netifapi_netif_remove(usb_netif) != ERR_OK)
313    {
314      usb_err("%s %d, remove netif failed!\n", __FUNCTION__, __LINE__);
315    }
316}
317
318void rndis_mkdevdesc(uint8_t *buf)
319{
320  errno_t ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_fether_device_desc, sizeof(g_fether_device_desc));
321  if (ret != EOK)
322    {
323      usb_err("memcpy_s fail!, ret:%d\n", ret);
324      return;
325    }
326}
327
328int16_t rndis_mkcfgdesc(uint8_t *buf, struct usbdev_devinfo_s *devinfo)
329{
330  int16_t total_len = 0;
331  int16_t len       = USB_CONFIG_DESC_SIZE;
332  errno_t ret;
333
334  (void)devinfo;
335
336  /* Copy RNDIS device configure descriptor. */
337
338  ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, g_rndis_hs_desc.rndis_config, (uint16_t)len);
339  if (ret != EOK)
340    {
341      usb_err("memcpy_s fail, ret:%d\n", ret);
342      return -1;
343    }
344  total_len += len;
345
346  /* Copy RNDIS device configure descriptor. */
347
348  buf += USB_CONFIG_DESC_SIZE;
349  len  = sizeof(g_rndis_hs_func_desc);
350  ret  = memcpy_s(buf, USB_COMP_EP0_BUFSIZ - (uint16_t)total_len, g_rndis_hs_desc.rndis_func, (uint16_t)len);
351  if (ret != EOK)
352    {
353      usb_err("memcpy_s fail, ret:%d\n", ret);
354      return -1;
355    }
356  total_len += len;
357
358  return total_len;
359}
360
361int rndis_mkstrdesc(uint8_t id, uint8_t *buf)
362{
363  const char *str;
364  errno_t ret;
365  int i;
366
367  for (i = 0; g_fether_device_strings[i].s != NULL; i++)
368    {
369      str = g_fether_device_strings[i].s;
370      if (g_fether_device_strings[i].id == id)
371        {
372          ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, str, str[0]);
373          if (ret != EOK)
374            {
375              usb_err("memcpy_s failed, ret = %d\n", ret);
376              return -1;
377            }
378          return str[0];
379        }
380    }
381
382  usb_err("Can not find the id = %u of string\n", id);
383  return -1;
384}
385
386void rndis_get_composite_devdesc(struct composite_devdesc_s *dev)
387{
388  (void)memset_s(dev, sizeof(struct composite_devdesc_s), 0, sizeof(struct composite_devdesc_s));
389
390  dev->mkdevdesc  = rndis_mkdevdesc;
391  dev->mkconfdesc = rndis_mkcfgdesc;
392  dev->mkstrdesc  = rndis_mkstrdesc;
393  dev->nconfigs   = ETHER_NCONFIGS; /* Number of configurations supported */
394  dev->configid   = ETHER_CONFIGID; /* The only supported configuration ID */
395
396  /* Interfaces.
397   *
398   * ifnobase must be provided by board-specific logic
399   */
400
401  dev->devinfo.ninterfaces = ETHER_NINTERFACES; /* Number of interfaces in the configuration */
402
403  /* Strings.
404   *
405   * strbase must be provided by board-specific logic
406   */
407
408  dev->devinfo.nstrings = ETHER_NSTRIDS;  /* Number of Strings */
409
410  /* Endpoints.
411   *
412   * Endpoint numbers must be provided by board-specific logic.
413   */
414
415  dev->devinfo.nendpoints = ETHER_NUM_EPS;
416}
417
418#ifdef __cplusplus
419#if __cplusplus
420}
421#endif /* __cplusplus */
422#endif /* __cplusplus */