1fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/* 2fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * acm_ms.c -- Composite driver, with ACM and mass storage support 3fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * 4fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Copyright (C) 2008 David Brownell 5fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Copyright (C) 2008 Nokia Corporation 6fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Author: David Brownell 7fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Modified: Klaus Schwarzkopf <schwarzkopf@sensortherm.de> 8fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * 9fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Heavily based on multi.c and cdc2.c 10fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * 11fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * This program is free software; you can redistribute it and/or modify 12fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * it under the terms of the GNU General Public License as published by 13fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * the Free Software Foundation; either version 2 of the License, or 14fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * (at your option) any later version. 15fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf */ 16fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 17fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf#include <linux/kernel.h> 18721e2e91945bc2520d57d795dfe1b502ecec567cSebastian Andrzej Siewior#include <linux/module.h> 19fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 20fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf#include "u_serial.h" 21fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 22fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf#define DRIVER_DESC "Composite Gadget (ACM + MS)" 23fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf#define DRIVER_VERSION "2011/10/10" 24fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 25fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/*-------------------------------------------------------------------------*/ 26fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 27fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/* 28fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! 29fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Instead: allocate your own, using normal USB-IF procedures. 30fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf */ 31fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf#define ACM_MS_VENDOR_NUM 0x1d6b /* Linux Foundation */ 32fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf#define ACM_MS_PRODUCT_NUM 0x0106 /* Composite Gadget: ACM + MS*/ 33fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 34e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz#include "f_mass_storage.h" 35fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 36fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/*-------------------------------------------------------------------------*/ 377d16e8d3eb704f5f6eb5a271d5758b495634e8e6Sebastian Andrzej SiewiorUSB_GADGET_COMPOSITE_OPTIONS(); 38fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 39fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct usb_device_descriptor device_desc = { 40fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bLength = sizeof device_desc, 41fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bDescriptorType = USB_DT_DEVICE, 42fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 43fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bcdUSB = cpu_to_le16(0x0200), 44fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 45fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bDeviceClass = USB_CLASS_MISC /* 0xEF */, 46fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bDeviceSubClass = 2, 47fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bDeviceProtocol = 1, 48fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 49fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* .bMaxPacketSize0 = f(hardware) */ 50fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 51fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* Vendor and product id can be overridden by module parameters. */ 52fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .idVendor = cpu_to_le16(ACM_MS_VENDOR_NUM), 53fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .idProduct = cpu_to_le16(ACM_MS_PRODUCT_NUM), 54fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* .bcdDevice = f(hardware) */ 55fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* .iManufacturer = DYNAMIC */ 56fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* .iProduct = DYNAMIC */ 57fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* NO SERIAL NUMBER */ 58fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /*.bNumConfigurations = DYNAMIC*/ 59fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 60fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 61fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct usb_otg_descriptor otg_descriptor = { 62fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bLength = sizeof otg_descriptor, 63fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bDescriptorType = USB_DT_OTG, 64fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 65fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* 66fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * REVISIT SRP-only hardware is possible, although 67fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * it would not be called "OTG" ... 68fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf */ 69fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 70fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 71fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 72fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic const struct usb_descriptor_header *otg_desc[] = { 73fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf (struct usb_descriptor_header *) &otg_descriptor, 74fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf NULL, 75fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 76fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 77fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/* string IDs are assigned dynamically */ 78fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct usb_string strings_dev[] = { 79cc2683c318a5bf192b75cd5c343b51009db0cf6cSebastian Andrzej Siewior [USB_GADGET_MANUFACTURER_IDX].s = "", 80276e2e4f1f3e07a0ad891bf757dbcfd655ff5f91Sebastian Andrzej Siewior [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, 81276e2e4f1f3e07a0ad891bf757dbcfd655ff5f91Sebastian Andrzej Siewior [USB_GADGET_SERIAL_IDX].s = "", 82fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf { } /* end of list */ 83fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 84fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 85fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct usb_gadget_strings stringtab_dev = { 86fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .language = 0x0409, /* en-us */ 87fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .strings = strings_dev, 88fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 89fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 90fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct usb_gadget_strings *dev_strings[] = { 91fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf &stringtab_dev, 92fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf NULL, 93fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 94fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 95fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/****************************** Configurations ******************************/ 96fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 97fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; 986fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz#ifdef CONFIG_USB_GADGET_DEBUG_FILES 996fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz 1006fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewiczstatic unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; 1016fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz 1026fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz#else 1036fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz 1046fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz/* 1056fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz * Number of buffers we will use. 1066fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz * 2 is usually enough for good buffering pipeline 1076fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz */ 1086fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS 1096fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz 1100c8b1992b4a180704a887b3c9128aa103b5ef60fGreg Kroah-Hartman#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ 1116fdc5dd25e0cd5afc114fe65427150c65f0eb67bAndrzej Pietrasiewicz 112fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus SchwarzkopfFSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); 113fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 114fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/*-------------------------------------------------------------------------*/ 1155f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewiorstatic struct usb_function *f_acm; 1165f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewiorstatic struct usb_function_instance *f_acm_inst; 117e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 118e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczstatic struct usb_function_instance *fi_msg; 119e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczstatic struct usb_function *f_msg; 120e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 121fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/* 122fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * We _always_ have both ACM and mass storage functions. 123fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf */ 124fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic int __init acm_ms_do_config(struct usb_configuration *c) 125fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf{ 126e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz struct fsg_opts *opts; 127fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf int status; 128fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 129fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf if (gadget_is_otg(c->cdev->gadget)) { 130fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf c->descriptors = otg_desc; 131fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 132fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf } 133fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 134e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz opts = fsg_opts_from_func_inst(fi_msg); 1355f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior 1365f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior f_acm = usb_get_function(f_acm_inst); 137e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (IS_ERR(f_acm)) 138e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz return PTR_ERR(f_acm); 139e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 140e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz f_msg = usb_get_function(fi_msg); 141e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (IS_ERR(f_msg)) { 142e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = PTR_ERR(f_msg); 143e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto put_acm; 1445f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior } 145fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 1465f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior status = usb_add_function(c, f_acm); 147fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf if (status < 0) 148e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto put_msg; 149fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 150e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = fsg_common_run_thread(opts->common); 151e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (status) 152e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto remove_acm; 153e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 154e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = usb_add_function(c, f_msg); 155e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (status) 156e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto remove_acm; 157fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 158fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf return 0; 159e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczremove_acm: 1605f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior usb_remove_function(c, f_acm); 161e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczput_msg: 162e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz usb_put_function(f_msg); 163e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczput_acm: 1645f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior usb_put_function(f_acm); 1655f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior return status; 166fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf} 167fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 168fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic struct usb_configuration acm_ms_config_driver = { 169fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .label = DRIVER_DESC, 170fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bConfigurationValue = 1, 171fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* .iConfiguration = DYNAMIC */ 172fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 173fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 174fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 175fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf/*-------------------------------------------------------------------------*/ 176fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 177fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic int __init acm_ms_bind(struct usb_composite_dev *cdev) 178fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf{ 179fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf struct usb_gadget *gadget = cdev->gadget; 180e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz struct fsg_opts *opts; 181e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz struct fsg_config config; 182fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf int status; 183fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 184e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz f_acm_inst = usb_get_function_instance("acm"); 185e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (IS_ERR(f_acm_inst)) 186e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz return PTR_ERR(f_acm_inst); 187e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 188e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fi_msg = usb_get_function_instance("mass_storage"); 189e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (IS_ERR(fi_msg)) { 190e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = PTR_ERR(fi_msg); 191e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail_get_msg; 192fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf } 193fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 194e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz /* set up mass storage function */ 195e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers); 196e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz opts = fsg_opts_from_func_inst(fi_msg); 197e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 198e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz opts->no_configfs = true; 199e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); 200e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (status) 201e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail; 202e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 203e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = fsg_common_set_nluns(opts->common, config.nluns); 204e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (status) 205e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail_set_nluns; 206e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 207e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); 208e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (status) 209e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail_set_cdev; 210e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 211e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fsg_common_set_sysfs(opts->common, true); 212e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz status = fsg_common_create_luns(opts->common, &config); 213e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz if (status) 214e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail_set_cdev; 215e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz 216e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fsg_common_set_inquiry_string(opts->common, config.vendor_name, 217e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz config.product_name); 218fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* 219fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * Allocate string descriptor numbers ... note that string 220fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf * contents can be overridden by the composite_dev glue. 221fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf */ 222e1f15ccbae40b55a4e2591373ea5f1808cf29855Sebastian Andrzej Siewior status = usb_string_ids_tab(cdev, strings_dev); 223fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf if (status < 0) 224e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail_string_ids; 225276e2e4f1f3e07a0ad891bf757dbcfd655ff5f91Sebastian Andrzej Siewior device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; 226276e2e4f1f3e07a0ad891bf757dbcfd655ff5f91Sebastian Andrzej Siewior device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 227fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 228fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* register our configuration */ 229fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); 230fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf if (status < 0) 231e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz goto fail_string_ids; 232fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 2337d16e8d3eb704f5f6eb5a271d5758b495634e8e6Sebastian Andrzej Siewior usb_composite_overwrite_options(cdev, &coverwrite); 234fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", 235fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf DRIVER_DESC); 236fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf return 0; 237fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 238fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf /* error recovery */ 239e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczfail_string_ids: 240e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fsg_common_remove_luns(opts->common); 241e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczfail_set_cdev: 242e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fsg_common_free_luns(opts->common); 243e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczfail_set_nluns: 244e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz fsg_common_free_buffers(opts->common); 245e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczfail: 246e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz usb_put_function_instance(fi_msg); 247e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewiczfail_get_msg: 248e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz usb_put_function_instance(f_acm_inst); 249fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf return status; 250fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf} 251fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 252fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopfstatic int __exit acm_ms_unbind(struct usb_composite_dev *cdev) 253fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf{ 254e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz usb_put_function(f_msg); 255e6c661ef18177f2f1ce32210140f8497851d9388Andrzej Pietrasiewicz usb_put_function_instance(fi_msg); 2565f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior usb_put_function(f_acm); 2575f72bbfd9f427565c85e71a63d47b3448e79a466Sebastian Andrzej Siewior usb_put_function_instance(f_acm_inst); 258fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf return 0; 259fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf} 260fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 261c2ec75c25112c9e0d9053f55ba8cf0a358d4a354Sebastian Andrzej Siewiorstatic __refdata struct usb_composite_driver acm_ms_driver = { 262fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .name = "g_acm_ms", 263fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .dev = &device_desc, 2646f47209b271661ecd5929397cbe646ff247f01b6Steve Bennett .max_speed = USB_SPEED_SUPER, 265fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .strings = dev_strings, 26603e42bd5937c4c24e411690ab165627e93c258b5Sebastian Andrzej Siewior .bind = acm_ms_bind, 267fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf .unbind = __exit_p(acm_ms_unbind), 268fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf}; 269fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus Schwarzkopf 270909346a819c5b81420d861bd53abd1140b26104eTobias Klausermodule_usb_composite_driver(acm_ms_driver); 271909346a819c5b81420d861bd53abd1140b26104eTobias Klauser 272fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus SchwarzkopfMODULE_DESCRIPTION(DRIVER_DESC); 273fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus SchwarzkopfMODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>"); 274fa3ae0c158c70e6cf227b3a194659ee7fed8c588Klaus SchwarzkopfMODULE_LICENSE("GPL v2"); 275