]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/westbridge/astoria/gadget/cyasgadget.c
staging: westbridge: improve error path
[net-next-2.6.git] / drivers / staging / westbridge / astoria / gadget / cyasgadget.c
1 /* cyangadget.c - Linux USB Gadget driver file for the Cypress West Bridge
2 ## ===========================
3 ## Copyright (C) 2010  Cypress Semiconductor
4 ##
5 ## This program is free software; you can redistribute it and/or
6 ## modify it under the terms of the GNU General Public License
7 ## as published by the Free Software Foundation; either version 2
8 ## of the License, or (at your option) any later version.
9 ##
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 ## GNU General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; if not, write to the Free Software
17 ## Foundation, Inc., 51 Franklin Street, Fifth Floor
18 ## Boston, MA  02110-1301, USA.
19 ## ===========================
20 */
21
22 /*
23  * Cypress West Bridge high/full speed usb device controller code
24  * Based on the Netchip 2280 device controller by David Brownell
25  * in the linux 2.6.10 kernel
26  *
27  * linux/drivers/usb/gadget/net2280.c
28  */
29
30 /*
31  * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
32  * Copyright (C) 2003 David Brownell
33  *
34  * This program is free software; you can redistribute it and/or modify
35  * it under the terms of the GNU General Public License as published by
36  * the Free Software Foundation; either version 2 of the License, or
37  * (at your option) any later version.
38  *
39  * This program is distributed in the hope that it will be useful,
40  * but WITHOUT ANY WARRANTY; without even the implied warranty of
41  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42  * GNU General Public License for more details.
43  *
44  * You should have received a copy of the GNU General Public License
45  * along with this program; if not, write to the Free Software
46  * Foundation, Inc., 59 Temple Place, Suite 330
47  * Boston, MA  02111-1307  USA
48  */
49
50 #include "cyasgadget.h"
51
52 #define CY_AS_DRIVER_DESC               "cypress west bridge usb gadget"
53 #define CY_AS_DRIVER_VERSION            "REV B"
54 #define DMA_ADDR_INVALID                        (~(dma_addr_t)0)
55
56 static const char cy_as_driver_name[] = "cy_astoria_gadget";
57 static const char cy_as_driver_desc[] = CY_AS_DRIVER_DESC;
58
59 static const char cy_as_ep0name[] = "EP0";
60 static const char *cy_as_ep_names[] = {
61         cy_as_ep0name, "EP1",
62         "EP2", "EP3", "EP4", "EP5", "EP6", "EP7", "EP8",
63         "EP9", "EP10", "EP11", "EP12", "EP13", "EP14", "EP15"
64 };
65
66 /* forward declarations */
67 static void
68 cyas_ep_reset(
69         struct cyasgadget_ep *an_ep) ;
70
71 static int
72 cyasgadget_fifo_status(
73         struct usb_ep *_ep) ;
74
75 static void
76 cyasgadget_stallcallback(
77         cy_as_device_handle h,
78         cy_as_return_status_t status,
79         uint32_t tag,
80         cy_as_funct_c_b_type cbtype,
81         void *cbdata);
82
83 /* variables */
84 static cyasgadget       *cy_as_gadget_controller;
85
86 static int append_mtp;
87 module_param(append_mtp, bool, S_IRUGO | S_IWUSR);
88 MODULE_PARM_DESC(append_mtp,
89         "west bridge to append descriptors for mtp 0=no 1=yes");
90
91 static int msc_enum_bus_0;
92 module_param(msc_enum_bus_0, bool, S_IRUGO | S_IWUSR);
93 MODULE_PARM_DESC(msc_enum_bus_0,
94         "west bridge to enumerate bus 0 as msc 0=no 1=yes");
95
96 static int msc_enum_bus_1;
97 module_param(msc_enum_bus_1, bool, S_IRUGO | S_IWUSR);
98 MODULE_PARM_DESC(msc_enum_bus_1,
99         "west bridge to enumerate bus 1 as msc 0=no 1=yes");
100
101 /* all Callbacks are placed in this subsection*/
102 static void cy_as_gadget_usb_event_callback(
103                                         cy_as_device_handle h,
104                                         cy_as_usb_event ev,
105                                         void *evdata
106                                         )
107 {
108         cyasgadget  *cy_as_dev ;
109         #ifndef WESTBRIDGE_NDEBUG
110         struct usb_ctrlrequest *ctrlreq;
111         #endif
112
113         /* cy_as_dev = container_of(h, cyasgadget, dev_handle); */
114         cy_as_dev = cy_as_gadget_controller ;
115         switch (ev) {
116         case cy_as_event_usb_suspend:
117                 #ifndef WESTBRIDGE_NDEBUG
118                 cy_as_hal_print_message(
119                         "<1>_cy_as_event_usb_suspend received\n") ;
120                 #endif
121                 cy_as_dev->driver->suspend(&cy_as_dev->gadget) ;
122                 break;
123
124         case cy_as_event_usb_resume:
125                 #ifndef WESTBRIDGE_NDEBUG
126                 cy_as_hal_print_message(
127                         "<1>_cy_as_event_usb_resume received\n") ;
128                 #endif
129                 cy_as_dev->driver->resume(&cy_as_dev->gadget) ;
130                 break;
131
132         case cy_as_event_usb_reset:
133                 #ifndef WESTBRIDGE_NDEBUG
134                 cy_as_hal_print_message(
135                         "<1>_cy_as_event_usb_reset received\n") ;
136                 #endif
137                 break;
138
139         case cy_as_event_usb_speed_change:
140                 #ifndef WESTBRIDGE_NDEBUG
141                 cy_as_hal_print_message(
142                         "<1>_cy_as_event_usb_speed_change received\n") ;
143                 #endif
144                 break;
145
146         case cy_as_event_usb_set_config:
147                 #ifndef WESTBRIDGE_NDEBUG
148                 cy_as_hal_print_message(
149                         "<1>_cy_as_event_usb_set_config received\n") ;
150                 #endif
151                 break;
152
153         case cy_as_event_usb_setup_packet:
154                 #ifndef WESTBRIDGE_NDEBUG
155                 ctrlreq = (struct usb_ctrlrequest *)evdata;
156
157                 cy_as_hal_print_message("<1>_cy_as_event_usb_setup_packet "
158                                                         "received"
159                                                         "bRequestType=0x%x,"
160                                                         "bRequest=0x%x,"
161                                                         "wValue=x%x,"
162                                                         "wIndex=0x%x,"
163                                                         "wLength=0x%x,",
164                                                         ctrlreq->bRequestType,
165                                                         ctrlreq->bRequest,
166                                                         ctrlreq->wValue,
167                                                         ctrlreq->wIndex,
168                                                         ctrlreq->wLength
169                                                         ) ;
170                 #endif
171                 cy_as_dev->outsetupreq = 0;
172                 if ((((uint8_t *)evdata)[0] & USB_DIR_IN) == USB_DIR_OUT)
173                         cy_as_dev->outsetupreq = 1;
174                 cy_as_dev->driver->setup(&cy_as_dev->gadget,
175                         (struct usb_ctrlrequest *)evdata) ;
176                 break;
177
178         case cy_as_event_usb_status_packet:
179                 #ifndef WESTBRIDGE_NDEBUG
180                 cy_as_hal_print_message(
181                         "<1>_cy_as_event_usb_status_packet received\n") ;
182                 #endif
183                 break;
184
185         case cy_as_event_usb_inquiry_before:
186                 #ifndef WESTBRIDGE_NDEBUG
187                 cy_as_hal_print_message(
188                         "<1>_cy_as_event_usb_inquiry_before received\n") ;
189                 #endif
190                 break;
191
192         case cy_as_event_usb_inquiry_after:
193                 #ifndef WESTBRIDGE_NDEBUG
194                 cy_as_hal_print_message(
195                         "<1>_cy_as_event_usb_inquiry_after received\n") ;
196                 #endif
197                 break;
198
199         case cy_as_event_usb_start_stop:
200                 #ifndef WESTBRIDGE_NDEBUG
201                 cy_as_hal_print_message(
202                         "<1>_cy_as_event_usb_start_stop received\n") ;
203                 #endif
204                 break;
205
206         default:
207                 break;
208         }
209 }
210
211 static void cy_as_gadget_mtp_event_callback(
212                                         cy_as_device_handle handle,
213                                         cy_as_mtp_event evtype,
214                                         void *evdata
215                                         )
216 {
217
218         cyasgadget *dev = cy_as_gadget_controller ;
219         (void) handle;
220
221         switch (evtype) {
222         case cy_as_mtp_send_object_complete:
223                 {
224                         cy_as_mtp_send_object_complete_data *send_obj_data =
225                                 (cy_as_mtp_send_object_complete_data *) evdata ;
226
227                         #ifndef WESTBRIDGE_NDEBUG
228                         cy_as_hal_print_message(
229                                 "<6>MTP EVENT: send_object_complete\n");
230                         cy_as_hal_print_message(
231                                 "<6>_bytes sent = %d\n_send status = %d",
232                                         send_obj_data->byte_count,
233                                         send_obj_data->status);
234                         #endif
235
236                         dev->tmtp_send_complete_data.byte_count =
237                                 send_obj_data->byte_count;
238                         dev->tmtp_send_complete_data.status =
239                                 send_obj_data->status;
240                         dev->tmtp_send_complete_data.transaction_id =
241                                 send_obj_data->transaction_id ;
242                         dev->tmtp_send_complete = cy_true ;
243                         break;
244                 }
245         case cy_as_mtp_get_object_complete:
246                 {
247                         cy_as_mtp_get_object_complete_data *get_obj_data =
248                                 (cy_as_mtp_get_object_complete_data *) evdata ;
249
250                         #ifndef WESTBRIDGE_NDEBUG
251                         cy_as_hal_print_message(
252                                 "<6>MTP EVENT: get_object_complete\n");
253                         cy_as_hal_print_message(
254                                 "<6>_bytes got = %d\n_get status = %d",
255                                 get_obj_data->byte_count, get_obj_data->status);
256                         #endif
257
258                         dev->tmtp_get_complete_data.byte_count =
259                                 get_obj_data->byte_count;
260                         dev->tmtp_get_complete_data.status =
261                                 get_obj_data->status ;
262                         dev->tmtp_get_complete = cy_true ;
263                         break;
264                 }
265         case cy_as_mtp_block_table_needed:
266                 {
267                         dev->tmtp_need_new_blk_tbl = cy_true ;
268                         #ifndef WESTBRIDGE_NDEBUG
269                         cy_as_hal_print_message(
270                                 "<6>MTP EVENT: cy_as_mtp_block_table_needed\n");
271                         #endif
272                         break;
273                 }
274         default:
275                 break;
276         }
277 }
278
279 static void
280 cyasgadget_setupreadcallback(
281                 cy_as_device_handle h,
282                 cy_as_end_point_number_t ep,
283                 uint32_t count,
284                 void *buf,
285                 cy_as_return_status_t status)
286 {
287     cyasgadget_ep  *an_ep;
288     cyasgadget_req *an_req;
289     cyasgadget     *cy_as_dev ;
290     unsigned       stopped ;
291     unsigned long       flags;
292     (void)buf ;
293
294     cy_as_dev = cy_as_gadget_controller ;
295     if (cy_as_dev->driver == NULL)
296                 return;
297
298     an_ep =  &cy_as_dev->an_gadget_ep[ep] ;
299     spin_lock_irqsave(&cy_as_dev->lock, flags);
300         stopped = an_ep->stopped ;
301
302 #ifndef WESTBRIDGE_NDEBUG
303     cy_as_hal_print_message(
304                 "%s: ep=%d, count=%d, "
305                 "status=%d\n", __func__,  ep, count, status) ;
306 #endif
307
308     an_req = list_entry(an_ep->queue.next,
309                 cyasgadget_req, queue) ;
310     list_del_init(&an_req->queue) ;
311
312     if (status == CY_AS_ERROR_SUCCESS)
313                 an_req->req.status = 0;
314     else
315                 an_req->req.status = -status;
316     an_req->req.actual = count ;
317     an_ep->stopped = 1;
318
319         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
320
321     an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
322
323     an_ep->stopped = stopped;
324
325 }
326 /*called when the write of a setup packet has been completed*/
327 static void cyasgadget_setupwritecallback(
328                                         cy_as_device_handle h,
329                                         cy_as_end_point_number_t ep,
330                                         uint32_t count,
331                                         void *buf,
332                                         cy_as_return_status_t status
333                                         )
334 {
335         cyasgadget_ep  *an_ep;
336         cyasgadget_req *an_req;
337         cyasgadget       *cy_as_dev ;
338         unsigned           stopped ;
339         unsigned long   flags;
340
341         (void)buf ;
342
343         #ifndef WESTBRIDGE_NDEBUG
344                 cy_as_hal_print_message("<1>%s called status=0x%x\n",
345                         __func__, status);
346         #endif
347
348         cy_as_dev = cy_as_gadget_controller ;
349
350         if (cy_as_dev->driver == NULL)
351                 return;
352
353         an_ep =  &cy_as_dev->an_gadget_ep[ep] ;
354
355         spin_lock_irqsave(&cy_as_dev->lock, flags);
356
357         stopped = an_ep->stopped ;
358
359 #ifndef WESTBRIDGE_NDEBUG
360         cy_as_hal_print_message("setup_write_callback: ep=%d, "
361                 "count=%d, status=%d\n", ep, count, status) ;
362 #endif
363
364         an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ;
365         list_del_init(&an_req->queue) ;
366
367         an_req->req.actual = count ;
368         an_req->req.status = 0 ;
369         an_ep->stopped = 1;
370
371         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
372
373         an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
374
375         an_ep->stopped = stopped;
376
377 }
378
379 /* called when a read operation has completed.*/
380 static void cyasgadget_readcallback(
381                                         cy_as_device_handle h,
382                                         cy_as_end_point_number_t ep,
383                                         uint32_t count,
384                                         void *buf,
385                                         cy_as_return_status_t status
386                                         )
387 {
388         cyasgadget_ep  *an_ep;
389         cyasgadget_req *an_req;
390         cyasgadget       *cy_as_dev ;
391         unsigned           stopped ;
392         cy_as_return_status_t  ret ;
393         unsigned long   flags;
394
395         (void)h ;
396         (void)buf ;
397
398         cy_as_dev = cy_as_gadget_controller ;
399
400         if (cy_as_dev->driver == NULL)
401                 return;
402
403         an_ep =  &cy_as_dev->an_gadget_ep[ep] ;
404         stopped = an_ep->stopped ;
405
406         #ifndef WESTBRIDGE_NDEBUG
407                 cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n",
408                         __func__, ep, count, status) ;
409         #endif
410
411         if (status == CY_AS_ERROR_CANCELED)
412                 return ;
413
414         spin_lock_irqsave(&cy_as_dev->lock, flags);
415
416         an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ;
417         list_del_init(&an_req->queue) ;
418
419         if (status == CY_AS_ERROR_SUCCESS)
420                 an_req->req.status = 0 ;
421         else
422                 an_req->req.status = -status ;
423
424         an_req->complete = 1;
425         an_req->req.actual = count ;
426         an_ep->stopped = 1;
427
428         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
429         an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
430
431         an_ep->stopped = stopped;
432
433         /* We need to call ReadAsync on this end-point
434          * again, so as to not miss any data packets. */
435         if (!an_ep->stopped) {
436                 spin_lock_irqsave(&cy_as_dev->lock, flags);
437                 an_req = 0 ;
438                 if (!list_empty(&an_ep->queue))
439                         an_req = list_entry(an_ep->queue.next,
440                                 cyasgadget_req, queue) ;
441
442                 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
443
444                 if ((an_req) && (an_req->req.status == -EINPROGRESS)) {
445                         ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
446                                 an_ep->num, cy_false, an_req->req.length,
447                                 an_req->req.buf, cyasgadget_readcallback);
448
449                         if (ret != CY_AS_ERROR_SUCCESS)
450                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
451                                         "cy_as_usb_read_data_async failed "
452                                         "with error code %d\n", ret) ;
453                         else
454                                 an_req->req.status = -EALREADY ;
455                 }
456         }
457 }
458
459 /* function is called when a usb write operation has completed*/
460 static void cyasgadget_writecallback(
461                                         cy_as_device_handle h,
462                                         cy_as_end_point_number_t ep,
463                                         uint32_t count,
464                                         void *buf,
465                                         cy_as_return_status_t status
466                                         )
467 {
468         cyasgadget_ep  *an_ep;
469         cyasgadget_req *an_req;
470         cyasgadget       *cy_as_dev ;
471         unsigned           stopped = 0;
472         cy_as_return_status_t  ret ;
473         unsigned long   flags;
474
475         (void)h ;
476         (void)buf ;
477
478         cy_as_dev = cy_as_gadget_controller ;
479         if (cy_as_dev->driver == NULL)
480                 return;
481
482         an_ep =  &cy_as_dev->an_gadget_ep[ep] ;
483
484         if (status == CY_AS_ERROR_CANCELED)
485                 return ;
486
487         #ifndef WESTBRIDGE_NDEBUG
488                 cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n",
489                         __func__, ep, count, status) ;
490         #endif
491
492         spin_lock_irqsave(&cy_as_dev->lock, flags);
493
494         an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ;
495         list_del_init(&an_req->queue) ;
496         an_req->req.actual = count ;
497
498         /* Verify the status value before setting req.status to zero */
499         if (status == CY_AS_ERROR_SUCCESS)
500                 an_req->req.status = 0 ;
501         else
502                 an_req->req.status = -status ;
503
504         an_ep->stopped = 1;
505
506         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
507
508         an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
509         an_ep->stopped = stopped;
510
511         /* We need to call WriteAsync on this end-point again, so as to not
512            miss any data packets. */
513         if (!an_ep->stopped) {
514                 spin_lock_irqsave(&cy_as_dev->lock, flags);
515                 an_req = 0 ;
516                 if (!list_empty(&an_ep->queue))
517                         an_req = list_entry(an_ep->queue.next,
518                                 cyasgadget_req, queue) ;
519                 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
520
521                 if ((an_req) && (an_req->req.status == -EINPROGRESS)) {
522                         ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
523                                 an_ep->num, an_req->req.length, an_req->req.buf,
524                                 cy_false, cyasgadget_writecallback);
525
526                         if (ret != CY_AS_ERROR_SUCCESS)
527                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
528                                         "cy_as_usb_write_data_async "
529                                         "failed with error code %d\n", ret) ;
530                         else
531                                 an_req->req.status = -EALREADY ;
532                 }
533         }
534 }
535
536 static void cyasgadget_stallcallback(
537                                                 cy_as_device_handle h,
538                                                 cy_as_return_status_t status,
539                                                 uint32_t tag,
540                                                 cy_as_funct_c_b_type cbtype,
541                                                 void *cbdata
542                                                 )
543 {
544         #ifndef WESTBRIDGE_NDEBUG
545         if (status != CY_AS_ERROR_SUCCESS)
546                 cy_as_hal_print_message("<1>_set/_clear stall "
547                         "failed with status %d\n", status) ;
548         #endif
549 }
550
551
552 /*******************************************************************/
553 /* All usb_ep_ops (cyasgadget_ep_ops) are placed in this subsection*/
554 /*******************************************************************/
555 static int cyasgadget_enable(
556                         struct usb_ep *_ep,
557                         const struct usb_endpoint_descriptor *desc
558                                         )
559 {
560         cyasgadget              *an_dev;
561         cyasgadget_ep   *an_ep;
562         u32                     max, tmp;
563         unsigned long   flags;
564
565         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
566         if (!_ep || !desc || an_ep->desc || _ep->name == cy_as_ep0name
567                 || desc->bDescriptorType != USB_DT_ENDPOINT)
568                 return -EINVAL;
569
570         an_dev = an_ep->dev;
571         if (!an_dev->driver || an_dev->gadget.speed == USB_SPEED_UNKNOWN)
572                 return -ESHUTDOWN;
573
574         max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
575
576         spin_lock_irqsave(&an_dev->lock, flags);
577         _ep->maxpacket = max & 0x7ff;
578         an_ep->desc = desc;
579
580         /* ep_reset() has already been called */
581         an_ep->stopped = 0;
582         an_ep->out_overflow = 0;
583
584         if (an_ep->cyepconfig.enabled != cy_true) {
585                 #ifndef WESTBRIDGE_NDEBUG
586                 cy_as_hal_print_message("<1>_cy_as_gadget: "
587                         "cy_as_usb_end_point_config EP %s mismatch "
588                         "on enabled\n", an_ep->usb_ep_inst.name) ;
589                 #endif
590                 return -EINVAL;
591         }
592
593         tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
594         an_ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
595
596         spin_unlock_irqrestore(&an_dev->lock, flags);
597
598         switch (tmp) {
599         case USB_ENDPOINT_XFER_ISOC:
600                 if (an_ep->cyepconfig.type != cy_as_usb_iso) {
601                         #ifndef WESTBRIDGE_NDEBUG
602                         cy_as_hal_print_message("<1>_cy_as_gadget: "
603                                 "cy_as_usb_end_point_config EP %s mismatch "
604                                 "on type %d %d\n", an_ep->usb_ep_inst.name,
605                                 an_ep->cyepconfig.type, cy_as_usb_iso) ;
606                         #endif
607                         return -EINVAL;
608                 }
609                 break;
610         case USB_ENDPOINT_XFER_INT:
611                 if (an_ep->cyepconfig.type != cy_as_usb_int) {
612                         #ifndef WESTBRIDGE_NDEBUG
613                         cy_as_hal_print_message("<1>_cy_as_gadget: "
614                                 "cy_as_usb_end_point_config EP %s mismatch "
615                                 "on type %d %d\n", an_ep->usb_ep_inst.name,
616                                 an_ep->cyepconfig.type, cy_as_usb_int) ;
617                         #endif
618                         return -EINVAL;
619                 }
620                 break;
621         default:
622                 if (an_ep->cyepconfig.type != cy_as_usb_bulk) {
623                         #ifndef WESTBRIDGE_NDEBUG
624                         cy_as_hal_print_message("<1>_cy_as_gadget: "
625                                 "cy_as_usb_end_point_config EP %s mismatch "
626                                 "on type %d %d\n", an_ep->usb_ep_inst.name,
627                                 an_ep->cyepconfig.type, cy_as_usb_bulk) ;
628                         #endif
629                         return -EINVAL;
630                 }
631                 break;
632         }
633
634         tmp = desc->bEndpointAddress;
635         an_ep->is_in = (tmp & USB_DIR_IN) != 0;
636
637         if ((an_ep->cyepconfig.dir == cy_as_usb_in) &&
638         (!an_ep->is_in)) {
639                 #ifndef WESTBRIDGE_NDEBUG
640                 cy_as_hal_print_message("<1>_cy_as_gadget: "
641                         "cy_as_usb_end_point_config EP %s mismatch "
642                         "on dir %d %d\n", an_ep->usb_ep_inst.name,
643                         an_ep->cyepconfig.dir, cy_as_usb_in) ;
644                 #endif
645                 return -EINVAL;
646         } else if ((an_ep->cyepconfig.dir == cy_as_usb_out) &&
647         (an_ep->is_in)) {
648                 #ifndef WESTBRIDGE_NDEBUG
649                 cy_as_hal_print_message("<1>_cy_as_gadget: "
650                         "cy_as_usb_end_point_config EP %s mismatch "
651                         "on dir %d %d\n", an_ep->usb_ep_inst.name,
652                         an_ep->cyepconfig.dir, cy_as_usb_out) ;
653                 #endif
654                 return -EINVAL;
655         }
656
657         cy_as_usb_clear_stall(an_dev->dev_handle, an_ep->num,
658                 cyasgadget_stallcallback, 0);
659
660         cy_as_hal_print_message("%s enabled %s (ep%d-%d) max %04x\n",
661                 __func__, _ep->name, an_ep->num, tmp, max);
662
663         return 0;
664 }
665
666 static int cyasgadget_disable(
667                                         struct usb_ep *_ep
668                                         )
669 {
670         cyasgadget_ep   *an_ep;
671         unsigned long   flags;
672
673         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
674         if (!_ep || !an_ep->desc || _ep->name == cy_as_ep0name)
675                 return -EINVAL;
676
677         spin_lock_irqsave(&an_ep->dev->lock, flags);
678         cyas_ep_reset(an_ep);
679
680         spin_unlock_irqrestore(&an_ep->dev->lock, flags);
681         return 0;
682 }
683
684 static struct usb_request *cyasgadget_alloc_request(
685                         struct usb_ep *_ep, gfp_t gfp_flags
686                         )
687 {
688         cyasgadget_ep   *an_ep;
689         cyasgadget_req  *an_req;
690
691         if (!_ep)
692                 return NULL;
693
694         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
695
696         an_req = kzalloc(sizeof(cyasgadget_req), gfp_flags);
697         if (!an_req)
698                 return NULL;
699
700         an_req->req.dma = DMA_ADDR_INVALID;
701         INIT_LIST_HEAD(&an_req->queue);
702
703         return &an_req->req;
704 }
705
706 static void cyasgadget_free_request(
707                                         struct usb_ep *_ep,
708                                         struct usb_request *_req
709                                         )
710 {
711         cyasgadget_req *an_req ;
712
713         if (!_ep || !_req)
714                 return ;
715
716         an_req = container_of(_req, cyasgadget_req, req) ;
717
718         kfree(an_req);
719 }
720
721 /* Load a packet into the fifo we use for usb IN transfers.
722  * works for all endpoints. */
723 static int cyasgadget_queue(
724                                 struct usb_ep *_ep,
725                                 struct usb_request *_req,
726                                 gfp_t gfp_flags
727                                 )
728 {
729         cyasgadget_req  *as_req;
730         cyasgadget_ep   *as_ep;
731         cyasgadget              *cy_as_dev;
732         unsigned long   flags;
733         cy_as_return_status_t  ret = 0;
734
735         as_req = container_of(_req, cyasgadget_req, req);
736         if (!_req || !_req->complete || !_req->buf
737                 || !list_empty(&as_req->queue))
738                 return -EINVAL;
739
740         as_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
741
742         if (!_ep || (!as_ep->desc && (as_ep->num != 0)))
743                 return -EINVAL;
744
745         cy_as_dev = as_ep->dev;
746         if (!cy_as_dev->driver ||
747                 cy_as_dev->gadget.speed == USB_SPEED_UNKNOWN)
748                 return -ESHUTDOWN;
749
750         spin_lock_irqsave(&cy_as_dev->lock, flags);
751
752         _req->status = -EINPROGRESS;
753         _req->actual = 0;
754
755         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
756
757         /* Call Async functions */
758         if (as_ep->is_in) {
759                 #ifndef WESTBRIDGE_NDEBUG
760                         cy_as_hal_print_message("<1>_cy_as_gadget: "
761                                 "cy_as_usb_write_data_async being called "
762                                 "on ep %d\n", as_ep->num) ;
763                 #endif
764
765                 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
766                         as_ep->num, _req->length, _req->buf,
767                         cy_false, cyasgadget_writecallback) ;
768                 if (ret != CY_AS_ERROR_SUCCESS)
769                         cy_as_hal_print_message("<1>_cy_as_gadget: "
770                                 "cy_as_usb_write_data_async failed with "
771                                 "error code %d\n", ret) ;
772                 else
773                         _req->status = -EALREADY ;
774         } else if (as_ep->num == 0) {
775                 /*
776                 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
777                         as_ep->num, _req->length, _req->buf, cy_false,
778                         cyasgadget_setupwritecallback) ;
779
780                 if (ret != CY_AS_ERROR_SUCCESS)
781                         cy_as_hal_print_message("<1>_cy_as_gadget: "
782                                 "cy_as_usb_write_data_async failed with error "
783                                 "code %d\n", ret) ;
784                 */
785                 if ((cy_as_dev->outsetupreq) && (_req->length)) {
786                         #ifndef WESTBRIDGE_NDEBUG
787                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
788                                         "cy_as_usb_read_data_async "
789                                         "being called on ep %d\n",
790                                         as_ep->num) ;
791                         #endif
792
793                         ret = cy_as_usb_read_data_async (
794                                 cy_as_dev->dev_handle, as_ep->num,
795                                 cy_true, _req->length, _req->buf,
796                                 cyasgadget_setupreadcallback);
797
798                         if (ret != CY_AS_ERROR_SUCCESS)
799                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
800                                 "cy_as_usb_read_data_async failed with "
801                                 "error code %d\n", ret) ;
802
803                 } else {
804                         #ifndef WESTBRIDGE_NDEBUG
805                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
806                                         "cy_as_usb_write_data_async "
807                                         "being called on ep %d\n",
808                                         as_ep->num) ;
809                         #endif
810
811                         ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
812                         as_ep->num, _req->length, _req->buf, cy_false,
813                         cyasgadget_setupwritecallback) ;
814
815                         if (ret != CY_AS_ERROR_SUCCESS)
816                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
817                                 "cy_as_usb_write_data_async failed with "
818                                 "error code %d\n", ret) ;
819                 }
820
821         } else if (list_empty(&as_ep->queue)) {
822                 #ifndef WESTBRIDGE_NDEBUG
823                         cy_as_hal_print_message("<1>_cy_as_gadget: "
824                                 "cy_as_usb_read_data_async being called since "
825                                 "ep queue empty%d\n", ret) ;
826                 #endif
827
828                 ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
829                         as_ep->num, cy_false, _req->length, _req->buf,
830                         cyasgadget_readcallback) ;
831                 if (ret != CY_AS_ERROR_SUCCESS)
832                         cy_as_hal_print_message("<1>_cy_as_gadget: "
833                                 "cy_as_usb_read_data_async failed with error "
834                                 "code %d\n", ret) ;
835                 else
836                         _req->status = -EALREADY ;
837         }
838
839         spin_lock_irqsave(&cy_as_dev->lock, flags);
840
841         if (as_req)
842                 list_add_tail(&as_req->queue, &as_ep->queue);
843
844         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
845
846         return 0;
847 }
848
849 /* dequeue request */
850 static int cyasgadget_dequeue(
851                                 struct usb_ep *_ep,
852                                 struct usb_request *_req
853                                 )
854 {
855         cyasgadget_ep   *an_ep;
856         cyasgadget              *dev;
857         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
858         dev = an_ep->dev ;
859
860         #ifndef WESTBRIDGE_NDEBUG
861                 cy_as_hal_print_message("<1>%s called\n", __func__);
862         #endif
863
864         cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
865
866         return 0;
867 }
868
869 static int cyasgadget_set_halt(
870                                 struct usb_ep *_ep,
871                                 int value
872                                 )
873 {
874         cyasgadget_ep   *an_ep;
875         int                     retval = 0;
876
877         #ifndef WESTBRIDGE_NDEBUG
878         cy_as_hal_print_message("<1>%s called\n", __func__);
879         #endif
880
881         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
882         if (!_ep || (!an_ep->desc && an_ep->num != 0))
883                 return -EINVAL;
884
885         if (!an_ep->dev->driver || an_ep->dev->gadget.speed ==
886                 USB_SPEED_UNKNOWN)
887                 return -ESHUTDOWN;
888
889         if (an_ep->desc /* not ep0 */ &&
890         (an_ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC)
891                 return -EINVAL;
892
893         if (!list_empty(&an_ep->queue))
894                 retval = -EAGAIN;
895         else if (an_ep->is_in && value &&
896                 cyasgadget_fifo_status(_ep) != 0)
897                         retval = -EAGAIN;
898         else {
899                 if (value) {
900                         cy_as_usb_set_stall(an_ep->dev->dev_handle,
901                                 an_ep->num, cyasgadget_stallcallback, 0) ;
902                 } else {
903                         cy_as_usb_clear_stall(an_ep->dev->dev_handle,
904                                 an_ep->num, cyasgadget_stallcallback, 0) ;
905                 }
906         }
907
908         return retval;
909 }
910
911 static int cyasgadget_fifo_status(
912                                 struct usb_ep *_ep
913                                 )
914 {
915         #ifndef WESTBRIDGE_NDEBUG
916         cy_as_hal_print_message("<1>%s called\n", __func__);
917         #endif
918
919         return 0 ;
920 }
921
922 static void cyasgadget_fifo_flush(
923                                 struct usb_ep *_ep
924                                 )
925 {
926         #ifndef WESTBRIDGE_NDEBUG
927         cy_as_hal_print_message("<1>%s called\n", __func__);
928         #endif
929 }
930
931 static struct usb_ep_ops cyasgadget_ep_ops = {
932         .enable         = cyasgadget_enable,
933         .disable        = cyasgadget_disable,
934         .alloc_request  = cyasgadget_alloc_request,
935         .free_request   = cyasgadget_free_request,
936         .queue          = cyasgadget_queue,
937         .dequeue        = cyasgadget_dequeue,
938         .set_halt       = cyasgadget_set_halt,
939         .fifo_status    = cyasgadget_fifo_status,
940         .fifo_flush     = cyasgadget_fifo_flush,
941 };
942
943 /*************************************************************/
944 /*This subsection contains all usb_gadget_ops cyasgadget_ops */
945 /*************************************************************/
946 static int cyasgadget_get_frame(
947                                 struct usb_gadget *_gadget
948                                 )
949 {
950         #ifndef WESTBRIDGE_NDEBUG
951         cy_as_hal_print_message("<1>%s called\n", __func__);
952         #endif
953         return 0 ;
954 }
955
956 static int cyasgadget_wakeup(
957                                         struct usb_gadget *_gadget
958                                         )
959 {
960         #ifndef WESTBRIDGE_NDEBUG
961         cy_as_hal_print_message("<1>%s called\n", __func__);
962         #endif
963         return 0;
964 }
965
966 static int cyasgadget_set_selfpowered(
967                                         struct usb_gadget *_gadget,
968                                         int value
969                                         )
970 {
971         #ifndef WESTBRIDGE_NDEBUG
972         cy_as_hal_print_message("<1>%s called\n", __func__);
973         #endif
974         return 0;
975 }
976
977 static int cyasgadget_pullup(
978                                         struct usb_gadget *_gadget,
979                                         int is_on
980                                         )
981 {
982         struct cyasgadget  *cy_as_dev ;
983         unsigned long   flags;
984
985         #ifndef WESTBRIDGE_NDEBUG
986         cy_as_hal_print_message("<1>%s called\n", __func__);
987         #endif
988
989         if (!_gadget)
990                 return -ENODEV;
991
992         cy_as_dev = container_of(_gadget, cyasgadget, gadget);
993
994         spin_lock_irqsave(&cy_as_dev->lock, flags);
995         cy_as_dev->softconnect = (is_on != 0);
996         if (is_on)
997                 cy_as_usb_connect(cy_as_dev->dev_handle, 0, 0) ;
998         else
999                 cy_as_usb_disconnect(cy_as_dev->dev_handle, 0, 0) ;
1000
1001         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
1002
1003         return 0;
1004 }
1005
1006 static int cyasgadget_ioctl(
1007                                         struct usb_gadget *_gadget,
1008                                         unsigned code,
1009                                         unsigned long param
1010                                         )
1011 {
1012         int err = 0;
1013         int retval = 0;
1014         int ret_stat = 0;
1015         cyasgadget *dev = cy_as_gadget_controller ;
1016
1017         #ifndef WESTBRIDGE_NDEBUG
1018         cy_as_hal_print_message("<1>%s called, code=%d, param=%ld\n",
1019                 __func__, code, param);
1020         #endif
1021         /*
1022          * extract the type and number bitfields, and don't decode
1023          * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
1024          */
1025         if (_IOC_TYPE(code) != CYASGADGET_IOC_MAGIC) {
1026                 #ifndef WESTBRIDGE_NDEBUG
1027                 cy_as_hal_print_message("%s, bad magic number = 0x%x\n",
1028                         __func__, _IOC_TYPE(code));
1029                 #endif
1030                 return -ENOTTY;
1031         }
1032
1033         if (_IOC_NR(code) > CYASGADGET_IOC_MAXNR) {
1034                 #ifndef WESTBRIDGE_NDEBUG
1035                 cy_as_hal_print_message("%s, bad ioctl code = 0x%x\n",
1036                         __func__, _IOC_NR(code));
1037                 #endif
1038                 return -ENOTTY;
1039         }
1040
1041         /*
1042          * the direction is a bitmask, and VERIFY_WRITE catches R/W
1043          * transfers. `Type' is user-oriented, while
1044          * access_ok is kernel-oriented, so the concept of "read" and
1045          * "write" is reversed
1046          */
1047         if (_IOC_DIR(code) & _IOC_READ)
1048                 err = !access_ok(VERIFY_WRITE,
1049                         (void __user *)param, _IOC_SIZE(code));
1050         else if (_IOC_DIR(code) & _IOC_WRITE)
1051                 err =  !access_ok(VERIFY_READ,
1052                         (void __user *)param, _IOC_SIZE(code));
1053
1054         if (err) {
1055                 cy_as_hal_print_message("%s, bad ioctl dir = 0x%x\n",
1056                         __func__, _IOC_DIR(code));
1057                 return -EFAULT;
1058         }
1059
1060         switch (code) {
1061         case CYASGADGET_GETMTPSTATUS:
1062                 {
1063                 cy_as_gadget_ioctl_tmtp_status *usr_d =
1064                         (cy_as_gadget_ioctl_tmtp_status *)param ;
1065
1066                 #ifndef WESTBRIDGE_NDEBUG
1067                 cy_as_hal_print_message("%s: got CYASGADGET_GETMTPSTATUS\n",
1068                         __func__);
1069                 #endif
1070
1071                 retval = __put_user(dev->tmtp_send_complete,
1072                         (uint32_t __user *)(&(usr_d->tmtp_send_complete)));
1073                 retval = __put_user(dev->tmtp_get_complete,
1074                         (uint32_t __user *)(&(usr_d->tmtp_get_complete)));
1075                 retval = __put_user(dev->tmtp_need_new_blk_tbl,
1076                         (uint32_t __user *)(&(usr_d->tmtp_need_new_blk_tbl)));
1077
1078                 if (copy_to_user((&(usr_d->tmtp_send_complete_data)),
1079                         (&(dev->tmtp_send_complete_data)),
1080                         sizeof(cy_as_gadget_ioctl_send_object)))
1081                         return -EFAULT;
1082
1083                 if (copy_to_user((&(usr_d->tmtp_get_complete_data)),
1084                         (&(dev->tmtp_get_complete_data)),
1085                         sizeof(cy_as_gadget_ioctl_get_object)))
1086                         return -EFAULT;
1087                 break;
1088                 }
1089         case CYASGADGET_CLEARTMTPSTATUS:
1090                 {
1091                 #ifndef WESTBRIDGE_NDEBUG
1092                 cy_as_hal_print_message("%s got CYASGADGET_CLEARTMTPSTATUS\n",
1093                         __func__);
1094                 #endif
1095
1096                 dev->tmtp_send_complete = 0 ;
1097                 dev->tmtp_get_complete = 0 ;
1098                 dev->tmtp_need_new_blk_tbl = 0 ;
1099
1100                 break;
1101                 }
1102         case CYASGADGET_INITSOJ:
1103                 {
1104                 cy_as_gadget_ioctl_i_s_o_j_d k_d ;
1105                 cy_as_gadget_ioctl_i_s_o_j_d *usr_d =
1106                         (cy_as_gadget_ioctl_i_s_o_j_d *)param ;
1107                 cy_as_mtp_block_table blk_table ;
1108                 struct scatterlist sg ;
1109                 char *alloc_filename;
1110                 struct file *file_to_allocate;
1111
1112                 #ifndef WESTBRIDGE_NDEBUG
1113                 cy_as_hal_print_message("%s got CYASGADGET_INITSOJ\n",
1114                         __func__);
1115                 #endif
1116
1117                 memset(&blk_table, 0, sizeof(blk_table));
1118
1119                 /* Get user argument structure  */
1120                 if (copy_from_user(&k_d, usr_d,
1121                         sizeof(cy_as_gadget_ioctl_i_s_o_j_d)))
1122                         return -EFAULT;
1123
1124                 /* better use fixed size buff*/
1125                 alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1126                 if (alloc_filename == NULL)
1127                         return -ENOMEM;
1128
1129                 /* get the filename */
1130                 if (copy_from_user(alloc_filename, k_d.file_name,
1131                         k_d.name_length + 1)) {
1132                         #ifndef WESTBRIDGE_NDEBUG
1133                         cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, "
1134                                 "copy file name from user space failed\n",
1135                                 __func__);
1136                         #endif
1137                         kfree(alloc_filename);
1138                         return -EFAULT;
1139                 }
1140
1141                 file_to_allocate = filp_open(alloc_filename, O_RDWR, 0);
1142
1143                 if (!IS_ERR(file_to_allocate)) {
1144
1145                         struct address_space *mapping =
1146                                 file_to_allocate->f_mapping;
1147                         const struct address_space_operations *a_ops =
1148                                 mapping->a_ops;
1149                         struct inode *inode = mapping->host;
1150                         struct inode *alloc_inode =
1151                                 file_to_allocate->f_path.dentry->d_inode;
1152                         int cluster = 0;
1153                         uint32_t num_clusters = 0;
1154                         struct buffer_head bh;
1155                         struct kstat stat;
1156                         struct iattr alloc_iattr;
1157                         int nr_pages = 0;
1158                         int ret_stat = 0;
1159
1160                         #ifndef WESTBRIDGE_NDEBUG
1161                         cy_as_hal_print_message("%s: fhandle is OK, "
1162                                 "calling vfs_getattr\n", __func__);
1163                         #endif
1164
1165                         ret_stat = vfs_getattr(file_to_allocate->f_path.mnt,
1166                                 file_to_allocate->f_path.dentry, &stat);
1167
1168                         #ifndef WESTBRIDGE_NDEBUG
1169                         cy_as_hal_print_message("%s: returned from "
1170                                 "vfs_getattr() stat->blksize=0x%lx\n",
1171                                 __func__, stat.blksize);
1172                         #endif
1173
1174                         /* TODO:  get this from disk properties
1175                          * (from blockdevice)*/
1176                         #define SECTOR_SIZE 512
1177                         if (stat.blksize != 0) {
1178                                 num_clusters = (k_d.num_bytes) / SECTOR_SIZE;
1179
1180                                 if (((k_d.num_bytes) % SECTOR_SIZE) != 0)
1181                                                 num_clusters++;
1182                         } else {
1183                                 goto initsoj_safe_exit;
1184                         }
1185
1186                         bh.b_state = 0;
1187                         bh.b_blocknr = 0;
1188                         /* block size is arbitrary , we'll use sector size*/
1189                         bh.b_size = SECTOR_SIZE ;
1190
1191                         #ifndef WESTBRIDGE_NDEBUG
1192                         cy_as_hal_print_message("%s: getting fat blocks %d "
1193                                 "size of  %d\n", __func__,
1194                                 num_clusters, bh.b_size);
1195                         #endif
1196                         for (cluster = 0; cluster < num_clusters; cluster++)  {
1197                                 ret_stat = fat_get_block(inode,
1198                                         cluster, &bh, 1);
1199                                 if (ret_stat) {
1200                                         cy_as_hal_print_message(
1201                                                 "%s: unable to get fat block, "
1202                                                 "ret_stat=0x%d\n",
1203                                                 __func__, ret_stat);
1204                                         goto initsoj_safe_exit;
1205                                 }
1206                         }
1207
1208                         #ifndef WESTBRIDGE_NDEBUG
1209                         cy_as_hal_print_message("%s: allocated clusters "
1210                                 "successfully (fat_get_block), check bmap..."
1211                                 "\n", __func__);
1212                         #endif
1213
1214                         alloc_iattr.ia_valid = ATTR_SIZE;
1215                         alloc_iattr.ia_size = k_d.num_bytes;
1216
1217                         #ifndef WESTBRIDGE_NDEBUG
1218                         cy_as_hal_print_message("%s: calling fat_notify_change "
1219                                 "(ia_valid:%d, ia_size:%d)\n", __func__,
1220                                 alloc_iattr.ia_valid,
1221                                 (int)alloc_iattr.ia_size);
1222                         #endif
1223
1224                         /* adjust the filesize */
1225                         ret_stat = alloc_inode->i_op->setattr(
1226                                 file_to_allocate->f_path.dentry, &alloc_iattr);
1227                         #ifndef WESTBRIDGE_NDEBUG
1228                         cy_as_hal_print_message("%s: fat_setattr() "
1229                                 "returned 0x%x\n",
1230                                 __func__, ret_stat);
1231                         #endif
1232
1233                         /* clear dirty pages in page cache
1234                          * (if were any allocated) */
1235                         nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE);
1236
1237                         if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0)
1238                                 nr_pages++;
1239
1240                         #ifndef WESTBRIDGE_NDEBUG
1241                         /*check out how many pages where actually allocated */
1242                         if (mapping->nrpages != nr_pages)
1243                                 cy_as_hal_print_message("%s mpage_cleardirty "
1244                                         "mapping->nrpages %d != num_pages %d\n",
1245                                         __func__, (int) mapping->nrpages,
1246                                         nr_pages);
1247
1248                                 cy_as_hal_print_message("%s: calling "
1249                                         "mpage_cleardirty() "
1250                                         "for %d pages\n", __func__, nr_pages);
1251                         #endif
1252
1253                         ret_stat = mpage_cleardirty(mapping, nr_pages);
1254
1255                         /*fill up the the block table from the addr mapping  */
1256                         if (a_ops->bmap) {
1257                                 int8_t blk_table_idx = -1;
1258                                 uint32_t file_block_idx = 0;
1259                                 uint32_t last_blk_addr_map = 0,
1260                                         curr_blk_addr_map = 0;
1261
1262                                 #ifndef WESTBRIDGE_NDEBUG
1263                                 if (alloc_inode->i_bytes == 0)
1264                                                 cy_as_hal_print_message(
1265                                                 "%s: alloc_inode->ibytes =0\n",
1266                                                 __func__);
1267                                 #endif
1268
1269                                 /* iterate through the list of
1270                                  * blocks (not clusters)*/
1271                                 for (file_block_idx = 0;
1272                                         file_block_idx < num_clusters
1273                                         /*inode->i_bytes*/; file_block_idx++) {
1274
1275                                         /* returns starting sector number */
1276                                         curr_blk_addr_map =
1277                                                 a_ops->bmap(mapping,
1278                                                         file_block_idx);
1279
1280                                         /*no valid mapping*/
1281                                         if (curr_blk_addr_map == 0) {
1282                                                 #ifndef WESTBRIDGE_NDEBUG
1283                                                 cy_as_hal_print_message(
1284                                                         "%s:hit invalid "
1285                                                         "mapping\n", __func__);
1286                                                 #endif
1287                                                 break;
1288                                         } else if (curr_blk_addr_map !=
1289                                                 (last_blk_addr_map + 1) ||
1290                                                 (blk_table.num_blocks
1291                                                 [blk_table_idx] == 65535)) {
1292
1293                                                 /* next table entry */
1294                                                 blk_table_idx++;
1295                                                 /* starting sector of a
1296                                                  * scattered cluster*/
1297                                                 blk_table.start_blocks
1298                                                         [blk_table_idx] =
1299                                                         curr_blk_addr_map;
1300                                                 /* ++ num of blocks in cur
1301                                                  * table entry*/
1302                                                 blk_table.
1303                                                 num_blocks[blk_table_idx]++;
1304
1305                                                 #ifndef WESTBRIDGE_NDEBUG
1306                                                 if (file_block_idx != 0)
1307                                                         cy_as_hal_print_message(
1308                                                          "<*> next table "
1309                                                          "entry:%d required\n",
1310                                                          blk_table_idx);
1311                                                 #endif
1312                                         } else {
1313                                                 /*add contiguous block*/
1314                                                 blk_table.num_blocks
1315                                                 [blk_table_idx]++;
1316                                         } /*if (curr_blk_addr_map == 0)*/
1317
1318                                         last_blk_addr_map = curr_blk_addr_map;
1319                                 } /* end for (file_block_idx = 0; file_block_idx
1320                                 < inode->i_bytes;) */
1321
1322                                 #ifndef WESTBRIDGE_NDEBUG
1323                                 /*print result for verification*/
1324                                 {
1325                                         int i;
1326                                         cy_as_hal_print_message(
1327                                                 "%s: print block table "
1328                                                 "mapping:\n",
1329                                                 __func__);
1330                                         for (i = 0; i <= blk_table_idx; i++) {
1331                                                 cy_as_hal_print_message(
1332                                                 "<1> %d 0x%x 0x%x\n", i,
1333                                                 blk_table.start_blocks[i],
1334                                                 blk_table.num_blocks[i]);
1335                                         }
1336                                 }
1337                                 #endif
1338
1339                                 /* copy the block table to user
1340                                  * space (for debug purposes) */
1341                                 retval = __put_user(
1342                                         blk_table.start_blocks[blk_table_idx],
1343                                         (uint32_t __user *)
1344                                                 (&(usr_d->blk_addr_p)));
1345
1346                                 retval = __put_user(
1347                                         blk_table.num_blocks[blk_table_idx],
1348                                         (uint32_t __user *)
1349                                                 (&(usr_d->blk_count_p)));
1350
1351                                 blk_table_idx++;
1352                                 retval = __put_user(blk_table_idx,
1353                                         (uint32_t __user *)
1354                                                 (&(usr_d->item_count)));
1355
1356                         } /*end if (a_ops->bmap)*/
1357
1358                         filp_close(file_to_allocate, NULL);
1359
1360                         dev->tmtp_send_complete = 0 ;
1361                         dev->tmtp_need_new_blk_tbl = 0 ;
1362
1363                         #ifndef WESTBRIDGE_NDEBUG
1364                         cy_as_hal_print_message(
1365                                 "%s: calling cy_as_mtp_init_send_object()\n",
1366                                 __func__);
1367                         #endif
1368                         sg_init_one(&sg, &blk_table, sizeof(blk_table));
1369                         ret_stat = cy_as_mtp_init_send_object(dev->dev_handle,
1370                                 (cy_as_mtp_block_table *)&sg,
1371                                 k_d.num_bytes, 0, 0);
1372                         #ifndef WESTBRIDGE_NDEBUG
1373                         cy_as_hal_print_message("%s: returned from "
1374                                 "cy_as_mtp_init_send_object()\n", __func__);
1375                         #endif
1376
1377                 }
1378                 #ifndef WESTBRIDGE_NDEBUG
1379                 else {
1380                         cy_as_hal_print_message(
1381                                 "%s: failed to allocate the file %s\n",
1382                                 __func__, alloc_filename);
1383                 } /* end if (file_to_allocate)*/
1384                 #endif
1385                 kfree(alloc_filename);
1386 initsoj_safe_exit:
1387                         ret_stat = 0;
1388                         retval = __put_user(ret_stat,
1389                                 (uint32_t __user *)(&(usr_d->ret_val)));
1390
1391                         break;
1392                 }
1393         case CYASGADGET_INITGOJ:
1394                 {
1395                 cy_as_gadget_ioctl_i_g_o_j_d k_d ;
1396                 cy_as_gadget_ioctl_i_g_o_j_d *usr_d =
1397                         (cy_as_gadget_ioctl_i_g_o_j_d *)param ;
1398                 cy_as_mtp_block_table blk_table ;
1399                 struct scatterlist sg ;
1400                 char *map_filename;
1401                 struct file *file_to_map;
1402
1403                 #ifndef WESTBRIDGE_NDEBUG
1404                 cy_as_hal_print_message(
1405                         "%s: got CYASGADGET_INITGOJ\n",
1406                                 __func__);
1407                 #endif
1408
1409                 memset(&blk_table, 0, sizeof(blk_table));
1410
1411                 /* Get user argument sturcutre */
1412                 if (copy_from_user(&k_d, usr_d,
1413                         sizeof(cy_as_gadget_ioctl_i_g_o_j_d)))
1414                                 return -EFAULT;
1415
1416                 map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1417                 if (map_filename == NULL)
1418                         return -ENOMEM;
1419                 if (copy_from_user(map_filename, k_d.file_name,
1420                         k_d.name_length + 1)) {
1421                         #ifndef WESTBRIDGE_NDEBUG
1422                         cy_as_hal_print_message("%s: copy file name from "
1423                                 "user space failed\n", __func__);
1424                         #endif
1425                         kfree(map_filename);
1426                         return -EFAULT;
1427                 }
1428
1429                 #ifndef WESTBRIDGE_NDEBUG
1430                 cy_as_hal_print_message("<*>%s: opening %s for kernel "
1431                         "mode access map\n", __func__, map_filename);
1432                 #endif
1433                 file_to_map = filp_open(map_filename, O_RDWR, 0);
1434                 if (file_to_map) {
1435                         struct address_space *mapping = file_to_map->f_mapping;
1436                         const struct address_space_operations
1437                                 *a_ops = mapping->a_ops;
1438                         struct inode *inode = mapping->host;
1439
1440                         int8_t blk_table_idx = -1;
1441                         uint32_t file_block_idx = 0;
1442                         uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0;
1443
1444                         /*verify operation exists*/
1445                         if (a_ops->bmap) {
1446                                 #ifndef WESTBRIDGE_NDEBUG
1447                                 cy_as_hal_print_message(
1448                                         "<*>%s: bmap found, i_bytes=0x%x, "
1449                                         "i_size=0x%x, i_blocks=0x%x\n",
1450                                         __func__, inode->i_bytes,
1451                                         (unsigned int) inode->i_size,
1452                                         (unsigned int) inode->i_blocks);
1453                                 #endif
1454
1455                                 k_d.num_bytes = inode->i_size;
1456
1457                                 #ifndef WESTBRIDGE_NDEBUG
1458                                 cy_as_hal_print_message(
1459                                         "<*>%s: k_d.num_bytes=0x%x\n",
1460                                         __func__, k_d.num_bytes);
1461                                 #endif
1462
1463                                 for (file_block_idx = 0;
1464                                         file_block_idx < inode->i_size;
1465                                         file_block_idx++) {
1466                                         curr_blk_addr_map =
1467                                                 a_ops->bmap(mapping,
1468                                                         file_block_idx);
1469
1470                                         if (curr_blk_addr_map == 0) {
1471                                                 /*no valid mapping*/
1472                                                 #ifndef WESTBRIDGE_NDEBUG
1473                                                 cy_as_hal_print_message(
1474                                                         "%s: no valid "
1475                                                         "mapping\n", __func__);
1476                                                 #endif
1477                                                 break;
1478                                         } else if (curr_blk_addr_map !=
1479                                         (last_blk_addr_map + 1)) {
1480                                                 /*non-contiguous break*/
1481                                                 blk_table_idx++;
1482                                                 blk_table.start_blocks
1483                                                         [blk_table_idx] =
1484                                                         curr_blk_addr_map;
1485                                                 blk_table.num_blocks
1486                                                         [blk_table_idx]++;
1487                                                 #ifndef WESTBRIDGE_NDEBUG
1488                                                 cy_as_hal_print_message(
1489                                                         "%s: found non-"
1490                                                         "contiguous break",
1491                                                         __func__);
1492                                                 #endif
1493                                         } else {
1494                                                 /*add contiguous block*/
1495                                                 blk_table.num_blocks
1496                                                         [blk_table_idx]++;
1497                                         }
1498                                         last_blk_addr_map = curr_blk_addr_map;
1499                                 }
1500
1501                                 /*print result for verification*/
1502                                 #ifndef WESTBRIDGE_NDEBUG
1503                                 {
1504                                         int i = 0;
1505
1506                                         for (i = 0 ; i <= blk_table_idx; i++) {
1507                                                 cy_as_hal_print_message(
1508                                                 "%s %d 0x%x 0x%x\n",
1509                                                 __func__, i,
1510                                                 blk_table.start_blocks[i],
1511                                                 blk_table.num_blocks[i]);
1512                                         }
1513                                 }
1514                                 #endif
1515                         } else {
1516                                 #ifndef WESTBRIDGE_NDEBUG
1517                                 cy_as_hal_print_message(
1518                                         "%s: could not find "
1519                                         "a_ops->bmap\n", __func__);
1520                                 #endif
1521                                 return -EFAULT;
1522                         }
1523
1524                         filp_close(file_to_map, NULL);
1525
1526                         dev->tmtp_get_complete = 0 ;
1527                         dev->tmtp_need_new_blk_tbl = 0 ;
1528
1529                         ret_stat = __put_user(
1530                                 blk_table.start_blocks[blk_table_idx],
1531                                 (uint32_t __user *)(&(usr_d->blk_addr_p)));
1532
1533                         ret_stat = __put_user(
1534                                 blk_table.num_blocks[blk_table_idx],
1535                                 (uint32_t __user *)(&(usr_d->blk_count_p)));
1536
1537                         sg_init_one(&sg, &blk_table, sizeof(blk_table));
1538
1539                         #ifndef WESTBRIDGE_NDEBUG
1540                         cy_as_hal_print_message(
1541                                 "%s: calling cy_as_mtp_init_get_object() "
1542                                 "start=0x%x, num =0x%x, tid=0x%x, "
1543                                 "num_bytes=0x%x\n",
1544                                 __func__,
1545                                 blk_table.start_blocks[0],
1546                                 blk_table.num_blocks[0],
1547                                 k_d.tid,
1548                                 k_d.num_bytes);
1549                         #endif
1550
1551                         ret_stat = cy_as_mtp_init_get_object(
1552                                 dev->dev_handle,
1553                                 (cy_as_mtp_block_table *)&sg,
1554                                 k_d.num_bytes, k_d.tid, 0, 0);
1555                         if (ret_stat != CY_AS_ERROR_SUCCESS) {
1556                                         #ifndef WESTBRIDGE_NDEBUG
1557                                         cy_as_hal_print_message(
1558                                                 "%s: cy_as_mtp_init_get_object "
1559                                                 "failed ret_stat=0x%x\n",
1560                                                 __func__, ret_stat);
1561                                         #endif
1562                         }
1563                 }
1564                 #ifndef WESTBRIDGE_NDEBUG
1565                 else {
1566                                 cy_as_hal_print_message(
1567                                         "%s: failed to open file %s\n",
1568                                         __func__, map_filename);
1569                 }
1570                 #endif
1571                 kfree(map_filename);
1572
1573                 ret_stat = 0;
1574                 retval = __put_user(ret_stat, (uint32_t __user *)
1575                         (&(usr_d->ret_val)));
1576                 break;
1577                 }
1578         case CYASGADGET_CANCELSOJ:
1579                 {
1580                 cy_as_gadget_ioctl_cancel *usr_d =
1581                         (cy_as_gadget_ioctl_cancel *)param ;
1582
1583                 #ifndef WESTBRIDGE_NDEBUG
1584                         cy_as_hal_print_message(
1585                                 "%s: got CYASGADGET_CANCELSOJ\n",
1586                                 __func__);
1587                 #endif
1588
1589                 ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0);
1590
1591                 retval = __put_user(ret_stat, (uint32_t __user *)
1592                         (&(usr_d->ret_val)));
1593                 break;
1594                 }
1595         case CYASGADGET_CANCELGOJ:
1596                 {
1597                 cy_as_gadget_ioctl_cancel *usr_d =
1598                         (cy_as_gadget_ioctl_cancel *)param ;
1599
1600                 #ifndef WESTBRIDGE_NDEBUG
1601                 cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n",
1602                         __func__);
1603                 #endif
1604
1605                 ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0);
1606
1607                 retval = __put_user(ret_stat,
1608                         (uint32_t __user *)(&(usr_d->ret_val)));
1609                 break;
1610                 }
1611         default:
1612                 {
1613                 #ifndef WESTBRIDGE_NDEBUG
1614                 cy_as_hal_print_message("%s: unknown ioctl received: %d\n",
1615                         __func__, code);
1616
1617                 cy_as_hal_print_message("%s: known codes:\n"
1618                         "CYASGADGET_GETMTPSTATUS=%d\n"
1619                         "CYASGADGET_CLEARTMTPSTATUS=%d\n"
1620                         "CYASGADGET_INITSOJ=%d\n"
1621                         "CYASGADGET_INITGOJ=%d\n"
1622                         "CYASGADGET_CANCELSOJ=%d\n"
1623                         "CYASGADGET_CANCELGOJ=%d\n",
1624                         __func__,
1625                         CYASGADGET_GETMTPSTATUS,
1626                         CYASGADGET_CLEARTMTPSTATUS,
1627                         CYASGADGET_INITSOJ,
1628                         CYASGADGET_INITGOJ,
1629                         CYASGADGET_CANCELSOJ,
1630                         CYASGADGET_CANCELGOJ);
1631                 #endif
1632                 break;
1633                 }
1634         }
1635
1636         return 0;
1637 }
1638
1639 static const struct usb_gadget_ops cyasgadget_ops = {
1640         .get_frame               = cyasgadget_get_frame,
1641         .wakeup          = cyasgadget_wakeup,
1642         .set_selfpowered = cyasgadget_set_selfpowered,
1643         .pullup          = cyasgadget_pullup,
1644         .ioctl     = cyasgadget_ioctl,
1645 };
1646
1647
1648 /* keeping it simple:
1649  * - one bus driver, initted first;
1650  * - one function driver, initted second
1651  *
1652  * most of the work to support multiple controllers would
1653  * be to associate this gadget driver with all of them, or
1654  * perhaps to bind specific drivers to specific devices.
1655  */
1656
1657 static void cyas_ep_reset(
1658                                 cyasgadget_ep *an_ep
1659                                 )
1660 {
1661         #ifndef WESTBRIDGE_NDEBUG
1662         cy_as_hal_print_message("<1>%s called\n", __func__);
1663         #endif
1664
1665         an_ep->desc = NULL;
1666         INIT_LIST_HEAD(&an_ep->queue);
1667
1668         an_ep->stopped = 0 ;
1669         an_ep->is_in   = 0 ;
1670         an_ep->is_iso  = 0 ;
1671         an_ep->usb_ep_inst.maxpacket = ~0;
1672         an_ep->usb_ep_inst.ops = &cyasgadget_ep_ops;
1673 }
1674
1675 static void cyas_usb_reset(
1676                                 cyasgadget *cy_as_dev
1677                                 )
1678 {
1679         cy_as_return_status_t ret;
1680         cy_as_usb_enum_control config ;
1681
1682         #ifndef WESTBRIDGE_NDEBUG
1683         cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ;
1684
1685         cy_as_hal_print_message("<1>%s called mtp_firmware=0x%x\n",
1686                 __func__, dev_p->is_mtp_firmware);
1687         #endif
1688
1689         ret = cy_as_misc_release_resource(cy_as_dev->dev_handle,
1690                 cy_as_bus_u_s_b) ;
1691         if (ret != CY_AS_ERROR_SUCCESS && ret !=
1692                 CY_AS_ERROR_RESOURCE_NOT_OWNED) {
1693                 cy_as_hal_print_message("<1>_cy_as_gadget: cannot "
1694                         "release usb resource: failed with error code %d\n",
1695                         ret) ;
1696                 return ;
1697         }
1698
1699         cy_as_dev->gadget.speed = USB_SPEED_HIGH ;
1700
1701         ret = cy_as_usb_start(cy_as_dev->dev_handle, 0, 0) ;
1702         if (ret != CY_AS_ERROR_SUCCESS) {
1703                 cy_as_hal_print_message("<1>_cy_as_gadget: "
1704                         "cy_as_usb_start failed with error code %d\n",
1705                         ret) ;
1706                 return ;
1707         }
1708         /* P port will do enumeration, not West Bridge */
1709         config.antioch_enumeration = cy_false ;
1710         /*  1  2  : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/
1711
1712         /* TODO: add module param to enumerate mass storage */
1713         config.mass_storage_interface = 0 ;
1714
1715         if (append_mtp) {
1716                 ret = cy_as_mtp_start(cy_as_dev->dev_handle,
1717                         cy_as_gadget_mtp_event_callback, 0, 0);
1718                 if (ret == CY_AS_ERROR_SUCCESS)  {
1719                         cy_as_hal_print_message("MTP start passed, enumerating "
1720                                 "MTP interface\n");
1721                         config.mtp_interface = append_mtp ;
1722                         /*Do not enumerate NAND storage*/
1723                         config.devices_to_enumerate[0][0] = cy_false;
1724
1725                         /*enumerate SD storage as MTP*/
1726                         config.devices_to_enumerate[1][0] = cy_true;
1727                 }
1728         } else {
1729                 cy_as_hal_print_message("MTP start not attempted, not "
1730                         "enumerating MTP interface\n");
1731                 config.mtp_interface = 0 ;
1732                 /* enumerate mass storage based on module parameters */
1733                 config.devices_to_enumerate[0][0] = msc_enum_bus_0;
1734                 config.devices_to_enumerate[1][0] = msc_enum_bus_1;
1735         }
1736
1737         ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle,
1738                 &config, 0, 0) ;
1739         if (ret != CY_AS_ERROR_SUCCESS) {
1740                 cy_as_hal_print_message("<1>_cy_as_gadget: "
1741                         "cy_as_usb_set_enum_config failed with error "
1742                         "code %d\n", ret) ;
1743                 return ;
1744         }
1745
1746         cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1);
1747
1748 }
1749
1750 static void cyas_usb_reinit(
1751                                 cyasgadget *cy_as_dev
1752                                 )
1753 {
1754         int index = 0;
1755         cyasgadget_ep *an_ep_p;
1756         cy_as_return_status_t ret;
1757         cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ;
1758
1759         INIT_LIST_HEAD(&cy_as_dev->gadget.ep_list);
1760
1761         #ifndef WESTBRIDGE_NDEBUG
1762         cy_as_hal_print_message("<1>%s called, is_mtp_firmware = "
1763                 "0x%x\n", __func__, dev_p->is_mtp_firmware);
1764         #endif
1765
1766         /* Init the end points */
1767         for (index = 1; index <= 15; index++) {
1768                 an_ep_p = &cy_as_dev->an_gadget_ep[index] ;
1769                 cyas_ep_reset(an_ep_p) ;
1770                 an_ep_p->usb_ep_inst.name = cy_as_ep_names[index] ;
1771                 an_ep_p->dev = cy_as_dev ;
1772                 an_ep_p->num = index ;
1773                 memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig));
1774
1775                 /* EP0, EPs 2,4,6,8 need not be added */
1776                 if ((index <= 8) && (index % 2 == 0) &&
1777                         (!dev_p->is_mtp_firmware)) {
1778                         /* EP0 is 64 and EPs 2,4,6,8 not allowed */
1779                         cy_as_dev->an_gadget_ep[index].fifo_size = 0 ;
1780                 } else {
1781                         if (index == 1)
1782                                 an_ep_p->fifo_size = 64;
1783                         else
1784                                 an_ep_p->fifo_size = 512 ;
1785                         list_add_tail(&an_ep_p->usb_ep_inst.ep_list,
1786                                 &cy_as_dev->gadget.ep_list);
1787                 }
1788         }
1789         /* need to setendpointconfig before usb connect, this is not
1790          * quite compatible with gadget methodology (ep_enable called
1791          * by gadget after connect), therefore need to set config in
1792          * initialization and verify compatibility in ep_enable,
1793          * kick up error otherwise*/
1794         an_ep_p = &cy_as_dev->an_gadget_ep[3] ;
1795         an_ep_p->cyepconfig.enabled = cy_true ;
1796         an_ep_p->cyepconfig.dir = cy_as_usb_out ;
1797         an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1798         an_ep_p->cyepconfig.size = 0 ;
1799         an_ep_p->cyepconfig.physical = 1 ;
1800         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1801                 3, &an_ep_p->cyepconfig) ;
1802         if (ret != CY_AS_ERROR_SUCCESS) {
1803                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1804                         "failed with error code %d\n", ret) ;
1805         }
1806
1807         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0);
1808
1809         an_ep_p = &cy_as_dev->an_gadget_ep[5] ;
1810         an_ep_p->cyepconfig.enabled = cy_true ;
1811         an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1812         an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1813         an_ep_p->cyepconfig.size = 0 ;
1814         an_ep_p->cyepconfig.physical = 2 ;
1815         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1816                 5, &an_ep_p->cyepconfig) ;
1817         if (ret != CY_AS_ERROR_SUCCESS) {
1818                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1819                         "failed with error code %d\n", ret) ;
1820         }
1821
1822         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0);
1823
1824         an_ep_p = &cy_as_dev->an_gadget_ep[9] ;
1825         an_ep_p->cyepconfig.enabled = cy_true ;
1826         an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1827         an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1828         an_ep_p->cyepconfig.size = 0 ;
1829         an_ep_p->cyepconfig.physical = 4 ;
1830         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1831                 9, &an_ep_p->cyepconfig) ;
1832         if (ret != CY_AS_ERROR_SUCCESS) {
1833                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1834                         "failed with error code %d\n", ret) ;
1835         }
1836
1837         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0);
1838
1839         if (dev_p->mtp_count != 0) {
1840                 /* these need to be set for compatibility with
1841                  * the gadget_enable logic */
1842                 an_ep_p = &cy_as_dev->an_gadget_ep[2] ;
1843                 an_ep_p->cyepconfig.enabled = cy_true ;
1844                 an_ep_p->cyepconfig.dir = cy_as_usb_out ;
1845                 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1846                 an_ep_p->cyepconfig.size = 0 ;
1847                 an_ep_p->cyepconfig.physical = 0 ;
1848                 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0);
1849
1850                 an_ep_p = &cy_as_dev->an_gadget_ep[6] ;
1851                 an_ep_p->cyepconfig.enabled = cy_true ;
1852                 an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1853                 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1854                 an_ep_p->cyepconfig.size = 0 ;
1855                 an_ep_p->cyepconfig.physical = 0 ;
1856                 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 6, 0, 0);
1857         }
1858
1859         cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]) ;
1860         cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0] ;
1861         cy_as_dev->an_gadget_ep[0].dev = cy_as_dev ;
1862         cy_as_dev->an_gadget_ep[0].num = 0 ;
1863         cy_as_dev->an_gadget_ep[0].fifo_size = 64 ;
1864
1865         cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64;
1866         cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst;
1867         cy_as_dev->an_gadget_ep[0].stopped = 0;
1868         INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list);
1869 }
1870
1871 static void cyas_ep0_start(
1872                                 cyasgadget *dev
1873                                 )
1874 {
1875         cy_as_return_status_t ret ;
1876
1877         #ifndef WESTBRIDGE_NDEBUG
1878         cy_as_hal_print_message("<1>%s called\n", __func__);
1879         #endif
1880
1881         ret = cy_as_usb_register_callback(dev->dev_handle,
1882                 cy_as_gadget_usb_event_callback) ;
1883         if (ret != CY_AS_ERROR_SUCCESS) {
1884                 #ifndef WESTBRIDGE_NDEBUG
1885                 cy_as_hal_print_message("%s: cy_as_usb_register_callback "
1886                         "failed with error code %d\n", __func__, ret) ;
1887                 #endif
1888                 return ;
1889         }
1890
1891         ret = cy_as_usb_commit_config(dev->dev_handle, 0, 0) ;
1892         if (ret != CY_AS_ERROR_SUCCESS) {
1893                 #ifndef WESTBRIDGE_NDEBUG
1894                 cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1895                         "failed with error code %d\n", __func__, ret) ;
1896                 #endif
1897                 return ;
1898         }
1899
1900         #ifndef WESTBRIDGE_NDEBUG
1901         cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1902                 "message sent\n", __func__) ;
1903         #endif
1904
1905         ret = cy_as_usb_connect(dev->dev_handle, 0, 0) ;
1906         if (ret != CY_AS_ERROR_SUCCESS) {
1907                 #ifndef WESTBRIDGE_NDEBUG
1908                 cy_as_hal_print_message("%s: cy_as_usb_connect failed "
1909                         "with error code %d\n", __func__, ret) ;
1910                 #endif
1911                 return ;
1912         }
1913
1914         #ifndef WESTBRIDGE_NDEBUG
1915         cy_as_hal_print_message("%s: cy_as_usb_connect message "
1916                 "sent\n", __func__) ;
1917         #endif
1918 }
1919
1920 /*
1921  * When a driver is successfully registered, it will receive
1922  * control requests including set_configuration(), which enables
1923  * non-control requests.  then usb traffic follows until a
1924  * disconnect is reported.  then a host may connect again, or
1925  * the driver might get unbound.
1926  */
1927 int usb_gadget_register_driver(
1928                                 struct usb_gadget_driver *driver
1929                                 )
1930 {
1931         cyasgadget *dev = cy_as_gadget_controller ;
1932         int             retval;
1933
1934         #ifndef WESTBRIDGE_NDEBUG
1935         cy_as_hal_print_message("<1>%s called driver=0x%x\n",
1936                 __func__, (unsigned int) driver);
1937         #endif
1938
1939         /* insist on high speed support from the driver, since
1940         * "must not be used in normal operation"
1941         */
1942         if (!driver
1943                 || !driver->bind
1944                 || !driver->unbind
1945                 || !driver->setup)
1946                 return -EINVAL;
1947
1948         if (!dev)
1949                 return -ENODEV;
1950
1951         if (dev->driver)
1952                 return -EBUSY;
1953
1954         /* hook up the driver ... */
1955         dev->softconnect = 1;
1956         driver->driver.bus = NULL;
1957         dev->driver = driver;
1958         dev->gadget.dev.driver = &driver->driver;
1959
1960         /* Do the needful */
1961         cyas_usb_reset(dev) ; /* External usb */
1962         cyas_usb_reinit(dev) ; /* Internal */
1963
1964         retval = driver->bind(&dev->gadget);
1965         if (retval) {
1966                 #ifndef WESTBRIDGE_NDEBUG
1967                 cy_as_hal_print_message("%s bind to driver %s --> %d\n",
1968                         __func__, driver->driver.name, retval);
1969                 #endif
1970
1971                 dev->driver = NULL;
1972                 dev->gadget.dev.driver = NULL;
1973                 return retval;
1974         }
1975
1976         /* ... then enable host detection and ep0; and we're ready
1977         * for set_configuration as well as eventual disconnect.
1978         */
1979         cyas_ep0_start(dev);
1980
1981         return 0;
1982 }
1983 EXPORT_SYMBOL(usb_gadget_register_driver);
1984
1985 static void cyasgadget_nuke(
1986                                                         cyasgadget_ep *an_ep
1987                                                         )
1988 {
1989         cyasgadget      *dev = cy_as_gadget_controller ;
1990
1991         #ifndef WESTBRIDGE_NDEBUG
1992         cy_as_hal_print_message("<1>%s called\n", __func__);
1993         #endif
1994
1995         cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
1996         an_ep->stopped = 1 ;
1997
1998         while (!list_empty(&an_ep->queue)) {
1999                 cyasgadget_req *an_req = list_entry
2000                         (an_ep->queue.next, cyasgadget_req, queue) ;
2001                 list_del_init(&an_req->queue) ;
2002                 an_req->req.status = -ESHUTDOWN ;
2003                 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req) ;
2004         }
2005 }
2006
2007 static void cyasgadget_stop_activity(
2008                                 cyasgadget *dev,
2009                                 struct usb_gadget_driver *driver
2010                                 )
2011 {
2012         int index ;
2013
2014         #ifndef WESTBRIDGE_NDEBUG
2015         cy_as_hal_print_message("<1>%s called\n", __func__);
2016         #endif
2017
2018         /* don't disconnect if it's not connected */
2019         if (dev->gadget.speed == USB_SPEED_UNKNOWN)
2020                 driver = NULL;
2021
2022         if (spin_is_locked(&dev->lock))
2023                 spin_unlock(&dev->lock);
2024
2025         /* Stop hardware; prevent new request submissions;
2026          * and kill any outstanding requests.
2027          */
2028         cy_as_usb_disconnect(dev->dev_handle, 0, 0) ;
2029
2030         for (index = 3; index <= 7; index += 2) {
2031                 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ;
2032                 cyasgadget_nuke(an_ep_p) ;
2033         }
2034
2035         for (index = 9; index <= 15; index++) {
2036                 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ;
2037                 cyasgadget_nuke(an_ep_p) ;
2038         }
2039
2040         /* report disconnect; the driver is already quiesced */
2041         if (driver)
2042                 driver->disconnect(&dev->gadget);
2043
2044         #ifndef WESTBRIDGE_NDEBUG
2045         cy_as_hal_print_message("cy_as_usb_disconnect returned success");
2046         #endif
2047
2048         /* Stop Usb */
2049         cy_as_usb_stop(dev->dev_handle, 0, 0) ;
2050
2051         #ifndef WESTBRIDGE_NDEBUG
2052         cy_as_hal_print_message("cy_as_usb_stop returned success");
2053         #endif
2054 }
2055
2056 int usb_gadget_unregister_driver(
2057                                 struct usb_gadget_driver *driver
2058                                 )
2059 {
2060         cyasgadget      *dev = cy_as_gadget_controller ;
2061
2062         #ifndef WESTBRIDGE_NDEBUG
2063         cy_as_hal_print_message("<1>%s called\n", __func__);
2064         #endif
2065
2066         if (!dev)
2067                 return -ENODEV;
2068
2069         if (!driver || driver != dev->driver)
2070                 return -EINVAL;
2071
2072         cyasgadget_stop_activity(dev, driver);
2073
2074         driver->unbind(&dev->gadget);
2075         dev->gadget.dev.driver = NULL;
2076         dev->driver = NULL;
2077
2078         #ifndef WESTBRIDGE_NDEBUG
2079         cy_as_hal_print_message("unregistered driver '%s'\n",
2080                 driver->driver.name) ;
2081         #endif
2082
2083         return 0;
2084 }
2085 EXPORT_SYMBOL(usb_gadget_unregister_driver);
2086
2087 static void cyas_gadget_release(
2088                                 struct device *_dev
2089                                 )
2090 {
2091         cyasgadget *dev = dev_get_drvdata(_dev);
2092
2093         #ifndef WESTBRIDGE_NDEBUG
2094         cy_as_hal_print_message("<1>%s called\n", __func__);
2095         #endif
2096
2097         kfree(dev);
2098 }
2099
2100 /* DeInitialize gadget driver  */
2101 static void cyasgadget_deinit(
2102                         cyasgadget *cy_as_dev
2103                         )
2104 {
2105         #ifndef WESTBRIDGE_NDEBUG
2106         cy_as_hal_print_message("<1>_cy_as_gadget deinitialize called\n") ;
2107         #endif
2108
2109         if (!cy_as_dev) {
2110                 #ifndef WESTBRIDGE_NDEBUG
2111                 cy_as_hal_print_message("<1>_cy_as_gadget_deinit: "
2112                         "invalid cyasgadget device\n") ;
2113                 #endif
2114                 return ;
2115         }
2116
2117         if (cy_as_dev->driver) {
2118                 /* should have been done already by driver model core */
2119                 #ifndef WESTBRIDGE_NDEBUG
2120                 cy_as_hal_print_message("<1> cy_as_gadget: '%s' "
2121                         "is still registered\n",
2122                         cy_as_dev->driver->driver.name);
2123                 #endif
2124                 usb_gadget_unregister_driver(cy_as_dev->driver);
2125         }
2126
2127         kfree(cy_as_dev) ;
2128         cy_as_gadget_controller = NULL ;
2129 }
2130
2131 /* Initialize gadget driver  */
2132 static int cyasgadget_initialize(void)
2133 {
2134         cyasgadget *cy_as_dev = 0 ;
2135         int              retval = 0 ;
2136
2137         #ifndef WESTBRIDGE_NDEBUG
2138         cy_as_hal_print_message("<1>_cy_as_gadget [V1.1] initialize called\n") ;
2139         #endif
2140
2141         if (cy_as_gadget_controller != 0) {
2142                 cy_as_hal_print_message("<1> cy_as_gadget: the device has "
2143                         "already been initilaized. ignoring\n") ;
2144                 return -EBUSY ;
2145         }
2146
2147         cy_as_dev = kzalloc(sizeof(cyasgadget), GFP_ATOMIC);
2148         if (cy_as_dev == NULL) {
2149                 cy_as_hal_print_message("<1> cy_as_gadget: memory "
2150                         "allocation failed\n") ;
2151                 return -ENOMEM;
2152         }
2153
2154         spin_lock_init(&cy_as_dev->lock);
2155         cy_as_dev->gadget.ops = &cyasgadget_ops;
2156         cy_as_dev->gadget.is_dualspeed = 1;
2157
2158         /* the "gadget" abstracts/virtualizes the controller */
2159         /*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/
2160         cy_as_dev->gadget.dev.release = cyas_gadget_release;
2161         cy_as_dev->gadget.name = cy_as_driver_name;
2162
2163         /* Get the device handle */
2164         cy_as_dev->dev_handle = cyasdevice_getdevhandle() ;
2165         if (0 == cy_as_dev->dev_handle) {
2166                 #ifndef NDEBUG
2167                 cy_as_hal_print_message("<1> cy_as_gadget: "
2168                         "no west bridge device\n") ;
2169                 #endif
2170                 retval = -EFAULT ;
2171                 goto done ;
2172         }
2173
2174         /* We are done now */
2175         cy_as_gadget_controller = cy_as_dev ;
2176         return 0 ;
2177
2178 /*
2179  * in case of an error
2180  */
2181 done:
2182         if (cy_as_dev)
2183                 cyasgadget_deinit(cy_as_dev) ;
2184
2185         return retval ;
2186 }
2187
2188 static int __init cyas_init(void)
2189 {
2190         int init_res = 0;
2191
2192         init_res = cyasgadget_initialize();
2193
2194         if (init_res != 0) {
2195                 printk(KERN_WARNING "<1> gadget ctl instance "
2196                         "init error:%d\n", init_res);
2197                 if (init_res > 0) {
2198                         /* force -E/0 linux convention */
2199                         init_res = init_res * -1;
2200                 }
2201         }
2202
2203         return init_res;
2204 }
2205 module_init(cyas_init);
2206
2207 static void __exit cyas_cleanup(void)
2208 {
2209         if (cy_as_gadget_controller != NULL)
2210                 cyasgadget_deinit(cy_as_gadget_controller);
2211 }
2212 module_exit(cyas_cleanup);
2213
2214
2215 MODULE_LICENSE("GPL");
2216 MODULE_DESCRIPTION(CY_AS_DRIVER_DESC);
2217 MODULE_AUTHOR("cypress semiconductor");
2218
2219 /*[]*/