upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / usb / gadget / f_gadgetfs.c
1 /*
2  * f_gadgetfs.c -- GadgetFS composite function driver
3  *
4  * Copyright (C) 2009 MCCI Corporation
5  *
6  * Based on f_acm.c by Al Borchers and David Brownell.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22
23 #include <linux/fs.h>
24 #include <linux/kernel.h>
25 #include <linux/device.h>
26
27 #include "u_gadgetfs.h"
28 #include "f_gadgetfs.h"
29
30 /*-------------------------------------------------------------------------*/
31
32 /**
33  * func_to_gadgetfs
34  *
35  * Helper function to find out the f_gagdetfs structure that a give usb_function is wrapped in.
36  */
37 static inline struct f_gadgetfs *func_to_gadgetfs(struct usb_function *f)
38 {
39         return container_of(f, struct f_gadgetfs, function);
40 }
41
42 /**
43  * gadgetfs_unbind
44  *
45  * Reconfigures altsettings; function drivers may initialize usb_ep.driver data at this time (when it is used).
46  * Note that setting an interface to its current altsetting resets interface state, and that all interfaces have
47  * a disabled state.
48  */
49 static void gadgetfs_unbind(struct usb_configuration *c, struct usb_function *f)
50 {
51         struct f_gadgetfs       *gadgetfs = func_to_gadgetfs(f);
52         
53         /* Free the descriptors that were set up in @gadgetfs_bind */
54         if (gadget_is_dualspeed(c->cdev->gadget))
55                 if (f->hs_descriptors)
56                         usb_free_descriptors(f->hs_descriptors);
57         if (f->descriptors)
58                 usb_free_descriptors(f->descriptors);
59
60         kfree(gadgetfs);
61 }
62
63 /**
64  * gadgetfs_bind
65  *
66  * The first function to get called when a new configuration is added. It's job is to allocate endpoints and
67  * store that information locally
68  */
69 static int __init gadgetfs_bind(struct usb_configuration *c, struct usb_function *f)
70 {
71         struct f_gadgetfs *gadgetfs = func_to_gadgetfs(f);
72         struct usb_gadget *gadget = c->cdev->gadget;
73         int status;
74         
75         /* Copy ep0 */
76         gadgetfs->ep0 = gadget->ep0;
77
78         /* Allocate new interface */
79         status = usb_interface_id_specify(c, f, GADGETFS_INTERFACE_ID);
80         if (status < 0)
81                 return status;
82
83         gadgetfs->interface_id = status;
84         gadgetfs_control_interface_descriptor.bInterfaceNumber = status;
85         
86         /* Allocate endpoints */
87         /* OUT */
88         gadgetfs->ep_out = usb_ep_autoconfig(gadget, &gadgetfs_full_speed_ep_out_descriptor);
89         if (!gadgetfs->ep_out)
90                 goto fail;
91         gadgetfs->ep_out->driver_data = gadgetfs;       // claim the endpoint
92
93         /* IN */
94         gadgetfs->ep_in = usb_ep_autoconfig(gadget, &gadgetfs_full_speed_ep_in_descriptor);
95         if (!gadgetfs->ep_in)
96                 goto fail;
97         gadgetfs->ep_in->driver_data = gadgetfs;        // claim the endpoint
98         
99         /* INT */
100         gadgetfs->ep_int = usb_ep_autoconfig(gadget, &gadgetfs_full_speed_status_descriptor);
101         if (!gadgetfs->ep_int)
102                 goto fail;
103         gadgetfs->ep_int->driver_data = gadgetfs;       // claim the endpoint
104         
105         /* copy descriptors, so they can be properly reported to the host */
106         f->descriptors = usb_copy_descriptors(gadgetfs_full_speed_function);
107         if (!f->descriptors)
108                 goto fail;
109
110         /* track endpoint copies */
111         gadgetfs->full_speed_descriptor.out = usb_find_endpoint(gadgetfs_full_speed_function, f->descriptors, &gadgetfs_full_speed_ep_out_descriptor);
112         gadgetfs->full_speed_descriptor.in = usb_find_endpoint(gadgetfs_full_speed_function, f->descriptors, &gadgetfs_full_speed_ep_in_descriptor);
113         gadgetfs->full_speed_descriptor.status = usb_find_endpoint(gadgetfs_full_speed_function, f->descriptors, &gadgetfs_full_speed_status_descriptor);
114
115         if (gadget_is_dualspeed(gadget)) {
116                 /* Assume endpoint addresses are the same for both speeds */
117                 gadgetfs_high_speed_ep_in_descriptor.bEndpointAddress = gadgetfs_full_speed_ep_in_descriptor.bEndpointAddress;
118                 gadgetfs_high_speed_ep_out_descriptor.bEndpointAddress = gadgetfs_full_speed_ep_out_descriptor.bEndpointAddress;
119                 gadgetfs_high_speed_status_descriptor.bEndpointAddress = gadgetfs_full_speed_status_descriptor.bEndpointAddress;
120
121                 /* copy descriptors, so they can be properly reported to the host */
122                 f->hs_descriptors = usb_copy_descriptors(gadgetfs_high_speed_function);
123                 if (!f->hs_descriptors)
124                         goto fail;
125
126                 /* track endpoint copies */
127                 gadgetfs->high_speed_descriptor.out = usb_find_endpoint(gadgetfs_high_speed_function, f->descriptors, &gadgetfs_high_speed_ep_out_descriptor);
128                 gadgetfs->high_speed_descriptor.in = usb_find_endpoint(gadgetfs_high_speed_function, f->descriptors, &gadgetfs_high_speed_ep_in_descriptor);
129                 gadgetfs->high_speed_descriptor.status = usb_find_endpoint(gadgetfs_high_speed_function, f->descriptors, &gadgetfs_high_speed_status_descriptor);
130         }
131
132         /* Create the root inode "(fake ep0)" file (which has the same name as the chip) for the application */
133         status = register_filesystem (&gadgetfs_type);
134         if (status == 0) {
135                 dbg_info ("%s, version %s\n", driver_desc, GADGETFS_DRIVER_VERSION);
136                 dbg_info ("ep-in = %s, ep-out = %s, ep-int = %s\n", gadgetfs->ep_in->name, gadgetfs->ep_out->name, gadgetfs->ep_int->name);
137         }
138         else
139                 goto fail;
140
141         return 0;
142         
143 fail:
144         gadgetfs_unbind(c, f);
145         return -ENOTSUPP;
146 }
147
148 /**
149  * gadgetfs_set_alt
150  *
151  * Reconfigures altsettings; function drivers may initialize usb_ep.driver data at this time (when it is used).
152  * Note that setting an interface to its current altsetting resets interface state, and that all interfaces have
153  * a disabled state.
154  */
155 static int gadgetfs_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
156 {
157         struct f_gadgetfs       *gadgetfs = func_to_gadgetfs(f);
158         //struct usb_composite_dev *cdev = f->config->cdev;
159
160         /* we know alt == 0, so this is an activation or a reset */
161
162         if (interface == gadgetfs->interface_id) {
163                 // Note that setting an interface to its current altsetting resets interface state
164                 // So we should 'reset interface state' now.
165         }
166
167         return 0;
168 }
169
170 /**
171  * gadgetfs_disable
172  *
173  * Indicates the function should be disabled. Reasons include host resetting or 
174  * reconfiguring the gadget, and disconnection.
175  */
176 static void gadgetfs_disable(struct usb_function *f)
177 {
178         gfs_disconnect();
179 }
180
181 /**
182  * gadgetfs_suspend
183  *
184  * Notifies functions when the host stops sending USB traffic.
185  */
186 static void gadgetfs_suspend(struct usb_function *f)
187 {
188         gfs_suspend();
189 }
190
191 /**
192  * gadgetfs_setup
193  *
194  * Handles ep0 requests that the composite.c driver doesn't know what to do with. Ie, interface
195  * specific requests that we have to handle. This is just a wrapper function into u_gadgetfs.
196  */
197 static int gadgetfs_setup(struct usb_function *func, const struct usb_ctrlrequest *ctrl)
198 {
199         return gfs_setup(func, ctrl);
200 }
201
202 /**
203  * gadgetfs_bind_config - add a gadgetFS function to a configuration
204  * @c: the configuration to support the gadgetFS instance
205  * Context: single threaded during gadget setup
206  *
207  * Returns zero on success, else negative errno.
208  */
209 int __init gadgetfs_bind_config(struct usb_composite_dev *c_dev, struct usb_configuration *c)
210 {
211         struct f_gadgetfs       *gadgetfs;
212         int                     status;
213
214         gadgetfs = kzalloc(sizeof *gadgetfs, GFP_KERNEL);
215         if (unlikely(!gadgetfs))
216                 return -ENOMEM;
217         the_gadget = gadgetfs;
218
219         /* allocate string id's */
220         if (gadgetfs_string_defines[GADGETFS_MANUFACTURER_IDX].id == 0) {
221                 status = usb_string_id(c_dev);
222                 if (status < 0)
223                         return status;
224                 gadgetfs_string_defines[GADGETFS_MANUFACTURER_IDX].id = status;
225
226                 status = usb_string_id(c_dev);
227                 if (status < 0)
228                         return status;
229                 gadgetfs_string_defines[GADGETFS_PRODUCT_IDX].id = status;
230
231                 status = usb_string_id(c_dev);
232                 if (status < 0)
233                         return status;
234                 gadgetfs_string_defines[GADGETFS_INTERFACE_IDX].id = status;
235                 gadgetfs_control_interface_descriptor.iInterface = status;
236         }
237
238         spin_lock_init(&gadgetfs->lock);
239
240         gadgetfs->cdev                  = c_dev;
241         gadgetfs->function.name         = GADGETFS_DRIVER_DESC;
242         gadgetfs->function.strings      = gadgetfs_strings;
243         gadgetfs->function.bind         = gadgetfs_bind;
244         gadgetfs->function.unbind       = gadgetfs_unbind;
245         gadgetfs->function.set_alt      = gadgetfs_set_alt;
246         gadgetfs->function.disable      = gadgetfs_disable;
247         gadgetfs->function.suspend      = gadgetfs_suspend;
248         gadgetfs->function.setup        = gadgetfs_setup;
249
250 #ifdef ESCAPE_MCCI
251         #ifdef CONFIG_USB_G_SAMSUNG_MULTI
252                 status = usb_add_function_head(c, &gadgetfs->function);
253         #else
254                 status = usb_add_function(c, &gadgetfs->function);
255         #endif
256 #else
257         status = usb_add_function(c, &gadgetfs->function);
258 #endif
259
260         if (status)
261                 kfree(gadgetfs);
262
263         return status;
264 }
265
266 /**
267  * init_gadgetfs - create device and copy endpoint data
268  * Context: may not sleep
269  *
270  * This function gets called after the endpoints have been configured and it's main purpose is to create
271  * a new device in u_gadgetfs and copy of the endpoint data that was set up here. We do the set up in
272  * f_gadgetfs, but most of the work is in u_gadgetfs so this is just a go-between between the two data structures
273  */
274 int init_gadgetfs(struct usb_composite_dev *cdev)
275 {
276         struct device_data      *dev;
277         struct f_gadgetfs       *gadgetfs = the_gadget;
278         
279         /* Sanity check */
280         if (!gadgetfs){
281                 dbg_err("Whoa. Wait. the_gadget is NULL. How can this be?\n");
282                 return -ENOMEM;
283         }
284
285         /* Create a new device structure for use in u_gadgetfs. This was previously done in @gfs_superblock
286          * when a 'mount' happened, but we set it up here now so that we can store the endpoint data there
287          */
288         dev = create_device ();
289         if (!dev)
290                 return -ENOMEM;
291         the_device = dev;       /* set the global device variable in u_gadgetfs */
292
293         /* Store the endpoint data */
294         dev->ep_in      = gadgetfs->ep_in;
295         dev->ep_out     = gadgetfs->ep_out;
296         dev->ep_int     = gadgetfs->ep_int;
297         dev->ep0        = gadgetfs->ep0;
298
299         /* Store the real endpoint descriptors */
300         dev->fs_in_desc         = gadgetfs->full_speed_descriptor.in;
301         dev->fs_out_desc        = gadgetfs->full_speed_descriptor.out;
302         dev->fs_status_desc     = gadgetfs->full_speed_descriptor.status;
303         dev->hs_in_desc         = gadgetfs->high_speed_descriptor.in;
304         dev->hs_out_desc        = gadgetfs->high_speed_descriptor.out;
305         dev->hs_status_desc     = gadgetfs->high_speed_descriptor.status;
306
307         if (gadget_is_dualspeed(cdev->gadget))
308                 dev->speed = USB_SPEED_HIGH;
309         else
310                 dev->speed = USB_SPEED_FULL;
311                 
312         return 0;
313 }
314
315 /**
316  * gadgetfs_cleanup
317  *
318  * Delete the device_data object in u_gadgetfs
319  */
320 void gadgetfs_cleanup(void)
321 {
322         /* this used to be done in u_gadgetfs.c/gfs_unmount() */
323         if (the_device) {
324                 device_decrement(the_device);
325                 the_device = NULL;
326         }
327
328         /* unregister filesystem */
329         gfs_cleanup();
330 }