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