linux/drivers/staging/westbridge/astoria/gadget/cyasgadget.c
<<
>>
Prefs
   1/* cyangadget.c - Linux USB Gadget driver file for the Cypress West Bridge
   2## ===========================
   3## Copyright (C) 2010  Cypress Semiconductor
   4##
   5## This program is free software; you can redistribute it and/or
   6## modify it under the terms of the GNU General Public License
   7## as published by the Free Software Foundation; either version 2
   8## of the License, or (at your option) any later version.
   9##
  10## This program is distributed in the hope that it will be useful,
  11## but WITHOUT ANY WARRANTY; without even the implied warranty of
  12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13## GNU General Public License for more details.
  14##
  15## You should have received a copy of the GNU General Public License
  16## along with this program; if not, write to the Free Software
  17## Foundation, Inc., 51 Franklin Street, Fifth Floor
  18## Boston, MA  02110-1301, USA.
  19## ===========================
  20*/
  21
  22/*
  23 * Cypress West Bridge high/full speed usb device controller code
  24 * Based on the Netchip 2280 device controller by David Brownell
  25 * in the linux 2.6.10 kernel
  26 *
  27 * linux/drivers/usb/gadget/net2280.c
  28 */
  29
  30/*
  31 * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
  32 * Copyright (C) 2003 David Brownell
  33 *
  34 * This program is free software; you can redistribute it and/or modify
  35 * it under the terms of the GNU General Public License as published by
  36 * the Free Software Foundation; either version 2 of the License, or
  37 * (at your option) any later version.
  38 *
  39 * This program is distributed in the hope that it will be useful,
  40 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  42 * GNU General Public License for more details.
  43 *
  44 * You should have received a copy of the GNU General Public License
  45 * along with this program; if not, write to the Free Software
  46 * Foundation, Inc., 59 Temple Place, Suite 330
  47 * Boston, MA  02111-1307  USA
  48 */
  49
  50#include "cyasgadget.h"
  51
  52#define CY_AS_DRIVER_DESC               "cypress west bridge usb gadget"
  53#define CY_AS_DRIVER_VERSION            "REV B"
  54#define DMA_ADDR_INVALID                        (~(dma_addr_t)0)
  55
  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/* forward declarations */
  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/* variables */
  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/* all Callbacks are placed in this subsection*/
 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        /* cy_as_dev = container_of(h, cyasgadget, dev_handle); */
 114        cy_as_dev = cy_as_gadget_controller;
 115        switch (ev) {
 116        case cy_as_event_usb_suspend:
 117                #ifndef WESTBRIDGE_NDEBUG
 118                cy_as_hal_print_message(
 119                        "<1>_cy_as_event_usb_suspend received\n");
 120                #endif
 121                cy_as_dev->driver->suspend(&cy_as_dev->gadget);
 122                break;
 123
 124        case cy_as_event_usb_resume:
 125                #ifndef WESTBRIDGE_NDEBUG
 126                cy_as_hal_print_message(
 127                        "<1>_cy_as_event_usb_resume received\n");
 128                #endif
 129                cy_as_dev->driver->resume(&cy_as_dev->gadget);
 130                break;
 131
 132        case cy_as_event_usb_reset:
 133                #ifndef WESTBRIDGE_NDEBUG
 134                cy_as_hal_print_message(
 135                        "<1>_cy_as_event_usb_reset received\n");
 136                #endif
 137                break;
 138
 139        case cy_as_event_usb_speed_change:
 140                #ifndef WESTBRIDGE_NDEBUG
 141                cy_as_hal_print_message(
 142                        "<1>_cy_as_event_usb_speed_change received\n");
 143                #endif
 144                break;
 145
 146        case cy_as_event_usb_set_config:
 147                #ifndef WESTBRIDGE_NDEBUG
 148                cy_as_hal_print_message(
 149                        "<1>_cy_as_event_usb_set_config received\n");
 150                #endif
 151                break;
 152
 153        case cy_as_event_usb_setup_packet:
 154                #ifndef WESTBRIDGE_NDEBUG
 155                ctrlreq = (struct usb_ctrlrequest *)evdata;
 156
 157                cy_as_hal_print_message("<1>_cy_as_event_usb_setup_packet "
 158                                                        "received"
 159                                                        "bRequestType=0x%x,"
 160                                                        "bRequest=0x%x,"
 161                                                        "wValue=x%x,"
 162                                                        "wIndex=0x%x,"
 163                                                        "wLength=0x%x,",
 164                                                        ctrlreq->bRequestType,
 165                                                        ctrlreq->bRequest,
 166                                                        ctrlreq->wValue,
 167                                                        ctrlreq->wIndex,
 168                                                        ctrlreq->wLength
 169                                                        );
 170                #endif
 171                cy_as_dev->outsetupreq = 0;
 172                if ((((uint8_t *)evdata)[0] & USB_DIR_IN) == USB_DIR_OUT)
 173                        cy_as_dev->outsetupreq = 1;
 174                cy_as_dev->driver->setup(&cy_as_dev->gadget,
 175                        (struct usb_ctrlrequest *)evdata);
 176                break;
 177
 178        case cy_as_event_usb_status_packet:
 179                #ifndef WESTBRIDGE_NDEBUG
 180                cy_as_hal_print_message(
 181                        "<1>_cy_as_event_usb_status_packet received\n");
 182                #endif
 183                break;
 184
 185        case cy_as_event_usb_inquiry_before:
 186                #ifndef WESTBRIDGE_NDEBUG
 187                cy_as_hal_print_message(
 188                        "<1>_cy_as_event_usb_inquiry_before received\n");
 189                #endif
 190                break;
 191
 192        case cy_as_event_usb_inquiry_after:
 193                #ifndef WESTBRIDGE_NDEBUG
 194                cy_as_hal_print_message(
 195                        "<1>_cy_as_event_usb_inquiry_after received\n");
 196                #endif
 197                break;
 198
 199        case cy_as_event_usb_start_stop:
 200                #ifndef WESTBRIDGE_NDEBUG
 201                cy_as_hal_print_message(
 202                        "<1>_cy_as_event_usb_start_stop received\n");
 203                #endif
 204                break;
 205
 206        default:
 207                break;
 208        }
 209}
 210
 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/*called when the write of a setup packet has been completed*/
 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/* called when a read operation has completed.*/
 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        /* We need to call ReadAsync on this end-point
 434         * again, so as to not miss any data packets. */
 435        if (!an_ep->stopped) {
 436                spin_lock_irqsave(&cy_as_dev->lock, flags);
 437                an_req = 0;
 438                if (!list_empty(&an_ep->queue))
 439                        an_req = list_entry(an_ep->queue.next,
 440                                cyasgadget_req, queue);
 441
 442                spin_unlock_irqrestore(&cy_as_dev->lock, flags);
 443
 444                if ((an_req) && (an_req->req.status == -EINPROGRESS)) {
 445                        ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
 446                                an_ep->num, cy_false, an_req->req.length,
 447                                an_req->req.buf, cyasgadget_readcallback);
 448
 449                        if (ret != CY_AS_ERROR_SUCCESS)
 450                                cy_as_hal_print_message("<1>_cy_as_gadget: "
 451                                        "cy_as_usb_read_data_async failed "
 452                                        "with error code %d\n", ret);
 453                        else
 454                                an_req->req.status = -EALREADY;
 455                }
 456        }
 457}
 458
 459/* function is called when a usb write operation has completed*/
 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        /* Verify the status value before setting req.status to zero */
 499        if (status == CY_AS_ERROR_SUCCESS)
 500                an_req->req.status = 0;
 501        else
 502                an_req->req.status = -status;
 503
 504        an_ep->stopped = 1;
 505
 506        spin_unlock_irqrestore(&cy_as_dev->lock, flags);
 507
 508        an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
 509        an_ep->stopped = stopped;
 510
 511        /* We need to call WriteAsync on this end-point again, so as to not
 512           miss any data packets. */
 513        if (!an_ep->stopped) {
 514                spin_lock_irqsave(&cy_as_dev->lock, flags);
 515                an_req = 0;
 516                if (!list_empty(&an_ep->queue))
 517                        an_req = list_entry(an_ep->queue.next,
 518                                cyasgadget_req, queue);
 519                spin_unlock_irqrestore(&cy_as_dev->lock, flags);
 520
 521                if ((an_req) && (an_req->req.status == -EINPROGRESS)) {
 522                        ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
 523                                an_ep->num, an_req->req.length, an_req->req.buf,
 524                                cy_false, cyasgadget_writecallback);
 525
 526                        if (ret != CY_AS_ERROR_SUCCESS)
 527                                cy_as_hal_print_message("<1>_cy_as_gadget: "
 528                                        "cy_as_usb_write_data_async "
 529                                        "failed with error code %d\n", ret);
 530                        else
 531                                an_req->req.status = -EALREADY;
 532                }
 533        }
 534}
 535
 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/* All usb_ep_ops (cyasgadget_ep_ops) are placed in this subsection*/
 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        /* ep_reset() has already been called */
 581        an_ep->stopped = 0;
 582        an_ep->out_overflow = 0;
 583
 584        if (an_ep->cyepconfig.enabled != cy_true) {
 585                #ifndef WESTBRIDGE_NDEBUG
 586                cy_as_hal_print_message("<1>_cy_as_gadget: "
 587                        "cy_as_usb_end_point_config EP %s mismatch "
 588                        "on enabled\n", an_ep->usb_ep_inst.name);
 589                #endif
 590                spin_unlock_irqrestore(&an_dev->lock, flags);
 591                return -EINVAL;
 592        }
 593
 594        tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
 595        an_ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
 596
 597        spin_unlock_irqrestore(&an_dev->lock, flags);
 598
 599        switch (tmp) {
 600        case USB_ENDPOINT_XFER_ISOC:
 601                if (an_ep->cyepconfig.type != cy_as_usb_iso) {
 602                        #ifndef WESTBRIDGE_NDEBUG
 603                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 604                                "cy_as_usb_end_point_config EP %s mismatch "
 605                                "on type %d %d\n", an_ep->usb_ep_inst.name,
 606                                an_ep->cyepconfig.type, cy_as_usb_iso);
 607                        #endif
 608                        return -EINVAL;
 609                }
 610                break;
 611        case USB_ENDPOINT_XFER_INT:
 612                if (an_ep->cyepconfig.type != cy_as_usb_int) {
 613                        #ifndef WESTBRIDGE_NDEBUG
 614                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 615                                "cy_as_usb_end_point_config EP %s mismatch "
 616                                "on type %d %d\n", an_ep->usb_ep_inst.name,
 617                                an_ep->cyepconfig.type, cy_as_usb_int);
 618                        #endif
 619                        return -EINVAL;
 620                }
 621                break;
 622        default:
 623                if (an_ep->cyepconfig.type != cy_as_usb_bulk) {
 624                        #ifndef WESTBRIDGE_NDEBUG
 625                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 626                                "cy_as_usb_end_point_config EP %s mismatch "
 627                                "on type %d %d\n", an_ep->usb_ep_inst.name,
 628                                an_ep->cyepconfig.type, cy_as_usb_bulk);
 629                        #endif
 630                        return -EINVAL;
 631                }
 632                break;
 633        }
 634
 635        tmp = desc->bEndpointAddress;
 636        an_ep->is_in = (tmp & USB_DIR_IN) != 0;
 637
 638        if ((an_ep->cyepconfig.dir == cy_as_usb_in) &&
 639        (!an_ep->is_in)) {
 640                #ifndef WESTBRIDGE_NDEBUG
 641                cy_as_hal_print_message("<1>_cy_as_gadget: "
 642                        "cy_as_usb_end_point_config EP %s mismatch "
 643                        "on dir %d %d\n", an_ep->usb_ep_inst.name,
 644                        an_ep->cyepconfig.dir, cy_as_usb_in);
 645                #endif
 646                return -EINVAL;
 647        } else if ((an_ep->cyepconfig.dir == cy_as_usb_out) &&
 648        (an_ep->is_in)) {
 649                #ifndef WESTBRIDGE_NDEBUG
 650                cy_as_hal_print_message("<1>_cy_as_gadget: "
 651                        "cy_as_usb_end_point_config EP %s mismatch "
 652                        "on dir %d %d\n", an_ep->usb_ep_inst.name,
 653                        an_ep->cyepconfig.dir, cy_as_usb_out);
 654                #endif
 655                return -EINVAL;
 656        }
 657
 658        cy_as_usb_clear_stall(an_dev->dev_handle, an_ep->num,
 659                cyasgadget_stallcallback, 0);
 660
 661        cy_as_hal_print_message("%s enabled %s (ep%d-%d) max %04x\n",
 662                __func__, _ep->name, an_ep->num, tmp, max);
 663
 664        return 0;
 665}
 666
 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/* Load a packet into the fifo we use for usb IN transfers.
 723 * works for all endpoints. */
 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        /* Call Async functions */
 759        if (as_ep->is_in) {
 760                #ifndef WESTBRIDGE_NDEBUG
 761                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 762                                "cy_as_usb_write_data_async being called "
 763                                "on ep %d\n", as_ep->num);
 764                #endif
 765
 766                ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
 767                        as_ep->num, _req->length, _req->buf,
 768                        cy_false, cyasgadget_writecallback);
 769                if (ret != CY_AS_ERROR_SUCCESS)
 770                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 771                                "cy_as_usb_write_data_async failed with "
 772                                "error code %d\n", ret);
 773                else
 774                        _req->status = -EALREADY;
 775        } else if (as_ep->num == 0) {
 776                /*
 777                ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
 778                        as_ep->num, _req->length, _req->buf, cy_false,
 779                        cyasgadget_setupwritecallback);
 780
 781                if (ret != CY_AS_ERROR_SUCCESS)
 782                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 783                                "cy_as_usb_write_data_async failed with error "
 784                                "code %d\n", ret);
 785                */
 786                if ((cy_as_dev->outsetupreq) && (_req->length)) {
 787                        #ifndef WESTBRIDGE_NDEBUG
 788                                cy_as_hal_print_message("<1>_cy_as_gadget: "
 789                                        "cy_as_usb_read_data_async "
 790                                        "being called on ep %d\n",
 791                                        as_ep->num);
 792                        #endif
 793
 794                        ret = cy_as_usb_read_data_async (
 795                                cy_as_dev->dev_handle, as_ep->num,
 796                                cy_true, _req->length, _req->buf,
 797                                cyasgadget_setupreadcallback);
 798
 799                        if (ret != CY_AS_ERROR_SUCCESS)
 800                                cy_as_hal_print_message("<1>_cy_as_gadget: "
 801                                "cy_as_usb_read_data_async failed with "
 802                                "error code %d\n", ret);
 803
 804                } else {
 805                        #ifndef WESTBRIDGE_NDEBUG
 806                                cy_as_hal_print_message("<1>_cy_as_gadget: "
 807                                        "cy_as_usb_write_data_async "
 808                                        "being called on ep %d\n",
 809                                        as_ep->num);
 810                        #endif
 811
 812                        ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
 813                        as_ep->num, _req->length, _req->buf, cy_false,
 814                        cyasgadget_setupwritecallback);
 815
 816                        if (ret != CY_AS_ERROR_SUCCESS)
 817                                cy_as_hal_print_message("<1>_cy_as_gadget: "
 818                                "cy_as_usb_write_data_async failed with "
 819                                "error code %d\n", ret);
 820                }
 821
 822        } else if (list_empty(&as_ep->queue)) {
 823                #ifndef WESTBRIDGE_NDEBUG
 824                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 825                                "cy_as_usb_read_data_async being called since "
 826                                "ep queue empty%d\n", ret);
 827                #endif
 828
 829                ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
 830                        as_ep->num, cy_false, _req->length, _req->buf,
 831                        cyasgadget_readcallback);
 832                if (ret != CY_AS_ERROR_SUCCESS)
 833                        cy_as_hal_print_message("<1>_cy_as_gadget: "
 834                                "cy_as_usb_read_data_async failed with error "
 835                                "code %d\n", ret);
 836                else
 837                        _req->status = -EALREADY;
 838        }
 839
 840        spin_lock_irqsave(&cy_as_dev->lock, flags);
 841
 842        if (as_req)
 843                list_add_tail(&as_req->queue, &as_ep->queue);
 844
 845        spin_unlock_irqrestore(&cy_as_dev->lock, flags);
 846
 847        return 0;
 848}
 849
 850/* dequeue request */
 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 /* not ep0 */ &&
 891        (an_ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC)
 892                return -EINVAL;
 893
 894        if (!list_empty(&an_ep->queue))
 895                retval = -EAGAIN;
 896        else if (an_ep->is_in && value &&
 897                cyasgadget_fifo_status(_ep) != 0)
 898                        retval = -EAGAIN;
 899        else {
 900                if (value) {
 901                        cy_as_usb_set_stall(an_ep->dev->dev_handle,
 902                                an_ep->num, cyasgadget_stallcallback, 0);
 903                } else {
 904                        cy_as_usb_clear_stall(an_ep->dev->dev_handle,
 905                                an_ep->num, cyasgadget_stallcallback, 0);
 906                }
 907        }
 908
 909        return retval;
 910}
 911
 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/*This subsection contains all usb_gadget_ops cyasgadget_ops */
 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         * extract the type and number bitfields, and don't decode
