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