iPXE
lan78xx.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <unistd.h>
29#include <errno.h>
30#include <ipxe/ethernet.h>
31#include <ipxe/usb.h>
32#include <ipxe/usbnet.h>
33#include "lan78xx.h"
34
35/** @file
36 *
37 * Microchip LAN78xx USB Ethernet driver
38 *
39 */
40
41/******************************************************************************
42 *
43 * MAC address
44 *
45 ******************************************************************************
46 */
47
48/**
49 * Fetch MAC address from EEPROM
50 *
51 * @v smscusb SMSC USB device
52 * @ret rc Return status code
53 */
54static int lan78xx_eeprom_fetch_mac ( struct smscusb_device *smscusb ) {
55 uint32_t hw_cfg;
56 uint32_t orig_hw_cfg;
57 int rc;
58
59 /* Read original HW_CFG value */
60 if ( ( rc = smscusb_readl ( smscusb, LAN78XX_HW_CFG, &hw_cfg ) ) != 0 )
61 goto err_read_hw_cfg;
62 orig_hw_cfg = hw_cfg;
63
64 /* Temporarily disable LED0 and LED1 (which share physical
65 * pins with EEDO and EECLK respectively).
66 */
68 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_HW_CFG, hw_cfg ) ) != 0 )
69 goto err_write_hw_cfg;
70
71 /* Fetch MAC address from EEPROM */
72 if ( ( rc = smscusb_eeprom_fetch_mac ( smscusb,
73 LAN78XX_E2P_BASE ) ) != 0 )
74 goto err_fetch_mac;
75
76 err_fetch_mac:
77 smscusb_writel ( smscusb, LAN78XX_HW_CFG, orig_hw_cfg );
78 err_write_hw_cfg:
79 err_read_hw_cfg:
80 return rc;
81}
82
83/**
84 * Fetch MAC address
85 *
86 * @v smscusb SMSC USB device
87 * @ret rc Return status code
88 */
89static int lan78xx_fetch_mac ( struct smscusb_device *smscusb ) {
90 struct net_device *netdev = smscusb->netdev;
91 int rc;
92
93 /* Read MAC address from EEPROM, if present */
94 if ( ( rc = lan78xx_eeprom_fetch_mac ( smscusb ) ) == 0 )
95 return 0;
96
97 /* Read MAC address from OTP, if present */
98 if ( ( rc = smscusb_otp_fetch_mac ( smscusb, LAN78XX_OTP_BASE ) ) == 0 )
99 return 0;
100
101 /* Read MAC address from device tree, if present */
102 if ( ( rc = smscusb_fdt_fetch_mac ( smscusb ) ) == 0 )
103 return 0;
104
105 /* Otherwise, generate a random MAC address */
106 eth_random_addr ( netdev->hw_addr );
107 DBGC ( smscusb, "LAN78XX %p using random MAC %s\n",
108 smscusb, eth_ntoa ( netdev->hw_addr ) );
109 return 0;
110}
111
112/******************************************************************************
113 *
114 * Device reset
115 *
116 ******************************************************************************
117 */
118
119/**
120 * Reset device
121 *
122 * @v smscusb SMSC USB device
123 * @ret rc Return status code
124 */
125static int lan78xx_reset ( struct smscusb_device *smscusb ) {
126 uint32_t hw_cfg;
127 unsigned int i;
128 int rc;
129
130 /* Reset device */
131 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_HW_CFG,
132 LAN78XX_HW_CFG_LRST ) ) != 0 )
133 return rc;
134
135 /* Wait for reset to complete */
136 for ( i = 0 ; i < LAN78XX_RESET_MAX_WAIT_MS ; i++ ) {
137
138 /* Check if reset has completed */
139 if ( ( rc = smscusb_readl ( smscusb, LAN78XX_HW_CFG,
140 &hw_cfg ) ) != 0 )
141 return rc;
142 if ( ! ( hw_cfg & LAN78XX_HW_CFG_LRST ) )
143 return 0;
144
145 /* Delay */
146 mdelay ( 1 );
147 }
148
149 DBGC ( smscusb, "LAN78XX %p timed out waiting for reset\n",
150 smscusb );
151 return -ETIMEDOUT;
152}
153
154/******************************************************************************
155 *
156 * Network device interface
157 *
158 ******************************************************************************
159 */
160
161/**
162 * Open network device
163 *
164 * @v netdev Network device
165 * @ret rc Return status code
166 */
167static int lan78xx_open ( struct net_device *netdev ) {
168 struct smscusb_device *smscusb = netdev->priv;
169 uint32_t usb_cfg0;
170 int rc;
171
172 /* Clear stored interrupt status */
173 smscusb->int_sts = 0;
174
175 /* Configure bulk IN empty response */
176 if ( ( rc = smscusb_readl ( smscusb, LAN78XX_USB_CFG0,
177 &usb_cfg0 ) ) != 0 )
178 goto err_usb_cfg0_read;
179 usb_cfg0 |= LAN78XX_USB_CFG0_BIR;
180 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_USB_CFG0,
181 usb_cfg0 ) ) != 0 )
182 goto err_usb_cfg0_write;
183
184 /* Open USB network device */
185 if ( ( rc = usbnet_open ( &smscusb->usbnet ) ) != 0 ) {
186 DBGC ( smscusb, "LAN78XX %p could not open: %s\n",
187 smscusb, strerror ( rc ) );
188 goto err_open;
189 }
190
191 /* Configure interrupt endpoint */
192 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_INT_EP_CTL,
194 LAN78XX_INT_EP_CTL_PHY_EN ) ) ) != 0 )
195 goto err_int_ep_ctl;
196
197 /* Configure bulk IN delay */
198 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_BULK_IN_DLY,
199 LAN78XX_BULK_IN_DLY_SET ( 0 ) ) ) != 0 )
200 goto err_bulk_in_dly;
201
202 /* Enable automatic speed and duplex detection */
203 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_MAC_CR,
206 LAN78XX_MAC_CR_ASD ) ) ) != 0 )
207 goto err_mac_cr;
208
209 /* Configure receive filters */
210 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_RFE_CTL,
213 LAN78XX_RFE_CTL_AU ) ) ) != 0 )
214 goto err_rfe_ctl;
215
216 /* Configure receive FIFO */
217 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_FCT_RX_CTL,
219 LAN78XX_FCT_RX_CTL_BAD ) ) ) != 0 )
220 goto err_fct_rx_ctl;
221
222 /* Configure transmit FIFO */
223 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_FCT_TX_CTL,
224 LAN78XX_FCT_TX_CTL_EN ) ) != 0 )
225 goto err_fct_tx_ctl;
226
227 /* Configure receive datapath */
228 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_MAC_RX,
231 LAN78XX_MAC_RX_EN ) ) ) != 0 )
232 goto err_mac_rx;
233
234 /* Configure transmit datapath */
235 if ( ( rc = smscusb_writel ( smscusb, LAN78XX_MAC_TX,
236 LAN78XX_MAC_TX_EN ) ) != 0 )
237 goto err_mac_tx;
238
239 /* Set MAC address */
240 if ( ( rc = smscusb_set_address ( smscusb,
241 LAN78XX_RX_ADDR_BASE ) ) != 0 )
242 goto err_set_address;
243
244 /* Set MAC address perfect filter */
245 if ( ( rc = smscusb_set_filter ( smscusb,
246 LAN78XX_ADDR_FILT_BASE ) ) != 0 )
247 goto err_set_filter;
248
249 /* Enable PHY interrupts and update link status */
254 LAN78XX_PHY_INTR_ANEG_DONE ) ) ) != 0 )
255 goto err_mii_open;
256
257 return 0;
258
259 err_mii_open:
260 err_set_filter:
261 err_set_address:
262 err_mac_tx:
263 err_mac_rx:
264 err_fct_tx_ctl:
265 err_fct_rx_ctl:
266 err_rfe_ctl:
267 err_mac_cr:
268 err_bulk_in_dly:
269 err_int_ep_ctl:
270 usbnet_close ( &smscusb->usbnet );
271 err_open:
272 err_usb_cfg0_write:
273 err_usb_cfg0_read:
274 lan78xx_reset ( smscusb );
275 return rc;
276}
277
278/**
279 * Close network device
280 *
281 * @v netdev Network device
282 */
283static void lan78xx_close ( struct net_device *netdev ) {
284 struct smscusb_device *smscusb = netdev->priv;
285
286 /* Close USB network device */
287 usbnet_close ( &smscusb->usbnet );
288
289 /* Dump statistics (for debugging) */
290 if ( DBG_LOG )
291 smsc75xx_dump_statistics ( smscusb );
292
293 /* Reset device */
294 lan78xx_reset ( smscusb );
295}
296
297/** LAN78xx network device operations */
299 .open = lan78xx_open,
300 .close = lan78xx_close,
301 .transmit = smsc75xx_transmit,
302 .poll = smsc75xx_poll,
303};
304
305/******************************************************************************
306 *
307 * USB interface
308 *
309 ******************************************************************************
310 */
311
312/**
313 * Probe device
314 *
315 * @v func USB function
316 * @v config Configuration descriptor
317 * @ret rc Return status code
318 */
319static int lan78xx_probe ( struct usb_function *func,
320 struct usb_configuration_descriptor *config ) {
321 struct net_device *netdev;
322 struct smscusb_device *smscusb;
323 int rc;
324
325 /* Allocate and initialise structure */
326 netdev = alloc_etherdev ( sizeof ( *smscusb ) );
327 if ( ! netdev ) {
328 rc = -ENOMEM;
329 goto err_alloc;
330 }
332 netdev->dev = &func->dev;
333 smscusb = netdev->priv;
334 memset ( smscusb, 0, sizeof ( *smscusb ) );
335 smscusb_init ( smscusb, netdev, func, &smsc75xx_in_operations );
340 DBGC ( smscusb, "LAN78XX %p on %s\n", smscusb, func->name );
341
342 /* Describe USB network device */
343 if ( ( rc = usbnet_describe ( &smscusb->usbnet, config ) ) != 0 ) {
344 DBGC ( smscusb, "LAN78XX %p could not describe: %s\n",
345 smscusb, strerror ( rc ) );
346 goto err_describe;
347 }
348
349 /* Reset device */
350 if ( ( rc = lan78xx_reset ( smscusb ) ) != 0 )
351 goto err_reset;
352
353 /* Read MAC address */
354 if ( ( rc = lan78xx_fetch_mac ( smscusb ) ) != 0 )
355 goto err_fetch_mac;
356
357 /* Register network device */
358 if ( ( rc = register_netdev ( netdev ) ) != 0 )
359 goto err_register;
360
362 return 0;
363
365 err_register:
366 err_fetch_mac:
367 err_reset:
368 err_describe:
370 netdev_put ( netdev );
371 err_alloc:
372 return rc;
373}
374
375/**
376 * Remove device
377 *
378 * @v func USB function
379 */
380static void lan78xx_remove ( struct usb_function *func ) {
381 struct net_device *netdev = usb_func_get_drvdata ( func );
382
385 netdev_put ( netdev );
386}
387
388/** LAN78xx device IDs */
389static struct usb_device_id lan78xx_ids[] = {
390 USB_ROM ( 0x0424, 0x7800, "lan7800", "SMSC LAN7800", 0 ),
391 USB_ROM ( 0x0424, 0x7850, "lan7850", "SMSC LAN7850", 0 ),
392};
393
394/** LAN78xx driver */
395struct usb_driver lan78xx_driver __usb_driver = {
396 .ids = lan78xx_ids,
397 .id_count = ( sizeof ( lan78xx_ids ) / sizeof ( lan78xx_ids[0] ) ),
398 .class = USB_CLASS_ID ( 0xff, 0x00, 0xff ),
399 .score = USB_SCORE_NORMAL,
400 .probe = lan78xx_probe,
401 .remove = lan78xx_remove,
402};
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
Error codes.
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition ethernet.c:265
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
void eth_random_addr(void *hw_addr)
Generate random Ethernet address.
Definition ethernet.c:160
Ethernet protocol.
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
#define DBG_LOG
Definition compiler.h:317
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
Universal Serial Bus (USB)
#define __usb_driver
Declare a USB driver.
Definition usb.h:1453
static void usb_refill_init(struct usb_endpoint *ep, size_t reserve, size_t len, unsigned int max)
Initialise USB endpoint refill.
Definition usb.h:617
#define USB_CLASS_ID(base, subclass, protocol)
Construct USB class ID.
Definition usb.h:1401
#define USB_ROM(_vendor, _product, _name, _description, _data)
Definition usb.h:1381
static void usb_func_set_drvdata(struct usb_function *func, void *priv)
Set USB function driver private data.
Definition usb.h:707
@ USB_SCORE_NORMAL
Normal driver.
Definition usb.h:1465
static void * usb_func_get_drvdata(struct usb_function *func)
Get USB function driver private data.
Definition usb.h:718
String functions.
void * memset(void *dest, int character, size_t len) __nonnull
static int lan78xx_fetch_mac(struct smscusb_device *smscusb)
Fetch MAC address.
Definition lan78xx.c:89
static int lan78xx_eeprom_fetch_mac(struct smscusb_device *smscusb)
Fetch MAC address from EEPROM.
Definition lan78xx.c:54
static void lan78xx_close(struct net_device *netdev)
Close network device.
Definition lan78xx.c:283
static struct usb_device_id lan78xx_ids[]
LAN78xx device IDs.
Definition lan78xx.c:389
static int lan78xx_open(struct net_device *netdev)
Open network device.
Definition lan78xx.c:167
static struct net_device_operations lan78xx_operations
LAN78xx network device operations.
Definition lan78xx.c:298
static int lan78xx_probe(struct usb_function *func, struct usb_configuration_descriptor *config)
Probe device.
Definition lan78xx.c:319
static void lan78xx_remove(struct usb_function *func)
Remove device.
Definition lan78xx.c:380
static int lan78xx_reset(struct smscusb_device *smscusb)
Reset device.
Definition lan78xx.c:125
Microchip LAN78xx USB Ethernet driver.
#define LAN78XX_MAC_CR_ASD
Auto speed.
Definition lan78xx.h:57
#define LAN78XX_FCT_RX_CTL_EN
FCT RX enable.
Definition lan78xx.h:46
#define LAN78XX_MAC_CR_ADP
Duplex polarity.
Definition lan78xx.h:55
#define LAN78XX_PHY_INTR_ANEG_ERR
PHY interrupt: auto-negotiation failure.
Definition lan78xx.h:90
#define LAN78XX_INT_EP_CTL_PHY_EN
PHY interrupt.
Definition lan78xx.h:25
#define LAN78XX_USB_CFG0_BIR
Bulk IN use NAK.
Definition lan78xx.h:36
#define LAN78XX_MAC_TX
MAC transmit register.
Definition lan78xx.h:68
#define LAN78XX_ADDR_FILT_BASE
MAC address perfect filter register base.
Definition lan78xx.h:96
#define LAN78XX_BULK_IN_DLY
Bulk IN delay register.
Definition lan78xx.h:28
#define LAN78XX_HW_CFG_LRST
Soft lite reset.
Definition lan78xx.h:20
#define LAN78XX_HW_CFG
Hardware configuration register.
Definition lan78xx.h:17
#define LAN78XX_E2P_BASE
EEPROM register base.
Definition lan78xx.h:32
#define LAN78XX_PHY_INTR_LINK
PHY interrupt: link state change.
Definition lan78xx.h:87
#define LAN78XX_OTP_BASE
OTP register base.
Definition lan78xx.h:99
#define LAN78XX_MAC_RX_MAX_SIZE_DEFAULT
Definition lan78xx.h:62
#define LAN78XX_MAC_RX
MAC receive register.
Definition lan78xx.h:60
#define LAN78XX_MII_PHY_INTR_SOURCE
PHY interrupt source MII register.
Definition lan78xx.h:81
#define LAN78XX_MAC_RX_EN
RX enable.
Definition lan78xx.h:65
#define LAN78XX_FCT_TX_CTL
FIFO controller TX FIFO control register.
Definition lan78xx.h:50
#define LAN78XX_USB_CFG0
USB configuration register 0.
Definition lan78xx.h:35
#define LAN78XX_RFE_CTL
Receive filtering engine control register.
Definition lan78xx.h:39
#define LAN78XX_FCT_RX_CTL_BAD
Store bad frames.
Definition lan78xx.h:47
#define LAN78XX_HW_CFG_LED1_EN
LED1 enable.
Definition lan78xx.h:18
#define LAN78XX_RFE_CTL_AM
Accept multicast.
Definition lan78xx.h:41
#define LAN78XX_MII_PHY_INTR_MASK
PHY interrupt mask MII register.
Definition lan78xx.h:78
#define LAN78XX_MAC_RX_FCS
FCS stripping.
Definition lan78xx.h:64
#define LAN78XX_RFE_CTL_AB
Accept broadcast.
Definition lan78xx.h:40
#define LAN78XX_RFE_CTL_AU
Accept unicast.
Definition lan78xx.h:42
#define LAN78XX_RX_ADDR_BASE
MAC receive address register base.
Definition lan78xx.h:72
#define LAN78XX_MII_BASE
MII register base.
Definition lan78xx.h:75
#define LAN78XX_FCT_RX_CTL
FIFO controller RX FIFO control register.
Definition lan78xx.h:45
#define LAN78XX_INT_EP_CTL
Interrupt endpoint control register.
Definition lan78xx.h:23
#define LAN78XX_BULK_IN_DLY_SET(ticks)
Delay / 16.7ns.
Definition lan78xx.h:29
#define LAN78XX_INT_EP_CTL_RDFO_EN
RX FIFO overflow.
Definition lan78xx.h:24
#define LAN78XX_MAC_CR
MAC control register.
Definition lan78xx.h:54
#define LAN78XX_MAC_TX_EN
TX enable.
Definition lan78xx.h:69
#define LAN78XX_FCT_TX_CTL_EN
FCT TX enable.
Definition lan78xx.h:51
#define LAN78XX_PHY_INTR_ANEG_DONE
PHY interrupt: auto-negotiation complete.
Definition lan78xx.h:93
#define LAN78XX_MAC_CR_ADD
Auto duplex.
Definition lan78xx.h:56
#define LAN78XX_RESET_MAX_WAIT_MS
Maximum time to wait for reset (in milliseconds)
Definition lan78xx.h:102
#define LAN78XX_HW_CFG_LED0_EN
LED1 enable.
Definition lan78xx.h:19
#define LAN78XX_PHY_INTR_ENABLE
PHY interrupt: global enable.
Definition lan78xx.h:84
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition netdevice.c:942
int register_netdev(struct net_device *netdev)
Register network device.
Definition netdevice.c:760
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition netdevice.h:519
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition netdevice.h:532
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
void smsc75xx_poll(struct net_device *netdev)
Poll for completed and received packets.
Definition smsc75xx.c:420
struct usb_endpoint_driver_operations smsc75xx_in_operations
Bulk IN endpoint operations.
Definition smsc75xx.c:234
int smsc75xx_dump_statistics(struct smscusb_device *smscusb)
Dump statistics (for debugging)
Definition smsc75xx.c:64
int smsc75xx_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet.
Definition smsc75xx.c:404
#define SMSC75XX_IN_MAX_FILL
Bulk IN maximum fill level.
Definition smsc75xx.h:210
#define SMSC75XX_IN_MTU
Bulk IN buffer size.
Definition smsc75xx.h:213
int smscusb_eeprom_fetch_mac(struct smscusb_device *smscusb, unsigned int e2p_base)
Fetch MAC address from EEPROM.
Definition smscusb.c:216
int smscusb_otp_fetch_mac(struct smscusb_device *smscusb, unsigned int otp_base)
Fetch MAC address from OTP.
Definition smscusb.c:401
int smscusb_fdt_fetch_mac(struct smscusb_device *smscusb)
Fetch MAC address from device tree.
Definition smscusb.c:457
int smscusb_set_address(struct smscusb_device *smscusb, unsigned int addr_base)
Set receive address.
Definition smscusb.c:687
int smscusb_set_filter(struct smscusb_device *smscusb, unsigned int filt_base)
Set receive filter.
Definition smscusb.c:719
int smscusb_mii_open(struct smscusb_device *smscusb, unsigned int phy_mask, unsigned int intrs)
Enable PHY interrupts and update link status.
Definition smscusb.c:656
static void smscusb_mii_init(struct smscusb_device *smscusb, unsigned int mii_base, unsigned int phy_source)
Initialise SMSC USB device MII interface.
Definition smscusb.h:278
static int smscusb_readl(struct smscusb_device *smscusb, unsigned int address, uint32_t *value)
Read register.
Definition smscusb.h:201
static int smscusb_writel(struct smscusb_device *smscusb, unsigned int address, uint32_t value)
Write register.
Definition smscusb.h:180
static void smscusb_init(struct smscusb_device *smscusb, struct net_device *netdev, struct usb_function *func, struct usb_endpoint_driver_operations *in)
Initialise SMSC USB device.
Definition smscusb.h:257
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
Network device operations.
Definition netdevice.h:214
A network device.
Definition netdevice.h:353
An SMSC USB device.
Definition smscusb.h:145
struct net_device * netdev
Network device.
Definition smscusb.h:151
uint32_t int_sts
Interrupt status.
Definition smscusb.h:163
struct usbnet_device usbnet
USB network device.
Definition smscusb.h:153
A USB configuration descriptor.
Definition usb.h:210
A USB device ID.
Definition usb.h:1361
A USB driver.
Definition usb.h:1419
A USB function.
Definition usb.h:674
struct device dev
Generic device.
Definition usb.h:682
const char * name
Name.
Definition usb.h:676
struct usb_endpoint in
Bulk IN endpoint.
Definition usbnet.h:30
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
int usbnet_open(struct usbnet_device *usbnet)
Open USB network device.
Definition usbnet.c:55
void usbnet_close(struct usbnet_device *usbnet)
Close USB network device.
Definition usbnet.c:128
int usbnet_describe(struct usbnet_device *usbnet, struct usb_configuration_descriptor *config)
Describe USB network device interfaces.
Definition usbnet.c:278
USB network devices.