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 30 USB_GADGET_COMPOSITE_OPTIONS(); 31 32 USB_ETHERNET_MODULE_PARAMETERS(); 33 34 static 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 43 static 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 55 FSG_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 64 static char manufacturer_nokia[] = "Nokia"; 65 static const char product_nokia[] = NOKIA_LONG_NAME; 66 static const char description_nokia[] = "PC-Suite Configuration"; 67 68 static struct usb_string strings_dev[] = { 69 [USB_GADGET_MANUFACTURER_IDX].s = manufacturer_nokia, 70 [USB_GADGET_PRODUCT_IDX].s = NOKIA_LONG_NAME, 71 [USB_GADGET_SERIAL_IDX].s = "", 72 [STRING_DESCRIPTION_IDX].s = description_nokia, 73 { } /* end of list */ 74 }; 75 76 static struct usb_gadget_strings stringtab_dev = { 77 .language = 0x0409, /* en-us */ 78 .strings = strings_dev, 79 }; 80 81 static struct usb_gadget_strings *dev_strings[] = { 82 &stringtab_dev, 83 NULL, 84 }; 85 86 static struct usb_device_descriptor device_desc = { 87 .bLength = USB_DT_DEVICE_SIZE, 88 .bDescriptorType = USB_DT_DEVICE, 89 /* .bcdUSB = DYNAMIC */ 90 .bDeviceClass = USB_CLASS_COMM, 91 .idVendor = cpu_to_le16(NOKIA_VENDOR_ID), 92 .idProduct = cpu_to_le16(NOKIA_PRODUCT_ID), 93 .bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM), 94 /* .iManufacturer = DYNAMIC */ 95 /* .iProduct = DYNAMIC */ 96 .bNumConfigurations = 1, 97 }; 98 99 /*-------------------------------------------------------------------------*/ 100 101 /* Module */ 102 MODULE_DESCRIPTION("Nokia composite gadget driver for N900"); 103 MODULE_AUTHOR("Felipe Balbi"); 104 MODULE_LICENSE("GPL"); 105 106 /*-------------------------------------------------------------------------*/ 107 static struct usb_function *f_acm_cfg1; 108 static struct usb_function *f_acm_cfg2; 109 static struct usb_function *f_ecm_cfg1; 110 static struct usb_function *f_ecm_cfg2; 111 static struct usb_function *f_obex1_cfg1; 112 static struct usb_function *f_obex2_cfg1; 113 static struct usb_function *f_obex1_cfg2; 114 static struct usb_function *f_obex2_cfg2; 115 static struct usb_function *f_phonet_cfg1; 116 static struct usb_function *f_phonet_cfg2; 117 static struct usb_function *f_msg_cfg1; 118 static struct usb_function *f_msg_cfg2; 119 120 121 static struct usb_configuration nokia_config_500ma_driver = { 122 .label = "Bus Powered", 123 .bConfigurationValue = 1, 124 /* .iConfiguration = DYNAMIC */ 125 .bmAttributes = USB_CONFIG_ATT_ONE, 126 .MaxPower = 500, 127 }; 128 129 static struct usb_configuration nokia_config_100ma_driver = { 130 .label = "Self Powered", 131 .bConfigurationValue = 2, 132 /* .iConfiguration = DYNAMIC */ 133 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, 134 .MaxPower = 100, 135 }; 136 137 static struct usb_function_instance *fi_acm; 138 static struct usb_function_instance *fi_ecm; 139 static struct usb_function_instance *fi_obex1; 140 static struct usb_function_instance *fi_obex2; 141 static struct usb_function_instance *fi_phonet; 142 static struct usb_function_instance *fi_msg; 143 144 static int nokia_bind_config(struct usb_configuration *c) 145 { 146 struct usb_function *f_acm; 147 struct usb_function *f_phonet = NULL; 148 struct usb_function *f_obex1 = NULL; 149 struct usb_function *f_ecm; 150 struct usb_function *f_obex2 = NULL; 151 struct usb_function *f_msg; 152 int status = 0; 153 int obex1_stat = -1; 154 int obex2_stat = -1; 155 int phonet_stat = -1; 156 157 if (!IS_ERR(fi_phonet)) { 158 f_phonet = usb_get_function(fi_phonet); 159 if (IS_ERR(f_phonet)) 160 pr_debug("could not get phonet function\n"); 161 } 162 163 if (!IS_ERR(fi_obex1)) { 164 f_obex1 = usb_get_function(fi_obex1); 165 if (IS_ERR(f_obex1)) 166 pr_debug("could not get obex function 0\n"); 167 } 168 169 if (!IS_ERR(fi_obex2)) { 170 f_obex2 = usb_get_function(fi_obex2); 171 if (IS_ERR(f_obex2)) 172 pr_debug("could not get obex function 1\n"); 173 } 174 175 f_acm = usb_get_function(fi_acm); 176 if (IS_ERR(f_acm)) { 177 status = PTR_ERR(f_acm); 178 goto err_get_acm; 179 } 180 181 f_ecm = usb_get_function(fi_ecm); 182 if (IS_ERR(f_ecm)) { 183 status = PTR_ERR(f_ecm); 184 goto err_get_ecm; 185 } 186 187 f_msg = usb_get_function(fi_msg); 188 if (IS_ERR(f_msg)) { 189 status = PTR_ERR(f_msg); 190 goto err_get_msg; 191 } 192 193 if (!IS_ERR_OR_NULL(f_phonet)) { 194 phonet_stat = usb_add_function(c, f_phonet); 195 if (phonet_stat) 196 pr_debug("could not add phonet function\n"); 197 } 198 199 if (!IS_ERR_OR_NULL(f_obex1)) { 200 obex1_stat = usb_add_function(c, f_obex1); 201 if (obex1_stat) 202 pr_debug("could not add obex function 0\n"); 203 } 204 205 if (!IS_ERR_OR_NULL(f_obex2)) { 206 obex2_stat = usb_add_function(c, f_obex2); 207 if (obex2_stat) 208 pr_debug("could not add obex function 1\n"); 209 } 210 211 status = usb_add_function(c, f_acm); 212 if (status) 213 goto err_conf; 214 215 status = usb_add_function(c, f_ecm); 216 if (status) { 217 pr_debug("could not bind ecm config %d\n", status); 218 goto err_ecm; 219 } 220 221 status = usb_add_function(c, f_msg); 222 if (status) 223 goto err_msg; 224 225 if (c == &nokia_config_500ma_driver) { 226 f_acm_cfg1 = f_acm; 227 f_ecm_cfg1 = f_ecm; 228 f_phonet_cfg1 = f_phonet; 229 f_obex1_cfg1 = f_obex1; 230 f_obex2_cfg1 = f_obex2; 231 f_msg_cfg1 = f_msg; 232 } else { 233 f_acm_cfg2 = f_acm; 234 f_ecm_cfg2 = f_ecm; 235 f_phonet_cfg2 = f_phonet; 236 f_obex1_cfg2 = f_obex1; 237 f_obex2_cfg2 = f_obex2; 238 f_msg_cfg2 = f_msg; 239 } 240 241 return status; 242 err_msg: 243 usb_remove_function(c, f_ecm); 244 err_ecm: 245 usb_remove_function(c, f_acm); 246 err_conf: 247 if (!obex2_stat) 248 usb_remove_function(c, f_obex2); 249 if (!obex1_stat) 250 usb_remove_function(c, f_obex1); 251 if (!phonet_stat) 252 usb_remove_function(c, f_phonet); 253 usb_put_function(f_msg); 254 err_get_msg: 255 usb_put_function(f_ecm); 256 err_get_ecm: 257 usb_put_function(f_acm); 258 err_get_acm: 259 if (!IS_ERR_OR_NULL(f_obex2)) 260 usb_put_function(f_obex2); 261 if (!IS_ERR_OR_NULL(f_obex1)) 262 usb_put_function(f_obex1); 263 if (!IS_ERR_OR_NULL(f_phonet)) 264 usb_put_function(f_phonet); 265 return status; 266 } 267 268 static int nokia_bind(struct usb_composite_dev *cdev) 269 { 270 struct usb_gadget *gadget = cdev->gadget; 271 struct fsg_opts *fsg_opts; 272 struct fsg_config fsg_config; 273 int status; 274 275 status = usb_string_ids_tab(cdev, strings_dev); 276 if (status < 0) 277 goto err_usb; 278 device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; 279 device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; 280 status = strings_dev[STRING_DESCRIPTION_IDX].id; 281 nokia_config_500ma_driver.iConfiguration = status; 282 nokia_config_100ma_driver.iConfiguration = status; 283 284 if (!gadget_is_altset_supported(gadget)) { 285 status = -ENODEV; 286 goto err_usb; 287 } 288 289 fi_phonet = usb_get_function_instance("phonet"); 290 if (IS_ERR(fi_phonet)) 291 pr_debug("could not find phonet function\n"); 292 293 fi_obex1 = usb_get_function_instance("obex"); 294 if (IS_ERR(fi_obex1)) 295 pr_debug("could not find obex function 1\n"); 296 297 fi_obex2 = usb_get_function_instance("obex"); 298 if (IS_ERR(fi_obex2)) 299 pr_debug("could not find obex function 2\n"); 300 301 fi_acm = usb_get_function_instance("acm"); 302 if (IS_ERR(fi_acm)) { 303 status = PTR_ERR(fi_acm); 304 goto err_obex2_inst; 305 } 306 307 fi_ecm = usb_get_function_instance("ecm"); 308 if (IS_ERR(fi_ecm)) { 309 status = PTR_ERR(fi_ecm); 310 goto err_acm_inst; 311 } 312 313 fi_msg = usb_get_function_instance("mass_storage"); 314 if (IS_ERR(fi_msg)) { 315 status = PTR_ERR(fi_msg); 316 goto err_ecm_inst; 317 } 318 319 /* set up mass storage function */ 320 fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers); 321 fsg_config.vendor_name = "Nokia"; 322 fsg_config.product_name = "N900"; 323 324 fsg_opts = fsg_opts_from_func_inst(fi_msg); 325 fsg_opts->no_configfs = true; 326 327 status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers); 328 if (status) 329 goto err_msg_inst; 330 331 status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall); 332 if (status) 333 goto err_msg_buf; 334 335 fsg_common_set_sysfs(fsg_opts->common, true); 336 337 status = fsg_common_create_luns(fsg_opts->common, &fsg_config); 338 if (status) 339 goto err_msg_buf; 340 341 fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name, 342 fsg_config.product_name); 343 344 /* finally register the configuration */ 345 status = usb_add_config(cdev, &nokia_config_500ma_driver, 346 nokia_bind_config); 347 if (status < 0) 348 goto err_msg_luns; 349 350 status = usb_add_config(cdev, &nokia_config_100ma_driver, 351 nokia_bind_config); 352 if (status < 0) 353 goto err_put_cfg1; 354 355 usb_composite_overwrite_options(cdev, &coverwrite); 356 dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME); 357 358 return 0; 359 360 err_put_cfg1: 361 usb_put_function(f_acm_cfg1); 362 if (!IS_ERR_OR_NULL(f_obex1_cfg1)) 363 usb_put_function(f_obex1_cfg1); 364 if (!IS_ERR_OR_NULL(f_obex2_cfg1)) 365 usb_put_function(f_obex2_cfg1); 366 if (!IS_ERR_OR_NULL(f_phonet_cfg1)) 367 usb_put_function(f_phonet_cfg1); 368 usb_put_function(f_ecm_cfg1); 369 err_msg_luns: 370 fsg_common_remove_luns(fsg_opts->common); 371 err_msg_buf: 372 fsg_common_free_buffers(fsg_opts->common); 373 err_msg_inst: 374 usb_put_function_instance(fi_msg); 375 err_ecm_inst: 376 usb_put_function_instance(fi_ecm); 377 err_acm_inst: 378 usb_put_function_instance(fi_acm); 379 err_obex2_inst: 380 if (!IS_ERR(fi_obex2)) 381 usb_put_function_instance(fi_obex2); 382 if (!IS_ERR(fi_obex1)) 383 usb_put_function_instance(fi_obex1); 384 if (!IS_ERR(fi_phonet)) 385 usb_put_function_instance(fi_phonet); 386 err_usb: 387 return status; 388 } 389 390 static int nokia_unbind(struct usb_composite_dev *cdev) 391 { 392 if (!IS_ERR_OR_NULL(f_obex1_cfg2)) 393 usb_put_function(f_obex1_cfg2); 394 if (!IS_ERR_OR_NULL(f_obex2_cfg2)) 395 usb_put_function(f_obex2_cfg2); 396 if (!IS_ERR_OR_NULL(f_obex1_cfg1)) 397 usb_put_function(f_obex1_cfg1); 398 if (!IS_ERR_OR_NULL(f_obex2_cfg1)) 399 usb_put_function(f_obex2_cfg1); 400 if (!IS_ERR_OR_NULL(f_phonet_cfg1)) 401 usb_put_function(f_phonet_cfg1); 402 if (!IS_ERR_OR_NULL(f_phonet_cfg2)) 403 usb_put_function(f_phonet_cfg2); 404 usb_put_function(f_acm_cfg1); 405 usb_put_function(f_acm_cfg2); 406 usb_put_function(f_ecm_cfg1); 407 usb_put_function(f_ecm_cfg2); 408 usb_put_function(f_msg_cfg1); 409 usb_put_function(f_msg_cfg2); 410 411 usb_put_function_instance(fi_msg); 412 usb_put_function_instance(fi_ecm); 413 if (!IS_ERR(fi_obex2)) 414 usb_put_function_instance(fi_obex2); 415 if (!IS_ERR(fi_obex1)) 416 usb_put_function_instance(fi_obex1); 417 if (!IS_ERR(fi_phonet)) 418 usb_put_function_instance(fi_phonet); 419 usb_put_function_instance(fi_acm); 420 421 return 0; 422 } 423 424 static struct usb_composite_driver nokia_driver = { 425 .name = "g_nokia", 426 .dev = &device_desc, 427 .strings = dev_strings, 428 .max_speed = USB_SPEED_HIGH, 429 .bind = nokia_bind, 430 .unbind = nokia_unbind, 431 }; 432 433 module_usb_composite_driver(nokia_driver); 434