linux/drivers/usb/gadget/nokia.c
<<
>>
Prefs
   1/*
   2 * nokia.c -- Nokia Composite Gadget Driver
   3 *
   4 * Copyright (C) 2008-2010 Nokia Corporation
   5 * Contact: Felipe Balbi <felipe.balbi@nokia.com>
   6 *
   7 * This gadget driver borrows from serial.c which is:
   8 *
   9 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
  10 * Copyright (C) 2008 by David Brownell
  11 * Copyright (C) 2008 by Nokia Corporation
  12 *
  13 * This software is distributed under the terms of the GNU General
  14 * Public License ("GPL") as published by the Free Software Foundation,
  15 * version 2 of that License.
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/utsname.h>
  20#include <linux/device.h>
  21
  22#include "u_serial.h"
  23#include "u_ether.h"
  24#include "u_phonet.h"
  25#include "gadget_chips.h"
  26
  27/* Defines */
  28
  29#define NOKIA_VERSION_NUM               0x0211
  30#define NOKIA_LONG_NAME                 "N900 (PC-Suite Mode)"
  31
  32/*-------------------------------------------------------------------------*/
  33
  34/*
  35 * Kbuild is not very cooperative with respect to linking separately
  36 * compiled library objects into one module.  So for now we won't use
  37 * separate compilation ... ensuring init/exit sections work to shrink
  38 * the runtime footprint, and giving us at least some parts of what
  39 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  40 */
  41#include "composite.c"
  42#include "usbstring.c"
  43#include "config.c"
  44#include "epautoconf.c"
  45
  46#include "u_serial.c"
  47#include "f_acm.c"
  48#include "f_ecm.c"
  49#include "f_obex.c"
  50#include "f_serial.c"
  51#include "f_phonet.c"
  52#include "u_ether.c"
  53
  54/*-------------------------------------------------------------------------*/
  55
  56#define NOKIA_VENDOR_ID                 0x0421  /* Nokia */
  57#define NOKIA_PRODUCT_ID                0x01c8  /* Nokia Gadget */
  58
  59/* string IDs are assigned dynamically */
  60
  61#define STRING_MANUFACTURER_IDX         0
  62#define STRING_PRODUCT_IDX              1
  63#define STRING_DESCRIPTION_IDX          2
  64
  65static char manufacturer_nokia[] = "Nokia";
  66static const char product_nokia[] = NOKIA_LONG_NAME;
  67static const char description_nokia[] = "PC-Suite Configuration";
  68
  69static struct usb_string strings_dev[] = {
  70        [STRING_MANUFACTURER_IDX].s = manufacturer_nokia,
  71        [STRING_PRODUCT_IDX].s = NOKIA_LONG_NAME,
  72        [STRING_DESCRIPTION_IDX].s = description_nokia,
  73        {  } /* end of list */
  74};
  75
  76static struct usb_gadget_strings stringtab_dev = {
  77        .language       = 0x0409,       /* en-us */
  78        .strings        = strings_dev,
  79};
  80
  81static struct usb_gadget_strings *dev_strings[] = {
  82        &stringtab_dev,
  83        NULL,
  84};
  85
  86static struct usb_device_descriptor device_desc = {
  87        .bLength                = USB_DT_DEVICE_SIZE,
  88        .bDescriptorType        = USB_DT_DEVICE,
  89        .bcdUSB                 = __constant_cpu_to_le16(0x0200),
  90        .bDeviceClass           = USB_CLASS_COMM,
  91        .idVendor               = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
  92        .idProduct              = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
  93        /* .iManufacturer = DYNAMIC */
  94        /* .iProduct = DYNAMIC */
  95        .bNumConfigurations =   1,
  96};
  97
  98/*-------------------------------------------------------------------------*/
  99
 100/* Module */
 101MODULE_DESCRIPTION("Nokia composite gadget driver for N900");
 102MODULE_AUTHOR("Felipe Balbi");
 103MODULE_LICENSE("GPL");
 104
 105/*-------------------------------------------------------------------------*/
 106
 107static u8 hostaddr[ETH_ALEN];
 108
 109static int __init nokia_bind_config(struct usb_configuration *c)
 110{
 111        int status = 0;
 112
 113        status = phonet_bind_config(c);
 114        if (status)
 115                printk(KERN_DEBUG "could not bind phonet config\n");
 116
 117        status = obex_bind_config(c, 0);
 118        if (status)
 119                printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 120
 121        status = obex_bind_config(c, 1);
 122        if (status)
 123                printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 124
 125        status = acm_bind_config(c, 2);
 126        if (status)
 127                printk(KERN_DEBUG "could not bind acm config\n");
 128
 129        status = ecm_bind_config(c, hostaddr);
 130        if (status)
 131                printk(KERN_DEBUG "could not bind ecm config\n");
 132
 133        return status;
 134}
 135
 136static struct usb_configuration nokia_config_500ma_driver = {
 137        .label          = "Bus Powered",
 138        .bConfigurationValue = 1,
 139        /* .iConfiguration = DYNAMIC */
 140        .bmAttributes   = USB_CONFIG_ATT_ONE,
 141        .bMaxPower      = 250, /* 500mA */
 142};
 143
 144static struct usb_configuration nokia_config_100ma_driver = {
 145        .label          = "Self Powered",
 146        .bConfigurationValue = 2,
 147        /* .iConfiguration = DYNAMIC */
 148        .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
 149        .bMaxPower      = 50, /* 100 mA */
 150};
 151
 152static int __init nokia_bind(struct usb_composite_dev *cdev)
 153{
 154        int                     gcnum;
 155        struct usb_gadget       *gadget = cdev->gadget;
 156        int                     status;
 157
 158        status = gphonet_setup(cdev->gadget);
 159        if (status < 0)
 160                goto err_phonet;
 161
 162        status = gserial_setup(cdev->gadget, 3);
 163        if (status < 0)
 164                goto err_serial;
 165
 166        status = gether_setup(cdev->gadget, hostaddr);
 167        if (status < 0)
 168                goto err_ether;
 169
 170        status = usb_string_id(cdev);
 171        if (status < 0)
 172                goto err_usb;
 173        strings_dev[STRING_MANUFACTURER_IDX].id = status;
 174
 175        device_desc.iManufacturer = status;
 176
 177        status = usb_string_id(cdev);
 178        if (status < 0)
 179                goto err_usb;
 180        strings_dev[STRING_PRODUCT_IDX].id = status;
 181
 182        device_desc.iProduct = status;
 183
 184        /* config description */
 185        status = usb_string_id(cdev);
 186        if (status < 0)
 187                goto err_usb;
 188        strings_dev[STRING_DESCRIPTION_IDX].id = status;
 189
 190        nokia_config_500ma_driver.iConfiguration = status;
 191        nokia_config_100ma_driver.iConfiguration = status;
 192
 193        /* set up other descriptors */
 194        gcnum = usb_gadget_controller_number(gadget);
 195        if (gcnum >= 0)
 196                device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM);
 197        else {
 198                /* this should only work with hw that supports altsettings
 199                 * and several endpoints, anything else, panic.
 200                 */
 201                pr_err("nokia_bind: controller '%s' not recognized\n",
 202                        gadget->name);
 203                goto err_usb;
 204        }
 205
 206        /* finally register the configuration */
 207        status = usb_add_config(cdev, &nokia_config_500ma_driver,
 208                        nokia_bind_config);
 209        if (status < 0)
 210                goto err_usb;
 211
 212        status = usb_add_config(cdev, &nokia_config_100ma_driver,
 213                        nokia_bind_config);
 214        if (status < 0)
 215                goto err_usb;
 216
 217        dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 218
 219        return 0;
 220
 221err_usb:
 222        gether_cleanup();
 223err_ether:
 224        gserial_cleanup();
 225err_serial:
 226        gphonet_cleanup();
 227err_phonet:
 228        return status;
 229}
 230
 231static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 232{
 233        gphonet_cleanup();
 234        gserial_cleanup();
 235        gether_cleanup();
 236
 237        return 0;
 238}
 239
 240static struct usb_composite_driver nokia_driver = {
 241        .name           = "g_nokia",
 242        .dev            = &device_desc,
 243        .strings        = dev_strings,
 244        .max_speed      = USB_SPEED_HIGH,
 245        .unbind         = __exit_p(nokia_unbind),
 246};
 247
 248static int __init nokia_init(void)
 249{
 250        return usb_composite_probe(&nokia_driver, nokia_bind);
 251}
 252module_init(nokia_init);
 253
 254static void __exit nokia_cleanup(void)
 255{
 256        usb_composite_unregister(&nokia_driver);
 257}
 258module_exit(nokia_cleanup);
 259
 260