1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
56static const char cy_as_driver_name[] = "cy_astoria_gadget";
57static const char cy_as_driver_desc[] = CY_AS_DRIVER_DESC;
58
59static const char cy_as_ep0name[] = "EP0";
60static 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
67static void
68cyas_ep_reset(
69 struct cyasgadget_ep *an_ep);
70
71static int
72cyasgadget_fifo_status(
73 struct usb_ep *_ep);
74
75static void
76cyasgadget_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
84static cyasgadget *cy_as_gadget_controller;
85
86static int append_mtp;
87module_param(append_mtp, bool, S_IRUGO | S_IWUSR);
88MODULE_PARM_DESC(append_mtp,
89 "west bridge to append descriptors for mtp 0=no 1=yes");
90
91static int msc_enum_bus_0;
92module_param(msc_enum_bus_0, bool, S_IRUGO | S_IWUSR);
93MODULE_PARM_DESC(msc_enum_bus_0,
94 "west bridge to enumerate bus 0 as msc 0=no 1=yes");
95
96static int msc_enum_bus_1;
97module_param(msc_enum_bus_1, bool, S_IRUGO | S_IWUSR);
98MODULE_PARM_DESC(msc_enum_bus_1,
99 "west bridge to enumerate bus 1 as msc 0=no 1=yes");
100
101
102static 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
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
211static 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
279static void
280cyasgadget_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
327static 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
380static 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
434
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
460static 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
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
512
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
536static 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
554
555static 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
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
667static 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
685static 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
707static 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
723
724static 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
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
778
779
780
781
782
783
784
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
851static 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
870static 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 &&
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
912static 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
923static 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
932static 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
946
947static 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
957static 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
967static 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
978static 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
1007static 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
1024
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
1044
1045
1046
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
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
1126 alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1127 if (alloc_filename == NULL)
1128 return -ENOMEM;
1129
1130
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
1174
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
1188 bh.b_size = SECTOR_SIZE;
1189
1190
1191
1192
1193
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
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
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
1229
1230 for (file_block_idx = 0;
1231 file_block_idx < num_clusters
1232 ; file_block_idx++) {
1233
1234
1235 curr_blk_addr_map =
1236 a_ops->bmap(mapping,
1237 file_block_idx);
1238
1239
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
1253 blk_table_idx++;
1254
1255
1256 blk_table.start_blocks
1257 [blk_table_idx] =
1258 curr_blk_addr_map;
1259
1260
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
1273 blk_table.num_blocks
1274 [blk_table_idx]++;
1275 }
1276
1277 last_blk_addr_map = curr_blk_addr_map;
1278 }
1279
1280
1281 #ifndef WESTBRIDGE_NDEBUG
1282
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
1299
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 }
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 }
1343 #endif
1344 kfree(alloc_filename);
1345initsoj_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
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
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
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
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
1454 blk_table.num_blocks
1455 [blk_table_idx]++;
1456 }
1457 last_blk_addr_map = curr_blk_addr_map;
1458 }
1459
1460
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
1598static 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
1608
1609
1610
1611
1612
1613
1614
1615
1616static 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
1634static 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
1668 config.antioch_enumeration = cy_false;
1669
1670
1671
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
1682 config.devices_to_enumerate[0][0] = cy_false;
1683
1684
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
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
1709static 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
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
1735 if ((index <= 8) && (index % 2 == 0) &&
1736 (!dev_p->is_mtp_firmware)) {
1737
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
1749
1750
1751
1752
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
1800
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
1830static 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
1881
1882
1883
1884
1885
1886int 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
1898
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
1913 dev->softconnect = 1;
1914 driver->driver.bus = NULL;
1915 dev->driver = driver;
1916 dev->gadget.dev.driver = &driver->driver;
1917
1918
1919 cyas_usb_reset(dev);
1920 cyas_usb_reinit(dev);
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
1935
1936
1937 cyas_ep0_start(dev);
1938
1939 return 0;
1940}
1941EXPORT_SYMBOL(usb_gadget_probe_driver);
1942
1943static 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
1965static 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
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
1984
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
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
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
2014int 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}
2043EXPORT_SYMBOL(usb_gadget_unregister_driver);
2044
2045static 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
2059static 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
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
2090static 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
2117
2118 cy_as_dev->gadget.dev.release = cyas_gadget_release;
2119 cy_as_dev->gadget.name = cy_as_driver_name;
2120
2121
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
2133 cy_as_gadget_controller = cy_as_dev;
2134 return 0;
2135
2136
2137
2138
2139done:
2140 if (cy_as_dev)
2141 cyasgadget_deinit(cy_as_dev);
2142
2143 return retval;
2144}
2145
2146static 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
2157 init_res = init_res * -1;
2158 }
2159 }
2160
2161 return init_res;
2162}
2163module_init(cyas_init);
2164
2165static void __exit cyas_cleanup(void)
2166{
2167 if (cy_as_gadget_controller != NULL)
2168 cyasgadget_deinit(cy_as_gadget_controller);
2169}
2170module_exit(cyas_cleanup);
2171
2172
2173MODULE_LICENSE("GPL");
2174MODULE_DESCRIPTION(CY_AS_DRIVER_DESC);
2175MODULE_AUTHOR("cypress semiconductor");
2176
2177
2178