1 /* cyangadget.c - Linux USB Gadget driver file for the Cypress West Bridge
2 ## ===========================
3 ## Copyright (C) 2010 Cypress Semiconductor
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.
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.
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 ## ===========================
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
27 * linux/drivers/usb/gadget/net2280.c
31 * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
32 * Copyright (C) 2003 David Brownell
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.
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.
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
50 #include "cyasgadget.h"
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)
56 static const char cy_as_driver_name[] = "cy_astoria_gadget";
57 static const char cy_as_driver_desc[] = CY_AS_DRIVER_DESC;
59 static const char cy_as_ep0name[] = "EP0";
60 static const char *cy_as_ep_names[] = {
62 "EP2", "EP3", "EP4", "EP5", "EP6", "EP7", "EP8",
63 "EP9", "EP10", "EP11", "EP12", "EP13", "EP14", "EP15"
66 /* forward declarations */
69 struct cyasgadget_ep *an_ep) ;
72 cyasgadget_fifo_status(
76 cyasgadget_stallcallback(
77 cy_as_device_handle h,
78 cy_as_return_status_t status,
80 cy_as_funct_c_b_type cbtype,
84 static cyasgadget *cy_as_gadget_controller;
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");
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");
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");
101 /* all Callbacks are placed in this subsection*/
102 static void cy_as_gadget_usb_event_callback(
103 cy_as_device_handle h,
108 cyasgadget *cy_as_dev ;
109 #ifndef WESTBRIDGE_NDEBUG
110 struct usb_ctrlrequest *ctrlreq;
113 /* cy_as_dev = container_of(h, cyasgadget, dev_handle); */
114 cy_as_dev = cy_as_gadget_controller ;
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") ;
121 cy_as_dev->driver->suspend(&cy_as_dev->gadget) ;
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") ;
129 cy_as_dev->driver->resume(&cy_as_dev->gadget) ;
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") ;
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") ;
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") ;
153 case cy_as_event_usb_setup_packet:
154 #ifndef WESTBRIDGE_NDEBUG
155 ctrlreq = (struct usb_ctrlrequest *)evdata;
157 cy_as_hal_print_message("<1>_cy_as_event_usb_setup_packet "
164 ctrlreq->bRequestType,
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) ;
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") ;
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") ;
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") ;
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") ;
211 static void cy_as_gadget_mtp_event_callback(
212 cy_as_device_handle handle,
213 cy_as_mtp_event evtype,
218 cyasgadget *dev = cy_as_gadget_controller ;
222 case cy_as_mtp_send_object_complete:
224 cy_as_mtp_send_object_complete_data *send_obj_data =
225 (cy_as_mtp_send_object_complete_data *) evdata ;
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);
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 ;
245 case cy_as_mtp_get_object_complete:
247 cy_as_mtp_get_object_complete_data *get_obj_data =
248 (cy_as_mtp_get_object_complete_data *) evdata ;
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);
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 ;
265 case cy_as_mtp_block_table_needed:
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");
280 cyasgadget_setupreadcallback(
281 cy_as_device_handle h,
282 cy_as_end_point_number_t ep,
285 cy_as_return_status_t status)
287 cyasgadget_ep *an_ep;
288 cyasgadget_req *an_req;
289 cyasgadget *cy_as_dev ;
294 cy_as_dev = cy_as_gadget_controller ;
295 if (cy_as_dev->driver == NULL)
298 an_ep = &cy_as_dev->an_gadget_ep[ep] ;
299 spin_lock_irqsave(&cy_as_dev->lock, flags);
300 stopped = an_ep->stopped ;
302 #ifndef WESTBRIDGE_NDEBUG
303 cy_as_hal_print_message(
304 "%s: ep=%d, count=%d, "
305 "status=%d\n", __func__, ep, count, status) ;
308 an_req = list_entry(an_ep->queue.next,
309 cyasgadget_req, queue) ;
310 list_del_init(&an_req->queue) ;
312 if (status == CY_AS_ERROR_SUCCESS)
313 an_req->req.status = 0;
315 an_req->req.status = -status;
316 an_req->req.actual = count ;
319 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
321 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
323 an_ep->stopped = stopped;
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,
332 cy_as_return_status_t status
335 cyasgadget_ep *an_ep;
336 cyasgadget_req *an_req;
337 cyasgadget *cy_as_dev ;
343 #ifndef WESTBRIDGE_NDEBUG
344 cy_as_hal_print_message("<1>%s called status=0x%x\n",
348 cy_as_dev = cy_as_gadget_controller ;
350 if (cy_as_dev->driver == NULL)
353 an_ep = &cy_as_dev->an_gadget_ep[ep] ;
355 spin_lock_irqsave(&cy_as_dev->lock, flags);
357 stopped = an_ep->stopped ;
359 #ifndef WESTBRIDGE_NDEBUG
360 cy_as_hal_print_message("setup_write_callback: ep=%d, "
361 "count=%d, status=%d\n", ep, count, status) ;
364 an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ;
365 list_del_init(&an_req->queue) ;
367 an_req->req.actual = count ;
368 an_req->req.status = 0 ;
371 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
373 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
375 an_ep->stopped = stopped;
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,
385 cy_as_return_status_t status
388 cyasgadget_ep *an_ep;
389 cyasgadget_req *an_req;
390 cyasgadget *cy_as_dev ;
392 cy_as_return_status_t ret ;
398 cy_as_dev = cy_as_gadget_controller ;
400 if (cy_as_dev->driver == NULL)
403 an_ep = &cy_as_dev->an_gadget_ep[ep] ;
404 stopped = an_ep->stopped ;
406 #ifndef WESTBRIDGE_NDEBUG
407 cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n",
408 __func__, ep, count, status) ;
411 if (status == CY_AS_ERROR_CANCELED)
414 spin_lock_irqsave(&cy_as_dev->lock, flags);
416 an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ;
417 list_del_init(&an_req->queue) ;
419 if (status == CY_AS_ERROR_SUCCESS)
420 an_req->req.status = 0 ;
422 an_req->req.status = -status ;
424 an_req->complete = 1;
425 an_req->req.actual = count ;
428 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
429 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
431 an_ep->stopped = stopped;
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);
438 if (!list_empty(&an_ep->queue))
439 an_req = list_entry(an_ep->queue.next,
440 cyasgadget_req, queue) ;
442 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
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);
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) ;
454 an_req->req.status = -EALREADY ;
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,
465 cy_as_return_status_t status
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 ;
478 cy_as_dev = cy_as_gadget_controller ;
479 if (cy_as_dev->driver == NULL)
482 an_ep = &cy_as_dev->an_gadget_ep[ep] ;
484 if (status == CY_AS_ERROR_CANCELED)
487 #ifndef WESTBRIDGE_NDEBUG
488 cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n",
489 __func__, ep, count, status) ;
492 spin_lock_irqsave(&cy_as_dev->lock, flags);
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 ;
498 /* Verify the status value before setting req.status to zero */
499 if (status == CY_AS_ERROR_SUCCESS)
500 an_req->req.status = 0 ;
502 an_req->req.status = -status ;
506 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
508 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
509 an_ep->stopped = stopped;
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);
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);
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);
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) ;
531 an_req->req.status = -EALREADY ;
536 static void cyasgadget_stallcallback(
537 cy_as_device_handle h,
538 cy_as_return_status_t status,
540 cy_as_funct_c_b_type cbtype,
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) ;
552 /*******************************************************************/
553 /* All usb_ep_ops (cyasgadget_ep_ops) are placed in this subsection*/
554 /*******************************************************************/
555 static int cyasgadget_enable(
557 const struct usb_endpoint_descriptor *desc
561 cyasgadget_ep *an_ep;
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)
571 if (!an_dev->driver || an_dev->gadget.speed == USB_SPEED_UNKNOWN)
574 max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
576 spin_lock_irqsave(&an_dev->lock, flags);
577 _ep->maxpacket = max & 0x7ff;
580 /* ep_reset() has already been called */
582 an_ep->out_overflow = 0;
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) ;
593 tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
594 an_ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
596 spin_unlock_irqrestore(&an_dev->lock, flags);
599 case USB_ENDPOINT_XFER_ISOC:
600 if (an_ep->cyepconfig.type != cy_as_usb_iso) {
601 #ifndef WESTBRIDGE_NDEBUG
602 cy_as_hal_print_message("<1>_cy_as_gadget: "
603 "cy_as_usb_end_point_config EP %s mismatch "
604 "on type %d %d\n", an_ep->usb_ep_inst.name,
605 an_ep->cyepconfig.type, cy_as_usb_iso) ;
610 case USB_ENDPOINT_XFER_INT:
611 if (an_ep->cyepconfig.type != cy_as_usb_int) {
612 #ifndef WESTBRIDGE_NDEBUG
613 cy_as_hal_print_message("<1>_cy_as_gadget: "
614 "cy_as_usb_end_point_config EP %s mismatch "
615 "on type %d %d\n", an_ep->usb_ep_inst.name,
616 an_ep->cyepconfig.type, cy_as_usb_int) ;
622 if (an_ep->cyepconfig.type != cy_as_usb_bulk) {
623 #ifndef WESTBRIDGE_NDEBUG
624 cy_as_hal_print_message("<1>_cy_as_gadget: "
625 "cy_as_usb_end_point_config EP %s mismatch "
626 "on type %d %d\n", an_ep->usb_ep_inst.name,
627 an_ep->cyepconfig.type, cy_as_usb_bulk) ;
634 tmp = desc->bEndpointAddress;
635 an_ep->is_in = (tmp & USB_DIR_IN) != 0;
637 if ((an_ep->cyepconfig.dir == cy_as_usb_in) &&
639 #ifndef WESTBRIDGE_NDEBUG
640 cy_as_hal_print_message("<1>_cy_as_gadget: "
641 "cy_as_usb_end_point_config EP %s mismatch "
642 "on dir %d %d\n", an_ep->usb_ep_inst.name,
643 an_ep->cyepconfig.dir, cy_as_usb_in) ;
646 } else if ((an_ep->cyepconfig.dir == cy_as_usb_out) &&
648 #ifndef WESTBRIDGE_NDEBUG
649 cy_as_hal_print_message("<1>_cy_as_gadget: "
650 "cy_as_usb_end_point_config EP %s mismatch "
651 "on dir %d %d\n", an_ep->usb_ep_inst.name,
652 an_ep->cyepconfig.dir, cy_as_usb_out) ;
657 cy_as_usb_clear_stall(an_dev->dev_handle, an_ep->num,
658 cyasgadget_stallcallback, 0);
660 cy_as_hal_print_message("%s enabled %s (ep%d-%d) max %04x\n",
661 __func__, _ep->name, an_ep->num, tmp, max);
666 static int cyasgadget_disable(
670 cyasgadget_ep *an_ep;
673 an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
674 if (!_ep || !an_ep->desc || _ep->name == cy_as_ep0name)
677 spin_lock_irqsave(&an_ep->dev->lock, flags);
678 cyas_ep_reset(an_ep);
680 spin_unlock_irqrestore(&an_ep->dev->lock, flags);
684 static struct usb_request *cyasgadget_alloc_request(
685 struct usb_ep *_ep, gfp_t gfp_flags
688 cyasgadget_ep *an_ep;
689 cyasgadget_req *an_req;
694 an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
696 an_req = kzalloc(sizeof(cyasgadget_req), gfp_flags);
700 an_req->req.dma = DMA_ADDR_INVALID;
701 INIT_LIST_HEAD(&an_req->queue);
706 static void cyasgadget_free_request(
708 struct usb_request *_req
711 cyasgadget_req *an_req ;
716 an_req = container_of(_req, cyasgadget_req, req) ;
721 /* Load a packet into the fifo we use for usb IN transfers.
722 * works for all endpoints. */
723 static int cyasgadget_queue(
725 struct usb_request *_req,
729 cyasgadget_req *as_req;
730 cyasgadget_ep *as_ep;
731 cyasgadget *cy_as_dev;
733 cy_as_return_status_t ret = 0;
735 as_req = container_of(_req, cyasgadget_req, req);
736 if (!_req || !_req->complete || !_req->buf
737 || !list_empty(&as_req->queue))
740 as_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
742 if (!_ep || (!as_ep->desc && (as_ep->num != 0)))
745 cy_as_dev = as_ep->dev;
746 if (!cy_as_dev->driver ||
747 cy_as_dev->gadget.speed == USB_SPEED_UNKNOWN)
750 spin_lock_irqsave(&cy_as_dev->lock, flags);
752 _req->status = -EINPROGRESS;
755 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
757 /* Call Async functions */
759 #ifndef WESTBRIDGE_NDEBUG
760 cy_as_hal_print_message("<1>_cy_as_gadget: "
761 "cy_as_usb_write_data_async being called "
762 "on ep %d\n", as_ep->num) ;
765 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
766 as_ep->num, _req->length, _req->buf,
767 cy_false, cyasgadget_writecallback) ;
768 if (ret != CY_AS_ERROR_SUCCESS)
769 cy_as_hal_print_message("<1>_cy_as_gadget: "
770 "cy_as_usb_write_data_async failed with "
771 "error code %d\n", ret) ;
773 _req->status = -EALREADY ;
774 } else if (as_ep->num == 0) {
776 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
777 as_ep->num, _req->length, _req->buf, cy_false,
778 cyasgadget_setupwritecallback) ;
780 if (ret != CY_AS_ERROR_SUCCESS)
781 cy_as_hal_print_message("<1>_cy_as_gadget: "
782 "cy_as_usb_write_data_async failed with error "
785 if ((cy_as_dev->outsetupreq) && (_req->length)) {
786 #ifndef WESTBRIDGE_NDEBUG
787 cy_as_hal_print_message("<1>_cy_as_gadget: "
788 "cy_as_usb_read_data_async "
789 "being called on ep %d\n",
793 ret = cy_as_usb_read_data_async (
794 cy_as_dev->dev_handle, as_ep->num,
795 cy_true, _req->length, _req->buf,
796 cyasgadget_setupreadcallback);
798 if (ret != CY_AS_ERROR_SUCCESS)
799 cy_as_hal_print_message("<1>_cy_as_gadget: "
800 "cy_as_usb_read_data_async failed with "
801 "error code %d\n", ret) ;
804 #ifndef WESTBRIDGE_NDEBUG
805 cy_as_hal_print_message("<1>_cy_as_gadget: "
806 "cy_as_usb_write_data_async "
807 "being called on ep %d\n",
811 ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
812 as_ep->num, _req->length, _req->buf, cy_false,
813 cyasgadget_setupwritecallback) ;
815 if (ret != CY_AS_ERROR_SUCCESS)
816 cy_as_hal_print_message("<1>_cy_as_gadget: "
817 "cy_as_usb_write_data_async failed with "
818 "error code %d\n", ret) ;
821 } else if (list_empty(&as_ep->queue)) {
822 #ifndef WESTBRIDGE_NDEBUG
823 cy_as_hal_print_message("<1>_cy_as_gadget: "
824 "cy_as_usb_read_data_async being called since "
825 "ep queue empty%d\n", ret) ;
828 ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
829 as_ep->num, cy_false, _req->length, _req->buf,
830 cyasgadget_readcallback) ;
831 if (ret != CY_AS_ERROR_SUCCESS)
832 cy_as_hal_print_message("<1>_cy_as_gadget: "
833 "cy_as_usb_read_data_async failed with error "
836 _req->status = -EALREADY ;
839 spin_lock_irqsave(&cy_as_dev->lock, flags);
842 list_add_tail(&as_req->queue, &as_ep->queue);
844 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
849 /* dequeue request */
850 static int cyasgadget_dequeue(
852 struct usb_request *_req
855 cyasgadget_ep *an_ep;
857 an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
860 #ifndef WESTBRIDGE_NDEBUG
861 cy_as_hal_print_message("<1>%s called\n", __func__);
864 cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
869 static int cyasgadget_set_halt(
874 cyasgadget_ep *an_ep;
877 #ifndef WESTBRIDGE_NDEBUG
878 cy_as_hal_print_message("<1>%s called\n", __func__);
881 an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
882 if (!_ep || (!an_ep->desc && an_ep->num != 0))
885 if (!an_ep->dev->driver || an_ep->dev->gadget.speed ==
889 if (an_ep->desc /* not ep0 */ &&
890 (an_ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC)
893 if (!list_empty(&an_ep->queue))
895 else if (an_ep->is_in && value &&
896 cyasgadget_fifo_status(_ep) != 0)
900 cy_as_usb_set_stall(an_ep->dev->dev_handle,
901 an_ep->num, cyasgadget_stallcallback, 0) ;
903 cy_as_usb_clear_stall(an_ep->dev->dev_handle,
904 an_ep->num, cyasgadget_stallcallback, 0) ;
911 static int cyasgadget_fifo_status(
915 #ifndef WESTBRIDGE_NDEBUG
916 cy_as_hal_print_message("<1>%s called\n", __func__);
922 static void cyasgadget_fifo_flush(
926 #ifndef WESTBRIDGE_NDEBUG
927 cy_as_hal_print_message("<1>%s called\n", __func__);
931 static struct usb_ep_ops cyasgadget_ep_ops = {
932 .enable = cyasgadget_enable,
933 .disable = cyasgadget_disable,
934 .alloc_request = cyasgadget_alloc_request,
935 .free_request = cyasgadget_free_request,
936 .queue = cyasgadget_queue,
937 .dequeue = cyasgadget_dequeue,
938 .set_halt = cyasgadget_set_halt,
939 .fifo_status = cyasgadget_fifo_status,
940 .fifo_flush = cyasgadget_fifo_flush,
943 /*************************************************************/
944 /*This subsection contains all usb_gadget_ops cyasgadget_ops */
945 /*************************************************************/
946 static int cyasgadget_get_frame(
947 struct usb_gadget *_gadget
950 #ifndef WESTBRIDGE_NDEBUG
951 cy_as_hal_print_message("<1>%s called\n", __func__);
956 static int cyasgadget_wakeup(
957 struct usb_gadget *_gadget
960 #ifndef WESTBRIDGE_NDEBUG
961 cy_as_hal_print_message("<1>%s called\n", __func__);
966 static int cyasgadget_set_selfpowered(
967 struct usb_gadget *_gadget,
971 #ifndef WESTBRIDGE_NDEBUG
972 cy_as_hal_print_message("<1>%s called\n", __func__);
977 static int cyasgadget_pullup(
978 struct usb_gadget *_gadget,
982 struct cyasgadget *cy_as_dev ;
985 #ifndef WESTBRIDGE_NDEBUG
986 cy_as_hal_print_message("<1>%s called\n", __func__);
992 cy_as_dev = container_of(_gadget, cyasgadget, gadget);
994 spin_lock_irqsave(&cy_as_dev->lock, flags);
995 cy_as_dev->softconnect = (is_on != 0);
997 cy_as_usb_connect(cy_as_dev->dev_handle, 0, 0) ;
999 cy_as_usb_disconnect(cy_as_dev->dev_handle, 0, 0) ;
1001 spin_unlock_irqrestore(&cy_as_dev->lock, flags);
1006 static int cyasgadget_ioctl(
1007 struct usb_gadget *_gadget,
1015 cyasgadget *dev = cy_as_gadget_controller ;
1017 #ifndef WESTBRIDGE_NDEBUG
1018 cy_as_hal_print_message("<1>%s called, code=%d, param=%ld\n",
1019 __func__, code, param);
1022 * extract the type and number bitfields, and don't decode
1023 * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
1025 if (_IOC_TYPE(code) != CYASGADGET_IOC_MAGIC) {
1026 #ifndef WESTBRIDGE_NDEBUG
1027 cy_as_hal_print_message("%s, bad magic number = 0x%x\n",
1028 __func__, _IOC_TYPE(code));
1033 if (_IOC_NR(code) > CYASGADGET_IOC_MAXNR) {
1034 #ifndef WESTBRIDGE_NDEBUG
1035 cy_as_hal_print_message("%s, bad ioctl code = 0x%x\n",
1036 __func__, _IOC_NR(code));
1042 * the direction is a bitmask, and VERIFY_WRITE catches R/W
1043 * transfers. `Type' is user-oriented, while
1044 * access_ok is kernel-oriented, so the concept of "read" and
1045 * "write" is reversed
1047 if (_IOC_DIR(code) & _IOC_READ)
1048 err = !access_ok(VERIFY_WRITE,
1049 (void __user *)param, _IOC_SIZE(code));
1050 else if (_IOC_DIR(code) & _IOC_WRITE)
1051 err = !access_ok(VERIFY_READ,
1052 (void __user *)param, _IOC_SIZE(code));
1055 cy_as_hal_print_message("%s, bad ioctl dir = 0x%x\n",
1056 __func__, _IOC_DIR(code));
1061 case CYASGADGET_GETMTPSTATUS:
1063 cy_as_gadget_ioctl_tmtp_status *usr_d =
1064 (cy_as_gadget_ioctl_tmtp_status *)param ;
1066 #ifndef WESTBRIDGE_NDEBUG
1067 cy_as_hal_print_message("%s: got CYASGADGET_GETMTPSTATUS\n",
1071 retval = __put_user(dev->tmtp_send_complete,
1072 (uint32_t __user *)(&(usr_d->tmtp_send_complete)));
1073 retval = __put_user(dev->tmtp_get_complete,
1074 (uint32_t __user *)(&(usr_d->tmtp_get_complete)));
1075 retval = __put_user(dev->tmtp_need_new_blk_tbl,
1076 (uint32_t __user *)(&(usr_d->tmtp_need_new_blk_tbl)));
1078 if (copy_to_user((&(usr_d->tmtp_send_complete_data)),
1079 (&(dev->tmtp_send_complete_data)),
1080 sizeof(cy_as_gadget_ioctl_send_object)))
1083 if (copy_to_user((&(usr_d->tmtp_get_complete_data)),
1084 (&(dev->tmtp_get_complete_data)),
1085 sizeof(cy_as_gadget_ioctl_get_object)))
1089 case CYASGADGET_CLEARTMTPSTATUS:
1091 #ifndef WESTBRIDGE_NDEBUG
1092 cy_as_hal_print_message("%s got CYASGADGET_CLEARTMTPSTATUS\n",
1096 dev->tmtp_send_complete = 0 ;
1097 dev->tmtp_get_complete = 0 ;
1098 dev->tmtp_need_new_blk_tbl = 0 ;
1102 case CYASGADGET_INITSOJ:
1104 cy_as_gadget_ioctl_i_s_o_j_d k_d ;
1105 cy_as_gadget_ioctl_i_s_o_j_d *usr_d =
1106 (cy_as_gadget_ioctl_i_s_o_j_d *)param ;
1107 cy_as_mtp_block_table blk_table ;
1108 struct scatterlist sg ;
1109 char *alloc_filename;
1110 struct file *file_to_allocate;
1112 #ifndef WESTBRIDGE_NDEBUG
1113 cy_as_hal_print_message("%s got CYASGADGET_INITSOJ\n",
1117 memset(&blk_table, 0, sizeof(blk_table));
1119 /* Get user argument structure */
1120 if (copy_from_user(&k_d, usr_d,
1121 sizeof(cy_as_gadget_ioctl_i_s_o_j_d)))
1124 /* better use fixed size buff*/
1125 alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1127 /* get the filename */
1128 if (copy_from_user(alloc_filename, k_d.file_name,
1129 k_d.name_length + 1)) {
1130 #ifndef WESTBRIDGE_NDEBUG
1131 cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, "
1132 "copy file name from user space failed\n",
1138 file_to_allocate = filp_open(alloc_filename, O_RDWR, 0);
1140 if ((int)file_to_allocate != 0xfffffffe) {
1142 struct address_space *mapping =
1143 file_to_allocate->f_mapping;
1144 const struct address_space_operations *a_ops =
1146 struct inode *inode = mapping->host;
1147 struct inode *alloc_inode =
1148 file_to_allocate->f_path.dentry->d_inode;
1150 uint32_t num_clusters = 0;
1151 struct buffer_head bh;
1153 struct iattr alloc_iattr;
1157 #ifndef WESTBRIDGE_NDEBUG
1158 cy_as_hal_print_message("%s: fhandle is OK, "
1159 "calling vfs_getattr\n", __func__);
1162 ret_stat = vfs_getattr(file_to_allocate->f_path.mnt,
1163 file_to_allocate->f_path.dentry, &stat);
1165 #ifndef WESTBRIDGE_NDEBUG
1166 cy_as_hal_print_message("%s: returned from "
1167 "vfs_getattr() stat->blksize=0x%lx\n",
1168 __func__, stat.blksize);
1171 /* TODO: get this from disk properties
1172 * (from blockdevice)*/
1173 #define SECTOR_SIZE 512
1174 if (stat.blksize != 0) {
1175 num_clusters = (k_d.num_bytes) / SECTOR_SIZE;
1177 if (((k_d.num_bytes) % SECTOR_SIZE) != 0)
1180 goto initsoj_safe_exit;
1185 /* block size is arbitrary , we'll use sector size*/
1186 bh.b_size = SECTOR_SIZE ;
1188 #ifndef WESTBRIDGE_NDEBUG
1189 cy_as_hal_print_message("%s: getting fat blocks %d "
1190 "size of %d\n", __func__,
1191 num_clusters, bh.b_size);
1193 for (cluster = 0; cluster < num_clusters; cluster++) {
1194 ret_stat = fat_get_block(inode,
1197 cy_as_hal_print_message(
1198 "%s: unable to get fat block, "
1200 __func__, ret_stat);
1201 goto initsoj_safe_exit;
1205 #ifndef WESTBRIDGE_NDEBUG
1206 cy_as_hal_print_message("%s: allocated clusters "
1207 "successfully (fat_get_block), check bmap..."
1211 alloc_iattr.ia_valid = ATTR_SIZE;
1212 alloc_iattr.ia_size = k_d.num_bytes;
1214 #ifndef WESTBRIDGE_NDEBUG
1215 cy_as_hal_print_message("%s: calling fat_notify_change "
1216 "(ia_valid:%d, ia_size:%d)\n", __func__,
1217 alloc_iattr.ia_valid,
1218 (int)alloc_iattr.ia_size);
1221 /* adjust the filesize */
1222 ret_stat = alloc_inode->i_op->setattr(
1223 file_to_allocate->f_path.dentry, &alloc_iattr);
1224 #ifndef WESTBRIDGE_NDEBUG
1225 cy_as_hal_print_message("%s: fat_setattr() "
1227 __func__, ret_stat);
1230 /* clear dirty pages in page cache
1231 * (if were any allocated) */
1232 nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE);
1234 if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0)
1237 #ifndef WESTBRIDGE_NDEBUG
1238 /*check out how many pages where actually allocated */
1239 if (mapping->nrpages != nr_pages)
1240 cy_as_hal_print_message("%s mpage_cleardirty "
1241 "mapping->nrpages %d != num_pages %d\n",
1242 __func__, (int) mapping->nrpages,
1245 cy_as_hal_print_message("%s: calling "
1246 "mpage_cleardirty() "
1247 "for %d pages\n", __func__, nr_pages);
1250 ret_stat = mpage_cleardirty(mapping, nr_pages);
1252 /*fill up the the block table from the addr mapping */
1254 int8_t blk_table_idx = -1;
1255 uint32_t file_block_idx = 0;
1256 uint32_t last_blk_addr_map = 0,
1257 curr_blk_addr_map = 0;
1259 #ifndef WESTBRIDGE_NDEBUG
1260 if (alloc_inode->i_bytes == 0)
1261 cy_as_hal_print_message(
1262 "%s: alloc_inode->ibytes =0\n",
1266 /* iterate through the list of
1267 * blocks (not clusters)*/
1268 for (file_block_idx = 0;
1269 file_block_idx < num_clusters
1270 /*inode->i_bytes*/; file_block_idx++) {
1272 /* returns starting sector number */
1274 a_ops->bmap(mapping,
1277 /*no valid mapping*/
1278 if (curr_blk_addr_map == 0) {
1279 #ifndef WESTBRIDGE_NDEBUG
1280 cy_as_hal_print_message(
1282 "mapping\n", __func__);
1285 } else if (curr_blk_addr_map !=
1286 (last_blk_addr_map + 1) ||
1287 (blk_table.num_blocks
1288 [blk_table_idx] == 65535)) {
1290 /* next table entry */
1292 /* starting sector of a
1293 * scattered cluster*/
1294 blk_table.start_blocks
1297 /* ++ num of blocks in cur
1300 num_blocks[blk_table_idx]++;
1302 #ifndef WESTBRIDGE_NDEBUG
1303 if (file_block_idx != 0)
1304 cy_as_hal_print_message(
1306 "entry:%d required\n",
1310 /*add contiguous block*/
1311 blk_table.num_blocks
1313 } /*if (curr_blk_addr_map == 0)*/
1315 last_blk_addr_map = curr_blk_addr_map;
1316 } /* end for (file_block_idx = 0; file_block_idx
1317 < inode->i_bytes;) */
1319 #ifndef WESTBRIDGE_NDEBUG
1320 /*print result for verification*/
1323 cy_as_hal_print_message(
1324 "%s: print block table "
1327 for (i = 0; i <= blk_table_idx; i++) {
1328 cy_as_hal_print_message(
1329 "<1> %d 0x%x 0x%x\n", i,
1330 blk_table.start_blocks[i],
1331 blk_table.num_blocks[i]);
1336 /* copy the block table to user
1337 * space (for debug purposes) */
1338 retval = __put_user(
1339 blk_table.start_blocks[blk_table_idx],
1341 (&(usr_d->blk_addr_p)));
1343 retval = __put_user(
1344 blk_table.num_blocks[blk_table_idx],
1346 (&(usr_d->blk_count_p)));
1349 retval = __put_user(blk_table_idx,
1351 (&(usr_d->item_count)));
1353 } /*end if (a_ops->bmap)*/
1355 filp_close(file_to_allocate, NULL);
1357 dev->tmtp_send_complete = 0 ;
1358 dev->tmtp_need_new_blk_tbl = 0 ;
1360 #ifndef WESTBRIDGE_NDEBUG
1361 cy_as_hal_print_message(
1362 "%s: calling cy_as_mtp_init_send_object()\n",
1365 sg_init_one(&sg, &blk_table, sizeof(blk_table));
1366 ret_stat = cy_as_mtp_init_send_object(dev->dev_handle,
1367 (cy_as_mtp_block_table *)&sg,
1368 k_d.num_bytes, 0, 0);
1369 #ifndef WESTBRIDGE_NDEBUG
1370 cy_as_hal_print_message("%s: returned from "
1371 "cy_as_mtp_init_send_object()\n", __func__);
1375 #ifndef WESTBRIDGE_NDEBUG
1377 cy_as_hal_print_message(
1378 "%s: failed to allocate the file %s\n",
1379 __func__, alloc_filename);
1380 } /* end if (file_to_allocate)*/
1384 retval = __put_user(ret_stat,
1385 (uint32_t __user *)(&(usr_d->ret_val)));
1389 case CYASGADGET_INITGOJ:
1391 cy_as_gadget_ioctl_i_g_o_j_d k_d ;
1392 cy_as_gadget_ioctl_i_g_o_j_d *usr_d =
1393 (cy_as_gadget_ioctl_i_g_o_j_d *)param ;
1394 cy_as_mtp_block_table blk_table ;
1395 struct scatterlist sg ;
1397 struct file *file_to_map;
1399 #ifndef WESTBRIDGE_NDEBUG
1400 cy_as_hal_print_message(
1401 "%s: got CYASGADGET_INITGOJ\n",
1405 memset(&blk_table, 0, sizeof(blk_table));
1407 /* Get user argument sturcutre */
1408 if (copy_from_user(&k_d, usr_d,
1409 sizeof(cy_as_gadget_ioctl_i_g_o_j_d)))
1412 map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1413 if (copy_from_user(map_filename, k_d.file_name,
1414 k_d.name_length + 1)) {
1415 #ifndef WESTBRIDGE_NDEBUG
1416 cy_as_hal_print_message("%s: copy file name from "
1417 "user space failed\n", __func__);
1422 #ifndef WESTBRIDGE_NDEBUG
1423 cy_as_hal_print_message("<*>%s: opening %s for kernel "
1424 "mode access map\n", __func__, map_filename);
1426 file_to_map = filp_open(map_filename, O_RDWR, 0);
1428 struct address_space *mapping = file_to_map->f_mapping;
1429 const struct address_space_operations
1430 *a_ops = mapping->a_ops;
1431 struct inode *inode = mapping->host;
1433 int8_t blk_table_idx = -1;
1434 uint32_t file_block_idx = 0;
1435 uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0;
1437 /*verify operation exists*/
1439 #ifndef WESTBRIDGE_NDEBUG
1440 cy_as_hal_print_message(
1441 "<*>%s: bmap found, i_bytes=0x%x, "
1442 "i_size=0x%x, i_blocks=0x%x\n",
1443 __func__, inode->i_bytes,
1444 (unsigned int) inode->i_size,
1445 (unsigned int) inode->i_blocks);
1448 k_d.num_bytes = inode->i_size;
1450 #ifndef WESTBRIDGE_NDEBUG
1451 cy_as_hal_print_message(
1452 "<*>%s: k_d.num_bytes=0x%x\n",
1453 __func__, k_d.num_bytes);
1456 for (file_block_idx = 0;
1457 file_block_idx < inode->i_size;
1460 a_ops->bmap(mapping,
1463 if (curr_blk_addr_map == 0) {
1464 /*no valid mapping*/
1465 #ifndef WESTBRIDGE_NDEBUG
1466 cy_as_hal_print_message(
1468 "mapping\n", __func__);
1471 } else if (curr_blk_addr_map !=
1472 (last_blk_addr_map + 1)) {
1473 /*non-contiguous break*/
1475 blk_table.start_blocks
1478 blk_table.num_blocks
1480 #ifndef WESTBRIDGE_NDEBUG
1481 cy_as_hal_print_message(
1487 /*add contiguous block*/
1488 blk_table.num_blocks
1491 last_blk_addr_map = curr_blk_addr_map;
1494 /*print result for verification*/
1495 #ifndef WESTBRIDGE_NDEBUG
1499 for (i = 0 ; i <= blk_table_idx; i++) {
1500 cy_as_hal_print_message(
1501 "%s %d 0x%x 0x%x\n",
1503 blk_table.start_blocks[i],
1504 blk_table.num_blocks[i]);
1509 #ifndef WESTBRIDGE_NDEBUG
1510 cy_as_hal_print_message(
1511 "%s: could not find "
1512 "a_ops->bmap\n", __func__);
1517 filp_close(file_to_map, NULL);
1519 dev->tmtp_get_complete = 0 ;
1520 dev->tmtp_need_new_blk_tbl = 0 ;
1522 ret_stat = __put_user(
1523 blk_table.start_blocks[blk_table_idx],
1524 (uint32_t __user *)(&(usr_d->blk_addr_p)));
1526 ret_stat = __put_user(
1527 blk_table.num_blocks[blk_table_idx],
1528 (uint32_t __user *)(&(usr_d->blk_count_p)));
1530 sg_init_one(&sg, &blk_table, sizeof(blk_table));
1532 #ifndef WESTBRIDGE_NDEBUG
1533 cy_as_hal_print_message(
1534 "%s: calling cy_as_mtp_init_get_object() "
1535 "start=0x%x, num =0x%x, tid=0x%x, "
1538 blk_table.start_blocks[0],
1539 blk_table.num_blocks[0],
1544 ret_stat = cy_as_mtp_init_get_object(
1546 (cy_as_mtp_block_table *)&sg,
1547 k_d.num_bytes, k_d.tid, 0, 0);
1548 if (ret_stat != CY_AS_ERROR_SUCCESS) {
1549 #ifndef WESTBRIDGE_NDEBUG
1550 cy_as_hal_print_message(
1551 "%s: cy_as_mtp_init_get_object "
1552 "failed ret_stat=0x%x\n",
1553 __func__, ret_stat);
1557 #ifndef WESTBRIDGE_NDEBUG
1559 cy_as_hal_print_message(
1560 "%s: failed to open file %s\n",
1561 __func__, map_filename);
1566 retval = __put_user(ret_stat, (uint32_t __user *)
1567 (&(usr_d->ret_val)));
1570 case CYASGADGET_CANCELSOJ:
1572 cy_as_gadget_ioctl_cancel *usr_d =
1573 (cy_as_gadget_ioctl_cancel *)param ;
1575 #ifndef WESTBRIDGE_NDEBUG
1576 cy_as_hal_print_message(
1577 "%s: got CYASGADGET_CANCELSOJ\n",
1581 ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0);
1583 retval = __put_user(ret_stat, (uint32_t __user *)
1584 (&(usr_d->ret_val)));
1587 case CYASGADGET_CANCELGOJ:
1589 cy_as_gadget_ioctl_cancel *usr_d =
1590 (cy_as_gadget_ioctl_cancel *)param ;
1592 #ifndef WESTBRIDGE_NDEBUG
1593 cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n",
1597 ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0);
1599 retval = __put_user(ret_stat,
1600 (uint32_t __user *)(&(usr_d->ret_val)));
1605 #ifndef WESTBRIDGE_NDEBUG
1606 cy_as_hal_print_message("%s: unknown ioctl received: %d\n",
1609 cy_as_hal_print_message("%s: known codes:\n"
1610 "CYASGADGET_GETMTPSTATUS=%d\n"
1611 "CYASGADGET_CLEARTMTPSTATUS=%d\n"
1612 "CYASGADGET_INITSOJ=%d\n"
1613 "CYASGADGET_INITGOJ=%d\n"
1614 "CYASGADGET_CANCELSOJ=%d\n"
1615 "CYASGADGET_CANCELGOJ=%d\n",
1617 CYASGADGET_GETMTPSTATUS,
1618 CYASGADGET_CLEARTMTPSTATUS,
1621 CYASGADGET_CANCELSOJ,
1622 CYASGADGET_CANCELGOJ);
1631 static const struct usb_gadget_ops cyasgadget_ops = {
1632 .get_frame = cyasgadget_get_frame,
1633 .wakeup = cyasgadget_wakeup,
1634 .set_selfpowered = cyasgadget_set_selfpowered,
1635 .pullup = cyasgadget_pullup,
1636 .ioctl = cyasgadget_ioctl,
1640 /* keeping it simple:
1641 * - one bus driver, initted first;
1642 * - one function driver, initted second
1644 * most of the work to support multiple controllers would
1645 * be to associate this gadget driver with all of them, or
1646 * perhaps to bind specific drivers to specific devices.
1649 static void cyas_ep_reset(
1650 cyasgadget_ep *an_ep
1653 #ifndef WESTBRIDGE_NDEBUG
1654 cy_as_hal_print_message("<1>%s called\n", __func__);
1658 INIT_LIST_HEAD(&an_ep->queue);
1660 an_ep->stopped = 0 ;
1663 an_ep->usb_ep_inst.maxpacket = ~0;
1664 an_ep->usb_ep_inst.ops = &cyasgadget_ep_ops;
1667 static void cyas_usb_reset(
1668 cyasgadget *cy_as_dev
1671 cy_as_return_status_t ret;
1672 cy_as_usb_enum_control config ;
1674 #ifndef WESTBRIDGE_NDEBUG
1675 cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ;
1677 cy_as_hal_print_message("<1>%s called mtp_firmware=0x%x\n",
1678 __func__, dev_p->is_mtp_firmware);
1681 ret = cy_as_misc_release_resource(cy_as_dev->dev_handle,
1683 if (ret != CY_AS_ERROR_SUCCESS && ret !=
1684 CY_AS_ERROR_RESOURCE_NOT_OWNED) {
1685 cy_as_hal_print_message("<1>_cy_as_gadget: cannot "
1686 "release usb resource: failed with error code %d\n",
1691 cy_as_dev->gadget.speed = USB_SPEED_HIGH ;
1693 ret = cy_as_usb_start(cy_as_dev->dev_handle, 0, 0) ;
1694 if (ret != CY_AS_ERROR_SUCCESS) {
1695 cy_as_hal_print_message("<1>_cy_as_gadget: "
1696 "cy_as_usb_start failed with error code %d\n",
1700 /* P port will do enumeration, not West Bridge */
1701 config.antioch_enumeration = cy_false ;
1702 /* 1 2 : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/
1704 /* TODO: add module param to enumerate mass storage */
1705 config.mass_storage_interface = 0 ;
1708 ret = cy_as_mtp_start(cy_as_dev->dev_handle,
1709 cy_as_gadget_mtp_event_callback, 0, 0);
1710 if (ret == CY_AS_ERROR_SUCCESS) {
1711 cy_as_hal_print_message("MTP start passed, enumerating "
1713 config.mtp_interface = append_mtp ;
1714 /*Do not enumerate NAND storage*/
1715 config.devices_to_enumerate[0][0] = cy_false;
1717 /*enumerate SD storage as MTP*/
1718 config.devices_to_enumerate[1][0] = cy_true;
1721 cy_as_hal_print_message("MTP start not attempted, not "
1722 "enumerating MTP interface\n");
1723 config.mtp_interface = 0 ;
1724 /* enumerate mass storage based on module parameters */
1725 config.devices_to_enumerate[0][0] = msc_enum_bus_0;
1726 config.devices_to_enumerate[1][0] = msc_enum_bus_1;
1729 ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle,
1731 if (ret != CY_AS_ERROR_SUCCESS) {
1732 cy_as_hal_print_message("<1>_cy_as_gadget: "
1733 "cy_as_usb_set_enum_config failed with error "
1738 cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1);
1742 static void cyas_usb_reinit(
1743 cyasgadget *cy_as_dev
1747 cyasgadget_ep *an_ep_p;
1748 cy_as_return_status_t ret;
1749 cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ;
1751 INIT_LIST_HEAD(&cy_as_dev->gadget.ep_list);
1753 #ifndef WESTBRIDGE_NDEBUG
1754 cy_as_hal_print_message("<1>%s called, is_mtp_firmware = "
1755 "0x%x\n", __func__, dev_p->is_mtp_firmware);
1758 /* Init the end points */
1759 for (index = 1; index <= 15; index++) {
1760 an_ep_p = &cy_as_dev->an_gadget_ep[index] ;
1761 cyas_ep_reset(an_ep_p) ;
1762 an_ep_p->usb_ep_inst.name = cy_as_ep_names[index] ;
1763 an_ep_p->dev = cy_as_dev ;
1764 an_ep_p->num = index ;
1765 memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig));
1767 /* EP0, EPs 2,4,6,8 need not be added */
1768 if ((index <= 8) && (index % 2 == 0) &&
1769 (!dev_p->is_mtp_firmware)) {
1770 /* EP0 is 64 and EPs 2,4,6,8 not allowed */
1771 cy_as_dev->an_gadget_ep[index].fifo_size = 0 ;
1774 an_ep_p->fifo_size = 64;
1776 an_ep_p->fifo_size = 512 ;
1777 list_add_tail(&an_ep_p->usb_ep_inst.ep_list,
1778 &cy_as_dev->gadget.ep_list);
1781 /* need to setendpointconfig before usb connect, this is not
1782 * quite compatible with gadget methodology (ep_enable called
1783 * by gadget after connect), therefore need to set config in
1784 * initialization and verify compatibility in ep_enable,
1785 * kick up error otherwise*/
1786 an_ep_p = &cy_as_dev->an_gadget_ep[3] ;
1787 an_ep_p->cyepconfig.enabled = cy_true ;
1788 an_ep_p->cyepconfig.dir = cy_as_usb_out ;
1789 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1790 an_ep_p->cyepconfig.size = 0 ;
1791 an_ep_p->cyepconfig.physical = 1 ;
1792 ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1793 3, &an_ep_p->cyepconfig) ;
1794 if (ret != CY_AS_ERROR_SUCCESS) {
1795 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1796 "failed with error code %d\n", ret) ;
1799 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0);
1801 an_ep_p = &cy_as_dev->an_gadget_ep[5] ;
1802 an_ep_p->cyepconfig.enabled = cy_true ;
1803 an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1804 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1805 an_ep_p->cyepconfig.size = 0 ;
1806 an_ep_p->cyepconfig.physical = 2 ;
1807 ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1808 5, &an_ep_p->cyepconfig) ;
1809 if (ret != CY_AS_ERROR_SUCCESS) {
1810 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1811 "failed with error code %d\n", ret) ;
1814 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0);
1816 an_ep_p = &cy_as_dev->an_gadget_ep[9] ;
1817 an_ep_p->cyepconfig.enabled = cy_true ;
1818 an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1819 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1820 an_ep_p->cyepconfig.size = 0 ;
1821 an_ep_p->cyepconfig.physical = 4 ;
1822 ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1823 9, &an_ep_p->cyepconfig) ;
1824 if (ret != CY_AS_ERROR_SUCCESS) {
1825 cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1826 "failed with error code %d\n", ret) ;
1829 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0);
1831 if (dev_p->mtp_count != 0) {
1832 /* these need to be set for compatibility with
1833 * the gadget_enable logic */
1834 an_ep_p = &cy_as_dev->an_gadget_ep[2] ;
1835 an_ep_p->cyepconfig.enabled = cy_true ;
1836 an_ep_p->cyepconfig.dir = cy_as_usb_out ;
1837 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1838 an_ep_p->cyepconfig.size = 0 ;
1839 an_ep_p->cyepconfig.physical = 0 ;
1840 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0);
1842 an_ep_p = &cy_as_dev->an_gadget_ep[6] ;
1843 an_ep_p->cyepconfig.enabled = cy_true ;
1844 an_ep_p->cyepconfig.dir = cy_as_usb_in ;
1845 an_ep_p->cyepconfig.type = cy_as_usb_bulk ;
1846 an_ep_p->cyepconfig.size = 0 ;
1847 an_ep_p->cyepconfig.physical = 0 ;
1848 cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 6, 0, 0);
1851 cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]) ;
1852 cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0] ;
1853 cy_as_dev->an_gadget_ep[0].dev = cy_as_dev ;
1854 cy_as_dev->an_gadget_ep[0].num = 0 ;
1855 cy_as_dev->an_gadget_ep[0].fifo_size = 64 ;
1857 cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64;
1858 cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst;
1859 cy_as_dev->an_gadget_ep[0].stopped = 0;
1860 INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list);
1863 static void cyas_ep0_start(
1867 cy_as_return_status_t ret ;
1869 #ifndef WESTBRIDGE_NDEBUG
1870 cy_as_hal_print_message("<1>%s called\n", __func__);
1873 ret = cy_as_usb_register_callback(dev->dev_handle,
1874 cy_as_gadget_usb_event_callback) ;
1875 if (ret != CY_AS_ERROR_SUCCESS) {
1876 #ifndef WESTBRIDGE_NDEBUG
1877 cy_as_hal_print_message("%s: cy_as_usb_register_callback "
1878 "failed with error code %d\n", __func__, ret) ;
1883 ret = cy_as_usb_commit_config(dev->dev_handle, 0, 0) ;
1884 if (ret != CY_AS_ERROR_SUCCESS) {
1885 #ifndef WESTBRIDGE_NDEBUG
1886 cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1887 "failed with error code %d\n", __func__, ret) ;
1892 #ifndef WESTBRIDGE_NDEBUG
1893 cy_as_hal_print_message("%s: cy_as_usb_commit_config "
1894 "message sent\n", __func__) ;
1897 ret = cy_as_usb_connect(dev->dev_handle, 0, 0) ;
1898 if (ret != CY_AS_ERROR_SUCCESS) {
1899 #ifndef WESTBRIDGE_NDEBUG
1900 cy_as_hal_print_message("%s: cy_as_usb_connect failed "
1901 "with error code %d\n", __func__, ret) ;
1906 #ifndef WESTBRIDGE_NDEBUG
1907 cy_as_hal_print_message("%s: cy_as_usb_connect message "
1908 "sent\n", __func__) ;
1913 * When a driver is successfully registered, it will receive
1914 * control requests including set_configuration(), which enables
1915 * non-control requests. then usb traffic follows until a
1916 * disconnect is reported. then a host may connect again, or
1917 * the driver might get unbound.
1919 int usb_gadget_register_driver(
1920 struct usb_gadget_driver *driver
1923 cyasgadget *dev = cy_as_gadget_controller ;
1926 #ifndef WESTBRIDGE_NDEBUG
1927 cy_as_hal_print_message("<1>%s called driver=0x%x\n",
1928 __func__, (unsigned int) driver);
1931 /* insist on high speed support from the driver, since
1932 * "must not be used in normal operation"
1946 /* hook up the driver ... */
1947 dev->softconnect = 1;
1948 driver->driver.bus = NULL;
1949 dev->driver = driver;
1950 dev->gadget.dev.driver = &driver->driver;
1952 /* Do the needful */
1953 cyas_usb_reset(dev) ; /* External usb */
1954 cyas_usb_reinit(dev) ; /* Internal */
1956 retval = driver->bind(&dev->gadget);
1958 #ifndef WESTBRIDGE_NDEBUG
1959 cy_as_hal_print_message("%s bind to driver %s --> %d\n",
1960 __func__, driver->driver.name, retval);
1964 dev->gadget.dev.driver = NULL;
1968 /* ... then enable host detection and ep0; and we're ready
1969 * for set_configuration as well as eventual disconnect.
1971 cyas_ep0_start(dev);
1975 EXPORT_SYMBOL(usb_gadget_register_driver);
1977 static void cyasgadget_nuke(
1978 cyasgadget_ep *an_ep
1981 cyasgadget *dev = cy_as_gadget_controller ;
1983 #ifndef WESTBRIDGE_NDEBUG
1984 cy_as_hal_print_message("<1>%s called\n", __func__);
1987 cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
1988 an_ep->stopped = 1 ;
1990 while (!list_empty(&an_ep->queue)) {
1991 cyasgadget_req *an_req = list_entry
1992 (an_ep->queue.next, cyasgadget_req, queue) ;
1993 list_del_init(&an_req->queue) ;
1994 an_req->req.status = -ESHUTDOWN ;
1995 an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req) ;
1999 static void cyasgadget_stop_activity(
2001 struct usb_gadget_driver *driver
2006 #ifndef WESTBRIDGE_NDEBUG
2007 cy_as_hal_print_message("<1>%s called\n", __func__);
2010 /* don't disconnect if it's not connected */
2011 if (dev->gadget.speed == USB_SPEED_UNKNOWN)
2014 if (spin_is_locked(&dev->lock))
2015 spin_unlock(&dev->lock);
2017 /* Stop hardware; prevent new request submissions;
2018 * and kill any outstanding requests.
2020 cy_as_usb_disconnect(dev->dev_handle, 0, 0) ;
2022 for (index = 3; index <= 7; index += 2) {
2023 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ;
2024 cyasgadget_nuke(an_ep_p) ;
2027 for (index = 9; index <= 15; index++) {
2028 cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ;
2029 cyasgadget_nuke(an_ep_p) ;
2032 /* report disconnect; the driver is already quiesced */
2034 driver->disconnect(&dev->gadget);
2036 #ifndef WESTBRIDGE_NDEBUG
2037 cy_as_hal_print_message("cy_as_usb_disconnect returned success");
2041 cy_as_usb_stop(dev->dev_handle, 0, 0) ;
2043 #ifndef WESTBRIDGE_NDEBUG
2044 cy_as_hal_print_message("cy_as_usb_stop returned success");
2048 int usb_gadget_unregister_driver(
2049 struct usb_gadget_driver *driver
2052 cyasgadget *dev = cy_as_gadget_controller ;
2054 #ifndef WESTBRIDGE_NDEBUG
2055 cy_as_hal_print_message("<1>%s called\n", __func__);
2061 if (!driver || driver != dev->driver)
2064 cyasgadget_stop_activity(dev, driver);
2066 driver->unbind(&dev->gadget);
2067 dev->gadget.dev.driver = NULL;
2070 #ifndef WESTBRIDGE_NDEBUG
2071 cy_as_hal_print_message("unregistered driver '%s'\n",
2072 driver->driver.name) ;
2077 EXPORT_SYMBOL(usb_gadget_unregister_driver);
2079 static void cyas_gadget_release(
2083 cyasgadget *dev = dev_get_drvdata(_dev);
2085 #ifndef WESTBRIDGE_NDEBUG
2086 cy_as_hal_print_message("<1>%s called\n", __func__);
2092 /* DeInitialize gadget driver */
2093 static void cyasgadget_deinit(
2094 cyasgadget *cy_as_dev
2097 #ifndef WESTBRIDGE_NDEBUG
2098 cy_as_hal_print_message("<1>_cy_as_gadget deinitialize called\n") ;
2102 #ifndef WESTBRIDGE_NDEBUG
2103 cy_as_hal_print_message("<1>_cy_as_gadget_deinit: "
2104 "invalid cyasgadget device\n") ;
2109 if (cy_as_dev->driver) {
2110 /* should have been done already by driver model core */
2111 #ifndef WESTBRIDGE_NDEBUG
2112 cy_as_hal_print_message("<1> cy_as_gadget: '%s' "
2113 "is still registered\n",
2114 cy_as_dev->driver->driver.name);
2116 usb_gadget_unregister_driver(cy_as_dev->driver);
2120 cy_as_gadget_controller = NULL ;
2123 /* Initialize gadget driver */
2124 static int cyasgadget_initialize(void)
2126 cyasgadget *cy_as_dev = 0 ;
2129 #ifndef WESTBRIDGE_NDEBUG
2130 cy_as_hal_print_message("<1>_cy_as_gadget [V1.1] initialize called\n") ;
2133 if (cy_as_gadget_controller != 0) {
2134 cy_as_hal_print_message("<1> cy_as_gadget: the device has "
2135 "already been initilaized. ignoring\n") ;
2139 cy_as_dev = kzalloc(sizeof(cyasgadget), GFP_ATOMIC);
2140 if (cy_as_dev == NULL) {
2141 cy_as_hal_print_message("<1> cy_as_gadget: memory "
2142 "allocation failed\n") ;
2146 spin_lock_init(&cy_as_dev->lock);
2147 cy_as_dev->gadget.ops = &cyasgadget_ops;
2148 cy_as_dev->gadget.is_dualspeed = 1;
2150 /* the "gadget" abstracts/virtualizes the controller */
2151 /*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/
2152 cy_as_dev->gadget.dev.release = cyas_gadget_release;
2153 cy_as_dev->gadget.name = cy_as_driver_name;
2155 /* Get the device handle */
2156 cy_as_dev->dev_handle = cyasdevice_getdevhandle() ;
2157 if (0 == cy_as_dev->dev_handle) {
2159 cy_as_hal_print_message("<1> cy_as_gadget: "
2160 "no west bridge device\n") ;
2166 /* We are done now */
2167 cy_as_gadget_controller = cy_as_dev ;
2171 * in case of an error
2175 cyasgadget_deinit(cy_as_dev) ;
2180 static int __init cyas_init(void)
2184 init_res = cyasgadget_initialize();
2186 if (init_res != 0) {
2187 printk(KERN_WARNING "<1> gadget ctl instance "
2188 "init error:%d\n", init_res);
2190 /* force -E/0 linux convention */
2191 init_res = init_res * -1;
2197 module_init(cyas_init);
2199 static void __exit cyas_cleanup(void)
2201 if (cy_as_gadget_controller != NULL)
2202 cyasgadget_deinit(cy_as_gadget_controller);
2204 module_exit(cyas_cleanup);
2207 MODULE_LICENSE("GPL");
2208 MODULE_DESCRIPTION(CY_AS_DRIVER_DESC);
2209 MODULE_AUTHOR("cypress semiconductor");