2
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
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.
24
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
28
#include <ipxe/netdevice.h>
29
#include <ipxe/ethernet.h>
30
#include <ipxe/if_ether.h>
31
#include <ipxe/base16.h>
32
#include <ipxe/profile.h>
38
* CDC-ECM USB Ethernet driver
42
/** Interrupt completion profiler */
43
static struct profiler ecm_intr_profiler __profiler =
44
{ .name = "ecm.intr" };
46
/** Bulk IN completion profiler */
47
static struct profiler ecm_in_profiler __profiler =
50
/** Bulk OUT profiler */
51
static struct profiler ecm_out_profiler __profiler =
52
{ .name = "ecm.out" };
54
/******************************************************************************
56
* Ethernet functional descriptor
58
******************************************************************************
62
* Locate Ethernet functional descriptor
64
* @v config Configuration descriptor
65
* @v interface Interface descriptor
66
* @ret desc Descriptor, or NULL if not found
68
struct ecm_ethernet_descriptor *
69
ecm_ethernet_descriptor ( struct usb_configuration_descriptor *config,
70
struct usb_interface_descriptor *interface ) {
71
struct ecm_ethernet_descriptor *desc;
73
for_each_interface_descriptor ( desc, config, interface ) {
74
if ( ( desc->header.type == USB_CS_INTERFACE_DESCRIPTOR ) &&
75
( desc->subtype == CDC_SUBTYPE_ETHERNET ) )
82
* Get hardware MAC address
85
* @v desc Ethernet functional descriptor
86
* @v hw_addr Hardware address to fill in
87
* @ret rc Return status code
89
int ecm_fetch_mac ( struct usb_device *usb,
90
struct ecm_ethernet_descriptor *desc, uint8_t *hw_addr ) {
91
char buf[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ];
95
/* Fetch MAC address string */
96
len = usb_get_string_descriptor ( usb, desc->mac, 0, buf,
104
if ( len != ( ( int ) ( sizeof ( buf ) - 1 /* NUL */ ) ) )
107
/* Decode MAC address */
108
len = base16_decode ( buf, hw_addr, ETH_ALEN );
117
/******************************************************************************
119
* CDC-ECM communications interface
121
******************************************************************************
125
* Complete interrupt transfer
128
* @v iobuf I/O buffer
129
* @v rc Completion status code
131
static void ecm_intr_complete ( struct usb_endpoint *ep,
132
struct io_buffer *iobuf, int rc ) {
133
struct ecm_device *ecm = container_of ( ep, struct ecm_device,
135
struct net_device *netdev = ecm->netdev;
136
struct usb_setup_packet *message;
137
size_t len = iob_len ( iobuf );
139
/* Profile completions */
140
profile_start ( &ecm_intr_profiler );
142
/* Ignore packets cancelled when the endpoint closes */
146
/* Drop packets with errors */
148
DBGC ( ecm, "ECM %p interrupt failed: %s\n",
149
ecm, strerror ( rc ) );
150
DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
154
/* Extract message header */
155
if ( len < sizeof ( *message ) ) {
156
DBGC ( ecm, "ECM %p underlength interrupt:\n", ecm );
157
DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
161
message = iobuf->data;
163
/* Parse message header */
164
switch ( message->request ) {
166
case cpu_to_le16 ( CDC_NETWORK_CONNECTION ) :
167
if ( message->value && ! netdev_link_ok ( netdev ) ) {
168
DBGC ( ecm, "ECM %p link up\n", ecm );
169
netdev_link_up ( netdev );
170
} else if ( netdev_link_ok ( netdev ) && ! message->value ) {
171
DBGC ( ecm, "ECM %p link down\n", ecm );
172
netdev_link_down ( netdev );
176
case cpu_to_le16 ( CDC_CONNECTION_SPEED_CHANGE ) :
181
DBGC ( ecm, "ECM %p unrecognised interrupt:\n", ecm );
182
DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
187
/* Free I/O buffer */
189
profile_stop ( &ecm_intr_profiler );
194
netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
200
/** Interrupt endpoint operations */
201
static struct usb_endpoint_driver_operations ecm_intr_operations = {
202
.complete = ecm_intr_complete,
205
/******************************************************************************
207
* CDC-ECM data interface
209
******************************************************************************
213
* Complete bulk IN transfer
216
* @v iobuf I/O buffer
217
* @v rc Completion status code
219
static void ecm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
221
struct ecm_device *ecm = container_of ( ep, struct ecm_device,
223
struct net_device *netdev = ecm->netdev;
225
/* Profile receive completions */
226
profile_start ( &ecm_in_profiler );
228
/* Ignore packets cancelled when the endpoint closes */
232
/* Record USB errors against the network device */
234
DBGC ( ecm, "ECM %p bulk IN failed: %s\n",
235
ecm, strerror ( rc ) );
239
/* Hand off to network stack */
240
netdev_rx ( netdev, iob_disown ( iobuf ) );
242
profile_stop ( &ecm_in_profiler );
246
netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
251
/** Bulk IN endpoint operations */
252
static struct usb_endpoint_driver_operations ecm_in_operations = {
253
.complete = ecm_in_complete,
259
* @v ecm CDC-ECM device
260
* @v iobuf I/O buffer
261
* @ret rc Return status code
263
static int ecm_out_transmit ( struct ecm_device *ecm,
264
struct io_buffer *iobuf ) {
267
/* Profile transmissions */
268
profile_start ( &ecm_out_profiler );
270
/* Enqueue I/O buffer */
271
if ( ( rc = usb_stream ( &ecm->usbnet.out, iobuf, 1 ) ) != 0 )
274
profile_stop ( &ecm_out_profiler );
279
* Complete bulk OUT transfer
282
* @v iobuf I/O buffer
283
* @v rc Completion status code
285
static void ecm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
287
struct ecm_device *ecm = container_of ( ep, struct ecm_device,
289
struct net_device *netdev = ecm->netdev;
291
/* Report TX completion */
292
netdev_tx_complete_err ( netdev, iobuf, rc );
295
/** Bulk OUT endpoint operations */
296
static struct usb_endpoint_driver_operations ecm_out_operations = {
297
.complete = ecm_out_complete,
300
/******************************************************************************
302
* Network device interface
304
******************************************************************************
308
* Open network device
310
* @v netdev Network device
311
* @ret rc Return status code
313
static int ecm_open ( struct net_device *netdev ) {
314
struct ecm_device *ecm = netdev->priv;
315
struct usb_device *usb = ecm->usb;
319
/* Open USB network device */
320
if ( ( rc = usbnet_open ( &ecm->usbnet ) ) != 0 ) {
321
DBGC ( ecm, "ECM %p could not open: %s\n",
322
ecm, strerror ( rc ) );
326
/* Set packet filter */
327
filter = ( ECM_PACKET_TYPE_PROMISCUOUS |
328
ECM_PACKET_TYPE_ALL_MULTICAST |
329
ECM_PACKET_TYPE_DIRECTED |
330
ECM_PACKET_TYPE_BROADCAST );
331
if ( ( rc = usb_control ( usb, ECM_SET_ETHERNET_PACKET_FILTER,
332
filter, ecm->usbnet.comms, NULL, 0 ) ) != 0 ){
333
DBGC ( ecm, "ECM %p could not set packet filter: %s\n",
334
ecm, strerror ( rc ) );
341
usbnet_close ( &ecm->usbnet );
347
* Close network device
349
* @v netdev Network device
351
static void ecm_close ( struct net_device *netdev ) {
352
struct ecm_device *ecm = netdev->priv;
354
/* Close USB network device */
355
usbnet_close ( &ecm->usbnet );
361
* @v netdev Network device
362
* @v iobuf I/O buffer
363
* @ret rc Return status code
365
static int ecm_transmit ( struct net_device *netdev,
366
struct io_buffer *iobuf ) {
367
struct ecm_device *ecm = netdev->priv;
370
/* Transmit packet */
371
if ( ( rc = ecm_out_transmit ( ecm, iobuf ) ) != 0 )
378
* Poll for completed and received packets
380
* @v netdev Network device
382
static void ecm_poll ( struct net_device *netdev ) {
383
struct ecm_device *ecm = netdev->priv;
387
usb_poll ( ecm->bus );
389
/* Refill endpoints */
390
if ( ( rc = usbnet_refill ( &ecm->usbnet ) ) != 0 )
391
netdev_rx_err ( netdev, NULL, rc );
394
/** CDC-ECM network device operations */
395
static struct net_device_operations ecm_operations = {
398
.transmit = ecm_transmit,
402
/******************************************************************************
406
******************************************************************************
412
* @v func USB function
413
* @v config Configuration descriptor
414
* @ret rc Return status code
416
static int ecm_probe ( struct usb_function *func,
417
struct usb_configuration_descriptor *config ) {
418
struct usb_device *usb = func->usb;
419
struct net_device *netdev;
420
struct ecm_device *ecm;
421
struct usb_interface_descriptor *comms;
422
struct ecm_ethernet_descriptor *ethernet;
425
/* Allocate and initialise structure */
426
netdev = alloc_etherdev ( sizeof ( *ecm ) );
431
netdev_init ( netdev, &ecm_operations );
432
netdev->dev = &func->dev;
434
memset ( ecm, 0, sizeof ( *ecm ) );
436
ecm->bus = usb->port->hub->bus;
437
ecm->netdev = netdev;
438
usbnet_init ( &ecm->usbnet, func, &ecm_intr_operations,
439
&ecm_in_operations, &ecm_out_operations );
440
usb_refill_init ( &ecm->usbnet.intr, 0, 0, ECM_INTR_MAX_FILL );
441
usb_refill_init ( &ecm->usbnet.in, 0, ECM_IN_MTU, ECM_IN_MAX_FILL );
442
DBGC ( ecm, "ECM %p on %s\n", ecm, func->name );
444
/* Describe USB network device */
445
if ( ( rc = usbnet_describe ( &ecm->usbnet, config ) ) != 0 ) {
446
DBGC ( ecm, "ECM %p could not describe: %s\n",
447
ecm, strerror ( rc ) );
451
/* Locate Ethernet descriptor */
452
comms = usb_interface_descriptor ( config, ecm->usbnet.comms, 0 );
453
assert ( comms != NULL );
454
ethernet = ecm_ethernet_descriptor ( config, comms );
456
DBGC ( ecm, "ECM %p has no Ethernet descriptor\n", ecm );
461
/* Fetch MAC address */
462
if ( ( rc = ecm_fetch_mac ( usb, ethernet, netdev->hw_addr ) ) != 0 ) {
463
DBGC ( ecm, "ECM %p could not fetch MAC address: %s\n",
464
ecm, strerror ( rc ) );
468
/* Register network device */
469
if ( ( rc = register_netdev ( netdev ) ) != 0 )
472
usb_func_set_drvdata ( func, ecm );
475
unregister_netdev ( netdev );
480
netdev_nullify ( netdev );
481
netdev_put ( netdev );
489
* @v func USB function
491
static void ecm_remove ( struct usb_function *func ) {
492
struct ecm_device *ecm = usb_func_get_drvdata ( func );
493
struct net_device *netdev = ecm->netdev;
495
unregister_netdev ( netdev );
496
netdev_nullify ( netdev );
497
netdev_put ( netdev );
500
/** CDC-ECM device IDs */
501
static struct usb_device_id ecm_ids[] = {
504
.vendor = USB_ANY_ID,
505
.product = USB_ANY_ID,
509
/** CDC-ECM driver */
510
struct usb_driver ecm_driver __usb_driver = {
512
.id_count = ( sizeof ( ecm_ids ) / sizeof ( ecm_ids[0] ) ),
513
.class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_ECM, 0 ),
514
.score = USB_SCORE_NORMAL,
516
.remove = ecm_remove,