]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/westbridge/astoria/gadget/cyasgadget.c
ced239dc367853091b374c81b159f7596fdcd1ff
[mv-sheeva.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
1127                 /* get the filename */
1128                 if (copy_from_user(alloc_filename, k_d.file_name,
1129                         k_d.name_length + 1)) {
1130                         #ifndef WESTBRIDGE_NDEBUG
1131                         cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, "
1132                                 "copy file name from user space failed\n",
1133                                 __func__);
1134                         #endif
1135                         return -EFAULT;
1136                 }
1137
1138                 file_to_allocate = filp_open(alloc_filename, O_RDWR, 0);
1139
1140                 if ((int)file_to_allocate != 0xfffffffe) {
1141
1142                         struct address_space *mapping =
1143                                 file_to_allocate->f_mapping;
1144                         const struct address_space_operations *a_ops =
1145                                 mapping->a_ops;
1146                         struct inode *inode = mapping->host;
1147                         struct inode *alloc_inode =
1148                                 file_to_allocate->f_path.dentry->d_inode;
1149                         int cluster = 0;
1150                         uint32_t num_clusters = 0;
1151                         struct buffer_head bh;
1152                         struct kstat stat;
1153                         struct iattr alloc_iattr;
1154                         int nr_pages = 0;
1155                         int ret_stat = 0;
1156
1157                         #ifndef WESTBRIDGE_NDEBUG
1158                         cy_as_hal_print_message("%s: fhandle is OK, "
1159                                 "calling vfs_getattr\n", __func__);
1160                         #endif
1161
1162                         ret_stat = vfs_getattr(file_to_allocate->f_path.mnt,
1163                                 file_to_allocate->f_path.dentry, &stat);
1164
1165                         #ifndef WESTBRIDGE_NDEBUG
1166                         cy_as_hal_print_message("%s: returned from "
1167                                 "vfs_getattr() stat->blksize=0x%lx\n",
1168                                 __func__, stat.blksize);
1169                         #endif
1170
1171                         /* TODO:  get this from disk properties
1172                          * (from blockdevice)*/
1173                         #define SECTOR_SIZE 512
1174                         if (stat.blksize != 0) {
1175                                 num_clusters = (k_d.num_bytes) / SECTOR_SIZE;
1176
1177                                 if (((k_d.num_bytes) % SECTOR_SIZE) != 0)
1178                                                 num_clusters++;
1179                         } else {
1180                                 goto initsoj_safe_exit;
1181                         }
1182
1183                         bh.b_state = 0;
1184                         bh.b_blocknr = 0;
1185                         /* block size is arbitrary , we'll use sector size*/
1186                         bh.b_size = SECTOR_SIZE ;
1187
1188                         #ifndef WESTBRIDGE_NDEBUG
1189                         cy_as_hal_print_message("%s: getting fat blocks %d "
1190                                 "size of  %d\n", __func__,
1191                                 num_clusters, bh.b_size);
1192                         #endif
1193                         for (cluster = 0; cluster < num_clusters; cluster++)  {
1194                                 ret_stat = fat_get_block(inode,
1195                                         cluster, &bh, 1);
1196                                 if (ret_stat) {
1197                                         cy_as_hal_print_message(
1198                                                 "%s: unable to get fat block, "
1199                                                 "ret_stat=0x%d\n",
1200                                                 __func__, ret_stat);
1201                                         goto initsoj_safe_exit;
1202                                 }
1203                         }
1204
1205                         #ifndef WESTBRIDGE_NDEBUG
1206                         cy_as_hal_print_message("%s: allocated clusters "
1207                                 "successfully (fat_get_block), check bmap..."
1208                                 "\n", __func__);
1209                         #endif
1210
1211                         alloc_iattr.ia_valid = ATTR_SIZE;
1212                         alloc_iattr.ia_size = k_d.num_bytes;
1213
1214                         #ifndef WESTBRIDGE_NDEBUG
1215                         cy_as_hal_print_message("%s: calling fat_notify_change "
1216                                 "(ia_valid:%d, ia_size:%d)\n", __func__,
1217                                 alloc_iattr.ia_valid,
1218                                 (int)alloc_iattr.ia_size);
1219                         #endif
1220
1221                         /* adjust the filesize */
1222                         ret_stat = alloc_inode->i_op->setattr(
1223                                 file_to_allocate->f_path.dentry, &alloc_iattr);
1224                         #ifndef WESTBRIDGE_NDEBUG
1225                         cy_as_hal_print_message("%s: fat_setattr() "
1226                                 "returned 0x%x\n",
1227                                 __func__, ret_stat);
1228                         #endif
1229
1230                         /* clear dirty pages in page cache
1231                          * (if were any allocated) */
1232                         nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE);
1233
1234                         if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0)
1235                                 nr_pages++;
1236
1237                         #ifndef WESTBRIDGE_NDEBUG
1238                         /*check out how many pages where actually allocated */
1239                         if (mapping->nrpages != nr_pages)
1240                                 cy_as_hal_print_message("%s mpage_cleardirty "
1241                                         "mapping->nrpages %d != num_pages %d\n",
1242                                         __func__, (int) mapping->nrpages,
1243                                         nr_pages);
1244
1245                                 cy_as_hal_print_message("%s: calling "
1246                                         "mpage_cleardirty() "
1247                                         "for %d pages\n", __func__, nr_pages);
1248                         #endif
1249
1250                         ret_stat = mpage_cleardirty(mapping, nr_pages);
1251
1252                         /*fill up the the block table from the addr mapping  */
1253                         if (a_ops->bmap) {
1254                                 int8_t blk_table_idx = -1;
1255                                 uint32_t file_block_idx = 0;
1256                                 uint32_t last_blk_addr_map = 0,
1257                                         curr_blk_addr_map = 0;
1258
1259                                 #ifndef WESTBRIDGE_NDEBUG
1260                                 if (alloc_inode->i_bytes == 0)
1261                                                 cy_as_hal_print_message(
1262                                                 "%s: alloc_inode->ibytes =0\n",
1263                                                 __func__);
1264                                 #endif
1265
1266                                 /* iterate through the list of
1267                                  * blocks (not clusters)*/
1268                                 for (file_block_idx = 0;
1269                                         file_block_idx < num_clusters
1270                                         /*inode->i_bytes*/; file_block_idx++) {
1271
1272                                         /* returns starting sector number */
1273                                         curr_blk_addr_map =
1274                                                 a_ops->bmap(mapping,
1275                                                         file_block_idx);
1276
1277                                         /*no valid mapping*/
1278                                         if (curr_blk_addr_map == 0) {
1279                                                 #ifndef WESTBRIDGE_NDEBUG
1280                                                 cy_as_hal_print_message(
1281                                                         "%s:hit invalid "
1282                                                         "mapping\n", __func__);
1283                                                 #endif
1284                                                 break;
1285                                         } else if (curr_blk_addr_map !=
1286                                                 (last_blk_addr_map + 1) ||
1287                                                 (blk_table.num_blocks
1288                                                 [blk_table_idx] == 65535)) {
1289
1290                                                 /* next table entry */
1291                                                 blk_table_idx++;
1292                                                 /* starting sector of a
1293                                                  * scattered cluster*/
1294                                                 blk_table.start_blocks
1295                                                         [blk_table_idx] =
1296                                                         curr_blk_addr_map;
1297                                                 /* ++ num of blocks in cur
1298                                                  * table entry*/
1299                                                 blk_table.
1300                                                 num_blocks[blk_table_idx]++;
1301
1302                                                 #ifndef WESTBRIDGE_NDEBUG
1303                                                 if (file_block_idx != 0)
1304                                                         cy_as_hal_print_message(
1305                                                          "<*> next table "
1306                                                          "entry:%d required\n",
1307                                                          blk_table_idx);
1308                                                 #endif
1309                                         } else {
1310                                                 /*add contiguous block*/
1311                                                 blk_table.num_blocks
1312                                                 [blk_table_idx]++;
1313                                         } /*if (curr_blk_addr_map == 0)*/
1314
1315                                         last_blk_addr_map = curr_blk_addr_map;
1316                                 } /* end for (file_block_idx = 0; file_block_idx
1317                                 < inode->i_bytes;) */
1318
1319                                 #ifndef WESTBRIDGE_NDEBUG
1320                                 /*print result for verification*/
1321                                 {
1322                                         int i;
1323                                         cy_as_hal_print_message(
1324                                                 "%s: print block table "
1325                                                 "mapping:\n",
1326                                                 __func__);
1327                                         for (i = 0; i <= blk_table_idx; i++) {
1328                                                 cy_as_hal_print_message(
1329                                                 "<1> %d 0x%x 0x%x\n", i,
1330                                                 blk_table.start_blocks[i],
1331                                                 blk_table.num_blocks[i]);
1332                                         }
1333                                 }
1334                                 #endif
1335
1336                                 /* copy the block table to user
1337                                  * space (for debug purposes) */
1338                                 retval = __put_user(
1339                                         blk_table.start_blocks[blk_table_idx],
1340                                         (uint32_t __user *)
1341                                                 (&(usr_d->blk_addr_p)));
1342
1343                                 retval = __put_user(
1344                                         blk_table.num_blocks[blk_table_idx],
1345                                         (uint32_t __user *)
1346                                                 (&(usr_d->blk_count_p)));
1347
1348                                 blk_table_idx++;
1349                                 retval = __put_user(blk_table_idx,
1350                                         (uint32_t __user *)
1351                                                 (&(usr_d->item_count)));
1352
1353                         } /*end if (a_ops->bmap)*/
1354
1355                         filp_close(file_to_allocate, NULL);
1356
1357                         dev->tmtp_send_complete = 0 ;
1358                         dev->tmtp_need_new_blk_tbl = 0 ;
1359
1360                         #ifndef WESTBRIDGE_NDEBUG
1361                         cy_as_hal_print_message(
1362                                 "%s: calling cy_as_mtp_init_send_object()\n",
1363                                 __func__);
1364                         #endif
1365                         sg_init_one(&sg, &blk_table, sizeof(blk_table));
1366                         ret_stat = cy_as_mtp_init_send_object(dev->dev_handle,
1367                                 (cy_as_mtp_block_table *)&sg,
1368                                 k_d.num_bytes, 0, 0);
1369                         #ifndef WESTBRIDGE_NDEBUG
1370                         cy_as_hal_print_message("%s: returned from "
1371                                 "cy_as_mtp_init_send_object()\n", __func__);
1372                         #endif
1373
1374                 }
1375                 #ifndef WESTBRIDGE_NDEBUG
1376                 else {
1377                         cy_as_hal_print_message(
1378                                 "%s: failed to allocate the file %s\n",
1379                                 __func__, alloc_filename);
1380                 } /* end if (file_to_allocate)*/
1381                 #endif
1382 initsoj_safe_exit:
1383                         ret_stat = 0;
1384                         retval = __put_user(ret_stat,
1385                                 (uint32_t __user *)(&(usr_d->ret_val)));
1386
1387                         break;
1388                 }
1389         case CYASGADGET_INITGOJ:
1390                 {
1391                 cy_as_gadget_ioctl_i_g_o_j_d k_d ;
1392                 cy_as_gadget_ioctl_i_g_o_j_d *usr_d =
1393                         (cy_as_gadget_ioctl_i_g_o_j_d *)param ;
1394                 cy_as_mtp_block_table blk_table ;
1395                 struct scatterlist sg ;
1396                 char *map_filename;
1397                 struct file *file_to_map;
1398
1399                 #ifndef WESTBRIDGE_NDEBUG
1400                 cy_as_hal_print_message(
1401                         "%s: got CYASGADGET_INITGOJ\n",
1402                                 __func__);
1403                 #endif
1404
1405                 memset(&blk_table, 0, sizeof(blk_table));
1406
1407                 /* Get user argument sturcutre */
1408                 if (copy_from_user(&k_d, usr_d,
1409                         sizeof(cy_as_gadget_ioctl_i_g_o_j_d)))
1410                                 return -EFAULT;
1411
1412                 map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1413                 if (copy_from_user(map_filename, k_d.file_name,
1414                         k_d.name_length + 1)) {
1415                         #ifndef WESTBRIDGE_NDEBUG
1416                         cy_as_hal_print_message("%s: copy file name from "
1417                                 "user space failed\n", __func__);
1418                         #endif
1419                         return -EFAULT;
1420                 }
1421
1422                 #ifndef WESTBRIDGE_NDEBUG
1423                 cy_as_hal_print_message("<*>%s: opening %s for kernel "
1424                         "mode access map\n", __func__, map_filename);
1425                 #endif
1426                 file_to_map = filp_open(map_filename, O_RDWR, 0);
1427                 if (file_to_map) {
1428                         struct address_space *mapping = file_to_map->f_mapping;
1429                         const struct address_space_operations
1430                                 *a_ops = mapping->a_ops;
1431                         struct inode *inode = mapping->host;
1432
1433                         int8_t blk_table_idx = -1;
1434                         uint32_t file_block_idx = 0;
1435                         uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0;
1436
1437                         /*verify operation exists*/
1438                         if (a_ops->bmap) {
1439                                 #ifndef WESTBRIDGE_NDEBUG
1440                                 cy_as_hal_print_message(
1441                                         "<*>%s: bmap found, i_bytes=0x%x, "
1442                                         "i_size=0x%x, i_blocks=0x%x\n",
1443                                         __func__, inode->i_bytes,
1444                                         (unsigned int) inode->i_size,
1445                                         (unsigned int) inode->i_blocks);
1446                                 #endif
1447
1448                                 k_d.num_bytes = inode->i_size;
1449
1450                                 #ifndef WESTBRIDGE_NDEBUG
1451                                 cy_as_hal_print_message(
1452                                         "<*>%s: k_d.num_bytes=0x%x\n",
1453                                         __func__, k_d.num_bytes);
1454                                 #endif
1455
1456                                 for (file_block_idx = 0;
1457                                         file_block_idx < inode->i_size;
1458                                         file_block_idx++) {
1459                                         curr_blk_addr_map =
1460                                                 a_ops->bmap(mapping,
1461                                                         file_block_idx);
1462
1463                                         if (curr_blk_addr_map == 0) {
1464                                                 /*no valid mapping*/
1465                                                 #ifndef WESTBRIDGE_NDEBUG
1466                                                 cy_as_hal_print_message(
1467                                                         "%s: no valid "
1468                                                         "mapping\n", __func__);
1469                                                 #endif
1470                                                 break;
1471                                         } else if (curr_blk_addr_map !=
1472                                         (last_blk_addr_map + 1)) {
1473                                                 /*non-contiguous break*/
1474                                                 blk_table_idx++;
1475                                                 blk_table.start_blocks
1476                                                         [blk_table_idx] =
1477                                                         curr_blk_addr_map;
1478                                                 blk_table.num_blocks
1479                                                         [blk_table_idx]++;
1480                                                 #ifndef WESTBRIDGE_NDEBUG
1481                                                 cy_as_hal_print_message(
1482                                                         "%s: found non-"
1483                                                         "contiguous break",
1484                                                         __func__);
1485                                                 #endif
1486                                         } else {
1487                                                 /*add contiguous block*/
1488                                                 blk_table.num_blocks
1489                                                         [blk_table_idx]++;
1490                                         }
1491                                         last_blk_addr_map = curr_blk_addr_map;
1492                                 }
1493
1494                                 /*print result for verification*/
1495                                 #ifndef WESTBRIDGE_NDEBUG
1496                                 {
1497                                         int i = 0;
1498
1499                                         for (i = 0 ; i <= blk_table_idx; i++) {
1500                                                 cy_as_hal_print_message(
1501                                                 "%s %d 0x%x 0x%x\n",
1502                                                 __func__, i,
1503                                                 blk_table.start_blocks[i],
1504                                                 blk_table.num_blocks[i]);
1505                                         }
1506                                 }
1507                                 #endif
1508                         } else {
1509                                 #ifndef WESTBRIDGE_NDEBUG
1510                                 cy_as_hal_print_message(
1511                                         "%s: could not find "
1512                                         "a_ops->bmap\n", __func__);
1513                                 #endif
1514                                 return -EFAULT;
1515                         }
1516
1517                         filp_close(file_to_map, NULL);
1518
1519                         dev->tmtp_get_complete = 0 ;
1520                         dev->tmtp_need_new_blk_tbl = 0 ;
1521
1522                         ret_stat = __put_user(
1523                                 blk_table.start_blocks[blk_table_idx],
1524                                 (uint32_t __user *)(&(usr_d->blk_addr_p)));
1525
1526                         ret_stat = __put_user(
1527                                 blk_table.num_blocks[blk_table_idx],
1528                                 (uint32_t __user *)(&(usr_d->blk_count_p)));
1529
1530                         sg_init_one(&sg, &blk_table, sizeof(blk_table));
1531
1532                         #ifndef WESTBRIDGE_NDEBUG
1533                         cy_as_hal_print_message(
1534                                 "%s: calling cy_as_mtp_init_get_object() "
1535                                 "start=0x%x, num =0x%x, tid=0x%x, "
1536                                 "num_bytes=0x%x\n",
1537                                 __func__,
1538                                 blk_table.start_blocks[0],
1539                                 blk_table.num_blocks[0],
1540                                 k_d.tid,
1541                                 k_d.num_bytes);
1542                         #endif
1543
1544                         ret_stat = cy_as_mtp_init_get_object(
1545                                 dev->dev_handle,
1546                                 (cy_as_mtp_block_table *)&sg,
1547                                 k_d.num_bytes, k_d.tid, 0, 0);
1548                         if (ret_stat != CY_AS_ERROR_SUCCESS) {
1549                                         #ifndef WESTBRIDGE_NDEBUG
1550                                         cy_as_hal_print_message(
1551                                                 "%s: cy_as_mtp_init_get_object "
1552                                                 "failed ret_stat=0x%x\n",
1553                                                 __func__, ret_stat);
1554                                         #endif
1555                         }
1556                 }
1557                 #ifndef WESTBRIDGE_NDEBUG
1558                 else {
1559                                 cy_as_hal_print_message(
1560                                         "%s: failed to open file %s\n",
1561                                         __func__, map_filename);
1562                 }
1563                 #endif
1564
1565                 ret_stat = 0;
1566                 retval = __put_user(ret_stat, (uint32_t __user *)
1567                         (&(usr_d->ret_val)));
1568                 break;
1569                 }
1570         case CYASGADGET_CANCELSOJ:
1571                 {
1572                 cy_as_gadget_ioctl_cancel *usr_d =
1573                         (cy_as_gadget_ioctl_cancel *)param ;
1574
1575                 #ifndef WESTBRIDGE_NDEBUG
1576                         cy_as_hal_print_message(
1577                                 "%s: got CYASGADGET_CANCELSOJ\n",
1578                                 __func__);
1579                 #endif
1580
1581                 ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0);
1582
1583                 retval = __put_user(ret_stat, (uint32_t __user *)
1584                         (&(usr_d->ret_val)));
1585                 break;
1586                 }
1587         case CYASGADGET_CANCELGOJ:
1588                 {
1589                 cy_as_gadget_ioctl_cancel *usr_d =
1590                         (cy_as_gadget_ioctl_cancel *)param ;
1591
1592                 #ifndef WESTBRIDGE_NDEBUG
1593                 cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n",
1594                         __func__);
1595                 #endif
1596
1597                 ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0);
1598
1599                 retval = __put_user(ret_stat,
1600                         (uint32_t __user *)(&(usr_d->ret_val)));
1601                 break;
1602                 }
1603         default:
1604                 {
1605                 #ifndef WESTBRIDGE_NDEBUG
1606                 cy_as_hal_print_message("%s: unknown ioctl received: %d\n",
1607                         __func__, code);
1608
1609                 cy_as_hal_print_message("%s: known codes:\n"
1610                         "CYASGADGET_GETMTPSTATUS=%d\n"
1611                         "CYASGADGET_CLEARTMTPSTATUS=%d\n"
1612                         "CYASGADGET_INITSOJ=%d\n"
1613                         "CYASGADGET_INITGOJ=%d\n"
1614                         "CYASGADGET_CANCELSOJ=%d\n"
1615                         "CYASGADGET_CANCELGOJ=%d\n",
1616                         __func__,
1617                         CYASGADGET_GETMTPSTATUS,
1618                         CYASGADGET_CLEARTMTPSTATUS,
1619                         CYASGADGET_INITSOJ,
1620                         CYASGADGET_INITGOJ,
1621                         CYASGADGET_CANCELSOJ,
1622                         CYASGADGET_CANCELGOJ);
1623                 #endif
1624                 break;
1625                 }
1626         }
1627
1628         return 0;
1629 }
1630
1631 static const struct usb_gadget_ops cyasgadget_ops = {
1632         .get_frame               = cyasgadget_get_frame,
1633         .wakeup          = cyasgadget_wakeup,
1634         .set_selfpowered = cyasgadget_set_selfpowered,
1635         .pullup          = cyasgadget_pullup,
1636         .ioctl     = cyasgadget_ioctl,
1637 };
1638
1639
1640 /* keeping it simple:
1641  * - one bus driver, initted first;
1642  * - one function driver, initted second
1643  *
1644  * most of the work to support multiple controllers would
1645  * be to associate this gadget driver with all of them, or
1646  * perhaps to bind specific drivers to specific devices.
1647  */
1648
1649 static void cyas_ep_reset(
1650                                 cyasgadget_ep *an_ep
1651                                 )
1652 {
1653         #ifndef WESTBRIDGE_NDEBUG
1654         cy_as_hal_print_message("<1>%s called\n", __func__);
1655         #endif
1656
1657         an_ep->desc = NULL;
1658         INIT_LIST_HEAD(&an_ep->queue);
1659
1660         an_ep->stopped = 0 ;
1661         an_ep->is_in   = 0 ;
1662         an_ep->is_iso  = 0 ;
1663         an_ep->usb_ep_inst.maxpacket = ~0;
1664         an_ep->usb_ep_inst.ops = &cyasgadget_ep_ops;
1665 }
1666
1667 static void cyas_usb_reset(
1668                                 cyasgadget *cy_as_dev
1669                                 )
1670 {
1671         cy_as_return_status_t ret;
1672         cy_as_usb_enum_control config ;
1673
1674         #ifndef WESTBRIDGE_NDEBUG
1675         cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ;
1676
1677         cy_as_hal_print_message("<1>%s called mtp_firmware=0x%x\n",
1678                 __func__, dev_p->is_mtp_firmware);
1679         #endif
1680
1681         ret = cy_as_misc_release_resource(cy_as_dev->dev_handle,
1682                 cy_as_bus_u_s_b) ;
1683         if (ret != CY_AS_ERROR_SUCCESS && ret !=
1684                 CY_AS_ERROR_RESOURCE_NOT_OWNED) {
1685                 cy_as_hal_print_message("<1>_cy_as_gadget: cannot "
1686                         "release usb resource: failed with error code %d\n",
1687                         ret) ;
1688                 return ;
1689         }
1690
1691         cy_as_dev->gadget.speed = USB_SPEED_HIGH ;
1692
1693         ret = cy_as_usb_start(cy_as_dev->dev_handle, 0, 0) ;
1694         if (ret != CY_AS_ERROR_SUCCESS) {
1695                 cy_as_hal_print_message("<1>_cy_as_gadget: "
1696                         "cy_as_usb_start failed with error code %d\n",
1697                         ret) ;
1698                 return ;
1699         }
1700         /* P port will do enumeration, not West Bridge */
1701         config.antioch_enumeration = cy_false ;
1702         /*  1  2  : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/
1703
1704         /* TODO: add module param to enumerate mass storage */
1705         config.mass_storage_interface = 0 ;
1706
1707         if (append_mtp) {
1708                 ret = cy_as_mtp_start(cy_as_dev->dev_handle,
1709                         cy_as_gadget_mtp_event_callback, 0, 0);
1710                 if (ret == CY_AS_ERROR_SUCCESS)  {
1711                         cy_as_hal_print_message("MTP start passed, enumerating "
1712                                 "MTP interface\n");
1713                         config.mtp_interface = append_mtp ;
1714                         /*Do not enumerate NAND storage*/
1715                         config.devices_to_enumerate[0][0] = cy_false;
1716
1717                         /*enumerate SD storage as MTP*/
1718                         config.devices_to_enumerate[1][0] = cy_true;
1719                 }
1720         } else {
1721                 cy_as_hal_print_message("MTP start not attempted, not "
1722                         "enumerating MTP interface\n");
1723                 config.mtp_interface = 0 ;
1724                 /* enumerate mass storage based on module parameters */
1725                 config.devices_to_enumerate[0][0] = msc_enum_bus_0;
1726                 config.devices_to_enumerate[1][0] = msc_enum_bus_1;
1727         }
1728
1729         ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle,
1730                 &config, 0, 0) ;
1731         if (ret != CY_AS_ERROR_SUCCESS) {
1732                 cy_as_hal_print_message("<1>_cy_as_gadget: "
1733                         "cy_as_usb_set_enum_config failed with error "
1734                         "code %d\n", ret) ;
1735                 return ;
1736         }
1737
1738         cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1);
1739
1740 }
1741
1742 static void cyas_usb_reinit(
1743                                 cyasgadget *cy_as_dev
1744                                 )
1745 {
1746         int index = 0;
1747         cyasgadget_ep *an_ep_p;
1748         cy_as_return_status_t ret;
1749         cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ;
1750
1751         INIT_LIST_HEAD(&cy_as_dev->gadget.ep_list);
1752
1753         #ifndef WESTBRIDGE_NDEBUG
1754         cy_as_hal_print_message("<1>%s called, is_mtp_firmware = "
1755                 "0x%x\n", __func__, dev_p->is_mtp_firmware);
1756         #endif
1757
1758         /* Init the end points */
1759         for (index = 1; index <= 15; index++) {
1760                 an_ep_p = &cy_as_dev->an_gadget_ep[index] ;
1761                 cyas_ep_reset(an_ep_p) ;
1762                 an_ep_p->usb_ep_inst.name = cy_as_ep_names[index] ;
1763                 an_ep_p->dev = cy_as_dev ;
1764                 an_ep_p->num = index ;
1765                 memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig));
1766
1767                 /* EP0, EPs 2,4,6,8 need not be added */
1768                 if ((index <= 8) && (index % 2 == 0) &&
1769                         (!dev_p->is_mtp_firmware)) {
1770                         /* EP0 is 64 and EPs 2,4,6,8 not allowed */
1771                         cy_as_dev->an_gadget_ep[index].fifo_size = 0 ;
1772                 } else {
1773                         if (index == 1)
1774                                 an_ep_p->fifo_size = 64;
1775                         else
1776                                 an_ep_p->fifo_size = 512 ;
1777                         list_add_tail(&an_ep_p->usb_ep_inst.ep_list,
1778                                 &cy_as_dev->gadget.ep_list);
1779                 }
1780         }
1781         /* need to setendpointconfig before usb connect, this is not
1782          * quite compatible with gadget methodology (ep_enable called
1783          * by gadget after connect), therefore need to set config in
1784          * initialization and verify compatibility in ep_enable,
1785          * kick up error otherwise*/
1786         an_ep_p = &cy_as_dev->an_gadget_ep[3] ;
1787         an_ep_p->cyepconfig.enabled = cy_true ;
1788         an_ep_p->cyepconfig.dir = cy_as_usb_out ;
1789         an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1790         an_ep_p->cyepconfig.size = 0 ;
1791         an_ep_p->cyepconfig.physical = 1 ;
1792         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1793                 3, &an_ep_p->cyepconfig) ;
1794         if (ret != CY_AS_ERROR_SUCCESS) {
1795                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1796                         "failed with error code %d\n", ret) ;
1797         }
1798
1799         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0);
1800
1801         an_ep_p = &cy_as_dev->an_gadget_ep[5] ;
1802         an_ep_p->cyepconfig.enabled = cy_true ;
1803         an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1804         an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1805         an_ep_p->cyepconfig.size = 0 ;
1806         an_ep_p->cyepconfig.physical = 2 ;
1807         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1808                 5, &an_ep_p->cyepconfig) ;
1809         if (ret != CY_AS_ERROR_SUCCESS) {
1810                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1811                         "failed with error code %d\n", ret) ;
1812         }
1813
1814         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0);
1815
1816         an_ep_p = &cy_as_dev->an_gadget_ep[9] ;
1817         an_ep_p->cyepconfig.enabled = cy_true ;
1818         an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1819         an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1820         an_ep_p->cyepconfig.size = 0 ;
1821         an_ep_p->cyepconfig.physical = 4 ;
1822         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1823                 9, &an_ep_p->cyepconfig) ;
1824         if (ret != CY_AS_ERROR_SUCCESS) {
1825                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1826                         "failed with error code %d\n", ret) ;
1827         }
1828
1829         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0);
1830
1831         if (dev_p->mtp_count != 0) {
1832                 /* these need to be set for compatibility with
1833                  * the gadget_enable logic */
1834                 an_ep_p = &cy_as_dev->an_gadget_ep[2] ;
1835                 an_ep_p->cyepconfig.enabled = cy_true ;
1836                 an_ep_p->cyepconfig.dir = cy_as_usb_out ;
1837                 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1838                 an_ep_p->cyepconfig.size = 0 ;
1839                 an_ep_p->cyepconfig.physical = 0 ;
1840                 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0);
1841
1842                 an_ep_p = &cy_as_dev->an_gadget_ep[6] ;
1843                 an_ep_p->cyepconfig.enabled = cy_true ;
1844                 an_ep_p->cyepconfig.dir = cy_as_usb_in ;
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, 6, 0, 0);
1849         }
1850
1851         cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]) ;
1852         cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0] ;
1853         cy_as_dev->an_gadget_ep[0].dev = cy_as_dev ;
1854         cy_as_dev->an_gadget_ep[0].num = 0 ;
1855         cy_as_dev->an_gadget_ep[0].fifo_size = 64 ;
1856
1857         cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64;
1858         cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst;
1859         cy_as_dev->an_gadget_ep[0].stopped = 0;
1860         INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list);
1861 }
1862
1863 static void cyas_ep0_start(
1864                                 cyasgadget *dev
1865                                 )
1866 {
1867         cy_as_return_status_t ret ;
1868
1869         #ifndef WESTBRIDGE_NDEBUG
1870         cy_as_hal_print_message("<1>%s called\n", __func__);
1871         #endif
1872
1873         ret = cy_as_usb_register_callback(dev->dev_handle,
1874                 cy_as_gadget_usb_event_callback) ;
1875         if (ret != CY_AS_ERROR_SUCCESS) {
1876                 #ifndef WESTBRIDGE_NDEBUG
1877                 cy_as_hal_print_message("%s: cy_as_usb_register_callback "
1878                         "failed with error code %d\n", __func__, ret) ;
1879                 #endif
1880                 return ;
1881         }
1882
1883         ret = cy_as_usb_commit_config(dev->dev_handle, 0, 0) ;
1884         if (ret != CY_AS_ERROR_SUCCESS) {
1885                 #ifndef WESTBRIDGE_NDEBUG
1886                 cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1887                         "failed with error code %d\n", __func__, ret) ;
1888                 #endif
1889                 return ;
1890         }
1891
1892         #ifndef WESTBRIDGE_NDEBUG
1893         cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1894                 "message sent\n", __func__) ;
1895         #endif
1896
1897         ret = cy_as_usb_connect(dev->dev_handle, 0, 0) ;
1898         if (ret != CY_AS_ERROR_SUCCESS) {
1899                 #ifndef WESTBRIDGE_NDEBUG
1900                 cy_as_hal_print_message("%s: cy_as_usb_connect failed "
1901                         "with error code %d\n", __func__, ret) ;
1902                 #endif
1903                 return ;
1904         }
1905
1906         #ifndef WESTBRIDGE_NDEBUG
1907         cy_as_hal_print_message("%s: cy_as_usb_connect message "
1908                 "sent\n", __func__) ;
1909         #endif
1910 }
1911
1912 /*
1913  * When a driver is successfully registered, it will receive
1914  * control requests including set_configuration(), which enables
1915  * non-control requests.  then usb traffic follows until a
1916  * disconnect is reported.  then a host may connect again, or
1917  * the driver might get unbound.
1918  */
1919 int usb_gadget_register_driver(
1920                                 struct usb_gadget_driver *driver
1921                                 )
1922 {
1923         cyasgadget *dev = cy_as_gadget_controller ;
1924         int             retval;
1925
1926         #ifndef WESTBRIDGE_NDEBUG
1927         cy_as_hal_print_message("<1>%s called driver=0x%x\n",
1928                 __func__, (unsigned int) driver);
1929         #endif
1930
1931         /* insist on high speed support from the driver, since
1932         * "must not be used in normal operation"
1933         */
1934         if (!driver
1935                 || !driver->bind
1936                 || !driver->unbind
1937                 || !driver->setup)
1938                 return -EINVAL;
1939
1940         if (!dev)
1941                 return -ENODEV;
1942
1943         if (dev->driver)
1944                 return -EBUSY;
1945
1946         /* hook up the driver ... */
1947         dev->softconnect = 1;
1948         driver->driver.bus = NULL;
1949         dev->driver = driver;
1950         dev->gadget.dev.driver = &driver->driver;
1951
1952         /* Do the needful */
1953         cyas_usb_reset(dev) ; /* External usb */
1954         cyas_usb_reinit(dev) ; /* Internal */
1955
1956         retval = driver->bind(&dev->gadget);
1957         if (retval) {
1958                 #ifndef WESTBRIDGE_NDEBUG
1959                 cy_as_hal_print_message("%s bind to driver %s --> %d\n",
1960                         __func__, driver->driver.name, retval);
1961                 #endif
1962
1963                 dev->driver = NULL;
1964                 dev->gadget.dev.driver = NULL;
1965                 return retval;
1966         }
1967
1968         /* ... then enable host detection and ep0; and we're ready
1969         * for set_configuration as well as eventual disconnect.
1970         */
1971         cyas_ep0_start(dev);
1972
1973         return 0;
1974 }
1975 EXPORT_SYMBOL(usb_gadget_register_driver);
1976
1977 static void cyasgadget_nuke(
1978                                                         cyasgadget_ep *an_ep
1979                                                         )
1980 {
1981         cyasgadget      *dev = cy_as_gadget_controller ;
1982
1983         #ifndef WESTBRIDGE_NDEBUG
1984         cy_as_hal_print_message("<1>%s called\n", __func__);
1985         #endif
1986
1987         cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
1988         an_ep->stopped = 1 ;
1989
1990         while (!list_empty(&an_ep->queue)) {
1991                 cyasgadget_req *an_req = list_entry
1992                         (an_ep->queue.next, cyasgadget_req, queue) ;
1993                 list_del_init(&an_req->queue) ;
1994                 an_req->req.status = -ESHUTDOWN ;
1995                 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req) ;
1996         }
1997 }
1998
1999 static void cyasgadget_stop_activity(
2000                                 cyasgadget *dev,
2001                                 struct usb_gadget_driver *driver
2002                                 )
2003 {
2004         int index ;
2005
2006         #ifndef WESTBRIDGE_NDEBUG
2007         cy_as_hal_print_message("<1>%s called\n", __func__);
2008         #endif
2009
2010         /* don't disconnect if it's not connected */
2011         if (dev->gadget.speed == USB_SPEED_UNKNOWN)
2012                 driver = NULL;
2013
2014         if (spin_is_locked(&dev->lock))
2015                 spin_unlock(&dev->lock);
2016
2017         /* Stop hardware; prevent new request submissions;
2018          * and kill any outstanding requests.
2019          */
2020         cy_as_usb_disconnect(dev->dev_handle, 0, 0) ;
2021
2022         for (index = 3; index <= 7; index += 2) {
2023                 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ;
2024                 cyasgadget_nuke(an_ep_p) ;
2025         }
2026
2027         for (index = 9; index <= 15; index++) {
2028                 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ;
2029                 cyasgadget_nuke(an_ep_p) ;
2030         }
2031
2032         /* report disconnect; the driver is already quiesced */
2033         if (driver)
2034                 driver->disconnect(&dev->gadget);
2035
2036         #ifndef WESTBRIDGE_NDEBUG
2037         cy_as_hal_print_message("cy_as_usb_disconnect returned success");
2038         #endif
2039
2040         /* Stop Usb */
2041         cy_as_usb_stop(dev->dev_handle, 0, 0) ;
2042
2043         #ifndef WESTBRIDGE_NDEBUG
2044         cy_as_hal_print_message("cy_as_usb_stop returned success");
2045         #endif
2046 }
2047
2048 int usb_gadget_unregister_driver(
2049                                 struct usb_gadget_driver *driver
2050                                 )
2051 {
2052         cyasgadget      *dev = cy_as_gadget_controller ;
2053
2054         #ifndef WESTBRIDGE_NDEBUG
2055         cy_as_hal_print_message("<1>%s called\n", __func__);
2056         #endif
2057
2058         if (!dev)
2059                 return -ENODEV;
2060
2061         if (!driver || driver != dev->driver)
2062                 return -EINVAL;
2063
2064         cyasgadget_stop_activity(dev, driver);
2065
2066         driver->unbind(&dev->gadget);
2067         dev->gadget.dev.driver = NULL;
2068         dev->driver = NULL;
2069
2070         #ifndef WESTBRIDGE_NDEBUG
2071         cy_as_hal_print_message("unregistered driver '%s'\n",
2072                 driver->driver.name) ;
2073         #endif
2074
2075         return 0;
2076 }
2077 EXPORT_SYMBOL(usb_gadget_unregister_driver);
2078
2079 static void cyas_gadget_release(
2080                                 struct device *_dev
2081                                 )
2082 {
2083         cyasgadget *dev = dev_get_drvdata(_dev);
2084
2085         #ifndef WESTBRIDGE_NDEBUG
2086         cy_as_hal_print_message("<1>%s called\n", __func__);
2087         #endif
2088
2089         kfree(dev);
2090 }
2091
2092 /* DeInitialize gadget driver  */
2093 static void cyasgadget_deinit(
2094                         cyasgadget *cy_as_dev
2095                         )
2096 {
2097         #ifndef WESTBRIDGE_NDEBUG
2098         cy_as_hal_print_message("<1>_cy_as_gadget deinitialize called\n") ;
2099         #endif
2100
2101         if (!cy_as_dev) {
2102                 #ifndef WESTBRIDGE_NDEBUG
2103                 cy_as_hal_print_message("<1>_cy_as_gadget_deinit: "
2104                         "invalid cyasgadget device\n") ;
2105                 #endif
2106                 return ;
2107         }
2108
2109         if (cy_as_dev->driver) {
2110                 /* should have been done already by driver model core */
2111                 #ifndef WESTBRIDGE_NDEBUG
2112                 cy_as_hal_print_message("<1> cy_as_gadget: '%s' "
2113                         "is still registered\n",
2114                         cy_as_dev->driver->driver.name);
2115                 #endif
2116                 usb_gadget_unregister_driver(cy_as_dev->driver);
2117         }
2118
2119         kfree(cy_as_dev) ;
2120         cy_as_gadget_controller = NULL ;
2121 }
2122
2123 /* Initialize gadget driver  */
2124 static int cyasgadget_initialize(void)
2125 {
2126         cyasgadget *cy_as_dev = 0 ;
2127         int              retval = 0 ;
2128
2129         #ifndef WESTBRIDGE_NDEBUG
2130         cy_as_hal_print_message("<1>_cy_as_gadget [V1.1] initialize called\n") ;
2131         #endif
2132
2133         if (cy_as_gadget_controller != 0) {
2134                 cy_as_hal_print_message("<1> cy_as_gadget: the device has "
2135                         "already been initilaized. ignoring\n") ;
2136                 return -EBUSY ;
2137         }
2138
2139         cy_as_dev = kzalloc(sizeof(cyasgadget), GFP_ATOMIC);
2140         if (cy_as_dev == NULL) {
2141                 cy_as_hal_print_message("<1> cy_as_gadget: memory "
2142                         "allocation failed\n") ;
2143                 return -ENOMEM;
2144         }
2145
2146         spin_lock_init(&cy_as_dev->lock);
2147         cy_as_dev->gadget.ops = &cyasgadget_ops;
2148         cy_as_dev->gadget.is_dualspeed = 1;
2149
2150         /* the "gadget" abstracts/virtualizes the controller */
2151         /*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/
2152         cy_as_dev->gadget.dev.release = cyas_gadget_release;
2153         cy_as_dev->gadget.name = cy_as_driver_name;
2154
2155         /* Get the device handle */
2156         cy_as_dev->dev_handle = cyasdevice_getdevhandle() ;
2157         if (0 == cy_as_dev->dev_handle) {
2158                 #ifndef NDEBUG
2159                 cy_as_hal_print_message("<1> cy_as_gadget: "
2160                         "no west bridge device\n") ;
2161                 #endif
2162                 retval = -EFAULT ;
2163                 goto done ;
2164         }
2165
2166         /* We are done now */
2167         cy_as_gadget_controller = cy_as_dev ;
2168         return 0 ;
2169
2170 /*
2171  * in case of an error
2172  */
2173 done:
2174         if (cy_as_dev)
2175                 cyasgadget_deinit(cy_as_dev) ;
2176
2177         return retval ;
2178 }
2179
2180 static int __init cyas_init(void)
2181 {
2182         int init_res = 0;
2183
2184         init_res = cyasgadget_initialize();
2185
2186         if (init_res != 0) {
2187                 printk(KERN_WARNING "<1> gadget ctl instance "
2188                         "init error:%d\n", init_res);
2189                 if (init_res > 0) {
2190                         /* force -E/0 linux convention */
2191                         init_res = init_res * -1;
2192                 }
2193         }
2194
2195         return init_res;
2196 }
2197 module_init(cyas_init);
2198
2199 static void __exit cyas_cleanup(void)
2200 {
2201         if (cy_as_gadget_controller != NULL)
2202                 cyasgadget_deinit(cy_as_gadget_controller);
2203 }
2204 module_exit(cyas_cleanup);
2205
2206
2207 MODULE_LICENSE("GPL");
2208 MODULE_DESCRIPTION(CY_AS_DRIVER_DESC);
2209 MODULE_AUTHOR("cypress semiconductor");
2210
2211 /*[]*/