2008-06-19 18:20:26 -07:00
/*
* cdc2 . c - - CDC Composite driver , with ECM and ACM support
*
* Copyright ( C ) 2008 David Brownell
* Copyright ( C ) 2008 Nokia Corporation
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/kernel.h>
2011-07-03 16:09:31 -04:00
# include <linux/module.h>
2008-06-19 18:20:26 -07:00
# include "u_ether.h"
# include "u_serial.h"
2013-05-23 10:32:04 +02:00
# include "u_ecm.h"
2008-06-19 18:20:26 -07:00
# define DRIVER_DESC "CDC Composite Gadget"
# define DRIVER_VERSION "King Kamehameha Day 2008"
/*-------------------------------------------------------------------------*/
/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead : allocate your own , using normal USB - IF procedures .
*/
/* Thanks to NetChip Technologies for donating this product ID.
* It ' s for devices with only this composite CDC configuration .
*/
# define CDC_VENDOR_NUM 0x0525 /* NetChip */
# define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */
2012-09-10 15:01:53 +02:00
USB_GADGET_COMPOSITE_OPTIONS ( ) ;
2008-06-19 18:20:26 -07:00
usb: gadget: u_ether: convert into module
u_ether.c has been #include'd by all gadgets which implement
USB Ethernet functions. In order to add configfs support,
the f_ecm.c, f_eem.c, f_ncm.c, f_subset.c, f_rndis.c need to be
converted into modules and must not be #include'd. Consequently,
the u_ether.c needs to be a module too, in a manner similar
to u_serial.c. The resulting module should not take any parameters,
so they are pushed to the current users of it, that is ether.c,
g_ffs.c, multi.c, ncm.c, nokia.c.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
2013-05-23 09:22:03 +02:00
USB_ETHERNET_MODULE_PARAMETERS ( ) ;
2008-08-18 17:43:56 -07:00
/*-------------------------------------------------------------------------*/
2008-06-19 18:20:26 -07:00
static struct usb_device_descriptor device_desc = {
. bLength = sizeof device_desc ,
. bDescriptorType = USB_DT_DEVICE ,
2009-02-11 14:11:36 -08:00
. bcdUSB = cpu_to_le16 ( 0x0200 ) ,
2008-06-19 18:20:26 -07:00
. bDeviceClass = USB_CLASS_COMM ,
. bDeviceSubClass = 0 ,
. bDeviceProtocol = 0 ,
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id can be overridden by module parameters. */
2009-02-11 14:11:36 -08:00
. idVendor = cpu_to_le16 ( CDC_VENDOR_NUM ) ,
. idProduct = cpu_to_le16 ( CDC_PRODUCT_NUM ) ,
2008-06-19 18:20:26 -07:00
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
. bNumConfigurations = 1 ,
} ;
static struct usb_otg_descriptor otg_descriptor = {
. bLength = sizeof otg_descriptor ,
. bDescriptorType = USB_DT_OTG ,
/* REVISIT SRP-only hardware is possible, although
* it would not be called " OTG " . . .
*/
. bmAttributes = USB_OTG_SRP | USB_OTG_HNP ,
} ;
static const struct usb_descriptor_header * otg_desc [ ] = {
( struct usb_descriptor_header * ) & otg_descriptor ,
NULL ,
} ;
/* string IDs are assigned dynamically */
static struct usb_string strings_dev [ ] = {
2012-09-10 15:01:58 +02:00
[ USB_GADGET_MANUFACTURER_IDX ] . s = " " ,
2012-09-06 20:11:21 +02:00
[ USB_GADGET_PRODUCT_IDX ] . s = DRIVER_DESC ,
[ USB_GADGET_SERIAL_IDX ] . s = " " ,
2008-06-19 18:20:26 -07:00
{ } /* end of list */
} ;
static struct usb_gadget_strings stringtab_dev = {
. language = 0x0409 , /* en-us */
. strings = strings_dev ,
} ;
static struct usb_gadget_strings * dev_strings [ ] = {
& stringtab_dev ,
NULL ,
} ;
/*-------------------------------------------------------------------------*/
2012-12-23 21:10:09 +01:00
static struct usb_function * f_acm ;
static struct usb_function_instance * fi_serial ;
2008-06-19 18:20:26 -07:00
2013-05-23 10:32:04 +02:00
static struct usb_function * f_ecm ;
static struct usb_function_instance * fi_ecm ;
2008-06-19 18:20:26 -07:00
/*
* We _always_ have both CDC ECM and CDC ACM functions .
*/
2010-08-12 17:43:52 +02:00
static int __init cdc_do_config ( struct usb_configuration * c )
2008-06-19 18:20:26 -07:00
{
int status ;
if ( gadget_is_otg ( c - > cdev - > gadget ) ) {
c - > descriptors = otg_desc ;
c - > bmAttributes | = USB_CONFIG_ATT_WAKEUP ;
}
2013-05-23 10:32:04 +02:00
f_ecm = usb_get_function ( fi_ecm ) ;
if ( IS_ERR ( f_ecm ) ) {
status = PTR_ERR ( f_ecm ) ;
goto err_get_ecm ;
}
status = usb_add_function ( c , f_ecm ) ;
if ( status )
goto err_add_ecm ;
2008-06-19 18:20:26 -07:00
2012-12-23 21:10:09 +01:00
f_acm = usb_get_function ( fi_serial ) ;
2013-04-06 17:25:21 +08:00
if ( IS_ERR ( f_acm ) ) {
status = PTR_ERR ( f_acm ) ;
2013-08-01 16:07:48 +02:00
goto err_get_acm ;
2013-04-06 17:25:21 +08:00
}
2012-12-23 21:10:09 +01:00
status = usb_add_function ( c , f_acm ) ;
if ( status )
2013-05-23 10:32:04 +02:00
goto err_add_acm ;
2008-06-19 18:20:26 -07:00
return 0 ;
2013-05-23 10:32:04 +02:00
err_add_acm :
2012-12-23 21:10:09 +01:00
usb_put_function ( f_acm ) ;
2013-05-23 10:32:04 +02:00
err_get_acm :
usb_remove_function ( c , f_ecm ) ;
err_add_ecm :
usb_put_function ( f_ecm ) ;
err_get_ecm :
2012-12-23 21:10:09 +01:00
return status ;
2008-06-19 18:20:26 -07:00
}
static struct usb_configuration cdc_config_driver = {
. label = " CDC Composite (ECM + ACM) " ,
. bConfigurationValue = 1 ,
/* .iConfiguration = DYNAMIC */
. bmAttributes = USB_CONFIG_ATT_SELFPOWER ,
} ;
/*-------------------------------------------------------------------------*/
2010-08-12 17:43:52 +02:00
static int __init cdc_bind ( struct usb_composite_dev * cdev )
2008-06-19 18:20:26 -07:00
{
struct usb_gadget * gadget = cdev - > gadget ;
2013-05-23 10:32:04 +02:00
struct f_ecm_opts * ecm_opts ;
2008-06-19 18:20:26 -07:00
int status ;
if ( ! can_support_ecm ( cdev - > gadget ) ) {
2008-08-18 17:43:56 -07:00
dev_err ( & gadget - > dev , " controller '%s' not usable \n " ,
gadget - > name ) ;
2008-06-19 18:20:26 -07:00
return - EINVAL ;
}
2013-05-23 10:32:04 +02:00
fi_ecm = usb_get_function_instance ( " ecm " ) ;
if ( IS_ERR ( fi_ecm ) )
return PTR_ERR ( fi_ecm ) ;
ecm_opts = container_of ( fi_ecm , struct f_ecm_opts , func_inst ) ;
gether_set_qmult ( ecm_opts - > net , qmult ) ;
if ( ! gether_set_host_addr ( ecm_opts - > net , host_addr ) )
pr_info ( " using host ethernet address: %s " , host_addr ) ;
if ( ! gether_set_dev_addr ( ecm_opts - > net , dev_addr ) )
pr_info ( " using self ethernet address: %s " , dev_addr ) ;
fi_serial = usb_get_function_instance ( " acm " ) ;
if ( IS_ERR ( fi_serial ) ) {
status = PTR_ERR ( fi_serial ) ;
goto fail ;
}
2008-06-19 18:20:26 -07:00
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue .
*/
2012-09-06 20:11:16 +02:00
status = usb_string_ids_tab ( cdev , strings_dev ) ;
2008-06-19 18:20:26 -07:00
if ( status < 0 )
goto fail1 ;
2012-09-06 20:11:21 +02:00
device_desc . iManufacturer = strings_dev [ USB_GADGET_MANUFACTURER_IDX ] . id ;
device_desc . iProduct = strings_dev [ USB_GADGET_PRODUCT_IDX ] . id ;
2008-06-19 18:20:26 -07:00
/* register our configuration */
2010-08-12 17:43:55 +02:00
status = usb_add_config ( cdev , & cdc_config_driver , cdc_do_config ) ;
2008-06-19 18:20:26 -07:00
if ( status < 0 )
goto fail1 ;
2012-09-10 15:01:53 +02:00
usb_composite_overwrite_options ( cdev , & coverwrite ) ;
2008-08-18 17:43:56 -07:00
dev_info ( & gadget - > dev , " %s, version: " DRIVER_VERSION " \n " ,
DRIVER_DESC ) ;
2008-06-19 18:20:26 -07:00
return 0 ;
fail1 :
2013-05-23 10:32:04 +02:00
usb_put_function_instance ( fi_serial ) ;
fail :
usb_put_function_instance ( fi_ecm ) ;
2008-06-19 18:20:26 -07:00
return status ;
}
static int __exit cdc_unbind ( struct usb_composite_dev * cdev )
{
2012-12-23 21:10:09 +01:00
usb_put_function ( f_acm ) ;
usb_put_function_instance ( fi_serial ) ;
2013-05-23 10:32:04 +02:00
if ( ! IS_ERR_OR_NULL ( f_ecm ) )
usb_put_function ( f_ecm ) ;
if ( ! IS_ERR_OR_NULL ( fi_ecm ) )
usb_put_function_instance ( fi_ecm ) ;
2008-06-19 18:20:26 -07:00
return 0 ;
}
2012-09-06 20:11:03 +02:00
static __refdata struct usb_composite_driver cdc_driver = {
2008-06-19 18:20:26 -07:00
. name = " g_cdc " ,
. dev = & device_desc ,
. strings = dev_strings ,
2011-06-29 16:41:49 +03:00
. max_speed = USB_SPEED_HIGH ,
2012-09-06 20:11:04 +02:00
. bind = cdc_bind ,
2008-06-19 18:20:26 -07:00
. unbind = __exit_p ( cdc_unbind ) ,
} ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_AUTHOR ( " David Brownell " ) ;
MODULE_LICENSE ( " GPL " ) ;
static int __init init ( void )
{
2012-09-06 20:11:04 +02:00
return usb_composite_probe ( & cdc_driver ) ;
2008-06-19 18:20:26 -07:00
}
module_init ( init ) ;
static void __exit cleanup ( void )
{
usb_composite_unregister ( & cdc_driver ) ;
}
module_exit ( cleanup ) ;