move usb to drivers for quilt patches
[kernel-power] / usbhost / drivers / usb / gadget / softupd.c
1 /*
2  * softupd.c -- Nokia Software Update Gadget
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Contact: Felipe Balbi <felipe.balbi@nokia.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/utsname.h>
24 #include <linux/device.h>
25 #include <linux/usb/ch9.h>
26 #include <linux/usb/gadget.h>
27 #include "gadget_chips.h"
28
29 /* Defines */
30
31 #define NOKIA_VERSION_NUM               0x0100
32
33 /*-------------------------------------------------------------------------*/
34
35 /*
36  * Kbuild is not very cooperative with respect to linking separately
37  * compiled library objects into one module.  So for now we won't use
38  * separate compilation ... ensuring init/exit sections work to shrink
39  * the runtime footprint, and giving us at least some parts of what
40  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
41  */
42 #include "composite.c"
43 #include "usbstring.c"
44 #include "config.c"
45 #include "epautoconf.c"
46
47 #include "u_phonet.h"
48
49 #include "f_raw.c"
50 #include "f_phonet.c"
51
52 /*-------------------------------------------------------------------------*/
53
54 #define NOKIA_VENDOR_ID                 0x0421  /* Nokia */
55 #define NOKIA_PRODUCT_ID                0x01c8  /* Nokia Update Gadget */
56
57 /* string IDs are assigned dynamically */
58
59 #define STRING_MANUFACTURER_IDX         0
60 #define STRING_PRODUCT_IDX              1
61 #define STRING_DESCRIPTION_IDX          2
62 #define STRING_SERIAL_IDX               3
63
64 static char manufacturer_nokia[] = "Nokia";
65 static const char product_nokia[] = "N900 (PC-Suite Mode)";
66 static const char description_nokia[] = "Firmware Upgrade Configuration";
67
68 static struct usb_string strings_dev[] = {
69         [STRING_MANUFACTURER_IDX].s = manufacturer_nokia,
70         [STRING_PRODUCT_IDX].s = product_nokia,
71         [STRING_DESCRIPTION_IDX].s = description_nokia,
72         [STRING_SERIAL_IDX].s = "",
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
90         .bcdUSB                 = __constant_cpu_to_le16(0x0200),
91
92         .bDeviceClass           = USB_CLASS_COMM,
93         .idVendor               = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
94         .idProduct              = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
95
96         /* .iManufacturer = DYNAMIC */
97         /* .iProduct = DYNAMIC */
98         /* .iSerialNumber = DYNAMIC */
99
100         .bNumConfigurations =   1,
101 };
102
103 /*-------------------------------------------------------------------------*/
104
105 /* Module */
106 MODULE_DESCRIPTION("Nokia Firmware Upgrade Gadget Driver");
107 MODULE_AUTHOR("Felipe Balbi");
108 MODULE_LICENSE("GPL");
109
110 /*-------------------------------------------------------------------------*/
111
112 static int __init softupd_bind_config(struct usb_configuration *c)
113 {
114         int status = 0;
115
116         status = phonet_bind_config(c);
117         if (status) {
118                 struct usb_composite_dev *cdev = c->cdev;
119
120                 dev_err(&cdev->gadget->dev, "could not bind phonet config\n");
121         }
122
123         status = raw_bind_config(c);
124         if (status)
125                 dev_err(&c->cdev->gadget->dev, "could not bind raw config\n");
126
127         return status;
128 }
129
130 static struct usb_configuration softupd_config_driver = {
131         .label          = "softupd",
132         .bind           = softupd_bind_config,
133
134         .bmAttributes   = USB_CONFIG_ATT_ONE,
135         .bMaxPower      = 250,
136
137         /* .iConfiguration = DYNAMIC */
138         .bConfigurationValue = 1,
139 };
140
141 static int __init softupd_bind(struct usb_composite_dev *cdev)
142 {
143         struct usb_gadget       *gadget = cdev->gadget;
144         int                     status;
145         int                     gcnum;
146
147         status = gphonet_setup(cdev->gadget);
148         if (status < 0)
149                 goto err_phonet;
150
151         status = graw_setup(cdev->gadget);
152         if (status < 0)
153                 goto err_raw;
154
155         status = usb_string_id(cdev);
156         if (status < 0)
157                 goto err_usb;
158         strings_dev[STRING_MANUFACTURER_IDX].id = status;
159
160         device_desc.iManufacturer = status;
161
162         status = usb_string_id(cdev);
163         if (status < 0)
164                 goto err_usb;
165         strings_dev[STRING_PRODUCT_IDX].id = status;
166
167         device_desc.iProduct = status;
168
169         status = usb_string_id(cdev);
170         if (status < 0)
171                 goto err_usb;
172         strings_dev[STRING_SERIAL_IDX].id = status;
173
174         device_desc.iSerialNumber = status;
175
176         /* config description */
177         status = usb_string_id(cdev);
178         if (status < 0)
179                 goto err_usb;
180         strings_dev[STRING_DESCRIPTION_IDX].id = status;
181
182         softupd_config_driver.iConfiguration = status;
183
184         /* set up other descriptors */
185         gcnum = usb_gadget_controller_number(gadget);
186         if (gcnum >= 0)
187                 device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM);
188         else {
189                 /* this should only work with hw that supports altsettings
190                  * and several endpoints, anything else, panic.
191                  */
192                 pr_err("%s: controller '%s' not recognized\n",
193                                 __func__, gadget->name);
194                 goto err_usb;
195         }
196
197         /* finaly register the configuration */
198         status = usb_add_config(cdev, &softupd_config_driver);
199         if (status < 0)
200                 goto err_usb;
201
202         INFO(cdev, "%s\n", product_nokia);
203
204         return 0;
205
206 err_usb:
207         graw_cleanup();
208
209 err_raw:
210         gphonet_cleanup();
211
212 err_phonet:
213         return status;
214 }
215
216 static int softupd_unbind(struct usb_composite_dev *cdev)
217 {
218         graw_cleanup();
219         gphonet_cleanup();
220
221         return 0;
222 }
223
224 static struct usb_composite_driver softupd_driver = {
225         .name           = "g_softupd",
226         .dev            = &device_desc,
227         .strings        = dev_strings,
228         .bind           = softupd_bind,
229         .unbind         = softupd_unbind,
230 };
231
232 static int __init softupd_init(void)
233 {
234         return usb_composite_register(&softupd_driver);
235 }
236 module_init(softupd_init);
237
238 static void __exit softupd_cleanup(void)
239 {
240         usb_composite_unregister(&softupd_driver);
241 }
242 module_exit(softupd_cleanup);
243