Linux-libre 3.0.32-gnu1
[librecmc/linux-libre.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                 spin_unlock_irqrestore(&an_dev->lock, flags);
591                 return -EINVAL;
592         }
593
594         tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
595         an_ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
596
597         spin_unlock_irqrestore(&an_dev->lock, flags);
598
599         switch (tmp) {
600         case USB_ENDPOINT_XFER_ISOC:
601                 if (an_ep->cyepconfig.type != cy_as_usb_iso) {
602                         #ifndef WESTBRIDGE_NDEBUG
603                         cy_as_hal_print_message("<1>_cy_as_gadget: "
604                                 "cy_as_usb_end_point_config EP %s mismatch "
605                                 "on type %d %d\n", an_ep->usb_ep_inst.name,
606                                 an_ep->cyepconfig.type, cy_as_usb_iso);
607                         #endif
608                         return -EINVAL;
609                 }
610                 break;
611         case USB_ENDPOINT_XFER_INT:
612                 if (an_ep->cyepconfig.type != cy_as_usb_int) {
613                         #ifndef WESTBRIDGE_NDEBUG
614                         cy_as_hal_print_message("<1>_cy_as_gadget: "
615                                 "cy_as_usb_end_point_config EP %s mismatch "
616                                 "on type %d %d\n", an_ep->usb_ep_inst.name,
617                                 an_ep->cyepconfig.type, cy_as_usb_int);
618                         #endif
619                         return -EINVAL;
620                 }
621                 break;
622         default:
623                 if (an_ep->cyepconfig.type != cy_as_usb_bulk) {
624                         #ifndef WESTBRIDGE_NDEBUG
625                         cy_as_hal_print_message("<1>_cy_as_gadget: "
626                                 "cy_as_usb_end_point_config EP %s mismatch "
627                                 "on type %d %d\n", an_ep->usb_ep_inst.name,
628                                 an_ep->cyepconfig.type, cy_as_usb_bulk);
629                         #endif
630                         return -EINVAL;
631                 }
632                 break;
633         }
634
635         tmp = desc->bEndpointAddress;
636         an_ep->is_in = (tmp & USB_DIR_IN) != 0;
637
638         if ((an_ep->cyepconfig.dir == cy_as_usb_in) &&
639         (!an_ep->is_in)) {
640                 #ifndef WESTBRIDGE_NDEBUG
641                 cy_as_hal_print_message("<1>_cy_as_gadget: "
642                         "cy_as_usb_end_point_config EP %s mismatch "
643                         "on dir %d %d\n", an_ep->usb_ep_inst.name,
644                         an_ep->cyepconfig.dir, cy_as_usb_in);
645                 #endif
646                 return -EINVAL;
647         } else if ((an_ep->cyepconfig.dir == cy_as_usb_out) &&
648         (an_ep->is_in)) {
649                 #ifndef WESTBRIDGE_NDEBUG
650                 cy_as_hal_print_message("<1>_cy_as_gadget: "
651                         "cy_as_usb_end_point_config EP %s mismatch "
652                         "on dir %d %d\n", an_ep->usb_ep_inst.name,
653                         an_ep->cyepconfig.dir, cy_as_usb_out);
654                 #endif
655                 return -EINVAL;
656         }
657
658         cy_as_usb_clear_stall(an_dev->dev_handle, an_ep->num,
659                 cyasgadget_stallcallback, 0);
660
661         cy_as_hal_print_message("%s enabled %s (ep%d-%d) max %04x\n",
662                 __func__, _ep->name, an_ep->num, tmp, max);
663
664         return 0;
665 }
666
667 static int cyasgadget_disable(
668                                         struct usb_ep *_ep
669                                         )
670 {
671         cyasgadget_ep   *an_ep;
672         unsigned long   flags;
673
674         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
675         if (!_ep || !an_ep->desc || _ep->name == cy_as_ep0name)
676                 return -EINVAL;
677
678         spin_lock_irqsave(&an_ep->dev->lock, flags);
679         cyas_ep_reset(an_ep);
680
681         spin_unlock_irqrestore(&an_ep->dev->lock, flags);
682         return 0;
683 }
684
685 static struct usb_request *cyasgadget_alloc_request(
686                         struct usb_ep *_ep, gfp_t gfp_flags
687                         )
688 {
689         cyasgadget_ep   *an_ep;
690         cyasgadget_req  *an_req;
691
692         if (!_ep)
693                 return NULL;
694
695         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
696
697         an_req = kzalloc(sizeof(cyasgadget_req), gfp_flags);
698         if (!an_req)
699                 return NULL;
700
701         an_req->req.dma = DMA_ADDR_INVALID;
702         INIT_LIST_HEAD(&an_req->queue);
703
704         return &an_req->req;
705 }
706
707 static void cyasgadget_free_request(
708                                         struct usb_ep *_ep,
709                                         struct usb_request *_req
710                                         )
711 {
712         cyasgadget_req *an_req;
713
714         if (!_ep || !_req)
715                 return;
716
717         an_req = container_of(_req, cyasgadget_req, req);
718
719         kfree(an_req);
720 }
721
722 /* Load a packet into the fifo we use for usb IN transfers.
723  * works for all endpoints. */
724 static int cyasgadget_queue(
725                                 struct usb_ep *_ep,
726                                 struct usb_request *_req,
727                                 gfp_t gfp_flags
728                                 )
729 {
730         cyasgadget_req  *as_req;
731         cyasgadget_ep   *as_ep;
732         cyasgadget              *cy_as_dev;
733         unsigned long   flags;
734         cy_as_return_status_t  ret = 0;
735
736         as_req = container_of(_req, cyasgadget_req, req);
737         if (!_req || !_req->complete || !_req->buf
738                 || !list_empty(&as_req->queue))
739                 return -EINVAL;
740
741         as_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
742
743         if (!_ep || (!as_ep->desc && (as_ep->num != 0)))
744                 return -EINVAL;
745
746         cy_as_dev = as_ep->dev;
747         if (!cy_as_dev->driver ||
748                 cy_as_dev->gadget.speed == USB_SPEED_UNKNOWN)
749                 return -ESHUTDOWN;
750
751         spin_lock_irqsave(&cy_as_dev->lock, flags);
752
753         _req->status = -EINPROGRESS;
754         _req->actual = 0;
755
756         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
757
758         /* Call Async functions */
759         if (as_ep->is_in) {
760                 #ifndef WESTBRIDGE_NDEBUG
761                         cy_as_hal_print_message("<1>_cy_as_gadget: "
762                                 "cy_as_usb_write_data_async being called "
763                                 "on ep %d\n", as_ep->num);
764                 #endif
765
766                 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
767                         as_ep->num, _req->length, _req->buf,
768                         cy_false, cyasgadget_writecallback);
769                 if (ret != CY_AS_ERROR_SUCCESS)
770                         cy_as_hal_print_message("<1>_cy_as_gadget: "
771                                 "cy_as_usb_write_data_async failed with "
772                                 "error code %d\n", ret);
773                 else
774                         _req->status = -EALREADY;
775         } else if (as_ep->num == 0) {
776                 /*
777                 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
778                         as_ep->num, _req->length, _req->buf, cy_false,
779                         cyasgadget_setupwritecallback);
780
781                 if (ret != CY_AS_ERROR_SUCCESS)
782                         cy_as_hal_print_message("<1>_cy_as_gadget: "
783                                 "cy_as_usb_write_data_async failed with error "
784                                 "code %d\n", ret);
785                 */
786                 if ((cy_as_dev->outsetupreq) && (_req->length)) {
787                         #ifndef WESTBRIDGE_NDEBUG
788                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
789                                         "cy_as_usb_read_data_async "
790                                         "being called on ep %d\n",
791                                         as_ep->num);
792                         #endif
793
794                         ret = cy_as_usb_read_data_async (
795                                 cy_as_dev->dev_handle, as_ep->num,
796                                 cy_true, _req->length, _req->buf,
797                                 cyasgadget_setupreadcallback);
798
799                         if (ret != CY_AS_ERROR_SUCCESS)
800                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
801                                 "cy_as_usb_read_data_async failed with "
802                                 "error code %d\n", ret);
803
804                 } else {
805                         #ifndef WESTBRIDGE_NDEBUG
806                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
807                                         "cy_as_usb_write_data_async "
808                                         "being called on ep %d\n",
809                                         as_ep->num);
810                         #endif
811
812                         ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
813                         as_ep->num, _req->length, _req->buf, cy_false,
814                         cyasgadget_setupwritecallback);
815
816                         if (ret != CY_AS_ERROR_SUCCESS)
817                                 cy_as_hal_print_message("<1>_cy_as_gadget: "
818                                 "cy_as_usb_write_data_async failed with "
819                                 "error code %d\n", ret);
820                 }
821
822         } else if (list_empty(&as_ep->queue)) {
823                 #ifndef WESTBRIDGE_NDEBUG
824                         cy_as_hal_print_message("<1>_cy_as_gadget: "
825                                 "cy_as_usb_read_data_async being called since "
826                                 "ep queue empty%d\n", ret);
827                 #endif
828
829                 ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
830                         as_ep->num, cy_false, _req->length, _req->buf,
831                         cyasgadget_readcallback);
832                 if (ret != CY_AS_ERROR_SUCCESS)
833                         cy_as_hal_print_message("<1>_cy_as_gadget: "
834                                 "cy_as_usb_read_data_async failed with error "
835                                 "code %d\n", ret);
836                 else
837                         _req->status = -EALREADY;
838         }
839
840         spin_lock_irqsave(&cy_as_dev->lock, flags);
841
842         if (as_req)
843                 list_add_tail(&as_req->queue, &as_ep->queue);
844
845         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
846
847         return 0;
848 }
849
850 /* dequeue request */
851 static int cyasgadget_dequeue(
852                                 struct usb_ep *_ep,
853                                 struct usb_request *_req
854                                 )
855 {
856         cyasgadget_ep   *an_ep;
857         cyasgadget              *dev;
858         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
859         dev = an_ep->dev;
860
861         #ifndef WESTBRIDGE_NDEBUG
862                 cy_as_hal_print_message("<1>%s called\n", __func__);
863         #endif
864
865         cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
866
867         return 0;
868 }
869
870 static int cyasgadget_set_halt(
871                                 struct usb_ep *_ep,
872                                 int value
873                                 )
874 {
875         cyasgadget_ep   *an_ep;
876         int                     retval = 0;
877
878         #ifndef WESTBRIDGE_NDEBUG
879         cy_as_hal_print_message("<1>%s called\n", __func__);
880         #endif
881
882         an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
883         if (!_ep || (!an_ep->desc && an_ep->num != 0))
884                 return -EINVAL;
885
886         if (!an_ep->dev->driver || an_ep->dev->gadget.speed ==
887                 USB_SPEED_UNKNOWN)
888                 return -ESHUTDOWN;
889
890         if (an_ep->desc /* not ep0 */ &&
891         (an_ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC)
892                 return -EINVAL;
893
894         if (!list_empty(&an_ep->queue))
895                 retval = -EAGAIN;
896         else if (an_ep->is_in && value &&
897                 cyasgadget_fifo_status(_ep) != 0)
898                         retval = -EAGAIN;
899         else {
900                 if (value) {
901                         cy_as_usb_set_stall(an_ep->dev->dev_handle,
902                                 an_ep->num, cyasgadget_stallcallback, 0);
903                 } else {
904                         cy_as_usb_clear_stall(an_ep->dev->dev_handle,
905                                 an_ep->num, cyasgadget_stallcallback, 0);
906                 }
907         }
908
909         return retval;
910 }
911
912 static int cyasgadget_fifo_status(
913                                 struct usb_ep *_ep
914                                 )
915 {
916         #ifndef WESTBRIDGE_NDEBUG
917         cy_as_hal_print_message("<1>%s called\n", __func__);
918         #endif
919
920         return 0;
921 }
922
923 static void cyasgadget_fifo_flush(
924                                 struct usb_ep *_ep
925                                 )
926 {
927         #ifndef WESTBRIDGE_NDEBUG
928         cy_as_hal_print_message("<1>%s called\n", __func__);
929         #endif
930 }
931
932 static struct usb_ep_ops cyasgadget_ep_ops = {
933         .enable         = cyasgadget_enable,
934         .disable        = cyasgadget_disable,
935         .alloc_request  = cyasgadget_alloc_request,
936         .free_request   = cyasgadget_free_request,
937         .queue          = cyasgadget_queue,
938         .dequeue        = cyasgadget_dequeue,
939         .set_halt       = cyasgadget_set_halt,
940         .fifo_status    = cyasgadget_fifo_status,
941         .fifo_flush     = cyasgadget_fifo_flush,
942 };
943
944 /*************************************************************/
945 /*This subsection contains all usb_gadget_ops cyasgadget_ops */
946 /*************************************************************/
947 static int cyasgadget_get_frame(
948                                 struct usb_gadget *_gadget
949                                 )
950 {
951         #ifndef WESTBRIDGE_NDEBUG
952         cy_as_hal_print_message("<1>%s called\n", __func__);
953         #endif
954         return 0;
955 }
956
957 static int cyasgadget_wakeup(
958                                         struct usb_gadget *_gadget
959                                         )
960 {
961         #ifndef WESTBRIDGE_NDEBUG
962         cy_as_hal_print_message("<1>%s called\n", __func__);
963         #endif
964         return 0;
965 }
966
967 static int cyasgadget_set_selfpowered(
968                                         struct usb_gadget *_gadget,
969                                         int value
970                                         )
971 {
972         #ifndef WESTBRIDGE_NDEBUG
973         cy_as_hal_print_message("<1>%s called\n", __func__);
974         #endif
975         return 0;
976 }
977
978 static int cyasgadget_pullup(
979                                         struct usb_gadget *_gadget,
980                                         int is_on
981                                         )
982 {
983         struct cyasgadget  *cy_as_dev;
984         unsigned long   flags;
985
986         #ifndef WESTBRIDGE_NDEBUG
987         cy_as_hal_print_message("<1>%s called\n", __func__);
988         #endif
989
990         if (!_gadget)
991                 return -ENODEV;
992
993         cy_as_dev = container_of(_gadget, cyasgadget, gadget);
994
995         spin_lock_irqsave(&cy_as_dev->lock, flags);
996         cy_as_dev->softconnect = (is_on != 0);
997         if (is_on)
998                 cy_as_usb_connect(cy_as_dev->dev_handle, 0, 0);
999         else
1000                 cy_as_usb_disconnect(cy_as_dev->dev_handle, 0, 0);
1001
1002         spin_unlock_irqrestore(&cy_as_dev->lock, flags);
1003
1004         return 0;
1005 }
1006
1007 static int cyasgadget_ioctl(
1008                                         struct usb_gadget *_gadget,
1009                                         unsigned code,
1010                                         unsigned long param
1011                                         )
1012 {
1013         int err = 0;
1014         int retval = 0;
1015         int ret_stat = 0;
1016         cyasgadget *dev = cy_as_gadget_controller;
1017
1018         #ifndef WESTBRIDGE_NDEBUG
1019         cy_as_hal_print_message("<1>%s called, code=%d, param=%ld\n",
1020                 __func__, code, param);
1021         #endif
1022         /*
1023          * extract the type and number bitfields, and don't decode
1024          * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
1025          */
1026         if (_IOC_TYPE(code) != CYASGADGET_IOC_MAGIC) {
1027                 #ifndef WESTBRIDGE_NDEBUG
1028                 cy_as_hal_print_message("%s, bad magic number = 0x%x\n",
1029                         __func__, _IOC_TYPE(code));
1030                 #endif
1031                 return -ENOTTY;
1032         }
1033
1034         if (_IOC_NR(code) > CYASGADGET_IOC_MAXNR) {
1035                 #ifndef WESTBRIDGE_NDEBUG
1036                 cy_as_hal_print_message("%s, bad ioctl code = 0x%x\n",
1037                         __func__, _IOC_NR(code));
1038                 #endif
1039                 return -ENOTTY;
1040         }
1041
1042         /*
1043          * the direction is a bitmask, and VERIFY_WRITE catches R/W
1044          * transfers. `Type' is user-oriented, while
1045          * access_ok is kernel-oriented, so the concept of "read" and
1046          * "write" is reversed
1047          */
1048         if (_IOC_DIR(code) & _IOC_READ)
1049                 err = !access_ok(VERIFY_WRITE,
1050                         (void __user *)param, _IOC_SIZE(code));
1051         else if (_IOC_DIR(code) & _IOC_WRITE)
1052                 err =  !access_ok(VERIFY_READ,
1053                         (void __user *)param, _IOC_SIZE(code));
1054
1055         if (err) {
1056                 cy_as_hal_print_message("%s, bad ioctl dir = 0x%x\n",
1057                         __func__, _IOC_DIR(code));
1058                 return -EFAULT;
1059         }
1060
1061         switch (code) {
1062         case CYASGADGET_GETMTPSTATUS:
1063                 {
1064                 cy_as_gadget_ioctl_tmtp_status *usr_d =
1065                         (cy_as_gadget_ioctl_tmtp_status *)param;
1066
1067                 #ifndef WESTBRIDGE_NDEBUG
1068                 cy_as_hal_print_message("%s: got CYASGADGET_GETMTPSTATUS\n",
1069                         __func__);
1070                 #endif
1071
1072                 retval = __put_user(dev->tmtp_send_complete,
1073                         (uint32_t __user *)(&(usr_d->tmtp_send_complete)));
1074                 retval = __put_user(dev->tmtp_get_complete,
1075                         (uint32_t __user *)(&(usr_d->tmtp_get_complete)));
1076                 retval = __put_user(dev->tmtp_need_new_blk_tbl,
1077                         (uint32_t __user *)(&(usr_d->tmtp_need_new_blk_tbl)));
1078
1079                 if (copy_to_user((&(usr_d->tmtp_send_complete_data)),
1080                         (&(dev->tmtp_send_complete_data)),
1081                         sizeof(cy_as_gadget_ioctl_send_object)))
1082                         return -EFAULT;
1083
1084                 if (copy_to_user((&(usr_d->tmtp_get_complete_data)),
1085                         (&(dev->tmtp_get_complete_data)),
1086                         sizeof(cy_as_gadget_ioctl_get_object)))
1087                         return -EFAULT;
1088                 break;
1089                 }
1090         case CYASGADGET_CLEARTMTPSTATUS:
1091                 {
1092                 #ifndef WESTBRIDGE_NDEBUG
1093                 cy_as_hal_print_message("%s got CYASGADGET_CLEARTMTPSTATUS\n",
1094                         __func__);
1095                 #endif
1096
1097                 dev->tmtp_send_complete = 0;
1098                 dev->tmtp_get_complete = 0;
1099                 dev->tmtp_need_new_blk_tbl = 0;
1100
1101                 break;
1102                 }
1103         case CYASGADGET_INITSOJ:
1104                 {
1105                 cy_as_gadget_ioctl_i_s_o_j_d k_d;
1106                 cy_as_gadget_ioctl_i_s_o_j_d *usr_d =
1107                         (cy_as_gadget_ioctl_i_s_o_j_d *)param;
1108                 cy_as_mtp_block_table blk_table;
1109                 struct scatterlist sg;
1110                 char *alloc_filename;
1111                 struct file *file_to_allocate;
1112
1113                 #ifndef WESTBRIDGE_NDEBUG
1114                 cy_as_hal_print_message("%s got CYASGADGET_INITSOJ\n",
1115                         __func__);
1116                 #endif
1117
1118                 memset(&blk_table, 0, sizeof(blk_table));
1119
1120                 /* Get user argument structure  */
1121                 if (copy_from_user(&k_d, usr_d,
1122                         sizeof(cy_as_gadget_ioctl_i_s_o_j_d)))
1123                         return -EFAULT;
1124
1125                 /* better use fixed size buff*/
1126                 alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1127                 if (alloc_filename == NULL)
1128                         return -ENOMEM;
1129
1130                 /* get the filename */
1131                 if (copy_from_user(alloc_filename, k_d.file_name,
1132                         k_d.name_length + 1)) {
1133                         #ifndef WESTBRIDGE_NDEBUG
1134                         cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, "
1135                                 "copy file name from user space failed\n",
1136                                 __func__);
1137                         #endif
1138                         kfree(alloc_filename);
1139                         return -EFAULT;
1140                 }
1141
1142                 file_to_allocate = filp_open(alloc_filename, O_RDWR, 0);
1143
1144                 if (!IS_ERR(file_to_allocate)) {
1145
1146                         struct address_space *mapping =
1147                                 file_to_allocate->f_mapping;
1148                         const struct address_space_operations *a_ops =
1149                                 mapping->a_ops;
1150                         struct inode *inode = mapping->host;
1151                         struct inode *alloc_inode =
1152                                 file_to_allocate->f_path.dentry->d_inode;
1153                         uint32_t num_clusters = 0;
1154                         struct buffer_head bh;
1155                         struct kstat stat;
1156                         int nr_pages = 0;
1157                         int ret_stat = 0;
1158
1159                         #ifndef WESTBRIDGE_NDEBUG
1160                         cy_as_hal_print_message("%s: fhandle is OK, "
1161                                 "calling vfs_getattr\n", __func__);
1162                         #endif
1163
1164                         ret_stat = vfs_getattr(file_to_allocate->f_path.mnt,
1165                                 file_to_allocate->f_path.dentry, &stat);
1166
1167                         #ifndef WESTBRIDGE_NDEBUG
1168                         cy_as_hal_print_message("%s: returned from "
1169                                 "vfs_getattr() stat->blksize=0x%lx\n",
1170                                 __func__, stat.blksize);
1171                         #endif
1172
1173                         /* TODO:  get this from disk properties
1174                          * (from blockdevice)*/
1175                         #define SECTOR_SIZE 512
1176                         if (stat.blksize != 0) {
1177                                 num_clusters = (k_d.num_bytes) / SECTOR_SIZE;
1178
1179                                 if (((k_d.num_bytes) % SECTOR_SIZE) != 0)
1180                                                 num_clusters++;
1181                         } else {
1182                                 goto initsoj_safe_exit;
1183                         }
1184
1185                         bh.b_state = 0;
1186                         bh.b_blocknr = 0;
1187                         /* block size is arbitrary , we'll use sector size*/
1188                         bh.b_size = SECTOR_SIZE;
1189
1190
1191
1192                         /* clear dirty pages in page cache
1193                          * (if were any allocated) */
1194                         nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE);
1195
1196                         if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0)
1197                                 nr_pages++;
1198
1199                         #ifndef WESTBRIDGE_NDEBUG
1200                         /*check out how many pages where actually allocated */
1201                         if (mapping->nrpages != nr_pages)
1202                                 cy_as_hal_print_message("%s mpage_cleardirty "
1203                                         "mapping->nrpages %d != num_pages %d\n",
1204                                         __func__, (int) mapping->nrpages,
1205                                         nr_pages);
1206
1207                                 cy_as_hal_print_message("%s: calling "
1208                                         "mpage_cleardirty() "
1209                                         "for %d pages\n", __func__, nr_pages);
1210                         #endif
1211
1212                         ret_stat = mpage_cleardirty(mapping, nr_pages);
1213
1214                         /*fill up the the block table from the addr mapping  */
1215                         if (a_ops->bmap) {
1216                                 int8_t blk_table_idx = -1;
1217                                 uint32_t file_block_idx = 0;
1218                                 uint32_t last_blk_addr_map = 0,
1219                                         curr_blk_addr_map = 0;
1220
1221                                 #ifndef WESTBRIDGE_NDEBUG
1222                                 if (alloc_inode->i_bytes == 0)
1223                                                 cy_as_hal_print_message(
1224                                                 "%s: alloc_inode->ibytes =0\n",
1225                                                 __func__);
1226                                 #endif
1227
1228                                 /* iterate through the list of
1229                                  * blocks (not clusters)*/
1230                                 for (file_block_idx = 0;
1231                                         file_block_idx < num_clusters
1232                                         /*inode->i_bytes*/; file_block_idx++) {
1233
1234                                         /* returns starting sector number */
1235                                         curr_blk_addr_map =
1236                                                 a_ops->bmap(mapping,
1237                                                         file_block_idx);
1238
1239                                         /*no valid mapping*/
1240                                         if (curr_blk_addr_map == 0) {
1241                                                 #ifndef WESTBRIDGE_NDEBUG
1242                                                 cy_as_hal_print_message(
1243                                                         "%s:hit invalid "
1244                                                         "mapping\n", __func__);
1245                                                 #endif
1246                                                 break;
1247                                         } else if (curr_blk_addr_map !=
1248                                                 (last_blk_addr_map + 1) ||
1249                                                 (blk_table.num_blocks
1250                                                 [blk_table_idx] == 65535)) {
1251
1252                                                 /* next table entry */
1253                                                 blk_table_idx++;
1254                                                 /* starting sector of a
1255                                                  * scattered cluster*/
1256                                                 blk_table.start_blocks
1257                                                         [blk_table_idx] =
1258                                                         curr_blk_addr_map;
1259                                                 /* ++ num of blocks in cur
1260                                                  * table entry*/
1261                                                 blk_table.
1262                                                 num_blocks[blk_table_idx]++;
1263
1264                                                 #ifndef WESTBRIDGE_NDEBUG
1265                                                 if (file_block_idx != 0)
1266                                                         cy_as_hal_print_message(
1267                                                          "<*> next table "
1268                                                          "entry:%d required\n",
1269                                                          blk_table_idx);
1270                                                 #endif
1271                                         } else {
1272                                                 /*add contiguous block*/
1273                                                 blk_table.num_blocks
1274                                                 [blk_table_idx]++;
1275                                         } /*if (curr_blk_addr_map == 0)*/
1276
1277                                         last_blk_addr_map = curr_blk_addr_map;
1278                                 } /* end for (file_block_idx = 0; file_block_idx
1279                                 < inode->i_bytes;) */
1280
1281                                 #ifndef WESTBRIDGE_NDEBUG
1282                                 /*print result for verification*/
1283                                 {
1284                                         int i;
1285                                         cy_as_hal_print_message(
1286                                                 "%s: print block table "
1287                                                 "mapping:\n",
1288                                                 __func__);
1289                                         for (i = 0; i <= blk_table_idx; i++) {
1290                                                 cy_as_hal_print_message(
1291                                                 "<1> %d 0x%x 0x%x\n", i,
1292                                                 blk_table.start_blocks[i],
1293                                                 blk_table.num_blocks[i]);
1294                                         }
1295                                 }
1296                                 #endif
1297
1298                                 /* copy the block table to user
1299                                  * space (for debug purposes) */
1300                                 retval = __put_user(
1301                                         blk_table.start_blocks[blk_table_idx],
1302                                         (uint32_t __user *)
1303                                                 (&(usr_d->blk_addr_p)));
1304
1305                                 retval = __put_user(
1306                                         blk_table.num_blocks[blk_table_idx],
1307                                         (uint32_t __user *)
1308                                                 (&(usr_d->blk_count_p)));
1309
1310                                 blk_table_idx++;
1311                                 retval = __put_user(blk_table_idx,
1312                                         (uint32_t __user *)
1313                                                 (&(usr_d->item_count)));
1314
1315                         } /*end if (a_ops->bmap)*/
1316
1317                         filp_close(file_to_allocate, NULL);
1318
1319                         dev->tmtp_send_complete = 0;
1320                         dev->tmtp_need_new_blk_tbl = 0;
1321
1322                         #ifndef WESTBRIDGE_NDEBUG
1323                         cy_as_hal_print_message(
1324                                 "%s: calling cy_as_mtp_init_send_object()\n",
1325                                 __func__);
1326                         #endif
1327                         sg_init_one(&sg, &blk_table, sizeof(blk_table));
1328                         ret_stat = cy_as_mtp_init_send_object(dev->dev_handle,
1329                                 (cy_as_mtp_block_table *)&sg,
1330                                 k_d.num_bytes, 0, 0);
1331                         #ifndef WESTBRIDGE_NDEBUG
1332                         cy_as_hal_print_message("%s: returned from "
1333                                 "cy_as_mtp_init_send_object()\n", __func__);
1334                         #endif
1335
1336                 }
1337                 #ifndef WESTBRIDGE_NDEBUG
1338                 else {
1339                         cy_as_hal_print_message(
1340                                 "%s: failed to allocate the file %s\n",
1341                                 __func__, alloc_filename);
1342                 } /* end if (file_to_allocate)*/
1343                 #endif
1344                 kfree(alloc_filename);
1345 initsoj_safe_exit:
1346                         ret_stat = 0;
1347                         retval = __put_user(ret_stat,
1348                                 (uint32_t __user *)(&(usr_d->ret_val)));
1349
1350                         break;
1351                 }
1352         case CYASGADGET_INITGOJ:
1353                 {
1354                 cy_as_gadget_ioctl_i_g_o_j_d k_d;
1355                 cy_as_gadget_ioctl_i_g_o_j_d *usr_d =
1356                         (cy_as_gadget_ioctl_i_g_o_j_d *)param;
1357                 cy_as_mtp_block_table blk_table;
1358                 struct scatterlist sg;
1359                 char *map_filename;
1360                 struct file *file_to_map;
1361
1362                 #ifndef WESTBRIDGE_NDEBUG
1363                 cy_as_hal_print_message(
1364                         "%s: got CYASGADGET_INITGOJ\n",
1365                                 __func__);
1366                 #endif
1367
1368                 memset(&blk_table, 0, sizeof(blk_table));
1369
1370                 /* Get user argument sturcutre */
1371                 if (copy_from_user(&k_d, usr_d,
1372                         sizeof(cy_as_gadget_ioctl_i_g_o_j_d)))
1373                                 return -EFAULT;
1374
1375                 map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1376                 if (map_filename == NULL)
1377                         return -ENOMEM;
1378                 if (copy_from_user(map_filename, k_d.file_name,
1379                         k_d.name_length + 1)) {
1380                         #ifndef WESTBRIDGE_NDEBUG
1381                         cy_as_hal_print_message("%s: copy file name from "
1382                                 "user space failed\n", __func__);
1383                         #endif
1384                         kfree(map_filename);
1385                         return -EFAULT;
1386                 }
1387
1388                 #ifndef WESTBRIDGE_NDEBUG
1389                 cy_as_hal_print_message("<*>%s: opening %s for kernel "
1390                         "mode access map\n", __func__, map_filename);
1391                 #endif
1392                 file_to_map = filp_open(map_filename, O_RDWR, 0);
1393                 if (file_to_map) {
1394                         struct address_space *mapping = file_to_map->f_mapping;
1395                         const struct address_space_operations
1396                                 *a_ops = mapping->a_ops;
1397                         struct inode *inode = mapping->host;
1398
1399                         int8_t blk_table_idx = -1;
1400                         uint32_t file_block_idx = 0;
1401                         uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0;
1402
1403                         /*verify operation exists*/
1404                         if (a_ops->bmap) {
1405                                 #ifndef WESTBRIDGE_NDEBUG
1406                                 cy_as_hal_print_message(
1407                                         "<*>%s: bmap found, i_bytes=0x%x, "
1408                                         "i_size=0x%x, i_blocks=0x%x\n",
1409                                         __func__, inode->i_bytes,
1410                                         (unsigned int) inode->i_size,
1411                                         (unsigned int) inode->i_blocks);
1412                                 #endif
1413
1414                                 k_d.num_bytes = inode->i_size;
1415
1416                                 #ifndef WESTBRIDGE_NDEBUG
1417                                 cy_as_hal_print_message(
1418                                         "<*>%s: k_d.num_bytes=0x%x\n",
1419                                         __func__, k_d.num_bytes);
1420                                 #endif
1421
1422                                 for (file_block_idx = 0;
1423                                         file_block_idx < inode->i_size;
1424                                         file_block_idx++) {
1425                                         curr_blk_addr_map =
1426                                                 a_ops->bmap(mapping,
1427                                                         file_block_idx);
1428
1429                                         if (curr_blk_addr_map == 0) {
1430                                                 /*no valid mapping*/
1431                                                 #ifndef WESTBRIDGE_NDEBUG
1432                                                 cy_as_hal_print_message(
1433                                                         "%s: no valid "
1434                                                         "mapping\n", __func__);
1435                                                 #endif
1436                                                 break;
1437                                         } else if (curr_blk_addr_map !=
1438                                         (last_blk_addr_map + 1)) {
1439                                                 /*non-contiguous break*/
1440                                                 blk_table_idx++;
1441                                                 blk_table.start_blocks
1442                                                         [blk_table_idx] =
1443                                                         curr_blk_addr_map;
1444                                                 blk_table.num_blocks
1445                                                         [blk_table_idx]++;
1446                                                 #ifndef WESTBRIDGE_NDEBUG
1447                                                 cy_as_hal_print_message(
1448                                                         "%s: found non-"
1449                                                         "contiguous break",
1450                                                         __func__);
1451                                                 #endif
1452                                         } else {
1453                                                 /*add contiguous block*/
1454                                                 blk_table.num_blocks
1455                                                         [blk_table_idx]++;
1456                                         }
1457                                         last_blk_addr_map = curr_blk_addr_map;
1458                                 }
1459
1460                                 /*print result for verification*/
1461                                 #ifndef WESTBRIDGE_NDEBUG
1462                                 {
1463                                         int i = 0;
1464
1465                                         for (i = 0; i <= blk_table_idx; i++) {
1466                                                 cy_as_hal_print_message(
1467                                                 "%s %d 0x%x 0x%x\n",
1468                                                 __func__, i,
1469                                                 blk_table.start_blocks[i],
1470                                                 blk_table.num_blocks[i]);
1471                                         }
1472                                 }
1473                                 #endif
1474                         } else {
1475                                 #ifndef WESTBRIDGE_NDEBUG
1476                                 cy_as_hal_print_message(
1477                                         "%s: could not find "
1478                                         "a_ops->bmap\n", __func__);
1479                                 #endif
1480                                 return -EFAULT;
1481                         }
1482
1483                         filp_close(file_to_map, NULL);
1484
1485                         dev->tmtp_get_complete = 0;
1486                         dev->tmtp_need_new_blk_tbl = 0;
1487
1488                         ret_stat = __put_user(
1489                                 blk_table.start_blocks[blk_table_idx],
1490                                 (uint32_t __user *)(&(usr_d->blk_addr_p)));
1491
1492                         ret_stat = __put_user(
1493                                 blk_table.num_blocks[blk_table_idx],
1494                                 (uint32_t __user *)(&(usr_d->blk_count_p)));
1495
1496                         sg_init_one(&sg, &blk_table, sizeof(blk_table));
1497
1498                         #ifndef WESTBRIDGE_NDEBUG
1499                         cy_as_hal_print_message(
1500                                 "%s: calling cy_as_mtp_init_get_object() "
1501                                 "start=0x%x, num =0x%x, tid=0x%x, "
1502                                 "num_bytes=0x%x\n",
1503                                 __func__,
1504                                 blk_table.start_blocks[0],
1505                                 blk_table.num_blocks[0],
1506                                 k_d.tid,
1507                                 k_d.num_bytes);
1508                         #endif
1509
1510                         ret_stat = cy_as_mtp_init_get_object(
1511                                 dev->dev_handle,
1512                                 (cy_as_mtp_block_table *)&sg,
1513                                 k_d.num_bytes, k_d.tid, 0, 0);
1514                         if (ret_stat != CY_AS_ERROR_SUCCESS) {
1515                                         #ifndef WESTBRIDGE_NDEBUG
1516                                         cy_as_hal_print_message(
1517                                                 "%s: cy_as_mtp_init_get_object "
1518                                                 "failed ret_stat=0x%x\n",
1519                                                 __func__, ret_stat);
1520                                         #endif
1521                         }
1522                 }
1523                 #ifndef WESTBRIDGE_NDEBUG
1524                 else {
1525                                 cy_as_hal_print_message(
1526                                         "%s: failed to open file %s\n",
1527                                         __func__, map_filename);
1528                 }
1529                 #endif
1530                 kfree(map_filename);
1531
1532                 ret_stat = 0;
1533                 retval = __put_user(ret_stat, (uint32_t __user *)
1534                         (&(usr_d->ret_val)));
1535                 break;
1536                 }
1537         case CYASGADGET_CANCELSOJ:
1538                 {
1539                 cy_as_gadget_ioctl_cancel *usr_d =
1540                         (cy_as_gadget_ioctl_cancel *)param;
1541
1542                 #ifndef WESTBRIDGE_NDEBUG
1543                         cy_as_hal_print_message(
1544                                 "%s: got CYASGADGET_CANCELSOJ\n",
1545                                 __func__);
1546                 #endif
1547
1548                 ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0);
1549
1550                 retval = __put_user(ret_stat, (uint32_t __user *)
1551                         (&(usr_d->ret_val)));
1552                 break;
1553                 }
1554         case CYASGADGET_CANCELGOJ:
1555                 {
1556                 cy_as_gadget_ioctl_cancel *usr_d =
1557                         (cy_as_gadget_ioctl_cancel *)param;
1558
1559                 #ifndef WESTBRIDGE_NDEBUG
1560                 cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n",
1561                         __func__);
1562                 #endif
1563
1564                 ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0);
1565
1566                 retval = __put_user(ret_stat,
1567                         (uint32_t __user *)(&(usr_d->ret_val)));
1568                 break;
1569                 }
1570         default:
1571                 {
1572                 #ifndef WESTBRIDGE_NDEBUG
1573                 cy_as_hal_print_message("%s: unknown ioctl received: %d\n",
1574                         __func__, code);
1575
1576                 cy_as_hal_print_message("%s: known codes:\n"
1577                         "CYASGADGET_GETMTPSTATUS=%d\n"
1578                         "CYASGADGET_CLEARTMTPSTATUS=%d\n"
1579                         "CYASGADGET_INITSOJ=%d\n"
1580                         "CYASGADGET_INITGOJ=%d\n"
1581                         "CYASGADGET_CANCELSOJ=%d\n"
1582                         "CYASGADGET_CANCELGOJ=%d\n",
1583                         __func__,
1584                         CYASGADGET_GETMTPSTATUS,
1585                         CYASGADGET_CLEARTMTPSTATUS,
1586                         CYASGADGET_INITSOJ,
1587                         CYASGADGET_INITGOJ,
1588                         CYASGADGET_CANCELSOJ,
1589                         CYASGADGET_CANCELGOJ);
1590                 #endif
1591                 break;
1592                 }
1593         }
1594
1595         return 0;
1596 }
1597
1598 static const struct usb_gadget_ops cyasgadget_ops = {
1599         .get_frame               = cyasgadget_get_frame,
1600         .wakeup          = cyasgadget_wakeup,
1601         .set_selfpowered = cyasgadget_set_selfpowered,
1602         .pullup          = cyasgadget_pullup,
1603         .ioctl     = cyasgadget_ioctl,
1604 };
1605
1606
1607 /* keeping it simple:
1608  * - one bus driver, initted first;
1609  * - one function driver, initted second
1610  *
1611  * most of the work to support multiple controllers would
1612  * be to associate this gadget driver with all of them, or
1613  * perhaps to bind specific drivers to specific devices.
1614  */
1615
1616 static void cyas_ep_reset(
1617                                 cyasgadget_ep *an_ep
1618                                 )
1619 {
1620         #ifndef WESTBRIDGE_NDEBUG
1621         cy_as_hal_print_message("<1>%s called\n", __func__);
1622         #endif
1623
1624         an_ep->desc = NULL;
1625         INIT_LIST_HEAD(&an_ep->queue);
1626
1627         an_ep->stopped = 0;
1628         an_ep->is_in   = 0;
1629         an_ep->is_iso  = 0;
1630         an_ep->usb_ep_inst.maxpacket = ~0;
1631         an_ep->usb_ep_inst.ops = &cyasgadget_ep_ops;
1632 }
1633
1634 static void cyas_usb_reset(
1635                                 cyasgadget *cy_as_dev
1636                                 )
1637 {
1638         cy_as_return_status_t ret;
1639         cy_as_usb_enum_control config;
1640
1641         #ifndef WESTBRIDGE_NDEBUG
1642         cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle;
1643
1644         cy_as_hal_print_message("<1>%s called mtp_firmware=0x%x\n",
1645                 __func__, dev_p->is_mtp_firmware);
1646         #endif
1647
1648         ret = cy_as_misc_release_resource(cy_as_dev->dev_handle,
1649                 cy_as_bus_u_s_b);
1650         if (ret != CY_AS_ERROR_SUCCESS && ret !=
1651                 CY_AS_ERROR_RESOURCE_NOT_OWNED) {
1652                 cy_as_hal_print_message("<1>_cy_as_gadget: cannot "
1653                         "release usb resource: failed with error code %d\n",
1654                         ret);
1655                 return;
1656         }
1657
1658         cy_as_dev->gadget.speed = USB_SPEED_HIGH;
1659
1660         ret = cy_as_usb_start(cy_as_dev->dev_handle, 0, 0);
1661         if (ret != CY_AS_ERROR_SUCCESS) {
1662                 cy_as_hal_print_message("<1>_cy_as_gadget: "
1663                         "cy_as_usb_start failed with error code %d\n",
1664                         ret);
1665                 return;
1666         }
1667         /* P port will do enumeration, not West Bridge */
1668         config.antioch_enumeration = cy_false;
1669         /*  1  2  : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/
1670
1671         /* TODO: add module param to enumerate mass storage */
1672         config.mass_storage_interface = 0;
1673
1674         if (append_mtp) {
1675                 ret = cy_as_mtp_start(cy_as_dev->dev_handle,
1676                         cy_as_gadget_mtp_event_callback, 0, 0);
1677                 if (ret == CY_AS_ERROR_SUCCESS)  {
1678                         cy_as_hal_print_message("MTP start passed, enumerating "
1679                                 "MTP interface\n");
1680                         config.mtp_interface = append_mtp;
1681                         /*Do not enumerate NAND storage*/
1682                         config.devices_to_enumerate[0][0] = cy_false;
1683
1684                         /*enumerate SD storage as MTP*/
1685                         config.devices_to_enumerate[1][0] = cy_true;
1686                 }
1687         } else {
1688                 cy_as_hal_print_message("MTP start not attempted, not "
1689                         "enumerating MTP interface\n");
1690                 config.mtp_interface = 0;
1691                 /* enumerate mass storage based on module parameters */
1692                 config.devices_to_enumerate[0][0] = msc_enum_bus_0;
1693                 config.devices_to_enumerate[1][0] = msc_enum_bus_1;
1694         }
1695
1696         ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle,
1697                 &config, 0, 0);
1698         if (ret != CY_AS_ERROR_SUCCESS) {
1699                 cy_as_hal_print_message("<1>_cy_as_gadget: "
1700                         "cy_as_usb_set_enum_config failed with error "
1701                         "code %d\n", ret);
1702                 return;
1703         }
1704
1705         cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1);
1706
1707 }
1708
1709 static void cyas_usb_reinit(
1710                                 cyasgadget *cy_as_dev
1711                                 )
1712 {
1713         int index = 0;
1714         cyasgadget_ep *an_ep_p;
1715         cy_as_return_status_t ret;
1716         cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle;
1717
1718         INIT_LIST_HEAD(&cy_as_dev->gadget.ep_list);
1719
1720         #ifndef WESTBRIDGE_NDEBUG
1721         cy_as_hal_print_message("<1>%s called, is_mtp_firmware = "
1722                 "0x%x\n", __func__, dev_p->is_mtp_firmware);
1723         #endif
1724
1725         /* Init the end points */
1726         for (index = 1; index <= 15; index++) {
1727                 an_ep_p = &cy_as_dev->an_gadget_ep[index];
1728                 cyas_ep_reset(an_ep_p);
1729                 an_ep_p->usb_ep_inst.name = cy_as_ep_names[index];
1730                 an_ep_p->dev = cy_as_dev;
1731                 an_ep_p->num = index;
1732                 memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig));
1733
1734                 /* EP0, EPs 2,4,6,8 need not be added */
1735                 if ((index <= 8) && (index % 2 == 0) &&
1736                         (!dev_p->is_mtp_firmware)) {
1737                         /* EP0 is 64 and EPs 2,4,6,8 not allowed */
1738                         cy_as_dev->an_gadget_ep[index].fifo_size = 0;
1739                 } else {
1740                         if (index == 1)
1741                                 an_ep_p->fifo_size = 64;
1742                         else
1743                                 an_ep_p->fifo_size = 512;
1744                         list_add_tail(&an_ep_p->usb_ep_inst.ep_list,
1745                                 &cy_as_dev->gadget.ep_list);
1746                 }
1747         }
1748         /* need to setendpointconfig before usb connect, this is not
1749          * quite compatible with gadget methodology (ep_enable called
1750          * by gadget after connect), therefore need to set config in
1751          * initialization and verify compatibility in ep_enable,
1752          * kick up error otherwise*/
1753         an_ep_p = &cy_as_dev->an_gadget_ep[3];
1754         an_ep_p->cyepconfig.enabled = cy_true;
1755         an_ep_p->cyepconfig.dir = cy_as_usb_out;
1756         an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1757         an_ep_p->cyepconfig.size = 0;
1758         an_ep_p->cyepconfig.physical = 1;
1759         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1760                 3, &an_ep_p->cyepconfig);
1761         if (ret != CY_AS_ERROR_SUCCESS) {
1762                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1763                         "failed with error code %d\n", ret);
1764         }
1765
1766         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0);
1767
1768         an_ep_p = &cy_as_dev->an_gadget_ep[5];
1769         an_ep_p->cyepconfig.enabled = cy_true;
1770         an_ep_p->cyepconfig.dir = cy_as_usb_in;
1771         an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1772         an_ep_p->cyepconfig.size = 0;
1773         an_ep_p->cyepconfig.physical = 2;
1774         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1775                 5, &an_ep_p->cyepconfig);
1776         if (ret != CY_AS_ERROR_SUCCESS) {
1777                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1778                         "failed with error code %d\n", ret);
1779         }
1780
1781         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0);
1782
1783         an_ep_p = &cy_as_dev->an_gadget_ep[9];
1784         an_ep_p->cyepconfig.enabled = cy_true;
1785         an_ep_p->cyepconfig.dir = cy_as_usb_in;
1786         an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1787         an_ep_p->cyepconfig.size = 0;
1788         an_ep_p->cyepconfig.physical = 4;
1789         ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1790                 9, &an_ep_p->cyepconfig);
1791         if (ret != CY_AS_ERROR_SUCCESS) {
1792                 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1793                         "failed with error code %d\n", ret);
1794         }
1795
1796         cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0);
1797
1798         if (dev_p->mtp_count != 0) {
1799                 /* these need to be set for compatibility with
1800                  * the gadget_enable logic */
1801                 an_ep_p = &cy_as_dev->an_gadget_ep[2];
1802                 an_ep_p->cyepconfig.enabled = cy_true;
1803                 an_ep_p->cyepconfig.dir = cy_as_usb_out;
1804                 an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1805                 an_ep_p->cyepconfig.size = 0;
1806                 an_ep_p->cyepconfig.physical = 0;
1807                 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0);
1808
1809                 an_ep_p = &cy_as_dev->an_gadget_ep[6];
1810                 an_ep_p->cyepconfig.enabled = cy_true;
1811                 an_ep_p->cyepconfig.dir = cy_as_usb_in;
1812                 an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1813                 an_ep_p->cyepconfig.size = 0;
1814                 an_ep_p->cyepconfig.physical = 0;
1815                 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 6, 0, 0);
1816         }
1817
1818         cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]);
1819         cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0];
1820         cy_as_dev->an_gadget_ep[0].dev = cy_as_dev;
1821         cy_as_dev->an_gadget_ep[0].num = 0;
1822         cy_as_dev->an_gadget_ep[0].fifo_size = 64;
1823
1824         cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64;
1825         cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst;
1826         cy_as_dev->an_gadget_ep[0].stopped = 0;
1827         INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list);
1828 }
1829
1830 static void cyas_ep0_start(
1831                                 cyasgadget *dev
1832                                 )
1833 {
1834         cy_as_return_status_t ret;
1835
1836         #ifndef WESTBRIDGE_NDEBUG
1837         cy_as_hal_print_message("<1>%s called\n", __func__);
1838         #endif
1839
1840         ret = cy_as_usb_register_callback(dev->dev_handle,
1841                 cy_as_gadget_usb_event_callback);
1842         if (ret != CY_AS_ERROR_SUCCESS) {
1843                 #ifndef WESTBRIDGE_NDEBUG
1844                 cy_as_hal_print_message("%s: cy_as_usb_register_callback "
1845                         "failed with error code %d\n", __func__, ret);
1846                 #endif
1847                 return;
1848         }
1849
1850         ret = cy_as_usb_commit_config(dev->dev_handle, 0, 0);
1851         if (ret != CY_AS_ERROR_SUCCESS) {
1852                 #ifndef WESTBRIDGE_NDEBUG
1853                 cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1854                         "failed with error code %d\n", __func__, ret);
1855                 #endif
1856                 return;
1857         }
1858
1859         #ifndef WESTBRIDGE_NDEBUG
1860         cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1861                 "message sent\n", __func__);
1862         #endif
1863
1864         ret = cy_as_usb_connect(dev->dev_handle, 0, 0);
1865         if (ret != CY_AS_ERROR_SUCCESS) {
1866                 #ifndef WESTBRIDGE_NDEBUG
1867                 cy_as_hal_print_message("%s: cy_as_usb_connect failed "
1868                         "with error code %d\n", __func__, ret);
1869                 #endif
1870                 return;
1871         }
1872
1873         #ifndef WESTBRIDGE_NDEBUG
1874         cy_as_hal_print_message("%s: cy_as_usb_connect message "
1875                 "sent\n", __func__);
1876         #endif
1877 }
1878
1879 /*
1880  * When a driver is successfully registered, it will receive
1881  * control requests including set_configuration(), which enables
1882  * non-control requests.  then usb traffic follows until a
1883  * disconnect is reported.  then a host may connect again, or
1884  * the driver might get unbound.
1885  */
1886 int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
1887                 int (*bind)(struct usb_gadget *))
1888 {
1889         cyasgadget *dev = cy_as_gadget_controller;
1890         int             retval;
1891
1892         #ifndef WESTBRIDGE_NDEBUG
1893         cy_as_hal_print_message("<1>%s called driver=0x%x\n",
1894                 __func__, (unsigned int) driver);
1895         #endif
1896
1897         /* insist on high speed support from the driver, since
1898         * "must not be used in normal operation"
1899         */
1900         if (!driver
1901                 || !bind
1902                 || !driver->unbind
1903                 || !driver->setup)
1904                 return -EINVAL;
1905
1906         if (!dev)
1907                 return -ENODEV;
1908
1909         if (dev->driver)
1910                 return -EBUSY;
1911
1912         /* hook up the driver ... */
1913         dev->softconnect = 1;
1914         driver->driver.bus = NULL;
1915         dev->driver = driver;
1916         dev->gadget.dev.driver = &driver->driver;
1917
1918         /* Do the needful */
1919         cyas_usb_reset(dev); /* External usb */
1920         cyas_usb_reinit(dev); /* Internal */
1921
1922         retval = bind(&dev->gadget);
1923         if (retval) {
1924                 #ifndef WESTBRIDGE_NDEBUG
1925                 cy_as_hal_print_message("%s bind to driver %s --> %d\n",
1926                         __func__, driver->driver.name, retval);
1927                 #endif
1928
1929                 dev->driver = NULL;
1930                 dev->gadget.dev.driver = NULL;
1931                 return retval;
1932         }
1933
1934         /* ... then enable host detection and ep0; and we're ready
1935         * for set_configuration as well as eventual disconnect.
1936         */
1937         cyas_ep0_start(dev);
1938
1939         return 0;
1940 }
1941 EXPORT_SYMBOL(usb_gadget_probe_driver);
1942
1943 static void cyasgadget_nuke(
1944                                                         cyasgadget_ep *an_ep
1945                                                         )
1946 {
1947         cyasgadget      *dev = cy_as_gadget_controller;
1948
1949         #ifndef WESTBRIDGE_NDEBUG
1950         cy_as_hal_print_message("<1>%s called\n", __func__);
1951         #endif
1952
1953         cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
1954         an_ep->stopped = 1;
1955
1956         while (!list_empty(&an_ep->queue)) {
1957                 cyasgadget_req *an_req = list_entry
1958                         (an_ep->queue.next, cyasgadget_req, queue);
1959                 list_del_init(&an_req->queue);
1960                 an_req->req.status = -ESHUTDOWN;
1961                 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
1962         }
1963 }
1964
1965 static void cyasgadget_stop_activity(
1966                                 cyasgadget *dev,
1967                                 struct usb_gadget_driver *driver
1968                                 )
1969 {
1970         int index;
1971
1972         #ifndef WESTBRIDGE_NDEBUG
1973         cy_as_hal_print_message("<1>%s called\n", __func__);
1974         #endif
1975
1976         /* don't disconnect if it's not connected */
1977         if (dev->gadget.speed == USB_SPEED_UNKNOWN)
1978                 driver = NULL;
1979
1980         if (spin_is_locked(&dev->lock))
1981                 spin_unlock(&dev->lock);
1982
1983         /* Stop hardware; prevent new request submissions;
1984          * and kill any outstanding requests.
1985          */
1986         cy_as_usb_disconnect(dev->dev_handle, 0, 0);
1987
1988         for (index = 3; index <= 7; index += 2) {
1989                 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index];
1990                 cyasgadget_nuke(an_ep_p);
1991         }
1992
1993         for (index = 9; index <= 15; index++) {
1994                 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index];
1995                 cyasgadget_nuke(an_ep_p);
1996         }
1997
1998         /* report disconnect; the driver is already quiesced */
1999         if (driver)
2000                 driver->disconnect(&dev->gadget);
2001
2002         #ifndef WESTBRIDGE_NDEBUG
2003         cy_as_hal_print_message("cy_as_usb_disconnect returned success");
2004         #endif
2005
2006         /* Stop Usb */
2007         cy_as_usb_stop(dev->dev_handle, 0, 0);
2008
2009         #ifndef WESTBRIDGE_NDEBUG
2010         cy_as_hal_print_message("cy_as_usb_stop returned success");
2011         #endif
2012 }
2013
2014 int usb_gadget_unregister_driver(
2015                                 struct usb_gadget_driver *driver
2016                                 )
2017 {
2018         cyasgadget      *dev = cy_as_gadget_controller;
2019
2020         #ifndef WESTBRIDGE_NDEBUG
2021         cy_as_hal_print_message("<1>%s called\n", __func__);
2022         #endif
2023
2024         if (!dev)
2025                 return -ENODEV;
2026
2027         if (!driver || driver != dev->driver)
2028                 return -EINVAL;
2029
2030         cyasgadget_stop_activity(dev, driver);
2031
2032         driver->unbind(&dev->gadget);
2033         dev->gadget.dev.driver = NULL;
2034         dev->driver = NULL;
2035
2036         #ifndef WESTBRIDGE_NDEBUG
2037         cy_as_hal_print_message("unregistered driver '%s'\n",
2038                 driver->driver.name);
2039         #endif
2040
2041         return 0;
2042 }
2043 EXPORT_SYMBOL(usb_gadget_unregister_driver);
2044
2045 static void cyas_gadget_release(
2046                                 struct device *_dev
2047                                 )
2048 {
2049         cyasgadget *dev = dev_get_drvdata(_dev);
2050
2051         #ifndef WESTBRIDGE_NDEBUG
2052         cy_as_hal_print_message("<1>%s called\n", __func__);
2053         #endif
2054
2055         kfree(dev);
2056 }
2057
2058 /* DeInitialize gadget driver  */
2059 static void cyasgadget_deinit(
2060                         cyasgadget *cy_as_dev
2061                         )
2062 {
2063         #ifndef WESTBRIDGE_NDEBUG
2064         cy_as_hal_print_message("<1>_cy_as_gadget deinitialize called\n");
2065         #endif
2066
2067         if (!cy_as_dev) {
2068                 #ifndef WESTBRIDGE_NDEBUG
2069                 cy_as_hal_print_message("<1>_cy_as_gadget_deinit: "
2070                         "invalid cyasgadget device\n");
2071                 #endif
2072                 return;
2073         }
2074
2075         if (cy_as_dev->driver) {
2076                 /* should have been done already by driver model core */
2077                 #ifndef WESTBRIDGE_NDEBUG
2078                 cy_as_hal_print_message("<1> cy_as_gadget: '%s' "
2079                         "is still registered\n",
2080                         cy_as_dev->driver->driver.name);
2081                 #endif
2082                 usb_gadget_unregister_driver(cy_as_dev->driver);
2083         }
2084
2085         kfree(cy_as_dev);
2086         cy_as_gadget_controller = NULL;
2087 }
2088
2089 /* Initialize gadget driver  */
2090 static int cyasgadget_initialize(void)
2091 {
2092         cyasgadget *cy_as_dev = 0;
2093         int              retval = 0;
2094
2095         #ifndef WESTBRIDGE_NDEBUG
2096         cy_as_hal_print_message("<1>_cy_as_gadget [V1.1] initialize called\n");
2097         #endif
2098
2099         if (cy_as_gadget_controller != 0) {
2100                 cy_as_hal_print_message("<1> cy_as_gadget: the device has "
2101                         "already been initilaized. ignoring\n");
2102                 return -EBUSY;
2103         }
2104
2105         cy_as_dev = kzalloc(sizeof(cyasgadget), GFP_ATOMIC);
2106         if (cy_as_dev == NULL) {
2107                 cy_as_hal_print_message("<1> cy_as_gadget: memory "
2108                         "allocation failed\n");
2109                 return -ENOMEM;
2110         }
2111
2112         spin_lock_init(&cy_as_dev->lock);
2113         cy_as_dev->gadget.ops = &cyasgadget_ops;
2114         cy_as_dev->gadget.is_dualspeed = 1;
2115
2116         /* the "gadget" abstracts/virtualizes the controller */
2117         /*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/
2118         cy_as_dev->gadget.dev.release = cyas_gadget_release;
2119         cy_as_dev->gadget.name = cy_as_driver_name;
2120
2121         /* Get the device handle */
2122         cy_as_dev->dev_handle = cyasdevice_getdevhandle();
2123         if (0 == cy_as_dev->dev_handle) {
2124                 #ifndef NDEBUG
2125                 cy_as_hal_print_message("<1> cy_as_gadget: "
2126                         "no west bridge device\n");
2127                 #endif
2128                 retval = -EFAULT;
2129                 goto done;
2130         }
2131
2132         /* We are done now */
2133         cy_as_gadget_controller = cy_as_dev;
2134         return 0;
2135
2136 /*
2137  * in case of an error
2138  */
2139 done:
2140         if (cy_as_dev)
2141                 cyasgadget_deinit(cy_as_dev);
2142
2143         return retval;
2144 }
2145
2146 static int __init cyas_init(void)
2147 {
2148         int init_res = 0;
2149
2150         init_res = cyasgadget_initialize();
2151
2152         if (init_res != 0) {
2153                 printk(KERN_WARNING "<1> gadget ctl instance "
2154                         "init error:%d\n", init_res);
2155                 if (init_res > 0) {
2156                         /* force -E/0 linux convention */
2157                         init_res = init_res * -1;
2158                 }
2159         }
2160
2161         return init_res;
2162 }
2163 module_init(cyas_init);
2164
2165 static void __exit cyas_cleanup(void)
2166 {
2167         if (cy_as_gadget_controller != NULL)
2168                 cyasgadget_deinit(cy_as_gadget_controller);
2169 }
2170 module_exit(cyas_cleanup);
2171
2172
2173 MODULE_LICENSE("GPL");
2174 MODULE_DESCRIPTION(CY_AS_DRIVER_DESC);
2175 MODULE_AUTHOR("cypress semiconductor");
2176
2177 /*[]*/