1024         * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
1025         */
1026        if (_IOC_TYPE(code) != CYASGADGET_IOC_MAGIC) {
1027                #ifndef WESTBRIDGE_NDEBUG
1028                cy_as_hal_print_message("%s, bad magic number = 0x%x\n",
1029                        __func__, _IOC_TYPE(code));
1030                #endif
1031                return -ENOTTY;
1032        }
1033
1034        if (_IOC_NR(code) > CYASGADGET_IOC_MAXNR) {
1035                #ifndef WESTBRIDGE_NDEBUG
1036                cy_as_hal_print_message("%s, bad ioctl code = 0x%x\n",
1037                        __func__, _IOC_NR(code));
1038                #endif
1039                return -ENOTTY;
1040        }
1041
1042        /*
1043         * the direction is a bitmask, and VERIFY_WRITE catches R/W
1044         * transfers. `Type' is user-oriented, while
1045         * access_ok is kernel-oriented, so the concept of "read" and
1046         * "write" is reversed
1047         */
1048        if (_IOC_DIR(code) & _IOC_READ)
1049                err = !access_ok(VERIFY_WRITE,
1050                        (void __user *)param, _IOC_SIZE(code));
1051        else if (_IOC_DIR(code) & _IOC_WRITE)
1052                err =  !access_ok(VERIFY_READ,
1053                        (void __user *)param, _IOC_SIZE(code));
1054
1055        if (err) {
1056                cy_as_hal_print_message("%s, bad ioctl dir = 0x%x\n",
1057                        __func__, _IOC_DIR(code));
1058                return -EFAULT;
1059        }
1060
1061        switch (code) {
1062        case CYASGADGET_GETMTPSTATUS:
1063                {
1064                cy_as_gadget_ioctl_tmtp_status *usr_d =
1065                        (cy_as_gadget_ioctl_tmtp_status *)param;
1066
1067                #ifndef WESTBRIDGE_NDEBUG
1068                cy_as_hal_print_message("%s: got CYASGADGET_GETMTPSTATUS\n",
1069                        __func__);
1070                #endif
1071
1072                retval = __put_user(dev->tmtp_send_complete,
1073                        (uint32_t __user *)(&(usr_d->tmtp_send_complete)));
1074                retval = __put_user(dev->tmtp_get_complete,
1075                        (uint32_t __user *)(&(usr_d->tmtp_get_complete)));
1076                retval = __put_user(dev->tmtp_need_new_blk_tbl,
1077                        (uint32_t __user *)(&(usr_d->tmtp_need_new_blk_tbl)));
1078
1079                if (copy_to_user((&(usr_d->tmtp_send_complete_data)),
1080                        (&(dev->tmtp_send_complete_data)),
1081                        sizeof(cy_as_gadget_ioctl_send_object)))
1082                        return -EFAULT;
1083
1084                if (copy_to_user((&(usr_d->tmtp_get_complete_data)),
1085                        (&(dev->tmtp_get_complete_data)),
1086                        sizeof(cy_as_gadget_ioctl_get_object)))
1087                        return -EFAULT;
1088                break;
1089                }
1090        case CYASGADGET_CLEARTMTPSTATUS:
1091                {
1092                #ifndef WESTBRIDGE_NDEBUG
1093                cy_as_hal_print_message("%s got CYASGADGET_CLEARTMTPSTATUS\n",
1094                        __func__);
1095                #endif
1096
1097                dev->tmtp_send_complete = 0;
1098                dev->tmtp_get_complete = 0;
1099                dev->tmtp_need_new_blk_tbl = 0;
1100
1101                break;
1102                }
1103        case CYASGADGET_INITSOJ:
1104                {
1105                cy_as_gadget_ioctl_i_s_o_j_d k_d;
1106                cy_as_gadget_ioctl_i_s_o_j_d *usr_d =
1107                        (cy_as_gadget_ioctl_i_s_o_j_d *)param;
1108                cy_as_mtp_block_table blk_table;
1109                struct scatterlist sg;
1110                char *alloc_filename;
1111                struct file *file_to_allocate;
1112
1113                #ifndef WESTBRIDGE_NDEBUG
1114                cy_as_hal_print_message("%s got CYASGADGET_INITSOJ\n",
1115                        __func__);
1116                #endif
1117
1118                memset(&blk_table, 0, sizeof(blk_table));
1119
1120                /* Get user argument structure  */
1121                if (copy_from_user(&k_d, usr_d,
1122                        sizeof(cy_as_gadget_ioctl_i_s_o_j_d)))
1123                        return -EFAULT;
1124
1125                /* better use fixed size buff*/
1126                alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1127                if (alloc_filename == NULL)
1128                        return -ENOMEM;
1129
1130                /* get the filename */
1131                if (copy_from_user(alloc_filename, k_d.file_name,
1132                        k_d.name_length + 1)) {
1133                        #ifndef WESTBRIDGE_NDEBUG
1134                        cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, "
1135                                "copy file name from user space failed\n",
1136                                __func__);
1137                        #endif
1138                        kfree(alloc_filename);
1139                        return -EFAULT;
1140                }
1141
1142                file_to_allocate = filp_open(alloc_filename, O_RDWR, 0);
1143
1144                if (!IS_ERR(file_to_allocate)) {
1145
1146                        struct address_space *mapping =
1147                                file_to_allocate->f_mapping;
1148                        const struct address_space_operations *a_ops =
1149                                mapping->a_ops;
1150                        struct inode *inode = mapping->host;
1151                        struct inode *alloc_inode =
1152                                file_to_allocate->f_path.dentry->d_inode;
1153                        uint32_t num_clusters = 0;
1154                        struct buffer_head bh;
1155                        struct kstat stat;
1156                        int nr_pages = 0;
1157                        int ret_stat = 0;
1158
1159                        #ifndef WESTBRIDGE_NDEBUG
1160                        cy_as_hal_print_message("%s: fhandle is OK, "
1161                                "calling vfs_getattr\n", __func__);
1162                        #endif
1163
1164                        ret_stat = vfs_getattr(file_to_allocate->f_path.mnt,
1165                                file_to_allocate->f_path.dentry, &stat);
1166
1167                        #ifndef WESTBRIDGE_NDEBUG
1168                        cy_as_hal_print_message("%s: returned from "
1169                                "vfs_getattr() stat->blksize=0x%lx\n",
1170                                __func__, stat.blksize);
1171                        #endif
1172
1173                        /* TODO:  get this from disk properties
1174                         * (from blockdevice)*/
1175                        #define SECTOR_SIZE 512
1176                        if (stat.blksize != 0) {
1177                                num_clusters = (k_d.num_bytes) / SECTOR_SIZE;
1178
1179                                if (((k_d.num_bytes) % SECTOR_SIZE) != 0)
1180                                                num_clusters++;
1181                        } else {
1182                                goto initsoj_safe_exit;
1183                        }
1184
1185                        bh.b_state = 0;
1186                        bh.b_blocknr = 0;
1187                        /* block size is arbitrary , we'll use sector size*/
1188                        bh.b_size = SECTOR_SIZE;
1189
1190
1191
1192                        /* clear dirty pages in page cache
1193                         * (if were any allocated) */
1194                        nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE);
1195
1196                        if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0)
1197                                nr_pages++;
1198
1199                        #ifndef WESTBRIDGE_NDEBUG
1200                        /*check out how many pages where actually allocated */
1201                        if (mapping->nrpages != nr_pages)
1202                                cy_as_hal_print_message("%s mpage_cleardirty "
1203                                        "mapping->nrpages %d != num_pages %d\n",
1204                                        __func__, (int) mapping->nrpages,
1205                                        nr_pages);
1206
1207                                cy_as_hal_print_message("%s: calling "
1208                                        "mpage_cleardirty() "
1209                                        "for %d pages\n", __func__, nr_pages);
1210                        #endif
1211
1212                        ret_stat = mpage_cleardirty(mapping, nr_pages);
1213
1214                        /*fill up the the block table from the addr mapping  */
1215                        if (a_ops->bmap) {
1216                                int8_t blk_table_idx = -1;
1217                                uint32_t file_block_idx = 0;
1218                                uint32_t last_blk_addr_map = 0,
1219                                        curr_blk_addr_map = 0;
1220
1221                                #ifndef WESTBRIDGE_NDEBUG
1222                                if (alloc_inode->i_bytes == 0)
1223                                                cy_as_hal_print_message(
1224                                                "%s: alloc_inode->ibytes =0\n",
1225                                                __func__);
1226                                #endif
1227
1228                                /* iterate through the list of
1229                                 * blocks (not clusters)*/
1230                                for (file_block_idx = 0;
1231                                        file_block_idx < num_clusters
1232                                        /*inode->i_bytes*/; file_block_idx++) {
1233
1234                                        /* returns starting sector number */
1235                                        curr_blk_addr_map =
1236                                                a_ops->bmap(mapping,
1237                                                        file_block_idx);
1238
1239                                        /*no valid mapping*/
1240                                        if (curr_blk_addr_map == 0) {
1241                                                #ifndef WESTBRIDGE_NDEBUG
1242                                                cy_as_hal_print_message(
1243                                                        "%s:hit invalid "
1244                                                        "mapping\n", __func__);
1245                                                #endif
1246                                                break;
1247                                        } else if (curr_blk_addr_map !=
1248                                                (last_blk_addr_map + 1) ||
1249                                                (blk_table.num_blocks
1250                                                [blk_table_idx] == 65535)) {
1251
1252                                                /* next table entry */
1253                                                blk_table_idx++;
1254                                                /* starting sector of a
1255                                                 * scattered cluster*/
1256                                                blk_table.start_blocks
1257                                                        [blk_table_idx] =
1258                                                        curr_blk_addr_map;
1259                                                /* ++ num of blocks in cur
1260                                                 * table entry*/
1261                                                blk_table.
1262                                                num_blocks[blk_table_idx]++;
1263
1264                                                #ifndef WESTBRIDGE_NDEBUG
1265                                                if (file_block_idx != 0)
1266                                                        cy_as_hal_print_message(
1267                                                         "<*> next table "
1268                                                         "entry:%d required\n",
1269                                                         blk_table_idx);
1270                                                #endif
1271                                        } else {
1272                                                /*add contiguous block*/
1273                                                blk_table.num_blocks
1274                                                [blk_table_idx]++;
1275                                        } /*if (curr_blk_addr_map == 0)*/
1276
1277                                        last_blk_addr_map = curr_blk_addr_map;
1278                                } /* end for (file_block_idx = 0; file_block_idx
1279                                < inode->i_bytes;) */
1280
1281                                #ifndef WESTBRIDGE_NDEBUG
1282                                /*print result for verification*/
1283                                {
1284                                        int i;
1285                                        cy_as_hal_print_message(
1286                                                "%s: print block table "
1287                                                "mapping:\n",
1288                                                __func__);
1289                                        for (i = 0; i <= blk_table_idx; i++) {
1290                                                cy_as_hal_print_message(
1291                                                "<1> %d 0x%x 0x%x\n", i,
1292                                                blk_table.start_blocks[i],
1293                                                blk_table.num_blocks[i]);
1294                                        }
1295                                }
1296                                #endif
1297
1298                                /* copy the block table to user
1299                                 * space (for debug purposes) */
1300                                retval = __put_user(
1301                                        blk_table.start_blocks[blk_table_idx],
1302                                        (uint32_t __user *)
1303                                                (&(usr_d->blk_addr_p)));
1304
1305                                retval = __put_user(
1306                                        blk_table.num_blocks[blk_table_idx],
1307                                        (uint32_t __user *)
1308                                                (&(usr_d->blk_count_p)));
1309
1310                                blk_table_idx++;
1311                                retval = __put_user(blk_table_idx,
1312                                        (uint32_t __user *)
1313                                                (&(usr_d->item_count)));
1314
1315                        } /*end if (a_ops->bmap)*/
1316
1317                        filp_close(file_to_allocate, NULL);
1318
1319                        dev->tmtp_send_complete = 0;
1320                        dev->tmtp_need_new_blk_tbl = 0;
1321
1322                        #ifndef WESTBRIDGE_NDEBUG
1323                        cy_as_hal_print_message(
1324                                "%s: calling cy_as_mtp_init_send_object()\n",
1325                                __func__);
1326                        #endif
1327                        sg_init_one(&sg, &blk_table, sizeof(blk_table));
1328                        ret_stat = cy_as_mtp_init_send_object(dev->dev_handle,
1329                                (cy_as_mtp_block_table *)&sg,
1330                                k_d.num_bytes, 0, 0);
1331                        #ifndef WESTBRIDGE_NDEBUG
1332                        cy_as_hal_print_message("%s: returned from "
1333                                "cy_as_mtp_init_send_object()\n", __func__);
1334                        #endif
1335
1336                }
1337                #ifndef WESTBRIDGE_NDEBUG
1338                else {
1339                        cy_as_hal_print_message(
1340                                "%s: failed to allocate the file %s\n",
1341                                __func__, alloc_filename);
1342                } /* end if (file_to_allocate)*/
1343                #endif
1344                kfree(alloc_filename);
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                /* Get user argument sturcutre */
1371                if (copy_from_user(&k_d, usr_d,
1372                        sizeof(cy_as_gadget_ioctl_i_g_o_j_d)))
1373                                return -EFAULT;
1374
1375                map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
1376                if (map_filename == NULL)
1377                        return -ENOMEM;
1378                if (copy_from_user(map_filename, k_d.file_name,
1379                        k_d.name_length + 1)) {
1380                        #ifndef WESTBRIDGE_NDEBUG
1381                        cy_as_hal_print_message("%s: copy file name from "
1382                                "user space failed\n", __func__);
1383                        #endif
1384                        kfree(map_filename);
1385                        return -EFAULT;
1386                }
1387
1388                #ifndef WESTBRIDGE_NDEBUG
1389                cy_as_hal_print_message("<*>%s: opening %s for kernel "
1390                        "mode access map\n", __func__, map_filename);
1391                #endif
1392                file_to_map = filp_open(map_filename, O_RDWR, 0);
1393                if (file_to_map) {
1394                        struct address_space *mapping = file_to_map->f_mapping;
1395                        const struct address_space_operations
1396                                *a_ops = mapping->a_ops;
1397                        struct inode *inode = mapping->host;
1398
1399                        int8_t blk_table_idx = -1;
1400                        uint32_t file_block_idx = 0;
1401                        uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0;
1402
1403                        /*verify operation exists*/
1404                        if (a_ops->bmap) {
1405                                #ifndef WESTBRIDGE_NDEBUG
1406                                cy_as_hal_print_message(
1407                                        "<*>%s: bmap found, i_bytes=0x%x, "
1408                                        "i_size=0x%x, i_blocks=0x%x\n",
1409                                        __func__, inode->i_bytes,
1410                                        (unsigned int) inode->i_size,
1411                                        (unsigned int) inode->i_blocks);
1412                                #endif
1413
1414                                k_d.num_bytes = inode->i_size;
1415
1416                                #ifndef WESTBRIDGE_NDEBUG
1417                                cy_as_hal_print_message(
1418                                        "<*>%s: k_d.num_bytes=0x%x\n",
1419                                        __func__, k_d.num_bytes);
1420                                #endif
1421
1422                                for (file_block_idx = 0;
1423                                        file_block_idx < inode->i_size;
1424                                        file_block_idx++) {
1425                                        curr_blk_addr_map =
1426                                                a_ops->bmap(mapping,
1427                                                        file_block_idx);
1428
1429                                        if (curr_blk_addr_map == 0) {
1430                                                /*no valid mapping*/
1431                                                #ifndef WESTBRIDGE_NDEBUG
1432                                                cy_as_hal_print_message(
1433                                                        "%s: no valid "
1434                                                        "mapping\n", __func__);
1435                                                #endif
1436                                                break;
1437                                        } else if (curr_blk_addr_map !=
1438                                        (last_blk_addr_map + 1)) {
1439                                                /*non-contiguous break*/
1440                                                blk_table_idx++;
1441                                                blk_table.start_blocks
1442                                                        [blk_table_idx] =
1443                                                        curr_blk_addr_map;
1444                                                blk_table.num_blocks
1445                                                        [blk_table_idx]++;
1446                                                #ifndef WESTBRIDGE_NDEBUG
1447                                                cy_as_hal_print_message(
1448                                                        "%s: found non-"
1449                                                        "contiguous break",
1450                                                        __func__);
1451                                                #endif
1452                                        } else {
1453                                                /*add contiguous block*/
1454                                                blk_table.num_blocks
1455                                                        [blk_table_idx]++;
1456                                        }
1457                                        last_blk_addr_map = curr_blk_addr_map;
1458                                }
1459
1460                                /*print result for verification*/
1461                                #ifndef WESTBRIDGE_NDEBUG
1462                                {
1463                                        int i = 0;
1464
1465                                        for (i = 0; i <= blk_table_idx; i++) {
1466                                                cy_as_hal_print_message(
1467                                                "%s %d 0x%x 0x%x\n",
1468                                                __func__, i,
1469                                                blk_table.start_blocks[i],
1470                                                blk_table.num_blocks[i]);
1471                                        }
1472                                }
1473                                #endif
1474                        } else {
1475                                #ifndef WESTBRIDGE_NDEBUG
1476                                cy_as_hal_print_message(
1477                                        "%s: could not find "
1478                                        "a_ops->bmap\n", __func__);
1479                                #endif
1480                                return -EFAULT;
1481                        }
1482
1483                        filp_close(file_to_map, NULL);
1484
1485                        dev->tmtp_get_complete = 0;
1486                        dev->tmtp_need_new_blk_tbl = 0;
1487
1488                        ret_stat = __put_user(
1489                                blk_table.start_blocks[blk_table_idx],
1490                                (uint32_t __user *)(&(usr_d->blk_addr_p)));
1491
1492                        ret_stat = __put_user(
1493                                blk_table.num_blocks[blk_table_idx],
1494                                (uint32_t __user *)(&(usr_d->blk_count_p)));
1495
1496                        sg_init_one(&sg, &blk_table, sizeof(blk_table));
1497
1498                        #ifndef WESTBRIDGE_NDEBUG
1499                        cy_as_hal_print_message(
1500                                "%s: calling cy_as_mtp_init_get_object() "
1501                                "start=0x%x, num =0x%x, tid=0x%x, "
1502                                "num_bytes=0x%x\n",
1503                                __func__,
1504                                blk_table.start_blocks[0],
1505                                blk_table.num_blocks[0],
1506                                k_d.tid,
1507                                k_d.num_bytes);
1508                        #endif
1509
1510                        ret_stat = cy_as_mtp_init_get_object(
1511                                dev->dev_handle,
1512                                (cy_as_mtp_block_table *)&sg,
1513                                k_d.num_bytes, k_d.tid, 0, 0);
1514                        if (ret_stat != CY_AS_ERROR_SUCCESS) {
1515                                        #ifndef WESTBRIDGE_NDEBUG
1516                                        cy_as_hal_print_message(
1517                                                "%s: cy_as_mtp_init_get_object "
1518                                                "failed ret_stat=0x%x\n",
1519                                                __func__, ret_stat);
1520                                        #endif
1521                        }
1522                }
1523                #ifndef WESTBRIDGE_NDEBUG
1524                else {
1525                                cy_as_hal_print_message(
1526                                        "%s: failed to open file %s\n",
1527                                        __func__, map_filename);
1528                }
1529                #endif
1530                kfree(map_filename);
1531
1532                ret_stat = 0;
1533                retval = __put_user(ret_stat, (uint32_t __user *)
1534                        (&(usr_d->ret_val)));
1535                break;
1536                }
1537        case CYASGADGET_CANCELSOJ:
1538                {
1539                cy_as_gadget_ioctl_cancel *usr_d =
1540                        (cy_as_gadget_ioctl_cancel *)param;
1541
1542                #ifndef WESTBRIDGE_NDEBUG
1543                        cy_as_hal_print_message(
1544                                "%s: got CYASGADGET_CANCELSOJ\n",
1545                                __func__);
1546                #endif
1547
1548                ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0);
1549
1550                retval = __put_user(ret_stat, (uint32_t __user *)
1551                        (&(usr_d->ret_val)));
1552                break;
1553                }
1554        case CYASGADGET_CANCELGOJ:
1555                {
1556                cy_as_gadget_ioctl_cancel *usr_d =
1557                        (cy_as_gadget_ioctl_cancel *)param;
1558
1559                #ifndef WESTBRIDGE_NDEBUG
1560                cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n",
1561                        __func__);
1562                #endif
1563
1564                ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0);
1565
1566                retval = __put_user(ret_stat,
1567                        (uint32_t __user *)(&(usr_d->ret_val)));
1568                break;
1569                }
1570        default:
1571                {
1572                #ifndef WESTBRIDGE_NDEBUG
1573                cy_as_hal_print_message("%s: unknown ioctl received: %d\n",
1574                        __func__, code);
1575
1576                cy_as_hal_print_message("%s: known codes:\n"
1577                        "CYASGADGET_GETMTPSTATUS=%d\n"
1578                        "CYASGADGET_CLEARTMTPSTATUS=%d\n"
1579                        "CYASGADGET_INITSOJ=%d\n"
1580                        "CYASGADGET_INITGOJ=%d\n"
1581                        "CYASGADGET_CANCELSOJ=%d\n"
1582                        "CYASGADGET_CANCELGOJ=%d\n",
1583                        __func__,
1584                        CYASGADGET_GETMTPSTATUS,
1585                        CYASGADGET_CLEARTMTPSTATUS,
1586                        CYASGADGET_INITSOJ,
1587                        CYASGADGET_INITGOJ,
1588                        CYASGADGET_CANCELSOJ,
1589                        CYASGADGET_CANCELGOJ);
1590                #endif
1591                break;
1592                }
1593        }
1594
1595        return 0;
1596}
1597
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/* keeping it simple:
1608 * - one bus driver, initted first;
1609 * - one function driver, initted second
1610 *
1611 * most of the work to support multiple controllers would
1612 * be to associate this gadget driver with all of them, or
1613 * perhaps to bind specific drivers to specific devices.
1614 */
1615
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        /* P port will do enumeration, not West Bridge */
1668        config.antioch_enumeration = cy_false;
1669        /*  1  2  : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/
1670
1671        /* TODO: add module param to enumerate mass storage */
1672        config.mass_storage_interface = 0;
1673
1674        if (append_mtp) {
1675                ret = cy_as_mtp_start(cy_as_dev->dev_handle,
1676                        cy_as_gadget_mtp_event_callback, 0, 0);
1677                if (ret == CY_AS_ERROR_SUCCESS)  {
1678                        cy_as_hal_print_message("MTP start passed, enumerating "
1679                                "MTP interface\n");
1680                        config.mtp_interface = append_mtp;
1681                        /*Do not enumerate NAND storage*/
1682                        config.devices_to_enumerate[0][0] = cy_false;
1683
1684                        /*enumerate SD storage as MTP*/
1685                        config.devices_to_enumerate[1][0] = cy_true;
1686                }
1687        } else {
1688                cy_as_hal_print_message("MTP start not attempted, not "
1689                        "enumerating MTP interface\n");
1690                config.mtp_interface = 0;
1691                /* enumerate mass storage based on module parameters */
1692                config.devices_to_enumerate[0][0] = msc_enum_bus_0;
1693                config.devices_to_enumerate[1][0] = msc_enum_bus_1;
1694        }
1695
1696        ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle,
1697                &config, 0, 0);
1698        if (ret != CY_AS_ERROR_SUCCESS) {
1699                cy_as_hal_print_message("<1>_cy_as_gadget: "
1700                        "cy_as_usb_set_enum_config failed with error "
1701                        "code %d\n", ret);
1702                return;
1703        }
1704
1705        cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1);
1706
1707}
1708
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        /* Init the end points */
1726        for (index = 1; index <= 15; index++) {
1727                an_ep_p = &cy_as_dev->an_gadget_ep[index];
1728                cyas_ep_reset(an_ep_p);
1729                an_ep_p->usb_ep_inst.name = cy_as_ep_names[index];
1730                an_ep_p->dev = cy_as_dev;
1731                an_ep_p->num = index;
1732                memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig));
1733
1734                /* EP0, EPs 2,4,6,8 need not be added */
1735                if ((index <= 8) && (index % 2 == 0) &&
1736                        (!dev_p->is_mtp_firmware)) {
1737                        /* EP0 is 64 and EPs 2,4,6,8 not allowed */
1738                        cy_as_dev->an_gadget_ep[index].fifo_size = 0;
1739                } else {
1740                        if (index == 1)
1741                                an_ep_p->fifo_size = 64;
1742                        else
1743                                an_ep_p->fifo_size = 512;
1744                        list_add_tail(&an_ep_p->usb_ep_inst.ep_list,
1745                                &cy_as_dev->gadget.ep_list);
1746                }
1747        }
1748        /* need to setendpointconfig before usb connect, this is not
1749         * quite compatible with gadget methodology (ep_enable called
1750         * by gadget after connect), therefore need to set config in
1751         * initialization and verify compatibility in ep_enable,
1752         * kick up error otherwise*/
1753        an_ep_p = &cy_as_dev->an_gadget_ep[3];
1754        an_ep_p->cyepconfig.enabled = cy_true;
1755        an_ep_p->cyepconfig.dir = cy_as_usb_out;
1756        an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1757        an_ep_p->cyepconfig.size = 0;
1758        an_ep_p->cyepconfig.physical = 1;
1759        ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1760                3, &an_ep_p->cyepconfig);
1761        if (ret != CY_AS_ERROR_SUCCESS) {
1762                cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1763                        "failed with error code %d\n", ret);
1764        }
1765
1766        cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0);
1767
1768        an_ep_p = &cy_as_dev->an_gadget_ep[5];
1769        an_ep_p->cyepconfig.enabled = cy_true;
1770        an_ep_p->cyepconfig.dir = cy_as_usb_in;
1771        an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1772        an_ep_p->cyepconfig.size = 0;
1773        an_ep_p->cyepconfig.physical = 2;
1774        ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1775                5, &an_ep_p->cyepconfig);
1776        if (ret != CY_AS_ERROR_SUCCESS) {
1777                cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1778                        "failed with error code %d\n", ret);
1779        }
1780
1781        cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0);
1782
1783        an_ep_p = &cy_as_dev->an_gadget_ep[9];
1784        an_ep_p->cyepconfig.enabled = cy_true;
1785        an_ep_p->cyepconfig.dir = cy_as_usb_in;
1786        an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1787        an_ep_p->cyepconfig.size = 0;
1788        an_ep_p->cyepconfig.physical = 4;
1789        ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
1790                9, &an_ep_p->cyepconfig);
1791        if (ret != CY_AS_ERROR_SUCCESS) {
1792                cy_as_hal_print_message("cy_as_usb_set_end_point_config "
1793                        "failed with error code %d\n", ret);
1794        }
1795
1796        cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0);
1797
1798        if (dev_p->mtp_count != 0) {
1799                /* these need to be set for compatibility with
1800                 * the gadget_enable logic */
1801                an_ep_p = &cy_as_dev->an_gadget_ep[2];
1802                an_ep_p->cyepconfig.enabled = cy_true;
1803                an_ep_p->cyepconfig.dir = cy_as_usb_out;
1804                an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1805                an_ep_p->cyepconfig.size = 0;
1806                an_ep_p->cyepconfig.physical = 0;
1807                cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0);
1808
1809                an_ep_p = &cy_as_dev->an_gadget_ep[6];
1810                an_ep_p->cyepconfig.enabled = cy_true;
1811                an_ep_p->cyepconfig.dir = cy_as_usb_in;
1812                an_ep_p->cyepconfig.type = cy_as_usb_bulk;
1813                an_ep_p->cyepconfig.size = 0;
1814                an_ep_p->cyepconfig.physical = 0;
1815                cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 6, 0, 0);
1816        }
1817
1818        cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]);
1819        cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0];
1820        cy_as_dev->an_gadget_ep[0].dev = cy_as_dev;
1821        cy_as_dev->an_gadget_ep[0].num = 0;
1822        cy_as_dev->an_gadget_ep[0].fifo_size = 64;
1823
1824        cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64;
1825        cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst;
1826        cy_as_dev->an_gadget_ep[0].stopped = 0;
1827        INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list);
1828}
1829
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 * When a driver is successfully registered, it will receive
1881 * control requests including set_configuration(), which enables
1882 * non-control requests.  then usb traffic follows until a
1883 * disconnect is reported.  then a host may connect again, or
1884 * the driver might get unbound.
1885 */
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        /* insist on high speed support from the driver, since
1898        * "must not be used in normal operation"
1899        */
1900        if (!driver
1901                || !bind
1902                || !driver->unbind
1903                || !driver->setup)
1904                return -EINVAL;
1905
1906        if (!dev)
1907                return -ENODEV;
1908
1909        if (dev->driver)
1910                return -EBUSY;
1911
1912        /* hook up the driver ... */
1913        dev->softconnect = 1;
1914        driver->driver.bus = NULL;
1915        dev->driver = driver;
1916        dev->gadget.dev.driver = &driver->driver;
1917
1918        /* Do the needful */
1919        cyas_usb_reset(dev); /* External usb */
1920        cyas_usb_reinit(dev); /* Internal */
1921
1922        retval = bind(&dev->gadget);
1923        if (retval) {
1924                #ifndef WESTBRIDGE_NDEBUG
1925                cy_as_hal_print_message("%s bind to driver %s --> %d\n",
1926                        __func__, driver->driver.name, retval);
1927                #endif
1928
1929                dev->driver = NULL;
1930                dev->gadget.dev.driver = NULL;
1931                return retval;
1932        }
1933
1934        /* ... then enable host detection and ep0; and we're ready
1935        * for set_configuration as well as eventual disconnect.
1936        */
1937        cyas_ep0_start(dev);
1938
1939        return 0;
1940}
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        /* don't disconnect if it's not connected */
1977        if (dev->gadget.speed == USB_SPEED_UNKNOWN)
1978                driver = NULL;
1979
1980        if (spin_is_locked(&dev->lock))
1981                spin_unlock(&dev->lock);
1982
1983        /* Stop hardware; prevent new request submissions;
1984         * and kill any outstanding requests.
1985         */
1986        cy_as_usb_disconnect(dev->dev_handle, 0, 0);
1987
1988        for (index = 3; index <= 7; index += 2) {
1989                cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index];
1990                cyasgadget_nuke(an_ep_p);
1991        }
1992
1993        for (index = 9; index <= 15; index++) {
1994                cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index];
1995                cyasgadget_nuke(an_ep_p);
1996        }
1997
1998        /* report disconnect; the driver is already quiesced */
1999        if (driver)
2000                driver->disconnect(&dev->gadget);
2001
2002        #ifndef WESTBRIDGE_NDEBUG
2003        cy_as_hal_print_message("cy_as_usb_disconnect returned success");
2004        #endif
2005
2006        /* Stop Usb */
2007        cy_as_usb_stop(dev->dev_handle, 0, 0);
2008
2009        #ifndef WESTBRIDGE_NDEBUG
2010        cy_as_hal_print_message("cy_as_usb_stop returned success");
2011        #endif
2012}
2013
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/* DeInitialize gadget driver  */
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                /* should have been done already by driver model core */
2077                #ifndef WESTBRIDGE_NDEBUG
2078                cy_as_hal_print_message("<1> cy_as_gadget: '%s' "
2079                        "is still registered\n",
2080                        cy_as_dev->driver->driver.name);
2081                #endif
2082                usb_gadget_unregister_driver(cy_as_dev->driver);
2083        }
2084
2085        kfree(cy_as_dev);
2086        cy_as_gadget_controller = NULL;
2087}
2088
2089/* Initialize gadget driver  */
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        /* the "gadget" abstracts/virtualizes the controller */
2117        /*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/
2118        cy_as_dev->gadget.dev.release = cyas_gadget_release;
2119        cy_as_dev->gadget.name = cy_as_driver_name;
2120
2121        /* Get the device handle */
2122        cy_as_dev->dev_handle = cyasdevice_getdevhandle();
2123        if (0 == cy_as_dev->dev_handle) {
2124                #ifndef NDEBUG
2125                cy_as_hal_print_message("<1> cy_as_gadget: "
2126                        "no west bridge device\n");
2127                #endif
2128                retval = -EFAULT;
2129                goto done;
2130        }
2131
2132        /* We are done now */
2133        cy_as_gadget_controller = cy_as_dev;
2134        return 0;
2135
2136/*
2137 * in case of an error
2138 */
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                        /* force -E/0 linux convention */
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