1 /*
2 * Copyright (c) 2022, aozima
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 /*
7 * Change Logs
8 * Date Author Notes
9 * 2022-04-17 aozima the first version for CherryUSB.
10 */
11
12 #include <string.h>
13
14 #include "usbh_core.h"
15 #include "axusbnet.h"
16
17 static const char *DEV_FORMAT = "/dev/u%d";
18
19 #define USE_RTTHREAD (1)
20 // #define RX_DUMP
21 // #define TX_DUMP
22 // #define DUMP_RAW
23
24 #if USE_RTTHREAD
25 #include <rtthread.h>
26
27 #include <netif/ethernetif.h>
28 #include <netdev.h>
29 #endif /* USE_RTTHREAD */
30
31 #define MAX_ADDR_LEN 6
32 #define ETH_ALEN MAX_ADDR_LEN
33 #define mdelay rt_thread_delay
34 #define msleep rt_thread_delay
35 #define deverr(dev, fmt, ...) USB_LOG_ERR(fmt, ##__VA_ARGS__)
36 #define cpu_to_le16(a) (a)
37 #define le32_to_cpus(a) (a)
38
39 /* Generic MII registers. */
40 #define MII_BMCR 0x00 /* Basic mode control register */
41 #define MII_BMSR 0x01 /* Basic mode status register */
42 #define MII_PHYSID1 0x02 /* PHYS ID 1 */
43 #define MII_PHYSID2 0x03 /* PHYS ID 2 */
44 #define MII_ADVERTISE 0x04 /* Advertisement control reg */
45 #define MII_LPA 0x05 /* Link partner ability reg */
46 #define MII_EXPANSION 0x06 /* Expansion register */
47 #define MII_CTRL1000 0x09 /* 1000BASE-T control */
48 #define MII_STAT1000 0x0a /* 1000BASE-T status */
49 #define MII_MMD_CTRL 0x0d /* MMD Access Control Register */
50 #define MII_MMD_DATA 0x0e /* MMD Access Data Register */
51 #define MII_ESTATUS 0x0f /* Extended Status */
52 #define MII_DCOUNTER 0x12 /* Disconnect counter */
53 #define MII_FCSCOUNTER 0x13 /* False carrier counter */
54 #define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
55 #define MII_RERRCOUNTER 0x15 /* Receive error counter */
56 #define MII_SREVISION 0x16 /* Silicon revision */
57 #define MII_RESV1 0x17 /* Reserved... */
58 #define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
59 #define MII_PHYADDR 0x19 /* PHY address */
60 #define MII_RESV2 0x1a /* Reserved... */
61 #define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
62 #define MII_NCONFIG 0x1c /* Network interface config */
63
64 /* Basic mode control register. */
65 #define BMCR_RESV 0x003f /* Unused... */
66 #define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
67 #define BMCR_CTST 0x0080 /* Collision test */
68 #define BMCR_FULLDPLX 0x0100 /* Full duplex */
69 #define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
70 #define BMCR_ISOLATE 0x0400 /* Isolate data paths from MII */
71 #define BMCR_PDOWN 0x0800 /* Enable low power state */
72 #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
73 #define BMCR_SPEED100 0x2000 /* Select 100Mbps */
74 #define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
75 #define BMCR_RESET 0x8000 /* Reset to default state */
76 #define BMCR_SPEED10 0x0000 /* Select 10Mbps */
77
78 /* Advertisement control register. */
79 #define ADVERTISE_SLCT 0x001f /* Selector bits */
80 #define ADVERTISE_CSMA 0x0001 /* Only selector supported */
81 #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
82 #define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
83 #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
84 #define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
85 #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
86 #define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
87 #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
88 #define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
89 #define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
90 #define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
91 #define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
92 #define ADVERTISE_RESV 0x1000 /* Unused... */
93 #define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
94 #define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
95 #define ADVERTISE_NPAGE 0x8000 /* Next page bit */
96
97 #define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
98 ADVERTISE_CSMA)
99 #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
100 ADVERTISE_100HALF | ADVERTISE_100FULL)
101
102 struct mii_if_info {
103 int phy_id;
104 };
105
106 struct usbnet
107 {
108 #if USE_RTTHREAD
109 /* inherit from ethernet device */
110 struct eth_device parent;
111 #endif /* USE_RTTHREAD */
112
113 struct usbh_axusbnet *class;
114
115 uint8_t dev_addr[MAX_ADDR_LEN];
116
117 uint8_t internalphy:1;
118 uint8_t PhySelect:1;
119 uint8_t OperationMode:1;
120
121 struct mii_if_info mii;
122 };
123 typedef struct usbnet * usbnet_t;
124 static struct usbnet usbh_axusbnet_eth_device;
125
126 #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
dump_hex(const void * ptr,uint32_t buflen)127 static void dump_hex(const void *ptr, uint32_t buflen)
128 {
129 unsigned char *buf = (unsigned char*)ptr;
130 int i, j;
131
132 for (i=0; i<buflen; i+=16)
133 {
134 printf("%08X:", i);
135
136 for (j=0; j<16; j++)
137 if (i+j < buflen)
138 {
139 if ((j % 8) == 0) {
140 printf(" ");
141 }
142
143 printf("%02X ", buf[i+j]);
144 }
145 else
146 printf(" ");
147 printf(" ");
148
149 for (j=0; j<16; j++)
150 if (i+j < buflen)
151 printf("%c", __is_print(buf[i+j]) ? buf[i+j] : '.');
152 printf("\n");
153 }
154 }
155
156 #if defined(RX_DUMP) || defined(TX_DUMP)
packet_dump(const char * msg,const struct pbuf * p)157 static void packet_dump(const char * msg, const struct pbuf* p)
158 {
159 rt_uint8_t header[6 + 6 + 2];
160 rt_uint16_t type;
161
162 pbuf_copy_partial(p, header, sizeof(header), 0);
163 type = (header[12] << 8) | header[13];
164
165 rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X <== %02X:%02X:%02X:%02X:%02X:%02X ",
166 header[0], header[1], header[2], header[3], header[4], header[5],
167 header[6], header[7], header[8], header[9], header[10], header[11]);
168
169 switch (type)
170 {
171 case 0x0800:
172 rt_kprintf("IPv4. ");
173 break;
174
175 case 0x0806:
176 rt_kprintf("ARP. ");
177 break;
178
179 case 0x86DD:
180 rt_kprintf("IPv6. ");
181 break;
182
183 default:
184 rt_kprintf("%04X. ", type);
185 break;
186 }
187
188 rt_kprintf("%s %d byte. \n", msg, p->tot_len);
189 #ifdef DUMP_RAW
190 const struct pbuf* q;
191 rt_uint32_t i,j;
192 rt_uint8_t *ptr;
193
194 // rt_kprintf("%s %d byte\n", msg, p->tot_len);
195
196 i=0;
197 for(q=p; q != RT_NULL; q= q->next)
198 {
199 ptr = q->payload;
200
201 for(j=0; j<q->len; j++)
202 {
203 if( (i%8) == 0 )
204 {
205 rt_kprintf(" ");
206 }
207 if( (i%16) == 0 )
208 {
209 rt_kprintf("\r\n");
210 }
211 rt_kprintf("%02X ", *ptr);
212
213 i++;
214 ptr++;
215 }
216 }
217
218 rt_kprintf("\n\n");
219 #endif /* DUMP_RAW */
220 }
221 #else
222 #define packet_dump(...)
223 #endif /* dump */
224
ax8817x_read_cmd(struct usbnet * dev,u8 cmd,u16 value,u16 index,u16 size,void * data)225 static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
226 u16 size, void *data)
227 {
228 int ret = 0;
229 struct usbh_hubport *hport = dev->class->hport;
230 struct usb_setup_packet *setup = hport->setup;
231 setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
232 setup->bRequest = cmd;
233 setup->wValue = value;
234 setup->wIndex = index;
235 setup->wLength = size;
236
237 ret = usbh_control_transfer(hport->ep0, setup, (uint8_t *)data);
238 if (ret != 0) {
239 USB_LOG_ERR("%s cmd=%d ret: %d\r\n", __FUNCTION__, cmd, ret);
240 return ret;
241 }
242
243 _exit:
244
245 return ret;
246 }
247
ax8817x_write_cmd(struct usbnet * dev,u8 cmd,u16 value,u16 index,u16 size,void * data)248 static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
249 u16 size, void *data)
250 {
251 int ret = 0;
252 struct usbh_hubport *hport = dev->class->hport;
253 struct usb_setup_packet *setup = hport->setup;
254 setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
255 setup->bRequest = cmd;
256 setup->wValue = value;
257 setup->wIndex = index;
258 setup->wLength = size;
259
260 ret = usbh_control_transfer(hport->ep0, setup, (uint8_t *)data);
261 if (ret != 0) {
262 USB_LOG_ERR("%s cmd=%d ret: %d\r\n", __FUNCTION__, cmd, ret);
263 return ret;
264 }
265
266 _exit:
267
268 return ret;
269 }
270
ax8817x_mdio_read(struct usbnet * dev,int phy_id,int loc)271 static int ax8817x_mdio_read(struct usbnet *dev, int phy_id, int loc)
272 {
273 // struct usbnet *dev = netdev_priv(netdev);
274 u16 res, ret;
275 u8 smsr;
276 int i = 0;
277
278 // res = kmalloc(2, GFP_ATOMIC);
279 // if (!res)
280 // return 0;
281
282 do {
283 ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
284
285 msleep(1);
286
287 // smsr = (u8 *)&ret;
288 ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, &smsr);
289 } while (!(smsr & AX_HOST_EN) && (i++ < 30));
290
291 ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (uint16_t)loc, 2, &res);
292 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
293
294 // ret = *res & 0xffff;
295 // kfree(res);
296
297 return res;
298 }
299
300 /* same as above, but converts resulting value to cpu byte order */
ax8817x_mdio_read_le(struct usbnet * netdev,int phy_id,int loc)301 static int ax8817x_mdio_read_le(struct usbnet *netdev, int phy_id, int loc)
302 {
303 return (ax8817x_mdio_read(netdev, phy_id, loc));
304 }
305
306 static void
ax8817x_mdio_write(struct usbnet * dev,int phy_id,int loc,int val)307 ax8817x_mdio_write(struct usbnet *dev, int phy_id, int loc, int val)
308 {
309 // struct usbnet *dev = netdev_priv(netdev);
310 u16 res;
311 u8 smsr;
312 int i = 0;
313
314 // res = kmalloc(2, GFP_ATOMIC);
315 // if (!res)
316 // return;
317 // smsr = (u8 *) res;
318
319 do {
320 ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
321
322 msleep(1);
323
324 ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, &smsr);
325 } while (!(smsr & AX_HOST_EN) && (i++ < 30));
326
327 // *res = val;
328 res = val;
329
330 ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (uint16_t)loc, 2, &res);
331 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
332
333 // kfree(res);
334 }
335
336 static void
ax88772b_mdio_write(struct usbnet * dev,int phy_id,int loc,int val)337 ax88772b_mdio_write(struct usbnet *dev, int phy_id, int loc, int val)
338 {
339 // struct usbnet *dev = netdev_priv(netdev);
340 u16 res = val;
341
342 // res = kmalloc(2, GFP_ATOMIC);
343 // if (!res)
344 // return;
345 // *res = val;
346
347 ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
348 ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (uint16_t)loc, 2, &res);
349
350 if (loc == MII_ADVERTISE) {
351 res = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
352 ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (uint16_t)MII_BMCR, 2, &res);
353 }
354
355 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
356
357 // kfree(res);
358 }
359
360 /* same as above, but converts new value to le16 byte order before writing */
361 static void
ax8817x_mdio_write_le(struct usbnet * netdev,int phy_id,int loc,int val)362 ax8817x_mdio_write_le(struct usbnet *netdev, int phy_id, int loc, int val)
363 {
364 ax8817x_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
365 }
366
access_eeprom_mac(struct usbnet * dev,u8 * buf,u8 offset,bool wflag)367 static int access_eeprom_mac(struct usbnet *dev, u8 *buf, u8 offset, bool wflag)
368 {
369 int ret = 0, i;
370 u16 *tmp = (u16 *)buf;
371
372 if (wflag) {
373 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_EN,
374 0, 0, 0, NULL);
375 if (ret < 0)
376 return ret;
377
378 mdelay(15);
379 }
380
381 for (i = 0; i < (ETH_ALEN >> 1); i++) {
382 if (wflag) {
383 // u16 wd = cpu_to_le16(*(tmp + i));
384 u16 wd = (*(tmp + i));
385 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM, offset + i,
386 wd, 0, NULL);
387 if (ret < 0)
388 break;
389
390 mdelay(15);
391 } else {
392 ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
393 offset + i, 0, 2, tmp + i);
394 if (ret < 0)
395 break;
396 }
397 }
398
399 if (!wflag) {
400 if (ret < 0) {
401 // #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
402 // netdev_dbg(dev->net, "Failed to read MAC address from EEPROM: %d\n", ret);
403 // #else
404 // devdbg(dev, "Failed to read MAC address from EEPROM: %d\n", ret);
405 // #endif
406 USB_LOG_ERR("Failed to read MAC address from EEPROM: %d\n", ret);
407 return ret;
408 }
409 // memcpy(dev->net->dev_addr, buf, ETH_ALEN);
410 } else {
411 ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_DIS,
412 0, 0, 0, NULL);
413 if (ret < 0)
414 return ret;
415
416 /* reload eeprom data */
417 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
418 AXGPIOS_RSE, 0, 0, NULL);
419 if (ret < 0)
420 return ret;
421 }
422
423 return 0;
424 }
425
ax88772a_phy_powerup(struct usbnet * dev)426 static int ax88772a_phy_powerup(struct usbnet *dev)
427 {
428 int ret;
429 /* set the embedded Ethernet PHY in power-down state */
430 ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
431 AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL);
432 if (ret < 0) {
433 deverr(dev, "Failed to power down PHY: %d", ret);
434 return ret;
435 }
436
437 msleep(10);
438
439 /* set the embedded Ethernet PHY in power-up state */
440 ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL,
441 0, 0, NULL);
442 if (ret < 0) {
443 deverr(dev, "Failed to reset PHY: %d", ret);
444 return ret;
445 }
446
447 msleep(600);
448
449 /* set the embedded Ethernet PHY in reset state */
450 ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
451 0, 0, NULL);
452 if (ret < 0) {
453 deverr(dev, "Failed to power up PHY: %d", ret);
454 return ret;
455 }
456
457 /* set the embedded Ethernet PHY in power-up state */
458 ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL,
459 0, 0, NULL);
460 if (ret < 0) {
461 deverr(dev, "Failed to reset PHY: %d", ret);
462 return ret;
463 }
464
465 return 0;
466 }
467
ax88772b_reset(struct usbnet * dev)468 static int ax88772b_reset(struct usbnet *dev)
469 {
470 int ret;
471
472 ret = ax88772a_phy_powerup(dev);
473 if (ret < 0)
474 return ret;
475
476 /* Set the MAC address */
477 ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
478 0, 0, ETH_ALEN, dev->dev_addr);
479 if (ret < 0) {
480 deverr(dev, "set MAC address failed: %d", ret);
481 }
482
483 /* stop MAC operation */
484 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
485 0, 0, NULL);
486 if (ret < 0){
487 deverr(dev, "Reset RX_CTL failed: %d", ret);
488 }
489
490 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
491 AX88772_MEDIUM_DEFAULT, 0, 0,
492 NULL);
493 if (ret < 0){
494 deverr(dev, "Write medium mode register: %d", ret);
495 }
496
497 return ret;
498 }
499
ax8817x_get_mac(struct usbnet * dev,u8 * buf)500 static int ax8817x_get_mac(struct usbnet *dev, u8 *buf)
501 {
502 int ret, i;
503
504 ret = access_eeprom_mac(dev, buf, 0x04, 0);
505 if (ret < 0)
506 goto out;
507
508 // if (ax8817x_check_ether_addr(dev)) {
509 // ret = access_eeprom_mac(dev, dev->net->dev_addr, 0x04, 1);
510 // if (ret < 0) {
511 // deverr(dev, "Failed to write MAC to EEPROM: %d", ret);
512 // goto out;
513 // }
514
515 // msleep(5);
516
517 // ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
518 // 0, 0, ETH_ALEN, buf);
519 // if (ret < 0) {
520 // deverr(dev, "Failed to read MAC address: %d", ret);
521 // goto out;
522 // }
523
524 // for (i = 0; i < ETH_ALEN; i++)
525 // if (*(dev->net->dev_addr + i) != *((u8 *)buf + i)) {
526 // devwarn(dev, "Found invalid EEPROM part or non-EEPROM");
527 // break;
528 // }
529 // }
530
531 // memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
532
533 // /* Set the MAC address */
534 // ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID, 0, 0,
535 // ETH_ALEN, dev->net->dev_addr);
536
537 // if (ret < 0) {
538 // deverr(dev, "Failed to write MAC address: %d", ret);
539 // goto out;
540 // }
541
542 return 0;
543 out:
544 return ret;
545 }
546
547 #if USE_RTTHREAD
rt_rndis_eth_init(rt_device_t dev)548 static rt_err_t rt_rndis_eth_init(rt_device_t dev)
549 {
550 return RT_EOK;
551 }
552
rt_rndis_eth_open(rt_device_t dev,rt_uint16_t oflag)553 static rt_err_t rt_rndis_eth_open(rt_device_t dev, rt_uint16_t oflag)
554 {
555 return RT_EOK;
556 }
557
rt_rndis_eth_close(rt_device_t dev)558 static rt_err_t rt_rndis_eth_close(rt_device_t dev)
559 {
560 return RT_EOK;
561 }
562
rt_rndis_eth_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)563 static rt_size_t rt_rndis_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
564 {
565 rt_set_errno(-RT_ENOSYS);
566 return 0;
567 }
568
rt_rndis_eth_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)569 static rt_size_t rt_rndis_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
570 {
571 rt_set_errno(-RT_ENOSYS);
572 return 0;
573 }
rt_rndis_eth_control(rt_device_t dev,int cmd,void * args)574 static rt_err_t rt_rndis_eth_control(rt_device_t dev, int cmd, void *args)
575 {
576 usbnet_t rndis_eth_dev = (usbnet_t)dev;
577
578 USB_LOG_INFO("%s L%d\r\n", __FUNCTION__, __LINE__);
579 switch(cmd)
580 {
581 case NIOCTL_GADDR:
582 /* get mac address */
583 if(args)
584 {
585 USB_LOG_INFO("%s L%d NIOCTL_GADDR\r\n", __FUNCTION__, __LINE__);
586 rt_memcpy(args, rndis_eth_dev->dev_addr, MAX_ADDR_LEN);
587 }
588 else
589 {
590 return -RT_ERROR;
591 }
592 break;
593 default :
594 break;
595 }
596
597 return RT_EOK;
598 }
599
600 /* reception packet. */
rt_rndis_eth_rx(rt_device_t dev)601 static struct pbuf *rt_rndis_eth_rx(rt_device_t dev)
602 {
603 struct pbuf* p = RT_NULL;
604
605 // USB_LOG_INFO("%s L%d\r\n", __FUNCTION__, __LINE__);
606
607 return p;
608 }
609
610 /* transmit packet. */
rt_rndis_eth_tx(rt_device_t dev,struct pbuf * p)611 static rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p)
612 {
613 int ret = 0;
614 rt_err_t result = RT_EOK;
615 uint8_t *tmp_buf = RT_NULL;
616 usbnet_t rndis_eth = (usbnet_t)dev;
617 struct usbh_axusbnet *class = rndis_eth->class;
618 rt_tick_t tick_start, tick_end;
619 uint8_t int_notify_buf[8];
620
621 #ifdef TX_DUMP
622 packet_dump("TX", p);
623 #endif /* TX_DUMP */
624
625 tmp_buf = (uint8_t *)rt_malloc(16 + p->tot_len );
626 if (!tmp_buf) {
627 USB_LOG_INFO("[%s L%d], no memory for pbuf, len=%d.", __FUNCTION__, __LINE__, p->tot_len);
628 goto _exit;
629 }
630
631 uint32_t slen = p->tot_len;
632
633 uint32_t head = slen;
634 head = ((head ^ 0x0000ffff) << 16) + (head);
635
636 tmp_buf[0] = head & 0xFF;
637 tmp_buf[1] = (head >> 8) & 0xFF;
638 tmp_buf[2] = (head >> 16) & 0xFF;
639 tmp_buf[3] = (head >> 24) & 0xFF;
640 slen += 4;
641
642 int padlen = ((p->tot_len + 4) % 512) ? 0 : 4;
643 if (padlen) {
644 tmp_buf[4 + slen + 0] = 0x00;
645 tmp_buf[4 + slen + 1] = 0x00;
646 tmp_buf[4 + slen + 2] = 0xFF;
647 tmp_buf[4 + slen + 3] = 0xFF;
648 slen += 4;
649 }
650
651 pbuf_copy_partial(p, tmp_buf + 4, p->tot_len, 0);
652
653 tick_start = rt_tick_get();
654 ret = usbh_ep_bulk_transfer(class->bulkout, tmp_buf, slen, 500);
655 if (ret < 0) {
656 result = -RT_EIO;
657 USB_LOG_ERR("%s L%d send over ret:%d\r\n", __FUNCTION__, __LINE__, ret);
658 goto _exit;
659 }
660 tick_end = rt_tick_get();
661
662 _exit:
663 if(tmp_buf)
664 {
665 rt_free(tmp_buf);
666 }
667
668 return result;
669 }
670
671 #ifdef RT_USING_DEVICE_OPS
672 const static struct rt_device_ops rndis_device_ops =
673 {
674 rt_rndis_eth_init,
675 rt_rndis_eth_open,
676 rt_rndis_eth_close,
677 rt_rndis_eth_read,
678 rt_rndis_eth_write,
679 rt_rndis_eth_control
680 }
681 #endif /* RT_USING_DEVICE_OPS */
682 #endif /* USE_RTTHREAD */
683
684 static void rt_thread_axusbnet_entry(void *parameter)
685 {
686 int ret;
687 struct usbh_hubport *hport;
688 uint8_t intf;
689 uint8_t buf[2+8];
690
691 USB_LOG_INFO("%s L%d\r\n", __FUNCTION__, __LINE__);
692 rt_thread_delay(200);
693 USB_LOG_INFO("%s L%d\r\n\r\n\r\n\r\n", __FUNCTION__, __LINE__);
694
695 const char *dname = "/dev/u0";
696 struct usbh_axusbnet *class = (struct usbh_axusbnet *)usbh_find_class_instance(dname);
697 if (class == NULL) {
698 USB_LOG_ERR("do not find %s\r\n", dname);
699 return;
700 }
701 USB_LOG_INFO("axusbnet=%p\r\n", dname);
702
703 usbh_axusbnet_eth_device.class = class;
704
705 struct usbnet *dev = &usbh_axusbnet_eth_device;
706
707 ret = ax8817x_read_cmd(dev, AX_CMD_SW_PHY_STATUS,
708 0, 0, 1, buf);
709 if (ret < 0) {
710 USB_LOG_ERR("AX_CMD_SW_PHY_STATUS ret=%d\r\n", ret);
711 return;
712 }
713 u8 tempphyselect = buf[0];
714 if (tempphyselect == AX_PHYSEL_SSRMII) {
715 USB_LOG_ERR("%s L%d AX_PHYSEL_SSRMII\r\n", __FUNCTION__, __LINE__);
716 dev->internalphy = false;
717 return;
718 // dev->OperationMode = OPERATION_MAC_MODE;
719 // dev->PhySelect = 0x00;
720 } else if (tempphyselect == AX_PHYSEL_SSRRMII) {
721 USB_LOG_ERR("%s L%d AX_PHYSEL_SSRRMII\r\n", __FUNCTION__, __LINE__);
722 dev->internalphy = true;
723 return;
724 // dev->OperationMode = OPERATION_PHY_MODE;
725 // dev->PhySelect = 0x00;
726 } else if (tempphyselect == AX_PHYSEL_SSMII) {
727 USB_LOG_INFO("%s L%d internalphy AX_PHYSEL_SSMII & OPERATION_MAC_MODE\r\n", __FUNCTION__, __LINE__);
728 dev->internalphy = true;
729 dev->OperationMode = OPERATION_MAC_MODE;
730 dev->PhySelect = 0x01;
731 } else {
732 // deverr(dev, "Unknown MII type\n");
733 USB_LOG_INFO("%s L%d Unknown MII type\r\n", __FUNCTION__, __LINE__);
734 return;
735 }
736
737 /* reload eeprom data */
738 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_RSE, 0, 0, NULL);
739 if (ret < 0) {
740 USB_LOG_ERR("reload eeprom data ret=%d\r\n", ret);
741 return;
742 }
743
744 /* Get the EEPROM data: power saving configuration*/
745 ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x18, 0, 2, buf);
746 if (ret < 0) {
747 USB_LOG_ERR("read SROM address 18h failed: %d\r\n", ret);
748 goto err_out;
749 }
750 USB_LOG_INFO("reading AX88772C psc: %02x %02x\r\n", buf[0], buf[1]);
751 // le16_to_cpus(tmp16);
752 // ax772b_data->psc = *tmp16 & 0xFF00;
753 /* End of get EEPROM data */
754
755 ret = ax8817x_get_mac(dev, buf);
756 if (ret < 0) {
757 USB_LOG_ERR("Get HW address failed: %d\r\n", ret);
758 return;
759 }
760 dump_hex(buf, ETH_ALEN);
761 memcpy(dev->dev_addr, buf, ETH_ALEN);
762
763 uint16_t chipcode = 0xFFFF;
764 {
765 uint16_t smsr;
766 // asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
767 ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, &chipcode);
768 USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG ret: %d %04X\r\n", ret, chipcode);
769
770 // #define AX_CHIPCODE_MASK 0x70
771 // #define AX_AX88772_CHIPCODE 0x00
772 // #define AX_AX88772A_CHIPCODE 0x10
773 // #define AX_AX88772B_CHIPCODE 0x20
774 // #define AX_HOST_EN 0x01
775
776 chipcode &= 0x70;//AX_CHIPCODE_MASK; AX_AX88772_CHIPCODE
777 if(chipcode == 0x00)
778 {
779 USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG AX_AX88772_CHIPCODE\r\n");
780 }
781 else if(chipcode == 0x10)
782 {
783 USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG AX_AX88772A_CHIPCODE\r\n");
784 }
785 else if(chipcode == 0x20)
786 {
787 USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG AX_AX88772B_CHIPCODE\r\n");
788 }
789 }
790
791 /* Get the PHY id: E0 10 */
792 ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
793 if (ret < 0) {
794 USB_LOG_ERR("Error reading PHY ID: %02x\r\n", ret);
795 return;
796 }
797 if (dev->internalphy) {
798 dev->mii.phy_id = *((u8 *)buf + 1);
799 } else {
800 dev->mii.phy_id = *((u8 *)buf);
801 }
802 USB_LOG_INFO("reading %s PHY ID: %02x\r\n", dev->internalphy?"internal":"external", dev->mii.phy_id);
803
804 ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, dev->PhySelect, 0, 0, NULL);
805 if (ret < 0) {
806 USB_LOG_ERR("Select PHY #1 failed: %d", ret);
807 return;
808 }
809
810 ret = ax88772a_phy_powerup(dev);
811 if (ret < 0) {
812 USB_LOG_ERR("ax88772a_phy_powerup failed: %d", ret);
813 return;
814 }
815
816 /* stop MAC operation */
817 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
818 AX_RX_CTL_STOP, 0, 0, NULL);
819 if (ret < 0) {
820 USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
821 goto err_out;
822 }
823
824 /* make sure the driver can enable sw mii operation */
825 ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
826 if (ret < 0) {
827 USB_LOG_ERR("Enabling software MII failed: %d\r\n", ret);
828 goto err_out;
829 }
830
831 if ((dev->OperationMode == OPERATION_MAC_MODE) &&
832 (dev->PhySelect == 0x00)) {
833 USB_LOG_ERR("not support the external phy\r\n");
834 goto err_out;
835 }
836
837 if (dev->OperationMode == OPERATION_PHY_MODE) {
838 ax8817x_mdio_write_le(dev, dev->mii.phy_id, MII_BMCR, 0x3900);
839 }
840
841 if (dev->mii.phy_id != 0x10)
842 {
843 USB_LOG_ERR("not support phy_id != 0x10\r\n");
844 // ax8817x_mdio_write_le(dev->net, 0x10, MII_BMCR, 0x3900);
845 }
846
847 if (dev->mii.phy_id == 0x10 && dev->OperationMode != OPERATION_PHY_MODE) {
848 u16 tmp16 = ax8817x_mdio_read_le(dev, dev->mii.phy_id, 0x12);
849 ax8817x_mdio_write_le(dev, dev->mii.phy_id, 0x12, ((tmp16 & 0xFF9F) | 0x0040));
850 }
851
852 ax8817x_mdio_write_le(dev, dev->mii.phy_id, MII_ADVERTISE,
853 ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
854
855 // mii_nway_restart(&dev->mii);
856 {
857 /* if autoneg is off, it's an error */
858 uint16_t bmcr = ax8817x_mdio_read_le(dev, dev->mii.phy_id, MII_BMCR);
859 if (bmcr & BMCR_ANENABLE) {
860 bmcr |= BMCR_ANRESTART;
861 USB_LOG_ERR("BMCR_ANENABLE ==> BMCR_ANRESTART\r\n");
862 ax8817x_mdio_write_le(dev, dev->mii.phy_id, MII_BMCR, bmcr);
863 } else
864 {
865 USB_LOG_ERR("not BMCR_ANENABLE BMCR=%04X\r\n", bmcr);
866 }
867 }
868
869 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0, 0, 0, NULL);
870 if (ret < 0) {
871 USB_LOG_ERR("Failed to write medium mode: %d", ret);
872 goto err_out;
873 }
874
875 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
876 AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
877 AX88772A_IPG2_DEFAULT, 0, NULL);
878 if (ret < 0) {
879 USB_LOG_ERR("Failed to write interframe gap: %d", ret);
880 goto err_out;
881 }
882
883 memset(buf, 0, 4);
884 ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf);
885 *((u8 *)buf + 3) = 0x00;
886 if (ret < 0) {
887 USB_LOG_ERR("Failed to read IPG,IPG1,IPG2 failed: %d", ret);
888 goto err_out;
889 } else {
890 uint32_t tmp32 = *((u32*)buf);
891 le32_to_cpus(&tmp32);
892 if (tmp32 != (AX88772A_IPG2_DEFAULT << 16 |
893 AX88772A_IPG1_DEFAULT << 8 | AX88772A_IPG0_DEFAULT)) {
894 USB_LOG_ERR("Non-authentic ASIX product\nASIX does not support it\n");
895 // ret = -ENODEV;
896 goto err_out;
897 }
898 }
899
900 // TODO: optimized for high speed.
901 ret = ax8817x_write_cmd(dev, 0x2A, 0x8000, 0x8001, 0, NULL);
902 if (ret < 0) {
903 USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
904 goto err_out;
905 }
906
907 ret = ax88772b_reset(dev);
908 if (ret < 0) {
909 USB_LOG_ERR("ax88772b_reset failed: %d", ret);
910 goto err_out;
911 }
912
913 // OUT 29 0 0 0 AX_CMD_WRITE_MONITOR_MODE
914 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, 0, 0, 0, NULL);
915 if (ret < 0) {
916 deverr(dev, "AX_CMD_WRITE_MONITOR_MODE failed: %d", ret);
917 }
918
919 /* Set the MAC address */
920 ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
921 0, 0, ETH_ALEN, dev->dev_addr);
922 if (ret < 0) {
923 deverr(dev, "set MAC address failed: %d", ret);
924 }
925
926 // update Multicast AX_CMD_WRITE_MULTI_FILTER.
927 const uint8_t multi_filter[] = {0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40};
928 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, AX_MCAST_FILTER_SIZE, (void *)multi_filter);
929 if (ret < 0) {
930 USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
931 goto err_out;
932 }
933
934 /* Configure RX header type */
935 // u16 rx_reg = (AX_RX_CTL_PRO | AX_RX_CTL_AMALL | AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT);
936 u16 rx_reg = (AX_RX_CTL_AB | AX_RX_CTL_AM | AX_RX_CTL_START);
937 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, rx_reg, 0, 0, NULL);
938 if (ret < 0) {
939 USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
940 goto err_out;
941 }
942
943 /* set the embedded Ethernet PHY in power-up state */
944 // ax772b_data->psc = *tmp16 & 0xFF00;
945 // psc: 15 5a AX88772C psc: %02x %02x\r\n", buf[0], buf[1]);
946 ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | (0x5a00 & 0x7FFF),
947 0, 0, NULL);
948 if (ret < 0) {
949 deverr(dev, "Failed to reset PHY: %d", ret);
950 // return ret;
951 }
952
953 rt_thread_delay(1000);
954 u16 mode = AX88772_MEDIUM_DEFAULT;
955 ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
956 if (ret < 0) {
957 USB_LOG_ERR("AX_CMD_WRITE_MEDIUM_MODE failed: %d", ret);
958 goto err_out;
959 }
960
961 #if USE_RTTHREAD
962 #ifdef RT_USING_DEVICE_OPS
963 usbh_axusbnet_eth_device.parent.parent.ops = &rndis_device_ops;
964 #else
965 usbh_axusbnet_eth_device.parent.parent.init = rt_rndis_eth_init;
966 usbh_axusbnet_eth_device.parent.parent.open = rt_rndis_eth_open;
967 usbh_axusbnet_eth_device.parent.parent.close = rt_rndis_eth_close;
968 usbh_axusbnet_eth_device.parent.parent.read = rt_rndis_eth_read;
969 usbh_axusbnet_eth_device.parent.parent.write = rt_rndis_eth_write;
970 usbh_axusbnet_eth_device.parent.parent.control = rt_rndis_eth_control;
971 #endif
972 usbh_axusbnet_eth_device.parent.parent.user_data = RT_NULL;
973
974 usbh_axusbnet_eth_device.parent.eth_rx = rt_rndis_eth_rx;
975 usbh_axusbnet_eth_device.parent.eth_tx = rt_rndis_eth_tx;
976
977 usbh_axusbnet_eth_device.class = class;
978
979 eth_device_init(&usbh_axusbnet_eth_device.parent, "u0");
980 eth_device_linkchange(&usbh_axusbnet_eth_device.parent, RT_FALSE);
981 #endif /* USE_RTTHREAD */
982 // check link status.
983 {
984 u16 bmcr = ax8817x_mdio_read_le(dev, dev->mii.phy_id, MII_BMCR);
985 u16 mode = AX88772_MEDIUM_DEFAULT;
986
987 USB_LOG_ERR("%s L%d MII_BMCR=%04X\r\n", __FUNCTION__, __LINE__, bmcr);
988 if (!(bmcr & BMCR_FULLDPLX))
989 {
990 mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
991 USB_LOG_ERR("%s L%d not AX88772_MEDIUM_FULL_DUPLEX\r\n", __FUNCTION__, __LINE__);
992 }
993 if (!(bmcr & BMCR_SPEED100))
994 {
995 mode &= ~AX88772_MEDIUM_100MB;
996 USB_LOG_ERR("%s L%d not AX88772_MEDIUM_100MB\r\n", __FUNCTION__, __LINE__);
997 }
998 ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
999 }
1000
1001 while (1)
1002 {
1003 // USB_LOG_INFO("%s L%d\r\n", __FUNCTION__, __LINE__);
1004
1005 ret = usbh_ep_bulk_transfer(class->bulkin, class->bulkin_buf, sizeof(class->bulkin_buf), 1000);
1006 if (ret < 0) {
1007 if (ret != -2) {
1008 USB_LOG_ERR("%s L%d bulk in error ret=%d\r\n", __FUNCTION__, __LINE__, ret);
1009 }
1010 continue;
1011 }
1012
1013 {
1014 const uint8_t *data = class->bulkin_buf;
1015 uint16_t len1, len2;
1016
1017 len1 = data[0] | ((uint16_t)(data[1])<<8);
1018 len2 = data[2] | ((uint16_t)(data[3])<<8);
1019
1020 // USB_LOG_INFO("transfer bulkin len1:%04X, len2:%04X, len2':%04X.\r\n", len1, len2, ~len2);
1021
1022 len1 &= 0x07ff;
1023
1024 if (data[0] != ((uint8_t)(~data[2]))) {
1025 USB_LOG_ERR("transfer bulkin len1:%04X, len2:%04X, len2':%04X.\r\n", len1, len2, ~len2);
1026
1027 dump_hex(data, 32);
1028 continue;
1029 }
1030
1031 #if !USE_RTTHREAD
1032 {
1033 static uint32_t count = 0;
1034 USB_LOG_INFO("recv: #%d, len=%d\r\n", count, ret);
1035 dump_hex(data+4, 32);
1036
1037 if ((count % 10) == 0) {
1038 // 192.168.89.14 ==> 255.255.255.255:7 echo hello world!
1039 const uint8_t packet_bytes[] = {
1040 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
1041 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
1042 0x00, 0x36, 0xb0, 0xfd, 0x00, 0x00, 0x80, 0x11,
1043 0x00, 0x00, 0xc0, 0xa8, 0x59, 0x0e, 0xff, 0xff,
1044 0xff, 0xff, 0x00, 0x07, 0x00, 0x07, 0x00, 0x22,
1045 0x53, 0x06, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
1046 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x66, 0x72,
1047 0x6f, 0x6d, 0x20, 0x41, 0x58, 0x38, 0x38, 0x37,
1048 0x37, 0x32, 0x43, 0x2e
1049 };
1050
1051 uint8_t *send_buf = (uint8_t *)class->bulkin_buf;
1052 send_buf[0] = sizeof(packet_bytes);
1053 send_buf[1] = sizeof(packet_bytes) >> 8;
1054 send_buf[2] = ~send_buf[0];
1055 send_buf[3] = ~send_buf[1];
1056 memcpy(send_buf+4, packet_bytes, sizeof(packet_bytes));
1057 memcpy(send_buf+4+6, dev->dev_addr, 6);// update src mac.
1058
1059 ret = usbh_ep_bulk_transfer(class->bulkout, send_buf, 4 + sizeof(packet_bytes), 500);
1060 USB_LOG_INFO("bulkout, ret=%d\r\n", ret);
1061 dump_hex(send_buf, 64);
1062 }
1063
1064 count++;
1065 }
1066 #endif /* RT-Thread */
1067
1068 #if USE_RTTHREAD
1069 {
1070 static uint32_t count = 0;
1071
1072 if (count == 0) {
1073 eth_device_linkchange(&usbh_axusbnet_eth_device.parent, RT_TRUE);
1074 }
1075
1076 count++;
1077 }
1078
1079 /* allocate buffer */
1080 struct pbuf *p = RT_NULL;
1081 p = pbuf_alloc(PBUF_LINK, len1, PBUF_RAM);
1082 if (p != NULL) {
1083 pbuf_take(p, data + 4, len1);
1084
1085 #ifdef RX_DUMP
1086 packet_dump("RX", p);
1087 #endif /* RX_DUMP */
1088 struct eth_device *eth_dev = &usbh_axusbnet_eth_device.parent;
1089 if ((eth_dev->netif->input(p, eth_dev->netif)) != ERR_OK) {
1090 USB_LOG_INFO("F:%s L:%d IP input error\r\n", __FUNCTION__, __LINE__);
1091 pbuf_free(p);
1092 p = RT_NULL;
1093 }
1094 // USB_LOG_INFO("%s L%d input OK\r\n", __FUNCTION__, __LINE__);
1095 } else {
1096 USB_LOG_ERR("%s L%d pbuf_alloc NULL\r\n", __FUNCTION__, __LINE__);
1097 }
1098 #endif /* RT-Thread */
1099 }
1100 } // while (1)
1101
1102 err_out:
1103 out2:
1104
1105 return;
1106 }
1107
1108 static int axusbnet_startup(void)
1109 {
1110 const char *tname = "axusbnet";
1111 usb_osal_thread_t usb_thread;
1112
1113 usb_thread = usb_osal_thread_create(tname, 1024 * 6, CONFIG_USBHOST_PSC_PRIO, rt_thread_axusbnet_entry, NULL);
1114 if (usb_thread == NULL) {
1115 return -1;
1116 }
1117
1118 return 0;
1119 }
1120
1121 static int usbh_axusbnet_connect(struct usbh_hubport *hport, uint8_t intf)
1122 {
1123 int ret = 0;
1124 struct usbh_endpoint_cfg ep_cfg = { 0 };
1125 struct usb_endpoint_descriptor *ep_desc;
1126
1127 USB_LOG_INFO("%s %d\r\n", __FUNCTION__, __LINE__);
1128
1129 struct usbh_axusbnet *class = usb_malloc(sizeof(struct usbh_axusbnet));
1130 if (class == NULL)
1131 {
1132 USB_LOG_ERR("Fail to alloc class\r\n");
1133 return -ENOMEM;
1134 }
1135 memset(class, 0, sizeof(struct usbh_axusbnet));
1136 class->hport = hport;
1137
1138 class->intf = intf;
1139
1140 snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, intf);
1141 USB_LOG_INFO("Register axusbnet Class:%s\r\n", hport->config.intf[intf].devname);
1142 hport->config.intf[intf].priv = class;
1143
1144 #if 1
1145 USB_LOG_INFO("hport=%p, intf=%d, intf_desc.bNumEndpoints:%d\r\n", hport, intf, hport->config.intf[intf].intf_desc.bNumEndpoints);
1146 for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++)
1147 {
1148 ep_desc = &hport->config.intf[intf].ep[i].ep_desc;
1149
1150 USB_LOG_INFO("ep[%d] bLength=%d, type=%d\r\n", i, ep_desc->bLength, ep_desc->bDescriptorType);
1151 USB_LOG_INFO("ep_addr=%02X, attr=%02X\r\n", ep_desc->bEndpointAddress, ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK);
1152 USB_LOG_INFO("wMaxPacketSize=%d, bInterval=%d\r\n\r\n", ep_desc->wMaxPacketSize, ep_desc->bInterval);
1153 }
1154 #endif
1155
1156 for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++)
1157 {
1158 ep_desc = &hport->config.intf[intf].ep[i].ep_desc;
1159
1160 ep_cfg.ep_addr = ep_desc->bEndpointAddress;
1161 ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
1162 ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
1163 ep_cfg.ep_interval = ep_desc->bInterval;
1164 ep_cfg.hport = hport;
1165
1166 if(ep_cfg.ep_type == USB_ENDPOINT_TYPE_BULK)
1167 {
1168 if (ep_desc->bEndpointAddress & 0x80) {
1169 usbh_pipe_alloc(&class->bulkin, &ep_cfg);
1170 } else {
1171 usbh_pipe_alloc(&class->bulkout, &ep_cfg);
1172 }
1173 }
1174 else
1175 {
1176 usbh_pipe_alloc(&class->int_notify, &ep_cfg);
1177 }
1178 }
1179
1180 axusbnet_startup();
1181
1182 return ret;
1183 }
1184
1185 static int usbh_axusbnet_disconnect(struct usbh_hubport *hport, uint8_t intf)
1186 {
1187 int ret = 0;
1188
1189 USB_LOG_ERR("TBD: %s %d\r\n", __FUNCTION__, __LINE__);
1190 return ret;
1191 }
1192
1193 // Class:0xff,Subclass:0xff,Protocl:0x00
1194 static const struct usbh_class_driver axusbnet_class_driver = {
1195 .driver_name = "axusbnet",
1196 .connect = usbh_axusbnet_connect,
1197 .disconnect = usbh_axusbnet_disconnect
1198 };
1199
1200 CLASS_INFO_DEFINE const struct usbh_class_info axusbnet_class_info = {
1201 .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
1202 .class = USB_DEVICE_CLASS_VEND_SPECIFIC,
1203 .subclass = 0xff,
1204 .protocol = 0x00,
1205 .vid = 0x0b95,
1206 .pid = 0x772b,
1207 .class_driver = &axusbnet_class_driver
1208 };
1209