16c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* 26c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * ncm.c -- NCM gadget driver 36c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * 46c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Copyright (C) 2010 Nokia Corporation 56c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Contact: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> 66c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * 76c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * The driver borrows from ether.c which is: 86c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * 96c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Copyright (C) 2003-2005,2008 David Brownell 106c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger 116c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Copyright (C) 2008 Nokia Corporation 126c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * 136c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * This program is free software; you can redistribute it and/or modify 146c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * it under the terms of the GNU General Public License as published by 156c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * the Free Software Foundation; either version 2 of the License, or 166c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * (at your option) any later version. 176c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 186c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 196c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* #define DEBUG */ 206c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* #define VERBOSE_DEBUG */ 216c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 226c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include <linux/kernel.h> 236c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include <linux/utsname.h> 246c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 256c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 266c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "u_ether.h" 276c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 286c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#define DRIVER_DESC "NCM Gadget" 296c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 306c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/*-------------------------------------------------------------------------*/ 316c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 326c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* 336c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Kbuild is not very cooperative with respect to linking separately 346c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * compiled library objects into one module. So for now we won't use 356c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * separate compilation ... ensuring init/exit sections work to shrink 366c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * the runtime footprint, and giving us at least some parts of what 376c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 386c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 396c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "composite.c" 406c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "usbstring.c" 416c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "config.c" 426c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "epautoconf.c" 436c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 446c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "f_ncm.c" 456c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#include "u_ether.c" 466c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 476c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/*-------------------------------------------------------------------------*/ 486c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 496c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! 506c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * Instead: allocate your own, using normal USB-IF procedures. 516c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 526c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 536c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* Thanks to NetChip Technologies for donating this product ID. 546c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * It's for devices with only CDC Ethernet configurations. 556c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 566c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#define CDC_VENDOR_NUM 0x0525 /* NetChip */ 576c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ 586c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 596c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/*-------------------------------------------------------------------------*/ 606c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 616c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_device_descriptor device_desc = { 626c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bLength = sizeof device_desc, 636c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bDescriptorType = USB_DT_DEVICE, 646c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 656c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bcdUSB = cpu_to_le16 (0x0200), 666c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 676c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bDeviceClass = USB_CLASS_COMM, 686c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bDeviceSubClass = 0, 696c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bDeviceProtocol = 0, 706c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* .bMaxPacketSize0 = f(hardware) */ 716c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 726c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* Vendor and product id defaults change according to what configs 736c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * we support. (As does bNumConfigurations.) These values can 746c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * also be overridden by module parameters. 756c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 766c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .idVendor = cpu_to_le16 (CDC_VENDOR_NUM), 776c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .idProduct = cpu_to_le16 (CDC_PRODUCT_NUM), 786c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* .bcdDevice = f(hardware) */ 796c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* .iManufacturer = DYNAMIC */ 806c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* .iProduct = DYNAMIC */ 816c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* NO SERIAL NUMBER */ 826c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bNumConfigurations = 1, 836c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 846c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 856c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_otg_descriptor otg_descriptor = { 866c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bLength = sizeof otg_descriptor, 876c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bDescriptorType = USB_DT_OTG, 886c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 896c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* REVISIT SRP-only hardware is possible, although 906c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * it would not be called "OTG" ... 916c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 926c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 936c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 946c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 956c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic const struct usb_descriptor_header *otg_desc[] = { 966c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta (struct usb_descriptor_header *) &otg_descriptor, 976c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta NULL, 986c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 996c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1006c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1016c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/* string IDs are assigned dynamically */ 1026c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1036c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#define STRING_MANUFACTURER_IDX 0 1046c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta#define STRING_PRODUCT_IDX 1 1056c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1066c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic char manufacturer[50]; 1076c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1086c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_string strings_dev[] = { 1096c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta [STRING_MANUFACTURER_IDX].s = manufacturer, 1106c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta [STRING_PRODUCT_IDX].s = DRIVER_DESC, 1116c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta { } /* end of list */ 1126c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 1136c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1146c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_gadget_strings stringtab_dev = { 1156c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .language = 0x0409, /* en-us */ 1166c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .strings = strings_dev, 1176c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 1186c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1196c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_gadget_strings *dev_strings[] = { 1206c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta &stringtab_dev, 1216c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta NULL, 1226c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 1236c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1246c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic u8 hostaddr[ETH_ALEN]; 1256c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1266c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/*-------------------------------------------------------------------------*/ 1276c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1286c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic int __init ncm_do_config(struct usb_configuration *c) 1296c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta{ 1306c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* FIXME alloc iConfiguration string, set it in c->strings */ 1316c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1326c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta if (gadget_is_otg(c->cdev->gadget)) { 1336c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta c->descriptors = otg_desc; 1346c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 1356c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta } 1366c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1376c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta return ncm_bind_config(c, hostaddr); 1386c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta} 1396c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1406c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_configuration ncm_config_driver = { 1416c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* .label = f(hardware) */ 1426c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .label = "CDC Ethernet (NCM)", 1436c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bConfigurationValue = 1, 1446c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* .iConfiguration = DYNAMIC */ 1456c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 1466c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 1476c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1486c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta/*-------------------------------------------------------------------------*/ 1496c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1506c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic int __init gncm_bind(struct usb_composite_dev *cdev) 1516c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta{ 1526c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta int gcnum; 1536c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta struct usb_gadget *gadget = cdev->gadget; 1546c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta int status; 1556c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1566c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* set up network link layer */ 1576c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta status = gether_setup(cdev->gadget, hostaddr); 1586c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta if (status < 0) 1596c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta return status; 1606c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1616c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta gcnum = usb_gadget_controller_number(gadget); 1626c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta if (gcnum >= 0) 1636c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); 1646c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta else { 1656c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* We assume that can_support_ecm() tells the truth; 1666c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * but if the controller isn't recognized at all then 1676c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * that assumption is a bit more likely to be wrong. 1686c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 1696c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta dev_warn(&gadget->dev, 1706c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta "controller '%s' not recognized; trying %s\n", 1716c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta gadget->name, 1726c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta ncm_config_driver.label); 1736c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta device_desc.bcdDevice = 1746c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta cpu_to_le16(0x0300 | 0x0099); 1756c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta } 1766c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1776c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1786c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* Allocate string descriptor numbers ... note that string 1796c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta * contents can be overridden by the composite_dev glue. 1806c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta */ 1816c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1826c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta /* device descriptor strings: manufacturer, product */ 1836c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", 1846c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta init_utsname()->sysname, init_utsname()->release, 1856c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta gadget->name); 1866c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta status = usb_string_id(cdev); 1876c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta if (status < 0) 1886c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta goto fail; 1896c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta strings_dev[STRING_MANUFACTURER_IDX].id = status; 1906c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta device_desc.iManufacturer = status; 1916c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1926c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta status = usb_string_id(cdev); 1936c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta if (status < 0) 1946c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta goto fail; 1956c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta strings_dev[STRING_PRODUCT_IDX].id = status; 1966c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta device_desc.iProduct = status; 1976c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 1986c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta status = usb_add_config(cdev, &ncm_config_driver, 1996c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta ncm_do_config); 2006c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta if (status < 0) 2016c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta goto fail; 2026c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2036c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta dev_info(&gadget->dev, "%s\n", DRIVER_DESC); 2046c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2056c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta return 0; 2066c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2076c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutafail: 2086c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta gether_cleanup(); 2096c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta return status; 2106c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta} 2116c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2126c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic int __exit gncm_unbind(struct usb_composite_dev *cdev) 2136c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta{ 2146c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta gether_cleanup(); 2156c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta return 0; 2166c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta} 2176c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2186c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic struct usb_composite_driver ncm_driver = { 2196c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .name = "g_ncm", 2206c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .dev = &device_desc, 2216c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .strings = dev_strings, 22235a0e0bf6f6b2b900d461e9f35c286953b2b1afcTatyana Brokhman .max_speed = USB_SPEED_HIGH, 2236c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta .unbind = __exit_p(gncm_unbind), 2246c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta}; 2256c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2266c34d2888221ca3df81e29f598873b4fb6cf838dYauheni KaliutaMODULE_DESCRIPTION(DRIVER_DESC); 2276c34d2888221ca3df81e29f598873b4fb6cf838dYauheni KaliutaMODULE_AUTHOR("Yauheni Kaliuta"); 2286c34d2888221ca3df81e29f598873b4fb6cf838dYauheni KaliutaMODULE_LICENSE("GPL"); 2296c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2306c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic int __init init(void) 2316c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta{ 2326c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta return usb_composite_probe(&ncm_driver, gncm_bind); 2336c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta} 2346c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutamodule_init(init); 2356c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta 2366c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutastatic void __exit cleanup(void) 2376c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta{ 2386c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta usb_composite_unregister(&ncm_driver); 2396c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliuta} 2406c34d2888221ca3df81e29f598873b4fb6cf838dYauheni Kaliutamodule_exit(cleanup); 241