nokia.c (11169B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * nokia.c -- Nokia Composite Gadget Driver 4 * 5 * Copyright (C) 2008-2010 Nokia Corporation 6 * Contact: Felipe Balbi <felipe.balbi@nokia.com> 7 * 8 * This gadget driver borrows from serial.c which is: 9 * 10 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) 11 * Copyright (C) 2008 by David Brownell 12 * Copyright (C) 2008 by Nokia Corporation 13 */ 14 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/device.h> 18 19#include "u_serial.h" 20#include "u_ether.h" 21#include "u_phonet.h" 22#include "u_ecm.h" 23#include "f_mass_storage.h" 24 25/* Defines */ 26 27#define NOKIA_VERSION_NUM 0x0211 28#define NOKIA_LONG_NAME "N900 (PC-Suite Mode)" 29 30USB_GADGET_COMPOSITE_OPTIONS(); 31 32USB_ETHERNET_MODULE_PARAMETERS(); 33 34static struct fsg_module_parameters fsg_mod_data = { 35 .stall = 0, 36 .luns = 2, 37 .removable_count = 2, 38 .removable = { 1, 1, }, 39}; 40 41#ifdef CONFIG_USB_GADGET_DEBUG_FILES 42 43static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; 44 45#else 46 47/* 48 * Number of buffers we will use. 49 * 2 is usually enough for good buffering pipeline 50 */ 51#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS 52 53#endif /* CONFIG_USB_DEBUG */ 54 55FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); 56 57#define NOKIA_VENDOR_ID 0x0421 /* Nokia */ 58#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ 59 60/* string IDs are assigned dynamically */ 61 62#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX 63 64static char manufacturer_nokia[] = "Nokia"; 65static const char description_nokia[] = "PC-Suite Configuration"; 66 67static struct usb_string strings_dev[] = { 68 [USB_GADGET_MANUFACTURER_IDX].s = manufacturer_nokia, 69 [USB_GADGET_PRODUCT_IDX].s = NOKIA_LONG_NAME, 70 [USB_GADGET_SERIAL_IDX].s = "", 71 [STRING_DESCRIPTION_IDX].s = description_nokia, 72 { } /* end of list */ 73}; 74 75static struct usb_gadget_strings stringtab_dev = { 76 .language = 0x0409, /* en-us */ 77 .strings = strings_dev, 78}; 79 80static struct usb_gadget_strings *dev_strings[] = { 81 &stringtab_dev, 82 NULL, 83}; 84 85static struct usb_device_descriptor device_desc = { 86 .bLength = USB_DT_DEVICE_SIZE, 87 .bDescriptorType = USB_DT_DEVICE, 88 /* .bcdUSB = DYNAMIC */ 89 .bDeviceClass = USB_CLASS_COMM, 90 .idVendor = cpu_to_le16(NOKIA_VENDOR_ID), 91 .idProduct = cpu_to_le16(NOKIA_PRODUCT_ID), 92 .bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM), 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/*-------------------------------------------------------------------------*/ 106static struct usb_function *f_acm_cfg1; 107static struct usb_function *f_acm_cfg2; 108static struct usb_function *f_ecm_cfg1; 109static struct usb_function *f_ecm_cfg2; 110static struct usb_function *f_obex1_cfg1; 111static struct usb_function *f_obex2_cfg1; 112static struct usb_function *f_obex1_cfg2; 113static struct usb_function *f_obex2_cfg2; 114static struct usb_function *f_phonet_cfg1; 115static struct usb_function *f_phonet_cfg2; 116static struct usb_function *f_msg_cfg1; 117static struct usb_function *f_msg_cfg2; 118 119 120static struct usb_configuration nokia_config_500ma_driver = { 121 .label = "Bus Powered", 122 .bConfigurationValue = 1, 123 /* .iConfiguration = DYNAMIC */ 124 .bmAttributes = USB_CONFIG_ATT_ONE, 125 .MaxPower = 500, 126}; 127 128static struct usb_configuration nokia_config_100ma_driver = { 129 .label = "Self Powered", 130 .bConfigurationValue = 2, 131 /* .iConfiguration = DYNAMIC */ 132 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, 133 .MaxPower = 100, 134}; 135 136static struct usb_function_instance *fi_acm; 137static struct usb_function_instance *fi_ecm; 138static struct usb_function_instance *fi_obex1; 139static struct usb_function_instance *fi_obex2; 140static struct usb_function_instance *fi_phonet; 141static struct usb_function_instance *fi_msg; 142 143static int nokia_bind_config(struct usb_configuration *c) 144{ 145 struct usb_function *f_acm; 146 struct usb_function *f_phonet = NULL; 147 struct usb_function *f_obex1 = NULL; 148 struct usb_function *f_ecm; 149 struct usb_function *f_obex2 = NULL; 150 struct usb_function *f_msg; 151 int status = 0; 152 int obex1_stat = -1; 153 int obex2_stat = -1; 154 int phonet_stat = -1; 155 156 if (!IS_ERR(fi_phonet)) { 157 f_phonet = usb_get_function(fi_phonet); 158 if (IS_ERR(f_phonet)) 159 pr_debug("could not get phonet function\n"); 160 } 161 162 if (!IS_ERR(fi_obex1)) { 163 f_obex1 = usb_get_function(fi_obex1); 164 if (IS_ERR(f_obex1)) 165 pr_debug("could not get obex function 0\n"); 166 } 167 168 if (!IS_ERR(fi_obex2)) { 169 f_obex2 = usb_get_function(fi_obex2); 170 if (IS_ERR(f_obex2)) 171 pr_debug("could not get obex function 1\n"); 172 } 173 174 f_acm = usb_get_function(fi_acm); 175 if (IS_ERR(f_acm)) { 176 status = PTR_ERR(f_acm); 177 goto err_get_acm; 178 } 179 180 f_ecm = usb_get_function(fi_ecm); 181 if (IS_ERR(f_ecm)) { 182 status = PTR_ERR(f_ecm); 183 goto err_get_ecm; 184 } 185 186 f_msg = usb_get_function(fi_msg); 187 if (IS_ERR(f_msg)) { 188 status = PTR_ERR(f_msg); 189 goto err_get_msg; 190 } 191 192 if (!IS_ERR_OR_NULL(f_phonet)) { 193 phonet_stat = usb_add_function(c, f_phonet); 194 if (phonet_stat) 195 pr_debug("could not add phonet function\n"); 196 } 197 198 if (!IS_ERR_OR_NULL(f_obex1)) { 199 obex1_stat = usb_add_function(c, f_obex1); 200 if (obex1_stat) 201 pr_debug("could not add obex function 0\n"); 202 } 203 204 if (!IS_ERR_OR_NULL(f_obex2)) { 205 obex2_stat = usb_add_function(c, f_obex2); 206 if (obex2_stat) 207 pr_debug("could not add obex function 1\n"); 208 } 209 210 status = usb_add_function(c, f_acm); 211 if (status) 212 goto err_conf; 213 214 status = usb_add_function(c, f_ecm); 215 if (status) { 216 pr_debug("could not bind ecm config %d\n", status); 217 goto err_ecm; 218 } 219 220 status = usb_add_function(c, f_msg); 221 if (status) 222 goto err_msg; 223 224 if (c == &nokia_config_500ma_driver) { 225 f_acm_cfg1 = f_acm; 226 f_ecm_cfg1 = f_ecm; 227 f_phonet_cfg1 = f_phonet; 228 f_obex1_cfg1 = f_obex1; 229 f_obex2_cfg1 = f_obex2; 230 f_msg_cfg1 = f_msg; 231 } else { 232 f_acm_cfg2 = f_acm; 233 f_ecm_cfg2 = f_ecm; 234 f_phonet_cfg2 = f_phonet; 235 f_obex1_cfg2 = f_obex1; 236 f_obex2_cfg2 = f_obex2; 237 f_msg_cfg2 = f_msg; 238 } 239 240 return status; 241err_msg: 242 usb_remove_function(c, f_ecm); 243err_ecm: 244 usb_remove_function(c, f_acm); 245err_conf: 246 if (!obex2_stat) 247 usb_remove_function(c, f_obex2); 248 if (!obex1_stat) 249 usb_remove_function(c, f_obex1); 250 if (!phonet_stat) 251 usb_remove_function(c, f_phonet); 252 usb_put_function(f_msg); 253err_get_msg: 254 usb_put_function(f_ecm); 255err_get_ecm: 256 usb_put_function(f_acm); 257err_get_acm: 258 if (!IS_ERR_OR_NULL(f_obex2)) 259 usb_put_function(f_obex2); 260 if (!IS_ERR_OR_NULL(f_obex1)) 261 usb_put_function(f_obex1); 262 if (!IS_ERR_OR_NULL(f_phonet)) 263 usb_put_function(f_phonet); 264 return status; 265} 266 267static int nokia_bind(struct usb_composite_dev *cdev) 268{ 269 struct usb_gadget *gadget = cdev->gadget; 270 struct fsg_opts *fsg_opts; 271 struct fsg_config fsg_config; 272 int status; 273 274 status = usb_string_ids_tab(cdev, strings_dev); 275 if (status < 0) 276 goto err_usb; 277 device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; 278 device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 279 status = strings_dev[STRING_DESCRIPTION_IDX].id; 280 nokia_config_500ma_driver.iConfiguration = status; 281 nokia_config_100ma_driver.iConfiguration = status; 282 283 if (!gadget_is_altset_supported(gadget)) { 284 status = -ENODEV; 285 goto err_usb; 286 } 287 288 fi_phonet = usb_get_function_instance("phonet"); 289 if (IS_ERR(fi_phonet)) 290 pr_debug("could not find phonet function\n"); 291 292 fi_obex1 = usb_get_function_instance("obex"); 293 if (IS_ERR(fi_obex1)) 294 pr_debug("could not find obex function 1\n"); 295 296 fi_obex2 = usb_get_function_instance("obex"); 297 if (IS_ERR(fi_obex2)) 298 pr_debug("could not find obex function 2\n"); 299 300 fi_acm = usb_get_function_instance("acm"); 301 if (IS_ERR(fi_acm)) { 302 status = PTR_ERR(fi_acm); 303 goto err_obex2_inst; 304 } 305 306 fi_ecm = usb_get_function_instance("ecm"); 307 if (IS_ERR(fi_ecm)) { 308 status = PTR_ERR(fi_ecm); 309 goto err_acm_inst; 310 } 311 312 fi_msg = usb_get_function_instance("mass_storage"); 313 if (IS_ERR(fi_msg)) { 314 status = PTR_ERR(fi_msg); 315 goto err_ecm_inst; 316 } 317 318 /* set up mass storage function */ 319 fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers); 320 fsg_config.vendor_name = "Nokia"; 321 fsg_config.product_name = "N900"; 322 323 fsg_opts = fsg_opts_from_func_inst(fi_msg); 324 fsg_opts->no_configfs = true; 325 326 status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers); 327 if (status) 328 goto err_msg_inst; 329 330 status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall); 331 if (status) 332 goto err_msg_buf; 333 334 fsg_common_set_sysfs(fsg_opts->common, true); 335 336 status = fsg_common_create_luns(fsg_opts->common, &fsg_config); 337 if (status) 338 goto err_msg_buf; 339 340 fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name, 341 fsg_config.product_name); 342 343 /* finally register the configuration */ 344 status = usb_add_config(cdev, &nokia_config_500ma_driver, 345 nokia_bind_config); 346 if (status < 0) 347 goto err_msg_luns; 348 349 status = usb_add_config(cdev, &nokia_config_100ma_driver, 350 nokia_bind_config); 351 if (status < 0) 352 goto err_put_cfg1; 353 354 usb_composite_overwrite_options(cdev, &coverwrite); 355 dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME); 356 357 return 0; 358 359err_put_cfg1: 360 usb_put_function(f_acm_cfg1); 361 if (!IS_ERR_OR_NULL(f_obex1_cfg1)) 362 usb_put_function(f_obex1_cfg1); 363 if (!IS_ERR_OR_NULL(f_obex2_cfg1)) 364 usb_put_function(f_obex2_cfg1); 365 if (!IS_ERR_OR_NULL(f_phonet_cfg1)) 366 usb_put_function(f_phonet_cfg1); 367 usb_put_function(f_ecm_cfg1); 368err_msg_luns: 369 fsg_common_remove_luns(fsg_opts->common); 370err_msg_buf: 371 fsg_common_free_buffers(fsg_opts->common); 372err_msg_inst: 373 usb_put_function_instance(fi_msg); 374err_ecm_inst: 375 usb_put_function_instance(fi_ecm); 376err_acm_inst: 377 usb_put_function_instance(fi_acm); 378err_obex2_inst: 379 if (!IS_ERR(fi_obex2)) 380 usb_put_function_instance(fi_obex2); 381 if (!IS_ERR(fi_obex1)) 382 usb_put_function_instance(fi_obex1); 383 if (!IS_ERR(fi_phonet)) 384 usb_put_function_instance(fi_phonet); 385err_usb: 386 return status; 387} 388 389static int nokia_unbind(struct usb_composite_dev *cdev) 390{ 391 if (!IS_ERR_OR_NULL(f_obex1_cfg2)) 392 usb_put_function(f_obex1_cfg2); 393 if (!IS_ERR_OR_NULL(f_obex2_cfg2)) 394 usb_put_function(f_obex2_cfg2); 395 if (!IS_ERR_OR_NULL(f_obex1_cfg1)) 396 usb_put_function(f_obex1_cfg1); 397 if (!IS_ERR_OR_NULL(f_obex2_cfg1)) 398 usb_put_function(f_obex2_cfg1); 399 if (!IS_ERR_OR_NULL(f_phonet_cfg1)) 400 usb_put_function(f_phonet_cfg1); 401 if (!IS_ERR_OR_NULL(f_phonet_cfg2)) 402 usb_put_function(f_phonet_cfg2); 403 usb_put_function(f_acm_cfg1); 404 usb_put_function(f_acm_cfg2); 405 usb_put_function(f_ecm_cfg1); 406 usb_put_function(f_ecm_cfg2); 407 usb_put_function(f_msg_cfg1); 408 usb_put_function(f_msg_cfg2); 409 410 usb_put_function_instance(fi_msg); 411 usb_put_function_instance(fi_ecm); 412 if (!IS_ERR(fi_obex2)) 413 usb_put_function_instance(fi_obex2); 414 if (!IS_ERR(fi_obex1)) 415 usb_put_function_instance(fi_obex1); 416 if (!IS_ERR(fi_phonet)) 417 usb_put_function_instance(fi_phonet); 418 usb_put_function_instance(fi_acm); 419 420 return 0; 421} 422 423static struct usb_composite_driver nokia_driver = { 424 .name = "g_nokia", 425 .dev = &device_desc, 426 .strings = dev_strings, 427 .max_speed = USB_SPEED_HIGH, 428 .bind = nokia_bind, 429 .unbind = nokia_unbind, 430}; 431 432module_usb_composite_driver(nokia_driver);