• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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