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