From patchwork Tue Jan 5 14:10:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felipe Balbi X-Patchwork-Id: 71011 X-Patchwork-Delegate: me@felipebalbi.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o05ED5oq010990 for ; Tue, 5 Jan 2010 14:13:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754497Ab0AEOM5 (ORCPT ); Tue, 5 Jan 2010 09:12:57 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754436Ab0AEOMz (ORCPT ); Tue, 5 Jan 2010 09:12:55 -0500 Received: from smtp.nokia.com ([192.100.122.230]:53774 "EHLO mgw-mx03.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753853Ab0AEOMx (ORCPT ); Tue, 5 Jan 2010 09:12:53 -0500 Received: from vaebh105.NOE.Nokia.com (vaebh105.europe.nokia.com [10.160.244.31]) by mgw-mx03.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id o05ECERI020162; Tue, 5 Jan 2010 16:12:46 +0200 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by vaebh105.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 5 Jan 2010 16:12:34 +0200 Received: from mgw-da02.ext.nokia.com ([147.243.128.26]) by esebh102.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Tue, 5 Jan 2010 16:12:33 +0200 Received: from localhost.localdomain (esdhcp04088.research.nokia.com [172.21.40.88]) by mgw-da02.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id o05ECQaZ025828; Tue, 5 Jan 2010 16:12:28 +0200 From: Felipe Balbi To: linux-usb@vger.kernel.org Cc: Linux OMAP Mailing List , Tony Lindgren , Greg KH , Felipe Balbi Subject: [PATCH 1/2] usb: gadget: introduce g_nokia gadget driver Date: Tue, 5 Jan 2010 16:10:13 +0200 Message-Id: <1262700614-16438-1-git-send-email-felipe.balbi@nokia.com> X-Mailer: git-send-email 1.6.6.rc0 X-OriginalArrivalTime: 05 Jan 2010 14:12:33.0932 (UTC) FILETIME=[203394C0:01CA8E11] X-Nokia-AV: Clean Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index ee41120..7460cd7 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -812,6 +812,16 @@ config USB_CDC_COMPOSITE Say "y" to link the driver statically, or "m" to build a dynamically linked module. +config USB_G_NOKIA + tristate "Nokia composite gadget" + depends on PHONET + help + The Nokia composite gadget provides support for acm, obex + and phonet in only one composite gadget driver. + + It's only really useful for N900 hardware. If you're building + a kernel for N900, say Y or M here. If unsure, say N. + config USB_G_MULTI tristate "Multifunction Composite Gadget (EXPERIMENTAL)" depends on BLOCK && NET diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 2e2c047..43b51da 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -43,6 +43,7 @@ g_mass_storage-objs := mass_storage.o g_printer-objs := printer.o g_cdc-objs := cdc2.o g_multi-objs := multi.o +g_nokia-objs := nokia.o obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_AUDIO) += g_audio.o @@ -55,4 +56,5 @@ obj-$(CONFIG_USB_G_PRINTER) += g_printer.o obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o obj-$(CONFIG_USB_G_MULTI) += g_multi.o +obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c new file mode 100644 index 0000000..7d6b66a --- /dev/null +++ b/drivers/usb/gadget/nokia.c @@ -0,0 +1,259 @@ +/* + * nokia.c -- Nokia Composite Gadget Driver + * + * Copyright (C) 2008-2010 Nokia Corporation + * Contact: Felipe Balbi + * + * This gadget driver borrows from serial.c which is: + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 by David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * version 2 of that License. + */ + +#include +#include +#include + +#include "u_serial.h" +#include "u_ether.h" +#include "u_phonet.h" +#include "gadget_chips.h" + +/* Defines */ + +#define NOKIA_VERSION_NUM 0x0211 +#define NOKIA_LONG_NAME "N900 (PC-Suite Mode)" + +/*-------------------------------------------------------------------------*/ + +/* + * Kbuild is not very cooperative with respect to linking separately + * compiled library objects into one module. So for now we won't use + * separate compilation ... ensuring init/exit sections work to shrink + * the runtime footprint, and giving us at least some parts of what + * a "gcc --combine ... part1.c part2.c part3.c ... " build would. + */ +#include "composite.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" + +#include "u_serial.c" +#include "f_acm.c" +#include "f_ecm.c" +#include "f_obex.c" +#include "f_serial.c" +#include "f_phonet.c" +#include "u_ether.c" + +/*-------------------------------------------------------------------------*/ + +#define NOKIA_VENDOR_ID 0x0421 /* Nokia */ +#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ + +/* string IDs are assigned dynamically */ + +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 +#define STRING_DESCRIPTION_IDX 2 + +static char manufacturer_nokia[] = "Nokia"; +static const char product_nokia[] = NOKIA_LONG_NAME; +static const char description_nokia[] = "PC-Suite Configuration"; + +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer_nokia, + [STRING_PRODUCT_IDX].s = NOKIA_LONG_NAME, + [STRING_DESCRIPTION_IDX].s = description_nokia, + { } /* 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, +}; + +static struct usb_device_descriptor device_desc = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = __constant_cpu_to_le16(0x0200), + .bDeviceClass = USB_CLASS_COMM, + .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID), + .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID), + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ + .bNumConfigurations = 1, +}; + +/*-------------------------------------------------------------------------*/ + +/* Module */ +MODULE_DESCRIPTION("Nokia composite gadget driver for N900"); +MODULE_AUTHOR("Felipe Balbi"); +MODULE_LICENSE("GPL"); + +/*-------------------------------------------------------------------------*/ + +static u8 hostaddr[ETH_ALEN]; + +static int __init nokia_bind_config(struct usb_configuration *c) +{ + int status = 0; + + status = phonet_bind_config(c); + if (status) + printk(KERN_DEBUG "could not bind phonet config\n"); + + status = obex_bind_config(c, 0); + if (status) + printk(KERN_DEBUG "could not bind obex config %d\n", 0); + + status = obex_bind_config(c, 1); + if (status) + printk(KERN_DEBUG "could not bind obex config %d\n", 0); + + status = acm_bind_config(c, 2); + if (status) + printk(KERN_DEBUG "could not bind acm config\n"); + + status = ecm_bind_config(c, hostaddr); + if (status) + printk(KERN_DEBUG "could not bind ecm config\n"); + + return status; +} + +static struct usb_configuration nokia_config_500ma_driver = { + .label = "Bus Powered", + .bind = nokia_bind_config, + .bConfigurationValue = 1, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_ONE, + .bMaxPower = 250, /* 500mA */ +}; + +static struct usb_configuration nokia_config_100ma_driver = { + .label = "Self Powered", + .bind = nokia_bind_config, + .bConfigurationValue = 2, + /* .iConfiguration = DYNAMIC */ + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 50, /* 100 mA */ +}; + +static int __init nokia_bind(struct usb_composite_dev *cdev) +{ + int gcnum; + struct usb_gadget *gadget = cdev->gadget; + int status; + + status = gphonet_setup(cdev->gadget); + if (status < 0) + goto err_phonet; + + status = gserial_setup(cdev->gadget, 3); + if (status < 0) + goto err_serial; + + status = gether_setup(cdev->gadget, hostaddr); + if (status < 0) + goto err_ether; + + status = usb_string_id(cdev); + if (status < 0) + goto err_usb; + strings_dev[STRING_MANUFACTURER_IDX].id = status; + + device_desc.iManufacturer = status; + + status = usb_string_id(cdev); + if (status < 0) + goto err_usb; + strings_dev[STRING_PRODUCT_IDX].id = status; + + device_desc.iProduct = status; + + /* config description */ + status = usb_string_id(cdev); + if (status < 0) + goto err_usb; + strings_dev[STRING_DESCRIPTION_IDX].id = status; + + nokia_config_500ma_driver.iConfiguration = status; + nokia_config_100ma_driver.iConfiguration = status; + + /* set up other descriptors */ + gcnum = usb_gadget_controller_number(gadget); + if (gcnum >= 0) + device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM); + else { + /* this should only work with hw that supports altsettings + * and several endpoints, anything else, panic. + */ + pr_err("nokia_bind: controller '%s' not recognized\n", + gadget->name); + goto err_usb; + } + + /* finaly register the configuration */ + status = usb_add_config(cdev, &nokia_config_500ma_driver); + if (status < 0) + goto err_usb; + + status = usb_add_config(cdev, &nokia_config_100ma_driver); + if (status < 0) + goto err_usb; + + dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME); + + return 0; + +err_usb: + gether_cleanup(); +err_ether: + gserial_cleanup(); +err_serial: + gphonet_cleanup(); +err_phonet: + return status; +} + +static int __exit nokia_unbind(struct usb_composite_dev *cdev) +{ + gphonet_cleanup(); + gserial_cleanup(); + gether_cleanup(); + + return 0; +} + +static struct usb_composite_driver nokia_driver = { + .name = "g_nokia", + .dev = &device_desc, + .strings = dev_strings, + .bind = nokia_bind, + .unbind = __exit_p(nokia_unbind), +}; + +static int __init nokia_init(void) +{ + return usb_composite_register(&nokia_driver); +} +module_init(nokia_init); + +static void __exit nokia_cleanup(void) +{ + usb_composite_unregister(&nokia_driver); +} +module_exit(nokia_cleanup); +