omap3530/beagle_drivers/wb/api/src/cyasusb.c
changeset 27 117faf51deac
child 52 254b9435d75e
equal deleted inserted replaced
26:b7e488c49d0d 27:117faf51deac
       
     1 /* Cypress West Bridge API source file (cyasusb.c)
       
     2 ## ===========================
       
     3 ##
       
     4 ##  Copyright Cypress Semiconductor Corporation, 2006-2009,
       
     5 ##  All Rights Reserved
       
     6 ##  UNPUBLISHED, LICENSED SOFTWARE.
       
     7 ##
       
     8 ##  CONFIDENTIAL AND PROPRIETARY INFORMATION
       
     9 ##  WHICH IS THE PROPERTY OF CYPRESS.
       
    10 ##
       
    11 ##  Use of this file is governed
       
    12 ##  by the license agreement included in the file
       
    13 ##
       
    14 ##     <install>/license/license.txt
       
    15 ##
       
    16 ##  where <install> is the Cypress software
       
    17 ##  installation root directory path.
       
    18 ##
       
    19 ## ===========================
       
    20 */
       
    21 
       
    22 #include "cyashal.h"
       
    23 #include "cyasusb.h"
       
    24 #include "cyaserr.h"
       
    25 #include "cyasdma.h"
       
    26 #include "cyaslowlevel.h"
       
    27 #include "cyaslep2pep.h"
       
    28 #include "cyasregs.h"
       
    29 #include "cyasstorage.h"
       
    30 
       
    31 extern CyAsMediaType
       
    32 CyAsStorageGetMediaFromAddress(uint16_t v) ;
       
    33 
       
    34 extern CyAsBusNumber_t
       
    35 CyAsStorageGetBusFromAddress(uint16_t v) ;
       
    36 
       
    37 extern uint32_t
       
    38 CyAsStorageGetDeviceFromAddress(uint16_t v) ;
       
    39 
       
    40 static CyAsReturnStatus_t
       
    41 CyAsUsbAckSetupPacket(
       
    42                       CyAsDeviceHandle                  handle,         /* Handle to the West Bridge device */
       
    43                       CyAsFunctionCallback              cb,             /* The callback if async call */
       
    44                       uint32_t                          client          /* Client supplied data */
       
    45                       ) ;
       
    46 
       
    47 static void
       
    48 CyAsUsbFuncCallback(
       
    49                     CyAsDevice *dev_p,
       
    50                     uint8_t context,
       
    51                     CyAsLLRequestResponse *rqt,
       
    52                     CyAsLLRequestResponse *resp,
       
    53                     CyAsReturnStatus_t ret) ;
       
    54 /*
       
    55 * Reset the USB EP0 state
       
    56 */
       
    57 static void
       
    58 CyAsUsbResetEP0State(CyAsDevice *dev_p)
       
    59 {
       
    60     CyAsLogDebugMessage(6, "CyAsUsbResetEP0State called") ;
       
    61 
       
    62     CyAsDeviceClearAckDelayed(dev_p) ;
       
    63     CyAsDeviceClearSetupPacket(dev_p) ;
       
    64     if (CyAsDeviceIsUsbAsyncPending(dev_p, 0))
       
    65         CyAsUsbCancelAsync((CyAsDeviceHandle)dev_p, 0) ;
       
    66 
       
    67     dev_p->usb_pending_buffer = 0 ;
       
    68 }
       
    69 
       
    70 /*
       
    71 * External function to map logical endpoints to physical endpoints
       
    72 */
       
    73 static CyAsReturnStatus_t
       
    74 IsUsbActive(CyAsDevice *dev_p)
       
    75 {
       
    76     if (!CyAsDeviceIsConfigured(dev_p))
       
    77         return CY_AS_ERROR_NOT_CONFIGURED ;
       
    78 
       
    79     if (!CyAsDeviceIsFirmwareLoaded(dev_p))
       
    80         return CY_AS_ERROR_NO_FIRMWARE ;
       
    81 
       
    82     if (dev_p->usb_count == 0)
       
    83         return CY_AS_ERROR_NOT_RUNNING ;
       
    84 
       
    85     if (CyAsDeviceIsInSuspendMode(dev_p))
       
    86         return CY_AS_ERROR_IN_SUSPEND ;
       
    87 
       
    88     return CY_AS_ERROR_SUCCESS ;
       
    89 }
       
    90 
       
    91 static void
       
    92 UsbAckCallback(CyAsDeviceHandle h,
       
    93                CyAsReturnStatus_t status,
       
    94                uint32_t client,
       
    95                CyAsFunctCBType  type,
       
    96                void* data)
       
    97 {
       
    98     CyAsDevice *dev_p = (CyAsDevice *)h ;
       
    99 
       
   100     (void)client ;
       
   101     (void)status ;
       
   102     (void)data ;
       
   103 
       
   104     CyAsHalAssert(type == CY_FUNCT_CB_NODATA) ;
       
   105 
       
   106     if (dev_p->usb_pending_buffer)
       
   107     {
       
   108         CyAsUsbIoCallback cb ;
       
   109 
       
   110         cb = dev_p->usb_cb[0] ;
       
   111         dev_p->usb_cb[0] = 0 ;
       
   112         CyAsDeviceClearUsbAsyncPending(dev_p, 0) ;
       
   113         if (cb)
       
   114             cb(h, 0, dev_p->usb_pending_size, dev_p->usb_pending_buffer, dev_p->usb_error) ;
       
   115 
       
   116         dev_p->usb_pending_buffer = 0 ;
       
   117     }
       
   118 
       
   119     CyAsDeviceClearSetupPacket(dev_p) ;
       
   120 }
       
   121 
       
   122 static void
       
   123 MyUsbRequestCallbackUsbEvent(CyAsDevice *dev_p, CyAsLLRequestResponse *req_p)
       
   124 {
       
   125     uint16_t ev ;
       
   126     uint16_t val ;
       
   127     CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
   128 
       
   129     ev = CyAsLLRequestResponse_GetWord(req_p, 0) ;
       
   130     switch(ev)
       
   131     {
       
   132     case 0:             /* Reserved */
       
   133         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_INVALID_REQUEST, 0) ;
       
   134         break ;
       
   135 
       
   136     case 1:             /* Reserved */
       
   137         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_INVALID_REQUEST, 0) ;
       
   138         break ;
       
   139 
       
   140     case 2:             /* USB Suspend */
       
   141         dev_p->usb_last_event = CyAsEventUsbSuspend ;
       
   142         if (dev_p->usb_event_cb_ms)
       
   143             dev_p->usb_event_cb_ms(h, CyAsEventUsbSuspend, 0) ;
       
   144         else if (dev_p->usb_event_cb)
       
   145             dev_p->usb_event_cb(h, CyAsEventUsbSuspend, 0) ;
       
   146         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   147         break;
       
   148 
       
   149     case 3:             /* USB Resume */
       
   150         dev_p->usb_last_event = CyAsEventUsbResume ;
       
   151         if (dev_p->usb_event_cb_ms)
       
   152             dev_p->usb_event_cb_ms(h, CyAsEventUsbResume, 0) ;
       
   153         else if (dev_p->usb_event_cb)
       
   154             dev_p->usb_event_cb(h, CyAsEventUsbResume, 0) ;
       
   155         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   156         break ;
       
   157 
       
   158     case 4:             /* USB Reset */
       
   159         /*
       
   160         * If we get a USB reset, the USB host did not understand our response
       
   161         * or we timed out for some reason.  Reset our internal state to be ready for
       
   162         * another set of enumeration based requests.
       
   163         */
       
   164         if (CyAsDeviceIsAckDelayed(dev_p))
       
   165         {
       
   166             CyAsUsbResetEP0State(dev_p) ;
       
   167         }
       
   168 
       
   169         dev_p->usb_last_event = CyAsEventUsbReset ;
       
   170         if (dev_p->usb_event_cb_ms)
       
   171             dev_p->usb_event_cb_ms(h, CyAsEventUsbReset, 0) ;
       
   172         else if (dev_p->usb_event_cb)
       
   173             dev_p->usb_event_cb(h, CyAsEventUsbReset, 0) ;
       
   174 
       
   175         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   176         CyAsDeviceClearUsbHighSpeed(dev_p) ;
       
   177         CyAsUsbSetDmaSizes(dev_p) ;
       
   178         dev_p->usb_max_tx_size = 0x40 ;
       
   179         CyAsDmaSetMaxDmaSize(dev_p, 0x06, 0x40) ;
       
   180         break ;
       
   181 
       
   182     case 5:             /* USB Set Configuration */
       
   183         val = CyAsLLRequestResponse_GetWord(req_p, 1) ;                 /* The configuration to set */
       
   184         dev_p->usb_last_event = CyAsEventUsbSetConfig ;
       
   185         if (dev_p->usb_event_cb_ms)
       
   186             dev_p->usb_event_cb_ms(h, CyAsEventUsbSetConfig, &val) ;
       
   187         else if (dev_p->usb_event_cb)
       
   188             dev_p->usb_event_cb(h, CyAsEventUsbSetConfig, &val) ;
       
   189         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   190         break ;
       
   191 
       
   192     case 6:             /* USB Speed change */
       
   193         val = CyAsLLRequestResponse_GetWord(req_p, 1) ;                 /* Connect speed */
       
   194         dev_p->usb_last_event = CyAsEventUsbSpeedChange ;
       
   195         if (dev_p->usb_event_cb_ms)
       
   196             dev_p->usb_event_cb_ms(h, CyAsEventUsbSpeedChange, &val) ;
       
   197         else if (dev_p->usb_event_cb)
       
   198             dev_p->usb_event_cb(h, CyAsEventUsbSpeedChange, &val) ;
       
   199         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   200         CyAsDeviceSetUsbHighSpeed(dev_p) ;
       
   201         CyAsUsbSetDmaSizes(dev_p) ;
       
   202         dev_p->usb_max_tx_size = 0x200 ;
       
   203         CyAsDmaSetMaxDmaSize(dev_p, 0x06, 0x200) ;
       
   204         break ;
       
   205 
       
   206     case 7:             /* USB Clear Feature */
       
   207         val = CyAsLLRequestResponse_GetWord(req_p, 1) ;                 /* EP Number */
       
   208         if (dev_p->usb_event_cb_ms)
       
   209             dev_p->usb_event_cb_ms(h, CyAsEventUsbClearFeature, &val) ;
       
   210         if (dev_p->usb_event_cb)
       
   211             dev_p->usb_event_cb(h, CyAsEventUsbClearFeature, &val) ;
       
   212         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   213         break ;
       
   214 
       
   215     default:
       
   216         CyAsHalPrintMessage("Invalid event type\n") ;
       
   217         CyAsLLSendDataResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_RESP_USB_INVALID_EVENT, sizeof(ev), &ev) ;
       
   218         break ;
       
   219     }
       
   220 }
       
   221 
       
   222 static void
       
   223 MyUsbRequestCallbackUsbData(CyAsDevice *dev_p, CyAsLLRequestResponse *req_p)
       
   224 {
       
   225     CyAsEndPointNumber_t ep ;
       
   226     uint8_t type ;
       
   227     uint16_t len ;
       
   228     uint16_t val ;
       
   229     CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
   230 
       
   231     val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
       
   232     ep = (CyAsEndPointNumber_t)((val >> 13) & 0x01) ;
       
   233     len = (val & 0x1ff) ;
       
   234 
       
   235     CyAsHalAssert(len <= 64) ;
       
   236     CyAsLLRequestResponse_Unpack(req_p, 1, len, dev_p->usb_ep_data) ;
       
   237 
       
   238     type = (uint8_t)((val >> 14) & 0x03) ;
       
   239     if (type == 0)
       
   240     {
       
   241         if (CyAsDeviceIsAckDelayed(dev_p))
       
   242         {
       
   243             /*
       
   244             * A setup packet has arrived while we are processing a previous setup packet.
       
   245             * Reset our state with respect to EP0 to be ready to process the new packet.
       
   246             */
       
   247             CyAsUsbResetEP0State(dev_p) ;
       
   248         }
       
   249 
       
   250         if (len != 8)
       
   251             CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_INVALID_REQUEST, 0) ;
       
   252         else
       
   253         {
       
   254             CyAsDeviceClearEp0Stalled(dev_p) ;
       
   255             CyAsDeviceSetSetupPacket(dev_p) ;
       
   256             CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   257             if (dev_p->usb_event_cb_ms)
       
   258                 dev_p->usb_event_cb_ms(h, CyAsEventUsbSetupPacket, dev_p->usb_ep_data) ;
       
   259             else
       
   260                 dev_p->usb_event_cb(h, CyAsEventUsbSetupPacket, dev_p->usb_ep_data) ;
       
   261 
       
   262             if ((!CyAsDeviceIsAckDelayed(dev_p)) && (!CyAsDeviceIsEp0Stalled(dev_p)))
       
   263             {
       
   264                 CyAsUsbAckSetupPacket(h, UsbAckCallback, 0) ;
       
   265             }
       
   266         }
       
   267     }
       
   268     else if (type == 2)
       
   269     {
       
   270         if (len != 0)
       
   271             CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_INVALID_REQUEST, 0) ;
       
   272         else
       
   273         {
       
   274             if (dev_p->usb_event_cb_ms)
       
   275                 dev_p->usb_event_cb_ms(h, CyAsEventUsbStatusPacket, 0) ;
       
   276             else
       
   277                 dev_p->usb_event_cb(h, CyAsEventUsbStatusPacket, 0) ;
       
   278 
       
   279             CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   280         }
       
   281     }
       
   282     else if (type == 1)
       
   283     {
       
   284         /*
       
   285         * We need to hand the data associated with these endpoints to the DMA
       
   286         * module.
       
   287         */
       
   288         CyAsDmaReceivedData(dev_p, ep, len, dev_p->usb_ep_data) ;
       
   289         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   290     }
       
   291 }
       
   292 
       
   293 static void
       
   294 MyUsbRequestCallbackInquiry(CyAsDevice *dev_p, CyAsLLRequestResponse *req_p)
       
   295 {
       
   296     CyAsUsbInquiryData_dep cbdata ;
       
   297     CyAsUsbInquiryData cbdata_ms ;
       
   298     void *data ;
       
   299     uint16_t val ;
       
   300     CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
   301     uint8_t def_inq_data[64] ;
       
   302     uint8_t evpd ;
       
   303     uint8_t codepage ;
       
   304     CyBool updated ;
       
   305     uint16_t length ;
       
   306 
       
   307     CyAsBusNumber_t bus ;
       
   308     uint32_t        device ;
       
   309     CyAsMediaType   media ;
       
   310 
       
   311     val    = CyAsLLRequestResponse_GetWord(req_p, 0) ;
       
   312     bus    = CyAsStorageGetBusFromAddress(val) ;
       
   313     device = CyAsStorageGetDeviceFromAddress(val) ;
       
   314     media  = CyAsStorageGetMediaFromAddress(val) ;
       
   315 
       
   316     val      = CyAsLLRequestResponse_GetWord(req_p, 1) ;
       
   317     evpd     = (uint8_t)((val >> 8) & 0x01) ;
       
   318     codepage = (uint8_t)(val & 0xff) ;
       
   319 
       
   320     length = CyAsLLRequestResponse_GetWord(req_p, 2) ;
       
   321     data   = (void *)def_inq_data ;
       
   322 
       
   323     updated = CyFalse ;
       
   324 
       
   325     if (dev_p->usb_event_cb_ms)
       
   326     {
       
   327         cbdata_ms.bus = bus ;
       
   328         cbdata_ms.device = device ;
       
   329         cbdata_ms.updated = updated ;
       
   330         cbdata_ms.evpd = evpd ;
       
   331         cbdata_ms.codepage = codepage ;
       
   332         cbdata_ms.length = length ;
       
   333         cbdata_ms.data = data ;
       
   334 
       
   335         CyAsHalAssert(cbdata_ms.length <= sizeof(def_inq_data)) ;
       
   336         CyAsLLRequestResponse_Unpack(req_p, 3, cbdata_ms.length, cbdata_ms.data) ;
       
   337 
       
   338         dev_p->usb_event_cb_ms(h, CyAsEventUsbInquiryBefore, &cbdata_ms) ;
       
   339 
       
   340         updated = cbdata_ms.updated;
       
   341         data    = cbdata_ms.data ;
       
   342         length  = cbdata_ms.length ;
       
   343     }
       
   344     else if (dev_p->usb_event_cb)
       
   345     {
       
   346         cbdata.media = media ;
       
   347         cbdata.updated = updated ;
       
   348         cbdata.evpd = evpd ;
       
   349         cbdata.codepage = codepage ;
       
   350         cbdata.length = length ;
       
   351         cbdata.data = data ;
       
   352 
       
   353         CyAsHalAssert(cbdata.length <= sizeof(def_inq_data)) ;
       
   354         CyAsLLRequestResponse_Unpack(req_p, 3, cbdata.length, cbdata.data) ;
       
   355 
       
   356         dev_p->usb_event_cb(h, CyAsEventUsbInquiryBefore, &cbdata) ;
       
   357 
       
   358         updated = cbdata.updated ;
       
   359         data    = cbdata.data ;
       
   360         length  = cbdata.length ;
       
   361     }
       
   362 
       
   363     if (updated && length > 192)
       
   364         CyAsHalPrintMessage("An inquiry result from a CyAsEventUsbInquiryBefore event was greater than 192 bytes.") ;
       
   365 
       
   366     /* Now send the reply with the data back to the West Bridge device */
       
   367     if (updated && length <= 192)
       
   368     {
       
   369         /*
       
   370         * The callback function modified the inquiry data, ship the data back
       
   371         * to the West Bridge firmware.
       
   372         */
       
   373         CyAsLLSendDataResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_RESP_INQUIRY_DATA, length, data) ;
       
   374     }
       
   375     else
       
   376     {
       
   377         /*
       
   378         * The callback did not modify the data, just acknowledge that we
       
   379         * processed the request
       
   380         */
       
   381         CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1) ;
       
   382     }
       
   383 
       
   384     if (dev_p->usb_event_cb_ms)
       
   385         dev_p->usb_event_cb_ms(h, CyAsEventUsbInquiryAfter, &cbdata_ms) ;
       
   386     else if (dev_p->usb_event_cb)
       
   387         dev_p->usb_event_cb(h, CyAsEventUsbInquiryAfter, &cbdata) ;
       
   388 }
       
   389 
       
   390 static void
       
   391 MyUsbRequestCallbackStartStop(CyAsDevice *dev_p, CyAsLLRequestResponse *req_p)
       
   392 {
       
   393     CyAsBusNumber_t bus ;
       
   394     CyAsMediaType media ;
       
   395     uint32_t device ;
       
   396     uint16_t val ;
       
   397 
       
   398     if (dev_p->usb_event_cb_ms || dev_p->usb_event_cb)
       
   399     {
       
   400         CyBool loej ;
       
   401         CyBool start ;
       
   402         CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
   403 
       
   404         val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
       
   405         bus = CyAsStorageGetBusFromAddress(val) ;
       
   406         device = CyAsStorageGetDeviceFromAddress(val) ;
       
   407         media = CyAsStorageGetMediaFromAddress(val) ;
       
   408 
       
   409         val = CyAsLLRequestResponse_GetWord(req_p, 1) ;
       
   410         loej = (val & 0x02) ? CyTrue : CyFalse ;
       
   411         start = (val & 0x01) ? CyTrue: CyFalse ;
       
   412 
       
   413         if (dev_p->usb_event_cb_ms)
       
   414         {
       
   415             CyAsUsbStartStopData cbdata_ms ;
       
   416 
       
   417             cbdata_ms.bus = bus ;
       
   418             cbdata_ms.device = device ;
       
   419             cbdata_ms.loej = loej ;
       
   420             cbdata_ms.start = start ;
       
   421             dev_p->usb_event_cb_ms(h, CyAsEventUsbStartStop, &cbdata_ms) ;
       
   422         }
       
   423         else if (dev_p->usb_event_cb)
       
   424         {
       
   425             CyAsUsbStartStopData_dep cbdata ;
       
   426 
       
   427             cbdata.media = media ;
       
   428             cbdata.loej = loej ;
       
   429             cbdata.start = start ;
       
   430             dev_p->usb_event_cb(h, CyAsEventUsbStartStop, &cbdata) ;
       
   431         }
       
   432     }
       
   433     CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1) ;
       
   434 }
       
   435 
       
   436 static void
       
   437 MyUsbRequestCallbackUknownCBW(CyAsDevice *dev_p, CyAsLLRequestResponse *req_p)
       
   438 {
       
   439     uint16_t val ;
       
   440     CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
   441     uint8_t buf[16] ;
       
   442 
       
   443     uint8_t response[4] ;
       
   444     uint16_t reqlen ;
       
   445     void *request ;
       
   446     uint8_t status ;
       
   447     uint8_t key ;
       
   448     uint8_t asc ;
       
   449     uint8_t ascq ;
       
   450 
       
   451     val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
       
   452     status = 1 ;                                            /* Failed by default */
       
   453     key = 0x05 ;                                            /* Invalid command */
       
   454     asc = 0x20 ;                                            /* Invalid command */
       
   455     ascq = 0x00 ;                                   /* Invalid command */
       
   456     reqlen = CyAsLLRequestResponse_GetWord(req_p, 1) ;
       
   457     request = buf ;
       
   458 
       
   459     CyAsHalAssert(reqlen <= sizeof(buf)) ;
       
   460     CyAsLLRequestResponse_Unpack(req_p, 2, reqlen, request) ;
       
   461 
       
   462     if (dev_p->usb_event_cb_ms)
       
   463     {
       
   464         CyAsUsbUnknownCommandData cbdata_ms ;
       
   465         cbdata_ms.bus = CyAsStorageGetBusFromAddress(val) ;
       
   466         cbdata_ms.device = CyAsStorageGetDeviceFromAddress(val) ;
       
   467         cbdata_ms.reqlen = reqlen ;
       
   468         cbdata_ms.request = request ;
       
   469         cbdata_ms.status = status ;
       
   470         cbdata_ms.key = key ;
       
   471         cbdata_ms.asc = asc ;
       
   472         cbdata_ms.ascq = ascq ;
       
   473 
       
   474         dev_p->usb_event_cb_ms(h, CyAsEventUsbUnknownStorage, &cbdata_ms) ;
       
   475         status = cbdata_ms.status ;
       
   476         key = cbdata_ms.key ;
       
   477         asc = cbdata_ms.asc ;
       
   478         ascq = cbdata_ms.ascq ;
       
   479     }
       
   480     else if (dev_p->usb_event_cb)
       
   481     {
       
   482         CyAsUsbUnknownCommandData_dep cbdata ;
       
   483         cbdata.media = CyAsStorageGetMediaFromAddress(val) ;
       
   484         cbdata.reqlen = reqlen ;
       
   485         cbdata.request = request ;
       
   486         cbdata.status = status ;
       
   487         cbdata.key = key ;
       
   488         cbdata.asc = asc ;
       
   489         cbdata.ascq = ascq ;
       
   490 
       
   491         dev_p->usb_event_cb(h, CyAsEventUsbUnknownStorage, &cbdata) ;
       
   492         status = cbdata.status ;
       
   493         key = cbdata.key ;
       
   494         asc = cbdata.asc ;
       
   495         ascq = cbdata.ascq ;
       
   496     }
       
   497 
       
   498     response[0] = status ;
       
   499     response[1] = key ;
       
   500     response[2] = asc ;
       
   501     response[3] = ascq ;
       
   502     CyAsLLSendDataResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_RESP_UNKNOWN_SCSI_COMMAND, sizeof(response), response) ;
       
   503 }
       
   504 
       
   505 static void
       
   506 MyUsbRequestCallbackMSCProgress(CyAsDevice *dev_p, CyAsLLRequestResponse *req_p)
       
   507 {
       
   508     uint16_t val1, val2 ;
       
   509     CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
   510 
       
   511     if ((dev_p->usb_event_cb) || (dev_p->usb_event_cb_ms))
       
   512     {
       
   513         CyAsMSCProgressData cbdata ;
       
   514 
       
   515         val1 = CyAsLLRequestResponse_GetWord(req_p, 0) ;
       
   516         val2 = CyAsLLRequestResponse_GetWord(req_p, 1) ;
       
   517         cbdata.wr_count = (uint32_t)((val1 << 16) | val2) ;
       
   518 
       
   519         val1 = CyAsLLRequestResponse_GetWord(req_p, 2) ;
       
   520         val2 = CyAsLLRequestResponse_GetWord(req_p, 3) ;
       
   521         cbdata.rd_count = (uint32_t)((val1 << 16) | val2) ;
       
   522 
       
   523         if (dev_p->usb_event_cb)
       
   524             dev_p->usb_event_cb(h, CyAsEventUsbMSCProgress, &cbdata) ;
       
   525         else
       
   526             dev_p->usb_event_cb_ms(h, CyAsEventUsbMSCProgress, &cbdata) ;
       
   527     }
       
   528 
       
   529     CyAsLLSendStatusResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
       
   530 }
       
   531 
       
   532 /*
       
   533 * This function processes the requests delivered from the firmware within the West Bridge
       
   534 * device that are delivered in the USB context.  These requests generally are EP0 and
       
   535 * EP1 related requests or USB events.
       
   536 */
       
   537 static void
       
   538 MyUsbRequestCallback(CyAsDevice *dev_p, uint8_t context, CyAsLLRequestResponse *req_p, CyAsLLRequestResponse *resp_p,
       
   539                      CyAsReturnStatus_t ret)
       
   540 {
       
   541     uint16_t val ;
       
   542     uint8_t code = CyAsLLRequestResponse_GetCode(req_p) ;
       
   543 
       
   544     (void)resp_p ;
       
   545     (void)context ;
       
   546     (void)ret ;
       
   547 
       
   548     switch(code)
       
   549     {
       
   550     case CY_RQT_USB_EVENT:
       
   551         MyUsbRequestCallbackUsbEvent(dev_p, req_p) ;
       
   552         break ;
       
   553 
       
   554     case CY_RQT_USB_EP_DATA:
       
   555         dev_p->usb_last_event = CyAsEventUsbSetupPacket ;
       
   556         MyUsbRequestCallbackUsbData(dev_p, req_p) ;
       
   557         break ;
       
   558 
       
   559     case CY_RQT_SCSI_INQUIRY_COMMAND:
       
   560         dev_p->usb_last_event = CyAsEventUsbInquiryAfter ;
       
   561         MyUsbRequestCallbackInquiry(dev_p, req_p) ;
       
   562         break ;
       
   563 
       
   564     case CY_RQT_SCSI_START_STOP_COMMAND:
       
   565         dev_p->usb_last_event = CyAsEventUsbStartStop ;
       
   566         MyUsbRequestCallbackStartStop(dev_p, req_p) ;
       
   567         break ;
       
   568 
       
   569     case CY_RQT_SCSI_UNKNOWN_COMMAND:
       
   570         dev_p->usb_last_event = CyAsEventUsbUnknownStorage ;
       
   571         MyUsbRequestCallbackUknownCBW(dev_p, req_p) ;
       
   572         break ;
       
   573 
       
   574     case CY_RQT_USB_ACTIVITY_UPDATE:
       
   575         dev_p->usb_last_event = CyAsEventUsbMSCProgress ;
       
   576         MyUsbRequestCallbackMSCProgress(dev_p, req_p) ;
       
   577         break ;
       
   578 
       
   579     default:
       
   580         CyAsHalPrintMessage("Invalid request received on USB context\n") ;
       
   581         val = req_p->box0 ;
       
   582         CyAsLLSendDataResponse(dev_p, CY_RQT_USB_RQT_CONTEXT, CY_RESP_INVALID_REQUEST, sizeof(val), &val) ;
       
   583         break ;
       
   584     }
       
   585 }
       
   586 
       
   587 static CyAsReturnStatus_t
       
   588 MyHandleResponseUsbStart(CyAsDevice* dev_p,
       
   589                          CyAsLLRequestResponse *req_p,
       
   590                          CyAsLLRequestResponse *reply_p,
       
   591                          CyAsReturnStatus_t ret)
       
   592 {
       
   593     if (ret != CY_AS_ERROR_SUCCESS)
       
   594         goto destroy ;
       
   595 
       
   596     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
   597     {
       
   598         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
   599         goto destroy ;
       
   600     }
       
   601 
       
   602     ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
   603     if (ret != CY_AS_ERROR_SUCCESS)
       
   604         goto destroy ;
       
   605 
       
   606     /*
       
   607     * Mark EP 0 and EP1 as 64 byte endpoints
       
   608     */
       
   609     CyAsDmaSetMaxDmaSize(dev_p, 0, 64) ;
       
   610     CyAsDmaSetMaxDmaSize(dev_p, 1, 64) ;
       
   611 
       
   612     dev_p->usb_count++ ;
       
   613 
       
   614 destroy :
       
   615     CyAsLLDestroyRequest(dev_p, req_p) ;
       
   616     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
   617 
       
   618     if (ret != CY_AS_ERROR_SUCCESS)
       
   619     {
       
   620         CyAsDestroyCBQueue(dev_p->usb_func_cbs) ;
       
   621         CyAsLLRegisterRequestCallback(dev_p, CY_RQT_USB_RQT_CONTEXT, 0) ;
       
   622     }
       
   623 
       
   624     CyAsDeviceClearUSSPending(dev_p) ;
       
   625 
       
   626     return ret ;
       
   627 
       
   628 }
       
   629 
       
   630 /*
       
   631 * This function starts the USB stack.  The stack is reference counted so if the stack is already
       
   632 * started, this function just increments the count.  If the stack has not been started, a start
       
   633 * request is sent to the West Bridge device.
       
   634 *
       
   635 * Note: Starting the USB stack does not cause the USB signals to be connected to the USB pins.  To do
       
   636 *       this and therefore initiate enumeration, CyAsUsbConnect() must be called.
       
   637 */
       
   638 CyAsReturnStatus_t
       
   639 CyAsUsbStart(CyAsDeviceHandle handle,
       
   640                CyAsFunctionCallback cb,
       
   641                uint32_t client)
       
   642 {
       
   643     CyAsLLRequestResponse *req_p, *reply_p ;
       
   644     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
   645 
       
   646     CyAsDevice*dev_p ;
       
   647 
       
   648     CyAsLogDebugMessage(6, "CyAsUsbStart called") ;
       
   649 
       
   650     dev_p = (CyAsDevice *)handle ;
       
   651     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
   652         return CY_AS_ERROR_INVALID_HANDLE ;
       
   653 
       
   654     if (!CyAsDeviceIsConfigured(dev_p))
       
   655         return CY_AS_ERROR_NOT_CONFIGURED ;
       
   656 
       
   657     if (!CyAsDeviceIsFirmwareLoaded(dev_p))
       
   658         return CY_AS_ERROR_NO_FIRMWARE ;
       
   659 
       
   660     if (CyAsDeviceIsInSuspendMode(dev_p))
       
   661         return CY_AS_ERROR_IN_SUSPEND ;
       
   662 
       
   663     if (CyAsDeviceIsInCallback(dev_p))
       
   664         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
   665 
       
   666     if(CyAsDeviceIsUSSPending(dev_p))
       
   667         return CY_AS_ERROR_STARTSTOP_PENDING ;
       
   668 
       
   669     CyAsDeviceSetUSSPending(dev_p) ;
       
   670 
       
   671     if (dev_p->usb_count == 0)
       
   672     {
       
   673         /*
       
   674         * Since we are just starting the stack, mark USB as not connected to the
       
   675         * remote host
       
   676         */
       
   677         CyAsDeviceClearUsbConnected(dev_p) ;
       
   678         dev_p->usb_phy_config = 0 ;
       
   679 
       
   680         /* Queue for 1.0 Async Requests, kept for backwards compatibility */
       
   681         dev_p->usb_func_cbs = CyAsCreateCBQueue(CYAS_USB_FUNC_CB) ;
       
   682         if(dev_p->usb_func_cbs == 0)
       
   683         {
       
   684             CyAsDeviceClearUSSPending(dev_p) ;
       
   685             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
   686         }
       
   687 
       
   688         /* Reset the EP0 state */
       
   689         CyAsUsbResetEP0State(dev_p) ;
       
   690 
       
   691         /*
       
   692         * We register here becuase the start request may cause events to occur before the
       
   693         * response to the start request.
       
   694         */
       
   695         CyAsLLRegisterRequestCallback(dev_p, CY_RQT_USB_RQT_CONTEXT, MyUsbRequestCallback) ;
       
   696 
       
   697         /* Create the request to send to the West Bridge device */
       
   698         req_p = CyAsLLCreateRequest(dev_p, CY_RQT_START_USB, CY_RQT_USB_RQT_CONTEXT, 0) ;
       
   699         if (req_p == 0)
       
   700         {
       
   701             CyAsDestroyCBQueue(dev_p->usb_func_cbs) ;
       
   702             dev_p->usb_func_cbs = 0 ;
       
   703             CyAsDeviceClearUSSPending(dev_p) ;
       
   704             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
   705         }
       
   706 
       
   707         /* Reserve space for the reply, the reply data will not exceed one word */
       
   708         reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
   709         if (reply_p == 0)
       
   710         {
       
   711             CyAsDestroyCBQueue(dev_p->usb_func_cbs) ;
       
   712             dev_p->usb_func_cbs = 0 ;
       
   713             CyAsLLDestroyRequest(dev_p, req_p) ;
       
   714             CyAsDeviceClearUSSPending(dev_p) ;
       
   715             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
   716         }
       
   717 
       
   718         if(cb == 0)
       
   719         {
       
   720             ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
   721             if (ret != CY_AS_ERROR_SUCCESS)
       
   722                 goto destroy ;
       
   723 
       
   724             return MyHandleResponseUsbStart(dev_p, req_p, reply_p, ret) ;
       
   725         }
       
   726         else
       
   727         {
       
   728             ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_START,
       
   729                 0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
   730                 CyAsUsbFuncCallback) ;
       
   731 
       
   732             if (ret != CY_AS_ERROR_SUCCESS)
       
   733                 goto destroy ;
       
   734 
       
   735             return ret ;
       
   736         }
       
   737 
       
   738 destroy:
       
   739         CyAsLLDestroyRequest(dev_p, req_p) ;
       
   740         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
   741     }
       
   742     else
       
   743     {
       
   744         dev_p->usb_count++ ;
       
   745         if (cb)
       
   746             cb(handle, ret, client, CY_FUNCT_CB_USB_START, 0) ;
       
   747     }
       
   748 
       
   749     CyAsDeviceClearUSSPending(dev_p) ;
       
   750 
       
   751     return ret ;
       
   752 }
       
   753 
       
   754 void
       
   755 CyAsUsbReset(CyAsDevice *dev_p)
       
   756 {
       
   757     int i ;
       
   758 
       
   759     CyAsDeviceClearUsbConnected(dev_p) ;
       
   760 
       
   761     for(i = 0 ; i < sizeof(dev_p->usb_config)/sizeof(dev_p->usb_config[0]) ; i++)
       
   762     {
       
   763         /*
       
   764          * Cancel all pending USB read/write operations, as it is possible
       
   765          * that the USB stack comes up in a different configuration with a
       
   766          * different set of endpoints.
       
   767          */
       
   768         if (CyAsDeviceIsUsbAsyncPending(dev_p, i))
       
   769             CyAsUsbCancelAsync(dev_p, (CyAsEndPointNumber_t)i) ;
       
   770 
       
   771         dev_p->usb_cb[i] = 0 ;
       
   772         dev_p->usb_config[i].enabled = CyFalse ;
       
   773     }
       
   774 
       
   775     dev_p->usb_phy_config = 0 ;
       
   776 }
       
   777 
       
   778 /*
       
   779  * This function does all the API side clean-up associated with CyAsUsbStop,
       
   780  * without any communication with firmware. This needs to be done when the
       
   781  * device is being reset while the USB stack is active.
       
   782  */
       
   783 void
       
   784 CyAsUsbCleanup(CyAsDevice *dev_p)
       
   785 {
       
   786     if (dev_p->usb_count)
       
   787     {
       
   788         CyAsUsbResetEP0State(dev_p) ;
       
   789         CyAsUsbReset(dev_p) ;
       
   790         CyAsHalMemSet(dev_p->usb_config, 0, sizeof(dev_p->usb_config)) ;
       
   791         CyAsDestroyCBQueue(dev_p->usb_func_cbs) ;
       
   792 
       
   793         dev_p->usb_count = 0 ;
       
   794     }
       
   795 }
       
   796 
       
   797 static CyAsReturnStatus_t
       
   798 MyHandleResponseUsbStop(CyAsDevice* dev_p,
       
   799                          CyAsLLRequestResponse *req_p,
       
   800                          CyAsLLRequestResponse *reply_p,
       
   801                          CyAsReturnStatus_t ret)
       
   802 {
       
   803     if (ret != CY_AS_ERROR_SUCCESS)
       
   804         goto destroy ;
       
   805 
       
   806     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
   807     {
       
   808         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
   809         goto destroy ;
       
   810     }
       
   811 
       
   812     ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
   813     if (ret != CY_AS_ERROR_SUCCESS)
       
   814         goto destroy ;
       
   815 
       
   816     /*
       
   817      * We sucessfully shutdown the stack, so decrement to make the count
       
   818      * zero.
       
   819      */
       
   820     CyAsUsbCleanup(dev_p) ;
       
   821 
       
   822 destroy :
       
   823     CyAsLLDestroyRequest(dev_p, req_p) ;
       
   824     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
   825 
       
   826     if (ret != CY_AS_ERROR_SUCCESS)
       
   827         CyAsLLRegisterRequestCallback(dev_p, CY_RQT_USB_RQT_CONTEXT, 0) ;
       
   828 
       
   829     CyAsDeviceClearUSSPending(dev_p) ;
       
   830 
       
   831     return ret ;
       
   832 }
       
   833 
       
   834 /*
       
   835 * This function stops the USB stack.  The USB stack is reference counted so first is reference count is
       
   836 * decremented.  If the reference count is then zero, a request is sent to the West Bridge device to stop the USB
       
   837 * stack on the West Bridge device.
       
   838 */
       
   839 CyAsReturnStatus_t
       
   840 CyAsUsbStop(CyAsDeviceHandle handle,
       
   841               CyAsFunctionCallback cb,
       
   842               uint32_t client)
       
   843 {
       
   844     CyAsLLRequestResponse *req_p = 0, *reply_p = 0 ;
       
   845     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
   846 
       
   847     CyAsDevice*dev_p ;
       
   848 
       
   849     CyAsLogDebugMessage(6, "CyAsUsbStop called") ;
       
   850 
       
   851     dev_p = (CyAsDevice *)handle ;
       
   852     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
   853         return CY_AS_ERROR_INVALID_HANDLE ;
       
   854 
       
   855     ret = IsUsbActive(dev_p) ;
       
   856     if (ret != CY_AS_ERROR_SUCCESS)
       
   857         return ret ;
       
   858 
       
   859     if (CyAsDeviceIsUsbConnected(dev_p))
       
   860         return CY_AS_ERROR_USB_CONNECTED ;
       
   861 
       
   862     if (CyAsDeviceIsInCallback(dev_p))
       
   863         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
   864 
       
   865     if(CyAsDeviceIsUSSPending(dev_p))
       
   866         return CY_AS_ERROR_STARTSTOP_PENDING ;
       
   867 
       
   868     CyAsDeviceSetUSSPending(dev_p) ;
       
   869 
       
   870     if (dev_p->usb_count == 1)
       
   871     {
       
   872         /* Create the request to send to the West Bridge device */
       
   873         req_p = CyAsLLCreateRequest(dev_p, CY_RQT_STOP_USB, CY_RQT_USB_RQT_CONTEXT, 0) ;
       
   874         if (req_p == 0)
       
   875         {
       
   876             ret = CY_AS_ERROR_OUT_OF_MEMORY ;
       
   877             goto destroy ;
       
   878         }
       
   879 
       
   880         /* Reserve space for the reply, the reply data will not exceed one word */
       
   881         reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
   882         if (reply_p == 0)
       
   883         {
       
   884             ret = CY_AS_ERROR_OUT_OF_MEMORY ;
       
   885             goto destroy ;
       
   886         }
       
   887 
       
   888         if(cb == 0)
       
   889         {
       
   890             ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
   891             if (ret != CY_AS_ERROR_SUCCESS)
       
   892                 goto destroy ;
       
   893 
       
   894             return MyHandleResponseUsbStop(dev_p, req_p, reply_p, ret) ;
       
   895         }
       
   896         else
       
   897         {
       
   898             ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_STOP,
       
   899                 0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
   900                 CyAsUsbFuncCallback) ;
       
   901 
       
   902             if (ret != CY_AS_ERROR_SUCCESS)
       
   903                 goto destroy ;
       
   904 
       
   905             return ret ;
       
   906         }
       
   907 
       
   908 destroy:
       
   909         CyAsLLDestroyRequest(dev_p, req_p) ;
       
   910         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
   911     }
       
   912     else if (dev_p->usb_count > 1)
       
   913     {
       
   914         /*
       
   915          * Reset all LEPs to inactive state, after cleaning up any
       
   916          * pending async read/write calls.
       
   917          */
       
   918         CyAsUsbReset(dev_p) ;
       
   919         dev_p->usb_count-- ;
       
   920 
       
   921         if (cb)
       
   922             cb(handle, ret, client, CY_FUNCT_CB_USB_STOP, 0) ;
       
   923     }
       
   924 
       
   925     CyAsDeviceClearUSSPending(dev_p) ;
       
   926 
       
   927     return ret ;
       
   928 }
       
   929 
       
   930 /*
       
   931 * This function registers a callback to be called when USB events are processed
       
   932 */
       
   933 CyAsReturnStatus_t
       
   934 CyAsUsbRegisterCallback(CyAsDeviceHandle handle, CyAsUsbEventCallback callback)
       
   935 {
       
   936     CyAsDevice*dev_p ;
       
   937 
       
   938     CyAsLogDebugMessage(6, "CyAsUsbRegisterCallback called") ;
       
   939 
       
   940     dev_p = (CyAsDevice *)handle ;
       
   941     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
   942         return CY_AS_ERROR_INVALID_HANDLE ;
       
   943 
       
   944     if (!CyAsDeviceIsConfigured(dev_p))
       
   945         return CY_AS_ERROR_NOT_CONFIGURED ;
       
   946 
       
   947     if (!CyAsDeviceIsFirmwareLoaded(dev_p))
       
   948         return CY_AS_ERROR_NO_FIRMWARE ;
       
   949 
       
   950     dev_p->usb_event_cb = NULL ;
       
   951     dev_p->usb_event_cb_ms = callback ;
       
   952     return CY_AS_ERROR_SUCCESS ;
       
   953 }
       
   954 
       
   955 
       
   956 static CyAsReturnStatus_t
       
   957 MyHandleResponseNoData(CyAsDevice* dev_p,
       
   958                          CyAsLLRequestResponse *req_p,
       
   959                          CyAsLLRequestResponse *reply_p)
       
   960 {
       
   961     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
   962 
       
   963     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
   964         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
   965     else
       
   966         ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
   967 
       
   968     CyAsLLDestroyRequest(dev_p, req_p) ;
       
   969     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
   970 
       
   971     return ret ;
       
   972 }
       
   973 
       
   974 static CyAsReturnStatus_t
       
   975 MyHandleResponseConnect(CyAsDevice* dev_p,
       
   976                        CyAsLLRequestResponse *req_p,
       
   977                        CyAsLLRequestResponse *reply_p,
       
   978                        CyAsReturnStatus_t ret)
       
   979 {
       
   980     if (ret != CY_AS_ERROR_SUCCESS)
       
   981         goto destroy ;
       
   982 
       
   983     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
   984     {
       
   985         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
   986         goto destroy ;
       
   987     }
       
   988 
       
   989     ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
   990     if (ret == CY_AS_ERROR_SUCCESS)
       
   991         CyAsDeviceSetUsbConnected(dev_p) ;
       
   992 
       
   993 destroy :
       
   994     CyAsLLDestroyRequest(dev_p, req_p) ;
       
   995     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
   996 
       
   997     return ret ;
       
   998 }
       
   999 
       
  1000 
       
  1001 /*
       
  1002 * This method asks the West Bridge device to connect the internal USB D+ and D- signals to the USB
       
  1003 * pins, thus starting the enumeration processes if the external pins are connnected to a USB host.
       
  1004 * If the external pins are not connect to a USB host, enumeration will begin as soon as the USB
       
  1005 * pins are connected to a host.
       
  1006 */
       
  1007 CyAsReturnStatus_t
       
  1008 CyAsUsbConnect(CyAsDeviceHandle handle,
       
  1009                  CyAsFunctionCallback cb,
       
  1010                  uint32_t client)
       
  1011 {
       
  1012     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1013     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1014 
       
  1015     CyAsDevice*dev_p ;
       
  1016 
       
  1017     CyAsLogDebugMessage(6, "CyAsUsbConnect called") ;
       
  1018 
       
  1019     dev_p = (CyAsDevice *)handle ;
       
  1020     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1021         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1022 
       
  1023     ret = IsUsbActive(dev_p) ;
       
  1024     if (ret != CY_AS_ERROR_SUCCESS)
       
  1025         return ret ;
       
  1026 
       
  1027     if (CyAsDeviceIsInCallback(dev_p))
       
  1028         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1029 
       
  1030     /* Create the request to send to the West Bridge device */
       
  1031     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1) ;
       
  1032     if (req_p == 0)
       
  1033         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1034 
       
  1035     /* 1 = Connect request */
       
  1036     CyAsLLRequestResponse_SetWord(req_p, 0, 1) ;
       
  1037 
       
  1038     /* Reserve space for the reply, the reply data will not exceed one word */
       
  1039     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  1040     if (reply_p == 0)
       
  1041     {
       
  1042         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1043         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1044     }
       
  1045 
       
  1046     if(cb == 0)
       
  1047     {
       
  1048         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1049         if (ret != CY_AS_ERROR_SUCCESS)
       
  1050             goto destroy ;
       
  1051 
       
  1052         return MyHandleResponseConnect(dev_p, req_p, reply_p, ret) ;
       
  1053     }
       
  1054     else
       
  1055     {
       
  1056         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_CONNECT,
       
  1057             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  1058             CyAsUsbFuncCallback) ;
       
  1059 
       
  1060         if (ret != CY_AS_ERROR_SUCCESS)
       
  1061             goto destroy ;
       
  1062 
       
  1063         return ret ;
       
  1064     }
       
  1065 
       
  1066 destroy:
       
  1067     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1068     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1069 
       
  1070     return ret ;
       
  1071 }
       
  1072 
       
  1073 static CyAsReturnStatus_t
       
  1074 MyHandleResponseDisconnect(CyAsDevice* dev_p,
       
  1075                        CyAsLLRequestResponse *req_p,
       
  1076                        CyAsLLRequestResponse *reply_p,
       
  1077                        CyAsReturnStatus_t ret)
       
  1078 {
       
  1079     if (ret != CY_AS_ERROR_SUCCESS)
       
  1080         goto destroy ;
       
  1081 
       
  1082     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
  1083     {
       
  1084         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  1085         goto destroy ;
       
  1086     }
       
  1087 
       
  1088     ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  1089     if (ret == CY_AS_ERROR_SUCCESS)
       
  1090         CyAsDeviceClearUsbConnected(dev_p) ;
       
  1091 
       
  1092 destroy :
       
  1093     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1094     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1095 
       
  1096     return ret ;
       
  1097 }
       
  1098 /*
       
  1099 * This method forces a disconnect of the D+ and D- pins external to the West Bridge device from the
       
  1100 * D+ and D- signals internally, effectively disconnecting the West Bridge device from any connectec
       
  1101 * USB host.
       
  1102 */
       
  1103 CyAsReturnStatus_t
       
  1104 CyAsUsbDisconnect(CyAsDeviceHandle handle,
       
  1105                     CyAsFunctionCallback cb,
       
  1106                     uint32_t client)
       
  1107 {
       
  1108     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1109     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1110 
       
  1111     CyAsDevice*dev_p ;
       
  1112 
       
  1113     CyAsLogDebugMessage(6, "CyAsUsbDisconnect called") ;
       
  1114 
       
  1115     dev_p = (CyAsDevice *)handle ;
       
  1116     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1117         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1118 
       
  1119     ret = IsUsbActive(dev_p) ;
       
  1120     if (ret != CY_AS_ERROR_SUCCESS)
       
  1121         return ret ;
       
  1122 
       
  1123     if (CyAsDeviceIsInCallback(dev_p))
       
  1124         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1125 
       
  1126     if (!CyAsDeviceIsUsbConnected(dev_p))
       
  1127         return CY_AS_ERROR_USB_NOT_CONNECTED ;
       
  1128 
       
  1129     /* Create the request to send to the West Bridge device */
       
  1130     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1) ;
       
  1131     if (req_p == 0)
       
  1132         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1133 
       
  1134     CyAsLLRequestResponse_SetWord(req_p, 0, 0) ;
       
  1135 
       
  1136     /* Reserve space for the reply, the reply data will not exceed two bytes */
       
  1137     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  1138     if (reply_p == 0)
       
  1139     {
       
  1140         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1141         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1142     }
       
  1143 
       
  1144     if(cb == 0)
       
  1145     {
       
  1146         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1147         if (ret != CY_AS_ERROR_SUCCESS)
       
  1148             goto destroy ;
       
  1149 
       
  1150         return MyHandleResponseDisconnect(dev_p, req_p, reply_p, ret) ;
       
  1151     }
       
  1152     else
       
  1153     {
       
  1154         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_DISCONNECT,
       
  1155             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  1156             CyAsUsbFuncCallback) ;
       
  1157 
       
  1158         if (ret != CY_AS_ERROR_SUCCESS)
       
  1159             goto destroy ;
       
  1160 
       
  1161         return ret ;
       
  1162     }
       
  1163 destroy:
       
  1164     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1165     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1166 
       
  1167     return ret ;
       
  1168 }
       
  1169 
       
  1170 static CyAsReturnStatus_t
       
  1171 MyHandleResponseSetEnumConfig(CyAsDevice* dev_p,
       
  1172                          CyAsLLRequestResponse *req_p,
       
  1173                          CyAsLLRequestResponse *reply_p)
       
  1174 {
       
  1175     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1176 
       
  1177     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
  1178     {
       
  1179         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  1180         goto destroy ;
       
  1181     }
       
  1182 
       
  1183     ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  1184 
       
  1185     if (ret == CY_AS_ERROR_SUCCESS)
       
  1186     {
       
  1187         /*
       
  1188         * We configured the West Bridge device and enumeration is going to happen
       
  1189         * on the P port processor.  Now we must enable endpoint zero
       
  1190         */
       
  1191         CyAsUsbEndPointConfig config ;
       
  1192 
       
  1193         config.dir = CyAsUsbInOut ;
       
  1194         config.type = CyAsUsbControl ;
       
  1195         config.enabled = CyTrue ;
       
  1196 
       
  1197         ret = CyAsUsbSetEndPointConfig((CyAsDeviceHandle*)dev_p, 0, &config) ;
       
  1198     }
       
  1199 
       
  1200 destroy :
       
  1201         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1202         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1203 
       
  1204         return ret ;
       
  1205 }
       
  1206 
       
  1207 /*
       
  1208 * This method sets how the USB is enumerated and should be called before the
       
  1209 * CyAsUsbConnect() is called.
       
  1210 */
       
  1211 static CyAsReturnStatus_t
       
  1212 MyUsbSetEnumConfig(CyAsDevice *dev_p,
       
  1213                     uint8_t bus_mask,
       
  1214                     uint8_t media_mask,
       
  1215                     CyBool use_antioch_enumeration,
       
  1216                     uint8_t mass_storage_interface,
       
  1217                     uint8_t mtp_interface,
       
  1218                     CyBool mass_storage_callbacks,
       
  1219                     CyAsFunctionCallback cb,
       
  1220                     uint32_t client)
       
  1221 {
       
  1222     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1223     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1224 
       
  1225     CyAsLogDebugMessage(6, "CyAsUsbSetEnumConfig called") ;
       
  1226 
       
  1227     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1228         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1229 
       
  1230     ret = IsUsbActive(dev_p) ;
       
  1231     if (ret != CY_AS_ERROR_SUCCESS)
       
  1232         return ret ;
       
  1233 
       
  1234     if (CyAsDeviceIsUsbConnected(dev_p))
       
  1235         return CY_AS_ERROR_USB_CONNECTED ;
       
  1236 
       
  1237     if (CyAsDeviceIsInCallback(dev_p))
       
  1238         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1239 
       
  1240     /* if we are using MTP firmware:  */
       
  1241     if (dev_p->is_mtp_firmware == 1)
       
  1242     {
       
  1243         if (mass_storage_interface != 0) /* we can not enemurate MSC */
       
  1244             return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1245 
       
  1246         if (bus_mask == 0)
       
  1247         {
       
  1248             if (mtp_interface != 0)
       
  1249                 return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1250         }
       
  1251         else if (bus_mask == 2)
       
  1252         {
       
  1253             /* enable EP 1 as it will be used */
       
  1254             CyAsDmaEnableEndPoint(dev_p, 1, CyTrue, CyAsDirectionIn) ;
       
  1255             dev_p->usb_config[1].enabled = CyTrue ;
       
  1256             dev_p->usb_config[1].dir = CyAsUsbIn ;
       
  1257             dev_p->usb_config[1].type = CyAsUsbInt ;
       
  1258         }
       
  1259         else
       
  1260         {
       
  1261             return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1262         }
       
  1263     }
       
  1264     else if (mtp_interface != 0) /* if we are not using MTP firmware, we can not enumerate MTP */
       
  1265         return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1266 
       
  1267     /*
       
  1268     * If we are not enumerating mass storage, we should not be providing an interface
       
  1269     * number.
       
  1270     */
       
  1271     if (bus_mask == 0 && mass_storage_interface != 0)
       
  1272         return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1273 
       
  1274     /*
       
  1275     * If we are going to use mtp_interface, bus mask must be 2.
       
  1276     */
       
  1277     if (mtp_interface != 0 && bus_mask != 2)
       
  1278         return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1279 
       
  1280 
       
  1281     /* Create the request to send to the West Bridge device */
       
  1282     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 4) ;
       
  1283     if (req_p == 0)
       
  1284         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1285 
       
  1286     /* Marshal the structure */
       
  1287     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((media_mask << 8) | bus_mask)) ;
       
  1288     CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)use_antioch_enumeration) ;
       
  1289     CyAsLLRequestResponse_SetWord(req_p, 2, dev_p->is_mtp_firmware ? mtp_interface : mass_storage_interface) ;
       
  1290     CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)mass_storage_callbacks) ;
       
  1291 
       
  1292     /* Reserve space for the reply, the reply data will not exceed one word */
       
  1293     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  1294     if (reply_p == 0)
       
  1295     {
       
  1296         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1297         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1298     }
       
  1299 
       
  1300     if(cb == 0)
       
  1301     {
       
  1302 
       
  1303         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1304         if (ret != CY_AS_ERROR_SUCCESS)
       
  1305             goto destroy ;
       
  1306 
       
  1307         return MyHandleResponseSetEnumConfig(dev_p, req_p, reply_p) ;
       
  1308     }
       
  1309     else
       
  1310     {
       
  1311         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_SETENUMCONFIG,
       
  1312             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  1313             CyAsUsbFuncCallback) ;
       
  1314 
       
  1315         if (ret != CY_AS_ERROR_SUCCESS)
       
  1316             goto destroy ;
       
  1317 
       
  1318         return ret ;
       
  1319     }
       
  1320 
       
  1321 destroy:
       
  1322     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1323     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1324 
       
  1325     return ret ;
       
  1326 }
       
  1327 
       
  1328 /*
       
  1329  * This method sets how the USB is enumerated and should be called before the
       
  1330  * CyAsUsbConnect() is called.
       
  1331  */
       
  1332 CyAsReturnStatus_t
       
  1333 CyAsUsbSetEnumConfig(CyAsDeviceHandle handle,
       
  1334                        CyAsUsbEnumControl *config_p,
       
  1335                        CyAsFunctionCallback cb,
       
  1336                        uint32_t client)
       
  1337 {
       
  1338     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  1339     uint8_t bus_mask, media_mask ;
       
  1340     uint32_t bus, device ;
       
  1341     CyAsReturnStatus_t ret ;
       
  1342 
       
  1343     dev_p = (CyAsDevice *)handle ;
       
  1344     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1345         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1346 
       
  1347     ret = IsUsbActive(dev_p) ;
       
  1348     if (ret != CY_AS_ERROR_SUCCESS)
       
  1349         return ret ;
       
  1350 
       
  1351     if ((CyAsDeviceIsInCallback(dev_p))  && (cb != 0))
       
  1352         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1353 
       
  1354     /* Since we are mapping the media types to bus with NAND to 0 and the rest
       
  1355      * to 1, and we are only allowing for enumerating all the devices on a bus
       
  1356      * we just scan the array for any positions where there a device is enabled
       
  1357      * and mark the bus to be enumerated.
       
  1358      */
       
  1359     bus_mask   = 0 ;
       
  1360     media_mask = 0 ;
       
  1361     media_mask = 0 ;
       
  1362     for( bus = 0; bus < CY_AS_MAX_BUSES; bus++)
       
  1363     {
       
  1364         for( device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++)
       
  1365         {
       
  1366             if (config_p->devices_to_enumerate[bus][device] == CyTrue)
       
  1367             {
       
  1368                 bus_mask   |= (0x01 << bus) ;
       
  1369                 media_mask |= dev_p->media_supported[bus] ;
       
  1370                 media_mask |= dev_p->media_supported[bus] ;
       
  1371             }
       
  1372         }
       
  1373     }
       
  1374 
       
  1375     return MyUsbSetEnumConfig(dev_p, bus_mask,media_mask,
       
  1376             config_p->antioch_enumeration,
       
  1377             config_p->mass_storage_interface,
       
  1378             config_p->mtp_interface,
       
  1379             config_p->mass_storage_callbacks,
       
  1380             cb,
       
  1381             client
       
  1382         ) ;
       
  1383 }
       
  1384 
       
  1385 
       
  1386 static CyAsReturnStatus_t
       
  1387 MyHandleResponseGetEnumConfig(CyAsDevice* dev_p,
       
  1388                          CyAsLLRequestResponse *req_p,
       
  1389                          CyAsLLRequestResponse *reply_p,
       
  1390                          void* config_p)
       
  1391 {
       
  1392     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1393     uint16_t val ;
       
  1394     uint8_t bus_mask ;
       
  1395     uint32_t bus ;
       
  1396 
       
  1397     if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_USB_CONFIG)
       
  1398     {
       
  1399         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  1400         goto destroy ;
       
  1401     }
       
  1402 
       
  1403     /* Marshal the reply */
       
  1404     if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
       
  1405     {
       
  1406         uint32_t device ;
       
  1407         CyBool state;
       
  1408         CyAsUsbEnumControl *ms_config_p = (CyAsUsbEnumControl*)config_p;
       
  1409 
       
  1410         bus_mask = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0) & 0xFF) ;
       
  1411         for( bus = 0; bus < CY_AS_MAX_BUSES; bus++)
       
  1412         {
       
  1413             if (bus_mask & (1 << bus))
       
  1414                 state = CyTrue ;
       
  1415             else
       
  1416                 state = CyFalse ;
       
  1417 
       
  1418             for( device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++)
       
  1419             {
       
  1420                 ms_config_p->devices_to_enumerate[bus][device] = state ;
       
  1421             }
       
  1422         }
       
  1423 
       
  1424         ms_config_p->antioch_enumeration = (CyBool)CyAsLLRequestResponse_GetWord(reply_p, 1) ;
       
  1425 
       
  1426         val = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
       
  1427         if (dev_p->is_mtp_firmware)
       
  1428         {
       
  1429             ms_config_p->mass_storage_interface = 0 ;
       
  1430             ms_config_p->mtp_interface          = (uint8_t)(val & 0xFF) ;
       
  1431         }
       
  1432         else
       
  1433         {
       
  1434             ms_config_p->mass_storage_interface = (uint8_t)(val & 0xFF) ;
       
  1435             ms_config_p->mtp_interface          = 0 ;
       
  1436         }
       
  1437         ms_config_p->mass_storage_callbacks = (CyBool)(val >> 8) ;
       
  1438 
       
  1439         /*
       
  1440         * Firmware returns an invalid interface number for mass storage,
       
  1441         * if mass storage is not enabled. This needs to be converted to zero
       
  1442         * to match the input configuration.
       
  1443         */
       
  1444         if (bus_mask == 0)
       
  1445         {
       
  1446             if (dev_p->is_mtp_firmware)
       
  1447                 ms_config_p->mtp_interface = 0 ;
       
  1448             else
       
  1449                 ms_config_p->mass_storage_interface = 0 ;
       
  1450         }
       
  1451     }
       
  1452     else
       
  1453     {
       
  1454         CyAsUsbEnumControl_dep *ex_config_p = (CyAsUsbEnumControl_dep*)config_p;
       
  1455 
       
  1456         ex_config_p->enum_mass_storage = (uint8_t)((CyAsLLRequestResponse_GetWord(reply_p, 0) >> 8) & 0xFF) ;
       
  1457         ex_config_p->antioch_enumeration = (CyBool)CyAsLLRequestResponse_GetWord(reply_p, 1) ;
       
  1458 
       
  1459         val = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
       
  1460         ex_config_p->mass_storage_interface = (uint8_t)(val & 0xFF) ;
       
  1461         ex_config_p->mass_storage_callbacks = (CyBool)(val >> 8) ;
       
  1462 
       
  1463         /*
       
  1464         * Firmware returns an invalid interface number for mass storage,
       
  1465         * if mass storage is not enabled. This needs to be converted to zero
       
  1466         * to match the input configuration.
       
  1467         */
       
  1468         if (ex_config_p->enum_mass_storage == 0)
       
  1469             ex_config_p->mass_storage_interface = 0 ;
       
  1470     }
       
  1471 
       
  1472 destroy :
       
  1473     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1474     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1475 
       
  1476     return ret ;
       
  1477 }
       
  1478 
       
  1479 /*
       
  1480 * This sets up the request for the enumerateion configuration information, based on if the request is from
       
  1481 * the old pre-1.2 functions.
       
  1482 */
       
  1483 static CyAsReturnStatus_t
       
  1484 MyUsbGetEnumConfig(CyAsDeviceHandle handle,
       
  1485                     uint16_t req_flags,
       
  1486                     void* config_p,
       
  1487                     CyAsFunctionCallback cb,
       
  1488                     uint32_t client)
       
  1489 {
       
  1490     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1491     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1492 
       
  1493     CyAsDevice*dev_p ;
       
  1494 
       
  1495     CyAsLogDebugMessage(6, "CyAsUsbGetEnumConfig called") ;
       
  1496 
       
  1497     dev_p = (CyAsDevice *)handle ;
       
  1498     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1499         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1500 
       
  1501     ret = IsUsbActive(dev_p) ;
       
  1502     if (ret != CY_AS_ERROR_SUCCESS)
       
  1503         return ret ;
       
  1504 
       
  1505     if (CyAsDeviceIsInCallback(dev_p))
       
  1506         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1507 
       
  1508     /* Create the request to send to the West Bridge device */
       
  1509     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_GET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 0) ;
       
  1510     if (req_p == 0)
       
  1511         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1512 
       
  1513     /* Reserve space for the reply, the reply data will not exceed two bytes */
       
  1514     reply_p = CyAsLLCreateResponse(dev_p, 3) ;
       
  1515     if (reply_p == 0)
       
  1516     {
       
  1517         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1518         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1519     }
       
  1520 
       
  1521     if(cb == 0)
       
  1522     {
       
  1523         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1524         if (ret != CY_AS_ERROR_SUCCESS)
       
  1525             goto destroy ;
       
  1526 
       
  1527         /* we need to know the type of request to know how to manage the data */
       
  1528         req_p->flags |= req_flags;
       
  1529         return MyHandleResponseGetEnumConfig(dev_p, req_p, reply_p, config_p) ;
       
  1530     }
       
  1531     else
       
  1532     {
       
  1533         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_GETENUMCONFIG,
       
  1534             config_p, dev_p->func_cbs_usb, req_flags, req_p, reply_p,
       
  1535             CyAsUsbFuncCallback) ;
       
  1536 
       
  1537         if (ret != CY_AS_ERROR_SUCCESS)
       
  1538             goto destroy ;
       
  1539 
       
  1540         return ret ;
       
  1541     }
       
  1542 
       
  1543 destroy:
       
  1544     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1545     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1546 
       
  1547     return ret ;
       
  1548 }
       
  1549 
       
  1550 /*
       
  1551  * This method returns the enumerateion configuration information from the West Bridge device.
       
  1552  * Generally this is not used by client software but is provided mostly for debug information.
       
  1553  * We want a method to read all state information from the device.
       
  1554  */
       
  1555 CyAsReturnStatus_t
       
  1556 CyAsUsbGetEnumConfig(CyAsDeviceHandle handle,
       
  1557                        CyAsUsbEnumControl *config_p,
       
  1558                        CyAsFunctionCallback cb,
       
  1559                        uint32_t client)
       
  1560 {
       
  1561     return MyUsbGetEnumConfig(handle, CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client);
       
  1562 }
       
  1563 
       
  1564 
       
  1565 /*
       
  1566 * This method sets the USB descriptor for a given entity.
       
  1567 */
       
  1568 CyAsReturnStatus_t
       
  1569 CyAsUsbSetDescriptor(CyAsDeviceHandle handle,
       
  1570                        CyAsUsbDescType type,
       
  1571                        uint8_t index,
       
  1572                        void *desc_p,
       
  1573                        uint16_t length,
       
  1574                        CyAsFunctionCallback cb,
       
  1575                        uint32_t client)
       
  1576 {
       
  1577     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1578     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1579     uint16_t pktlen ;
       
  1580 
       
  1581     CyAsDevice*dev_p ;
       
  1582 
       
  1583     CyAsLogDebugMessage(6, "CyAsUsbSetDescriptor called") ;
       
  1584 
       
  1585     dev_p = (CyAsDevice *)handle ;
       
  1586     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1587         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1588 
       
  1589     ret = IsUsbActive(dev_p) ;
       
  1590     if (ret != CY_AS_ERROR_SUCCESS)
       
  1591         return ret ;
       
  1592 
       
  1593     if (CyAsDeviceIsInCallback(dev_p))
       
  1594         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1595 
       
  1596     if (length > CY_AS_MAX_USB_DESCRIPTOR_SIZE)
       
  1597         return CY_AS_ERROR_INVALID_DESCRIPTOR ;
       
  1598 
       
  1599     pktlen = (uint16_t)length / 2 ;
       
  1600     if (length % 2)
       
  1601         pktlen++ ;
       
  1602     pktlen += 2 ;                       /* 1 for type, 1 for length */
       
  1603 
       
  1604     /* Create the request to send to the West Bridge device */
       
  1605     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, (uint16_t)pktlen) ;
       
  1606     if (req_p == 0)
       
  1607         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1608 
       
  1609     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((uint8_t)type | (index << 8))) ;
       
  1610     CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)length) ;
       
  1611     CyAsLLRequestResponse_Pack(req_p, 2, length, desc_p) ;
       
  1612 
       
  1613     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  1614     if (reply_p == 0)
       
  1615     {
       
  1616         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1617         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1618     }
       
  1619 
       
  1620     if(cb == 0)
       
  1621     {
       
  1622 
       
  1623         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1624         if (ret != CY_AS_ERROR_SUCCESS)
       
  1625             goto destroy ;
       
  1626 
       
  1627         return MyHandleResponseNoData(dev_p, req_p, reply_p) ;
       
  1628     }
       
  1629     else
       
  1630     {
       
  1631         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_SETDESCRIPTOR,
       
  1632             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  1633             CyAsUsbFuncCallback) ;
       
  1634 
       
  1635         if (ret != CY_AS_ERROR_SUCCESS)
       
  1636             goto destroy ;
       
  1637 
       
  1638         return ret ;
       
  1639     }
       
  1640 
       
  1641 destroy:
       
  1642     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1643     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1644 
       
  1645     return ret ;
       
  1646 }
       
  1647 
       
  1648 /*
       
  1649  * This method clears all descriptors that were previously stored on the West Bridge
       
  1650  * through CyAsUsbSetDescriptor calls.
       
  1651  */
       
  1652 CyAsReturnStatus_t
       
  1653 CyAsUsbClearDescriptors(CyAsDeviceHandle handle,
       
  1654                        CyAsFunctionCallback cb,
       
  1655                        uint32_t client)
       
  1656 {
       
  1657     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1658     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1659 
       
  1660     CyAsDevice*dev_p ;
       
  1661 
       
  1662     CyAsLogDebugMessage(6, "CyAsUsbClearDescriptors called") ;
       
  1663 
       
  1664     dev_p = (CyAsDevice *)handle ;
       
  1665     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1666         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1667 
       
  1668     ret = IsUsbActive(dev_p) ;
       
  1669     if (ret != CY_AS_ERROR_SUCCESS)
       
  1670         return ret ;
       
  1671 
       
  1672     if ((CyAsDeviceIsInCallback(dev_p)) && (cb == 0))
       
  1673         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1674 
       
  1675     /* Create the request to send to the West Bridge device */
       
  1676     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CLEAR_DESCRIPTORS, CY_RQT_USB_RQT_CONTEXT, 1) ;
       
  1677     if (req_p == 0)
       
  1678         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1679 
       
  1680     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  1681     if (reply_p == 0)
       
  1682     {
       
  1683         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1684         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1685     }
       
  1686 
       
  1687     if(cb == 0)
       
  1688     {
       
  1689 
       
  1690         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1691         if (ret != CY_AS_ERROR_SUCCESS)
       
  1692             goto destroy ;
       
  1693 
       
  1694         return MyHandleResponseNoData(dev_p, req_p, reply_p) ;
       
  1695     }
       
  1696     else
       
  1697     {
       
  1698         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_CLEARDESCRIPTORS,
       
  1699             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  1700             CyAsUsbFuncCallback) ;
       
  1701 
       
  1702         if (ret != CY_AS_ERROR_SUCCESS)
       
  1703             goto destroy ;
       
  1704 
       
  1705         return ret ;
       
  1706     }
       
  1707 
       
  1708 destroy:
       
  1709     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1710     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1711 
       
  1712     return ret ;
       
  1713 }
       
  1714 
       
  1715 static CyAsReturnStatus_t
       
  1716 MyHandleResponseGetDescriptor(CyAsDevice* dev_p,
       
  1717                          CyAsLLRequestResponse *req_p,
       
  1718                          CyAsLLRequestResponse *reply_p,
       
  1719                          CyAsGetDescriptorData* data)
       
  1720 {
       
  1721     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  1722      uint32_t retlen ;
       
  1723 
       
  1724     if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SUCCESS_FAILURE)
       
  1725     {
       
  1726         ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  1727         goto destroy ;
       
  1728     }
       
  1729     else if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_USB_DESCRIPTOR)
       
  1730     {
       
  1731         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  1732         goto destroy ;
       
  1733     }
       
  1734 
       
  1735     retlen = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  1736     if (retlen > data->length)
       
  1737     {
       
  1738         ret = CY_AS_ERROR_INVALID_SIZE ;
       
  1739         goto destroy ;
       
  1740     }
       
  1741 
       
  1742     ret = CY_AS_ERROR_SUCCESS ;
       
  1743     CyAsLLRequestResponse_Unpack(reply_p, 1, retlen, data->desc_p) ;
       
  1744 
       
  1745 
       
  1746 destroy :
       
  1747         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1748         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1749 
       
  1750         return ret ;
       
  1751 }
       
  1752 
       
  1753 /*
       
  1754 * This method retreives the USB descriptor for a given type.
       
  1755 */
       
  1756 CyAsReturnStatus_t
       
  1757 CyAsUsbGetDescriptor(CyAsDeviceHandle handle,
       
  1758                        CyAsUsbDescType type,
       
  1759                        uint8_t index,
       
  1760                        CyAsGetDescriptorData* data,
       
  1761                        CyAsFunctionCallback cb,
       
  1762                        uint32_t client)
       
  1763 {
       
  1764     CyAsReturnStatus_t ret ;
       
  1765     CyAsLLRequestResponse *req_p , *reply_p ;
       
  1766 
       
  1767     CyAsDevice*dev_p ;
       
  1768 
       
  1769     CyAsLogDebugMessage(6, "CyAsUsbGetDescriptor called") ;
       
  1770 
       
  1771     dev_p = (CyAsDevice *)handle ;
       
  1772     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1773         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1774 
       
  1775     ret = IsUsbActive(dev_p) ;
       
  1776     if (ret != CY_AS_ERROR_SUCCESS)
       
  1777         return ret ;
       
  1778 
       
  1779     if (CyAsDeviceIsInCallback(dev_p))
       
  1780         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  1781 
       
  1782     /* Create the request to send to the West Bridge device */
       
  1783     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_GET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, 1) ;
       
  1784     if (req_p == 0)
       
  1785         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1786 
       
  1787     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((uint8_t)type | (index << 8))) ;
       
  1788 
       
  1789     /* Add one for the length field */
       
  1790     reply_p = CyAsLLCreateResponse(dev_p, CY_AS_MAX_USB_DESCRIPTOR_SIZE + 1) ;
       
  1791     if (reply_p == 0)
       
  1792     {
       
  1793         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1794         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  1795     }
       
  1796 
       
  1797     if(cb == 0)
       
  1798     {
       
  1799         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  1800         if (ret != CY_AS_ERROR_SUCCESS)
       
  1801             goto destroy ;
       
  1802 
       
  1803         return MyHandleResponseGetDescriptor(dev_p, req_p, reply_p, data) ;
       
  1804     }
       
  1805     else
       
  1806     {
       
  1807         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_GETDESCRIPTOR,
       
  1808             data, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  1809             CyAsUsbFuncCallback) ;
       
  1810 
       
  1811         if (ret != CY_AS_ERROR_SUCCESS)
       
  1812             goto destroy ;
       
  1813 
       
  1814         return ret ;
       
  1815     }
       
  1816 
       
  1817 destroy:
       
  1818     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  1819     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  1820 
       
  1821     return ret ;
       
  1822 }
       
  1823 
       
  1824 CyAsReturnStatus_t
       
  1825 CyAsUsbSetPhysicalConfiguration(CyAsDeviceHandle handle, uint8_t config)
       
  1826 {
       
  1827     CyAsReturnStatus_t ret ;
       
  1828     CyAsDevice*dev_p ;
       
  1829 
       
  1830     CyAsLogDebugMessage(6, "CyAsUsbSetPhysicalConfiguration called") ;
       
  1831 
       
  1832     dev_p = (CyAsDevice *)handle ;
       
  1833     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1834         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1835 
       
  1836     ret = IsUsbActive(dev_p) ;
       
  1837     if (ret != CY_AS_ERROR_SUCCESS)
       
  1838         return ret ;
       
  1839 
       
  1840     if (CyAsDeviceIsUsbConnected(dev_p))
       
  1841         return CY_AS_ERROR_USB_CONNECTED ;
       
  1842 
       
  1843     if (config < 1 || config > 12)
       
  1844         return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1845 
       
  1846     dev_p->usb_phy_config = config ;
       
  1847 
       
  1848     return CY_AS_ERROR_SUCCESS ;
       
  1849 }
       
  1850 
       
  1851 static CyBool
       
  1852 IsPhysicalValid(uint8_t config, CyAsEndPointNumber_t ep)
       
  1853 {
       
  1854     static uint8_t validmask[12] =
       
  1855     {
       
  1856         0x0f,       /* Config  1 - 1, 2, 3, 4 */
       
  1857         0x07,       /* Config  2 - 1, 2, 3 */
       
  1858         0x07,       /* Config  3 - 1, 2, 3 */
       
  1859         0x0d,       /* Config  4 - 1, 3, 4 */
       
  1860         0x05,       /* Config  5 - 1, 3 */
       
  1861         0x05,       /* Config  6 - 1, 3 */
       
  1862         0x0d,       /* Config  7 - 1, 3, 4 */
       
  1863         0x05,       /* Config  8 - 1, 3 */
       
  1864         0x05,       /* Config  9 - 1, 3 */
       
  1865         0x0d,       /* Config 10 - 1, 3, 4 */
       
  1866         0x09,       /* Config 11 - 1, 4 */
       
  1867         0x01        /* Config 12 - 1 */
       
  1868     } ;
       
  1869 
       
  1870     return (validmask[config - 1] & (1 << (ep - 1))) ? CyTrue : CyFalse ;
       
  1871 }
       
  1872 
       
  1873 /*
       
  1874 * This method sets the configuration for an endpoint
       
  1875 */
       
  1876 CyAsReturnStatus_t
       
  1877 CyAsUsbSetEndPointConfig(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep, CyAsUsbEndPointConfig *config_p)
       
  1878 {
       
  1879     CyAsReturnStatus_t ret ;
       
  1880     CyAsDevice*dev_p ;
       
  1881 
       
  1882     CyAsLogDebugMessage(6, "CyAsUsbSetEndPointConfig called") ;
       
  1883 
       
  1884     dev_p = (CyAsDevice *)handle ;
       
  1885     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1886         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1887 
       
  1888     ret = IsUsbActive(dev_p) ;
       
  1889     if (ret != CY_AS_ERROR_SUCCESS)
       
  1890         return ret ;
       
  1891 
       
  1892     if (CyAsDeviceIsUsbConnected(dev_p))
       
  1893         return CY_AS_ERROR_USB_CONNECTED ;
       
  1894 
       
  1895     if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
       
  1896         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  1897 
       
  1898     if (ep == 0)
       
  1899     {
       
  1900         /* Endpoint 0 must be 64 byte, dir IN/OUT, and control type */
       
  1901         if (config_p->dir != CyAsUsbInOut || config_p->type != CyAsUsbControl)
       
  1902             return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1903     }
       
  1904     else if (ep == 1)
       
  1905     {
       
  1906         if ((dev_p->is_mtp_firmware == 1) && (dev_p->usb_config[1].enabled == CyTrue))
       
  1907         {
       
  1908             return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  1909         }
       
  1910 
       
  1911         /*
       
  1912          * EP1 can only be used either as an OUT ep, or as an IN ep.
       
  1913          */
       
  1914         if ((config_p->type == CyAsUsbControl) || (config_p->type == CyAsUsbIso) || (config_p->dir == CyAsUsbInOut))
       
  1915             return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1916     }
       
  1917     else
       
  1918     {
       
  1919         if (config_p->dir == CyAsUsbInOut || config_p->type == CyAsUsbControl)
       
  1920             return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1921 
       
  1922         if (!IsPhysicalValid(dev_p->usb_phy_config, config_p->physical))
       
  1923             return CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT ;
       
  1924 
       
  1925         /*
       
  1926         * ISO endpoints must be on EPs 3, 5, 7 or 9 as they need to align directly
       
  1927         * with the underlying physical endpoint.
       
  1928         */
       
  1929         if (config_p->type == CyAsUsbIso)
       
  1930         {
       
  1931             if (ep != 3 && ep != 5 && ep != 7 && ep != 9)
       
  1932                 return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1933 
       
  1934             if (ep == 3 && config_p->physical != 1)
       
  1935                 return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1936 
       
  1937             if (ep == 5 && config_p->physical != 2)
       
  1938                 return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1939 
       
  1940             if (ep == 7 && config_p->physical != 3)
       
  1941                 return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1942 
       
  1943             if (ep == 9 && config_p->physical != 4)
       
  1944                 return CY_AS_ERROR_INVALID_CONFIGURATION ;
       
  1945         }
       
  1946     }
       
  1947 
       
  1948     /* Store the configuration information until a CyAsUsbCommitConfig is done */
       
  1949     dev_p->usb_config[ep] = *config_p ;
       
  1950 
       
  1951     /* If the endpoint is enabled, enable DMA associated with the endpoint */
       
  1952     /*
       
  1953     * We make some assumptions that we check here.  We assume that the direction fields for the
       
  1954     * DMA module are the same values as the direction values for the USB module.  At some point these should
       
  1955     * be consolidated into a single enumerated type. - BWG
       
  1956     */
       
  1957     CyAsHalAssert((int)CyAsUsbIn == (int)CyAsDirectionIn);
       
  1958     CyAsHalAssert((int)CyAsUsbOut == (int)CyAsDirectionOut);
       
  1959     CyAsHalAssert((int)CyAsUsbInOut == (int)CyAsDirectionInOut) ;
       
  1960 
       
  1961     return CyAsDmaEnableEndPoint(dev_p, ep, config_p->enabled, (CyAsDmaDirection)config_p->dir) ;
       
  1962 }
       
  1963 
       
  1964 CyAsReturnStatus_t
       
  1965 CyAsUsbGetEndPointConfig(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep, CyAsUsbEndPointConfig *config_p)
       
  1966 {
       
  1967     CyAsReturnStatus_t ret ;
       
  1968 
       
  1969     CyAsDevice*dev_p ;
       
  1970 
       
  1971     CyAsLogDebugMessage(6, "CyAsUsbGetEndPointConfig called") ;
       
  1972 
       
  1973     dev_p = (CyAsDevice *)handle ;
       
  1974     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  1975         return CY_AS_ERROR_INVALID_HANDLE ;
       
  1976 
       
  1977     ret = IsUsbActive(dev_p) ;
       
  1978     if (ret != CY_AS_ERROR_SUCCESS)
       
  1979         return ret ;
       
  1980 
       
  1981     if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
       
  1982         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  1983 
       
  1984     *config_p = dev_p->usb_config[ep] ;
       
  1985 
       
  1986     return CY_AS_ERROR_SUCCESS ;
       
  1987 }
       
  1988 
       
  1989 /*
       
  1990 * Commit the configuration of the various endpoints to the hardware.
       
  1991 */
       
  1992 CyAsReturnStatus_t
       
  1993 CyAsUsbCommitConfig(CyAsDeviceHandle handle,
       
  1994                       CyAsFunctionCallback cb,
       
  1995                       uint32_t client)
       
  1996 {
       
  1997     uint32_t i ;
       
  1998     CyAsReturnStatus_t ret ;
       
  1999     CyAsLLRequestResponse *req_p , *reply_p ;
       
  2000     CyAsDevice*dev_p ;
       
  2001     uint16_t data ;
       
  2002 
       
  2003     CyAsLogDebugMessage(6, "CyAsUsbCommitConfig called") ;
       
  2004 
       
  2005     dev_p = (CyAsDevice *)handle ;
       
  2006     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2007         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2008 
       
  2009     ret = IsUsbActive(dev_p) ;
       
  2010     if (ret != CY_AS_ERROR_SUCCESS)
       
  2011         return ret ;
       
  2012 
       
  2013     if (CyAsDeviceIsUsbConnected(dev_p))
       
  2014         return CY_AS_ERROR_USB_CONNECTED ;
       
  2015 
       
  2016     if (CyAsDeviceIsInCallback(dev_p))
       
  2017         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  2018 
       
  2019     /*
       
  2020     * This performs the mapping based on informatation that was previously
       
  2021     * stored on the device about the various endpoints and how they are configured.  The
       
  2022     * output of this mapping is setting the the 14 register values contained in usb_lepcfg
       
  2023     * and usb_pepcfg
       
  2024     */
       
  2025     ret = CyAsUsbMapLogical2Physical(dev_p) ;
       
  2026     if (ret != CY_AS_ERROR_SUCCESS)
       
  2027         return ret ;
       
  2028 
       
  2029     /*
       
  2030     * Now, package the information about the various logical and physical
       
  2031     * endpoint configuration registers and send it across to the West Bridge
       
  2032     * device.
       
  2033     */
       
  2034     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_USB_CONFIG_REGISTERS, CY_RQT_USB_RQT_CONTEXT, 8) ;
       
  2035     if (req_p == 0)
       
  2036         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2037 
       
  2038     CyAsHalPrintMessage("USB Configuration: %d\n", dev_p->usb_phy_config) ;
       
  2039     CyAsHalPrintMessage("EP1OUT: 0x%02x EP1IN: 0x%02x\n", dev_p->usb_ep1cfg[0], dev_p->usb_ep1cfg[1]) ;
       
  2040     CyAsHalPrintMessage("PEP Registers: 0x%02x 0x%02x 0x%02x 0x%02x\n", dev_p->usb_pepcfg[0],
       
  2041         dev_p->usb_pepcfg[1], dev_p->usb_pepcfg[2], dev_p->usb_pepcfg[3]) ;
       
  2042 
       
  2043     CyAsHalPrintMessage("LEP Registers: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
       
  2044         dev_p->usb_lepcfg[0],dev_p->usb_lepcfg[1], dev_p->usb_lepcfg[2], dev_p->usb_lepcfg[3],
       
  2045         dev_p->usb_lepcfg[4],dev_p->usb_lepcfg[5], dev_p->usb_lepcfg[6], dev_p->usb_lepcfg[7],
       
  2046         dev_p->usb_lepcfg[8],dev_p->usb_lepcfg[9]) ;
       
  2047 
       
  2048     /* Write the EP1OUTCFG and EP1INCFG data in the first word. */
       
  2049     data = (uint16_t)((dev_p->usb_ep1cfg[0] << 8) | dev_p->usb_ep1cfg[1]) ;
       
  2050     CyAsLLRequestResponse_SetWord(req_p, 0, data) ;
       
  2051 
       
  2052     /* Write the PEP CFG data in the next 2 words */
       
  2053     for(i = 0 ; i < 4 ; i += 2)
       
  2054     {
       
  2055         data = (uint16_t)((dev_p->usb_pepcfg[i] << 8) | dev_p->usb_pepcfg[i + 1]) ;
       
  2056         CyAsLLRequestResponse_SetWord(req_p, 1 + i / 2, data) ;
       
  2057     }
       
  2058 
       
  2059     /* Write the LEP CFG data in the next 5 words */
       
  2060     for(i = 0 ; i < 10 ; i += 2)
       
  2061     {
       
  2062         data = (uint16_t)((dev_p->usb_lepcfg[i] << 8) | dev_p->usb_lepcfg[i + 1]) ;
       
  2063         CyAsLLRequestResponse_SetWord(req_p, 3 + i / 2, data) ;
       
  2064     }
       
  2065 
       
  2066     /* A single status word response type */
       
  2067     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2068     if (reply_p == 0)
       
  2069     {
       
  2070         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2071         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2072     }
       
  2073 
       
  2074     if(cb == 0)
       
  2075     {
       
  2076         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  2077         if (ret != CY_AS_ERROR_SUCCESS)
       
  2078             goto destroy ;
       
  2079 
       
  2080         ret = MyHandleResponseNoData(dev_p, req_p, reply_p) ;
       
  2081 
       
  2082         if (ret == CY_AS_ERROR_SUCCESS)
       
  2083             ret = CyAsUsbSetupDma(dev_p) ;
       
  2084 
       
  2085         return ret ;
       
  2086     }
       
  2087     else
       
  2088     {
       
  2089         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_COMMITCONFIG,
       
  2090             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  2091             CyAsUsbFuncCallback) ;
       
  2092 
       
  2093         if (ret != CY_AS_ERROR_SUCCESS)
       
  2094             goto destroy ;
       
  2095 
       
  2096         return ret ;
       
  2097     }
       
  2098 
       
  2099 destroy:
       
  2100     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2101     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  2102 
       
  2103     return ret ;
       
  2104 }
       
  2105 
       
  2106 static void
       
  2107 SyncRequestCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
       
  2108 {
       
  2109     (void)ep ;
       
  2110     (void)buf_p ;
       
  2111 
       
  2112     dev_p->usb_error = err ;
       
  2113     dev_p->usb_actual_cnt = size ;
       
  2114 }
       
  2115 
       
  2116 static void
       
  2117 AsyncReadRequestCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
       
  2118 {
       
  2119     CyAsDeviceHandle h ;
       
  2120 
       
  2121     CyAsLogDebugMessage(6, "AsyncReadRequestCallback called") ;
       
  2122 
       
  2123     h = (CyAsDeviceHandle)dev_p ;
       
  2124 
       
  2125     if (ep == 0 && CyAsDeviceIsAckDelayed(dev_p))
       
  2126     {
       
  2127         dev_p->usb_pending_buffer = buf_p ;
       
  2128         dev_p->usb_pending_size = size ;
       
  2129         dev_p->usb_error = err ;
       
  2130         CyAsUsbAckSetupPacket(h, UsbAckCallback, 0) ;
       
  2131     }
       
  2132     else
       
  2133     {
       
  2134         CyAsUsbIoCallback cb ;
       
  2135 
       
  2136         cb = dev_p->usb_cb[ep] ;
       
  2137         dev_p->usb_cb[ep] = 0 ;
       
  2138         CyAsDeviceClearUsbAsyncPending(dev_p, ep) ;
       
  2139         if (cb)
       
  2140             cb(h, ep, size, buf_p, err) ;
       
  2141     }
       
  2142 }
       
  2143 
       
  2144 static void
       
  2145 AsyncWriteRequestCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
       
  2146 {
       
  2147     CyAsDeviceHandle h ;
       
  2148 
       
  2149     CyAsLogDebugMessage(6, "AsyncWriteRequestCallback called") ;
       
  2150 
       
  2151     h = (CyAsDeviceHandle)dev_p ;
       
  2152 
       
  2153     if (ep == 0 && CyAsDeviceIsAckDelayed(dev_p))
       
  2154     {
       
  2155         dev_p->usb_pending_buffer = buf_p ;
       
  2156         dev_p->usb_pending_size = size ;
       
  2157         dev_p->usb_error = err ;
       
  2158 
       
  2159         /* The west bridge protocol generates ZLPs as required. */
       
  2160         CyAsUsbAckSetupPacket(h, UsbAckCallback, 0) ;
       
  2161     }
       
  2162     else
       
  2163     {
       
  2164         CyAsUsbIoCallback cb ;
       
  2165 
       
  2166         cb = dev_p->usb_cb[ep] ;
       
  2167         dev_p->usb_cb[ep] = 0 ;
       
  2168 
       
  2169         CyAsDeviceClearUsbAsyncPending(dev_p, ep) ;
       
  2170         if (cb)
       
  2171             cb(h, ep, size, buf_p, err) ;
       
  2172     }
       
  2173 }
       
  2174 
       
  2175 static void
       
  2176 MyTurboRqtCallback(CyAsDevice *dev_p,
       
  2177                     uint8_t context,
       
  2178                     CyAsLLRequestResponse *rqt,
       
  2179                     CyAsLLRequestResponse *resp,
       
  2180                     CyAsReturnStatus_t stat)
       
  2181 {
       
  2182     uint8_t code ;
       
  2183 
       
  2184     (void)context ;
       
  2185     (void)stat ;
       
  2186 
       
  2187     /* The Handlers are responsible for Deleting the rqt and resp when
       
  2188      * they are finished
       
  2189      */
       
  2190     code = CyAsLLRequestResponse_GetCode(rqt) ;
       
  2191     switch(code)
       
  2192     {
       
  2193     case CY_RQT_TURBO_SWITCH_ENDPOINT:
       
  2194         CyAsHalAssert(stat == CY_AS_ERROR_SUCCESS) ;
       
  2195         CyAsLLDestroyRequest(dev_p, rqt) ;
       
  2196         CyAsLLDestroyResponse(dev_p, resp) ;
       
  2197         break;
       
  2198     default:
       
  2199         CyAsHalAssert(CyFalse) ;
       
  2200         break ;
       
  2201     }
       
  2202 }
       
  2203 
       
  2204 /* Send a mailbox request to prepare the endpoint for switching */
       
  2205 static CyAsReturnStatus_t
       
  2206 MySendTurboSwitch(CyAsDevice* dev_p, uint32_t size, CyBool pktread)
       
  2207 {
       
  2208     CyAsReturnStatus_t ret ;
       
  2209     CyAsLLRequestResponse *req_p , *reply_p ;
       
  2210 
       
  2211     /* Create the request to send to the West Bridge device */
       
  2212     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_TURBO_SWITCH_ENDPOINT, CY_RQT_TUR_RQT_CONTEXT, 3) ;
       
  2213     if (req_p == 0)
       
  2214         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2215 
       
  2216     /* Reserve space for the reply, the reply data will not exceed one word */
       
  2217     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2218     if (reply_p == 0)
       
  2219     {
       
  2220         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2221         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2222     }
       
  2223 
       
  2224     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)pktread) ;
       
  2225     CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((size >> 16) & 0xFFFF)) ;
       
  2226     CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(size & 0xFFFF)) ;
       
  2227 
       
  2228     ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, MyTurboRqtCallback) ;
       
  2229     if (ret != CY_AS_ERROR_SUCCESS)
       
  2230     {
       
  2231         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2232         CyAsLLDestroyRequest(dev_p, reply_p) ;
       
  2233         return ret ;
       
  2234     }
       
  2235 
       
  2236     return CY_AS_ERROR_SUCCESS ;
       
  2237 }
       
  2238 
       
  2239 CyAsReturnStatus_t
       
  2240 CyAsUsbReadData(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep, CyBool pktread, uint32_t dsize, uint32_t *dataread, void *data)
       
  2241 {
       
  2242     CyAsReturnStatus_t ret ;
       
  2243     CyAsDevice *dev_p ;
       
  2244 
       
  2245     CyAsLogDebugMessage(6, "CyAsUsbReadData called") ;
       
  2246 
       
  2247     dev_p = (CyAsDevice *)handle ;
       
  2248     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2249         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2250 
       
  2251     ret = IsUsbActive(dev_p) ;
       
  2252     if (ret != CY_AS_ERROR_SUCCESS)
       
  2253         return ret ;
       
  2254 
       
  2255     if (CyAsDeviceIsInCallback(dev_p))
       
  2256         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  2257 
       
  2258     if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
       
  2259         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2260 
       
  2261     /* EP2 is available for reading when MTP is active */
       
  2262     if(dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
       
  2263         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2264 
       
  2265     /* If the endpoint is disabled, we cannot write data to the endpoint */
       
  2266     if (!dev_p->usb_config[ep].enabled)
       
  2267         return CY_AS_ERROR_ENDPOINT_DISABLED ;
       
  2268 
       
  2269     if (dev_p->usb_config[ep].dir != CyAsUsbOut)
       
  2270         return CY_AS_ERROR_USB_BAD_DIRECTION ;
       
  2271 
       
  2272     ret = CyAsDmaQueueRequest(dev_p, ep, data, dsize, pktread, CyTrue, SyncRequestCallback) ;
       
  2273     if (ret != CY_AS_ERROR_SUCCESS)
       
  2274         return ret ;
       
  2275 
       
  2276     if (ep == CY_AS_MTP_READ_ENDPOINT )
       
  2277     {
       
  2278         ret = MySendTurboSwitch(dev_p, dsize, pktread) ;
       
  2279         if (ret != CY_AS_ERROR_SUCCESS)
       
  2280         {
       
  2281             CyAsDmaCancel(dev_p, ep, ret) ;
       
  2282             return ret ;
       
  2283         }
       
  2284 
       
  2285         ret = CyAsDmaDrainQueue(dev_p, ep, CyFalse) ;
       
  2286         if (ret != CY_AS_ERROR_SUCCESS)
       
  2287             return ret ;
       
  2288     }
       
  2289     else
       
  2290     {
       
  2291         ret = CyAsDmaDrainQueue(dev_p, ep, CyTrue) ;
       
  2292         if (ret != CY_AS_ERROR_SUCCESS)
       
  2293             return ret ;
       
  2294     }
       
  2295 
       
  2296     ret = dev_p->usb_error ;
       
  2297     *dataread = dev_p->usb_actual_cnt ;
       
  2298 
       
  2299     return ret ;
       
  2300 }
       
  2301 
       
  2302 CyAsReturnStatus_t
       
  2303 CyAsUsbReadDataAsync(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep, CyBool pktread, uint32_t dsize, void *data, CyAsUsbIoCallback cb)
       
  2304 {
       
  2305     CyAsReturnStatus_t ret ;
       
  2306     uint32_t mask ;
       
  2307     CyAsDevice *dev_p ;
       
  2308 
       
  2309     CyAsLogDebugMessage(6, "CyAsUsbReadDataAsync called") ;
       
  2310 
       
  2311     dev_p = (CyAsDevice *)handle ;
       
  2312     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2313         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2314 
       
  2315     ret = IsUsbActive(dev_p) ;
       
  2316     if (ret != CY_AS_ERROR_SUCCESS)
       
  2317         return ret ;
       
  2318 
       
  2319     if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
       
  2320         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2321 
       
  2322     /* EP2 is available for reading when MTP is active */
       
  2323     if(dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
       
  2324         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2325 
       
  2326     /* If the endpoint is disabled, we cannot write data to the endpoint */
       
  2327     if (!dev_p->usb_config[ep].enabled)
       
  2328         return CY_AS_ERROR_ENDPOINT_DISABLED ;
       
  2329 
       
  2330     if (dev_p->usb_config[ep].dir != CyAsUsbOut && dev_p->usb_config[ep].dir != CyAsUsbInOut)
       
  2331         return CY_AS_ERROR_USB_BAD_DIRECTION ;
       
  2332 
       
  2333     /*
       
  2334     * Since async operations can be triggered by interrupt code, we must
       
  2335     * insure that we do not get multiple async operations going at one time and
       
  2336     * protect this test and set operation from interrupts.
       
  2337     */
       
  2338     mask = CyAsHalDisableInterrupts() ;
       
  2339     if (CyAsDeviceIsUsbAsyncPending(dev_p, ep))
       
  2340     {
       
  2341         CyAsHalEnableInterrupts(mask) ;
       
  2342         return CY_AS_ERROR_ASYNC_PENDING ;
       
  2343     }
       
  2344     CyAsDeviceSetUsbAsyncPending(dev_p, ep) ;
       
  2345 
       
  2346     /*
       
  2347     * If this is for EP0, we set this bit to delay the ACK response
       
  2348     * until after this read has completed.
       
  2349     */
       
  2350     if (ep == 0)
       
  2351         CyAsDeviceSetAckDelayed(dev_p) ;
       
  2352 
       
  2353     CyAsHalEnableInterrupts(mask) ;
       
  2354 
       
  2355     CyAsHalAssert(dev_p->usb_cb[ep] == 0) ;
       
  2356     dev_p->usb_cb[ep] = cb ;
       
  2357 
       
  2358     ret = CyAsDmaQueueRequest(dev_p, ep, data, dsize, pktread, CyTrue, AsyncReadRequestCallback) ;
       
  2359     if (ret != CY_AS_ERROR_SUCCESS)
       
  2360         return ret ;
       
  2361 
       
  2362     if (ep == CY_AS_MTP_READ_ENDPOINT)
       
  2363     {
       
  2364         ret = MySendTurboSwitch(dev_p, dsize, pktread) ;
       
  2365         if (ret != CY_AS_ERROR_SUCCESS)
       
  2366         {
       
  2367             CyAsDmaCancel(dev_p, ep, ret) ;
       
  2368             return ret ;
       
  2369         }
       
  2370     }
       
  2371     else
       
  2372     {
       
  2373         /* Kick start the queue if it is not running */
       
  2374         CyAsDmaKickStart(dev_p, ep) ;
       
  2375     }
       
  2376     return ret ;
       
  2377 }
       
  2378 
       
  2379 CyAsReturnStatus_t
       
  2380 CyAsUsbWriteData(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep, uint32_t dsize, void *data)
       
  2381 {
       
  2382     CyAsReturnStatus_t ret ;
       
  2383     CyAsDevice *dev_p ;
       
  2384 
       
  2385     CyAsLogDebugMessage(6, "CyAsUsbWriteData called") ;
       
  2386 
       
  2387     dev_p = (CyAsDevice *)handle ;
       
  2388     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2389         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2390 
       
  2391     ret = IsUsbActive(dev_p) ;
       
  2392     if (ret != CY_AS_ERROR_SUCCESS)
       
  2393         return ret ;
       
  2394 
       
  2395     if (CyAsDeviceIsInCallback(dev_p))
       
  2396         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  2397 
       
  2398     if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
       
  2399         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2400 
       
  2401     /* EP6 is available for writing when MTP is active */
       
  2402     if(dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
       
  2403         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2404 
       
  2405     /* If the endpoint is disabled, we cannot write data to the endpoint */
       
  2406     if (!dev_p->usb_config[ep].enabled)
       
  2407         return CY_AS_ERROR_ENDPOINT_DISABLED ;
       
  2408 
       
  2409     if (dev_p->usb_config[ep].dir != CyAsUsbIn && dev_p->usb_config[ep].dir != CyAsUsbInOut)
       
  2410         return CY_AS_ERROR_USB_BAD_DIRECTION ;
       
  2411 
       
  2412     /* Write on Turbo endpoint */
       
  2413     if (ep == CY_AS_MTP_WRITE_ENDPOINT)
       
  2414     {
       
  2415         CyAsLLRequestResponse *req_p, *reply_p ;
       
  2416 
       
  2417         req_p = CyAsLLCreateRequest(dev_p, CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST, CY_RQT_TUR_RQT_CONTEXT, 3) ;
       
  2418         if (req_p == 0)
       
  2419             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2420 
       
  2421         CyAsLLRequestResponse_SetWord(req_p, 0, 0x0006) ; /* EP number to use. */
       
  2422         CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((dsize >> 16) & 0xFFFF)) ;
       
  2423         CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(dsize & 0xFFFF)) ;
       
  2424 
       
  2425         /* Reserve space for the reply, the reply data will not exceed one word */
       
  2426         reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2427         if (reply_p == 0)
       
  2428         {
       
  2429             CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2430             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2431         }
       
  2432 
       
  2433         if (dsize)
       
  2434         {
       
  2435             ret = CyAsDmaQueueRequest(dev_p, ep, data, dsize, CyFalse, CyFalse, SyncRequestCallback) ;
       
  2436             if (ret != CY_AS_ERROR_SUCCESS)
       
  2437                 return ret ;
       
  2438         }
       
  2439 
       
  2440         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  2441         if (ret == CY_AS_ERROR_SUCCESS)
       
  2442         {
       
  2443             if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
  2444                 ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  2445             else
       
  2446                 ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  2447         }
       
  2448 
       
  2449         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2450         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  2451 
       
  2452         if (ret != CY_AS_ERROR_SUCCESS)
       
  2453         {
       
  2454             if (dsize)
       
  2455                 CyAsDmaCancel(dev_p, ep, ret) ;
       
  2456             return ret ;
       
  2457         }
       
  2458 
       
  2459         /* If this is a zero-byte write, firmware will handle it.
       
  2460          * There is no need to do any work here.
       
  2461          */
       
  2462         if (!dsize)
       
  2463             return CY_AS_ERROR_SUCCESS ;
       
  2464     }
       
  2465     else
       
  2466     {
       
  2467         ret = CyAsDmaQueueRequest(dev_p, ep, data, dsize, CyFalse, CyFalse, SyncRequestCallback) ;
       
  2468         if (ret != CY_AS_ERROR_SUCCESS)
       
  2469             return ret ;
       
  2470     }
       
  2471 
       
  2472     if (ep != CY_AS_MTP_WRITE_ENDPOINT)
       
  2473         ret = CyAsDmaDrainQueue(dev_p, ep, CyTrue) ;
       
  2474     else
       
  2475         ret = CyAsDmaDrainQueue(dev_p, ep, CyFalse) ;
       
  2476 
       
  2477     if (ret != CY_AS_ERROR_SUCCESS)
       
  2478         return ret ;
       
  2479 
       
  2480     ret = dev_p->usb_error ;
       
  2481     return ret ;
       
  2482 }
       
  2483 
       
  2484 static void
       
  2485 MtpWriteCallback(
       
  2486         CyAsDevice *dev_p,
       
  2487         uint8_t context,
       
  2488         CyAsLLRequestResponse *rqt,
       
  2489         CyAsLLRequestResponse *resp,
       
  2490         CyAsReturnStatus_t ret)
       
  2491 {
       
  2492     CyAsUsbIoCallback cb ;
       
  2493     CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
       
  2494 
       
  2495     CyAsHalAssert(context == CY_RQT_TUR_RQT_CONTEXT) ;
       
  2496 
       
  2497     if (ret == CY_AS_ERROR_SUCCESS)
       
  2498     {
       
  2499         if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
       
  2500             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  2501         else
       
  2502             ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
       
  2503     }
       
  2504 
       
  2505     /* If this was a zero byte transfer request, we can call the callback from
       
  2506      * here. */
       
  2507     if ((CyAsLLRequestResponse_GetWord(rqt, 1) == 0) &&
       
  2508             (CyAsLLRequestResponse_GetWord(rqt, 2) == 0))
       
  2509     {
       
  2510         cb = dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] ;
       
  2511         dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] = 0 ;
       
  2512         CyAsDeviceClearUsbAsyncPending(dev_p, CY_AS_MTP_WRITE_ENDPOINT) ;
       
  2513         if (cb)
       
  2514             cb(h, CY_AS_MTP_WRITE_ENDPOINT, 0, 0, ret) ;
       
  2515 
       
  2516         goto destroy ;
       
  2517     }
       
  2518 
       
  2519     if (ret != CY_AS_ERROR_SUCCESS)
       
  2520     {
       
  2521         /* Firmware failed the request. Cancel the DMA transfer. */
       
  2522         CyAsDmaCancel(dev_p, 0x06, CY_AS_ERROR_CANCELED) ;
       
  2523         dev_p->usb_cb[0x06] = 0 ;
       
  2524         CyAsDeviceClearUsbAsyncPending(dev_p, 0x06) ;
       
  2525     }
       
  2526 
       
  2527 destroy:
       
  2528     CyAsLLDestroyResponse(dev_p, resp) ;
       
  2529     CyAsLLDestroyRequest(dev_p, rqt) ;
       
  2530 }
       
  2531 
       
  2532 CyAsReturnStatus_t
       
  2533 CyAsUsbWriteDataAsync(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep, uint32_t dsize, void *data, CyBool spacket, CyAsUsbIoCallback cb)
       
  2534 {
       
  2535     uint32_t mask ;
       
  2536     CyAsReturnStatus_t ret ;
       
  2537     CyAsDevice *dev_p ;
       
  2538 
       
  2539     CyAsLogDebugMessage(6, "CyAsUsbWriteDataAsync called") ;
       
  2540 
       
  2541     dev_p = (CyAsDevice *)handle ;
       
  2542     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2543         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2544 
       
  2545     ret = IsUsbActive(dev_p) ;
       
  2546     if (ret != CY_AS_ERROR_SUCCESS)
       
  2547         return ret ;
       
  2548 
       
  2549     if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
       
  2550         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2551 
       
  2552      /* EP6 is available for writing when MTP is active */
       
  2553     if(dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
       
  2554         return CY_AS_ERROR_INVALID_ENDPOINT ;
       
  2555 
       
  2556     /* If the endpoint is disabled, we cannot write data to the endpoint */
       
  2557     if (!dev_p->usb_config[ep].enabled)
       
  2558         return CY_AS_ERROR_ENDPOINT_DISABLED ;
       
  2559 
       
  2560     if (dev_p->usb_config[ep].dir != CyAsUsbIn && dev_p->usb_config[ep].dir != CyAsUsbInOut)
       
  2561         return CY_AS_ERROR_USB_BAD_DIRECTION ;
       
  2562 
       
  2563     /*
       
  2564     * Since async operations can be triggered by interrupt code, we must
       
  2565     * insure that we do not get multiple async operations going at one time and
       
  2566     * protect this test and set operation from interrupts.
       
  2567     */
       
  2568     mask = CyAsHalDisableInterrupts() ;
       
  2569     if (CyAsDeviceIsUsbAsyncPending(dev_p, ep))
       
  2570     {
       
  2571         CyAsHalEnableInterrupts(mask) ;
       
  2572         return CY_AS_ERROR_ASYNC_PENDING ;
       
  2573     }
       
  2574 
       
  2575     CyAsDeviceSetUsbAsyncPending(dev_p, ep) ;
       
  2576 
       
  2577     if (ep == 0)
       
  2578         CyAsDeviceSetAckDelayed(dev_p) ;
       
  2579 
       
  2580     CyAsHalEnableInterrupts(mask) ;
       
  2581 
       
  2582     CyAsHalAssert(dev_p->usb_cb[ep] == 0) ;
       
  2583     dev_p->usb_cb[ep] = cb ;
       
  2584     dev_p->usb_spacket[ep] = spacket ;
       
  2585 
       
  2586     /* Write on Turbo endpoint */
       
  2587     if (ep == CY_AS_MTP_WRITE_ENDPOINT)
       
  2588     {
       
  2589         CyAsLLRequestResponse *req_p, *reply_p ;
       
  2590 
       
  2591         req_p = CyAsLLCreateRequest(dev_p, CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST, CY_RQT_TUR_RQT_CONTEXT, 3) ;
       
  2592         if (req_p == 0)
       
  2593             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2594 
       
  2595         CyAsLLRequestResponse_SetWord(req_p, 0, 0x0006) ; /* EP number to use. */
       
  2596         CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((dsize >> 16) & 0xFFFF)) ;
       
  2597         CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(dsize & 0xFFFF)) ;
       
  2598 
       
  2599         /* Reserve space for the reply, the reply data will not exceed one word */
       
  2600         reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2601         if (reply_p == 0)
       
  2602         {
       
  2603             CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2604             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2605         }
       
  2606 
       
  2607         if (dsize)
       
  2608         {
       
  2609             ret = CyAsDmaQueueRequest(dev_p, ep, data, dsize, CyFalse, CyFalse, AsyncWriteRequestCallback) ;
       
  2610             if (ret != CY_AS_ERROR_SUCCESS)
       
  2611                 return ret ;
       
  2612         }
       
  2613 
       
  2614         ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, MtpWriteCallback) ;
       
  2615         if (ret != CY_AS_ERROR_SUCCESS)
       
  2616         {
       
  2617             if (dsize)
       
  2618                 CyAsDmaCancel(dev_p, ep, ret) ;
       
  2619             return ret ;
       
  2620         }
       
  2621 
       
  2622         /* Firmware will handle a zero byte transfer without any DMA transfers. */
       
  2623         if (!dsize)
       
  2624             return CY_AS_ERROR_SUCCESS ;
       
  2625     }
       
  2626     else
       
  2627     {
       
  2628         ret = CyAsDmaQueueRequest(dev_p, ep, data, dsize, CyFalse, CyFalse, AsyncWriteRequestCallback) ;
       
  2629         if (ret != CY_AS_ERROR_SUCCESS)
       
  2630             return ret ;
       
  2631     }
       
  2632 
       
  2633     /* Kick start the queue if it is not running */
       
  2634     if (ep != CY_AS_MTP_WRITE_ENDPOINT)
       
  2635     {
       
  2636         CyAsDmaKickStart(dev_p, ep) ;
       
  2637     }
       
  2638 
       
  2639     return CY_AS_ERROR_SUCCESS ;
       
  2640 }
       
  2641 
       
  2642 static void
       
  2643 MyUsbCancelAsyncCallback(
       
  2644                    CyAsDevice *dev_p,
       
  2645                    uint8_t context,
       
  2646                    CyAsLLRequestResponse *rqt,
       
  2647                    CyAsLLRequestResponse *resp,
       
  2648                    CyAsReturnStatus_t ret)
       
  2649 {
       
  2650     uint8_t ep ;
       
  2651     (void)context ;
       
  2652 
       
  2653     ep = (uint8_t)CyAsLLRequestResponse_GetWord(rqt, 0) ;
       
  2654     if (ret == CY_AS_ERROR_SUCCESS)
       
  2655     {
       
  2656         if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
       
  2657             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  2658         else
       
  2659             ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
       
  2660     }
       
  2661 
       
  2662     CyAsLLDestroyRequest(dev_p, rqt) ;
       
  2663     CyAsLLDestroyResponse(dev_p, resp) ;
       
  2664 
       
  2665     if (ret == CY_AS_ERROR_SUCCESS)
       
  2666     {
       
  2667         CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
       
  2668         dev_p->usb_cb[ep] = 0 ;
       
  2669         CyAsDeviceClearUsbAsyncPending(dev_p, ep) ;
       
  2670     }
       
  2671 }
       
  2672 
       
  2673 CyAsReturnStatus_t
       
  2674 CyAsUsbCancelAsync(CyAsDeviceHandle handle, CyAsEndPointNumber_t ep)
       
  2675 {
       
  2676     CyAsReturnStatus_t ret ;
       
  2677     CyAsLLRequestResponse *req_p, *reply_p ;
       
  2678 
       
  2679     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  2680     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2681         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2682 
       
  2683     ep &= 0x7F;         /* Remove the direction bit. */
       
  2684     if (!CyAsDeviceIsUsbAsyncPending(dev_p, ep))
       
  2685         return CY_AS_ERROR_ASYNC_NOT_PENDING;
       
  2686 
       
  2687     ret = IsUsbActive(dev_p) ;
       
  2688     if (ret != CY_AS_ERROR_SUCCESS)
       
  2689         return ret ;
       
  2690 
       
  2691     if (CyAsDeviceIsInSuspendMode(dev_p))
       
  2692         return CY_AS_ERROR_IN_SUSPEND ;
       
  2693 
       
  2694     if ((ep == CY_AS_MTP_WRITE_ENDPOINT) || (ep == CY_AS_MTP_READ_ENDPOINT))
       
  2695     {
       
  2696         /* Need firmware support for the cancel operation. */
       
  2697         req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CANCEL_ASYNC_TRANSFER, CY_RQT_TUR_RQT_CONTEXT, 1) ;
       
  2698         if (req_p == 0)
       
  2699             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2700 
       
  2701         reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2702         if (reply_p == 0)
       
  2703         {
       
  2704             CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2705             return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2706         }
       
  2707 
       
  2708         CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)ep) ;
       
  2709         ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, MyUsbCancelAsyncCallback) ;
       
  2710 
       
  2711         if (ret != CY_AS_ERROR_SUCCESS)
       
  2712         {
       
  2713             CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2714             CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  2715             return ret ;
       
  2716         }
       
  2717     }
       
  2718     else
       
  2719     {
       
  2720         ret = CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
       
  2721         if (ret != CY_AS_ERROR_SUCCESS)
       
  2722             return ret ;
       
  2723 
       
  2724         dev_p->usb_cb[ep] = 0 ;
       
  2725         CyAsDeviceClearUsbAsyncPending(dev_p, ep) ;
       
  2726     }
       
  2727 
       
  2728     return CY_AS_ERROR_SUCCESS ;
       
  2729 }
       
  2730 
       
  2731 static void
       
  2732 CyAsUsbAckCallback(
       
  2733                    CyAsDevice *dev_p,
       
  2734                    uint8_t context,
       
  2735                    CyAsLLRequestResponse *rqt,
       
  2736                    CyAsLLRequestResponse *resp,
       
  2737                    CyAsReturnStatus_t ret)
       
  2738 {
       
  2739     CyAsFuncCBNode* node  = (CyAsFuncCBNode*)dev_p->func_cbs_usb->head_p ;
       
  2740 
       
  2741     (void)context ;
       
  2742 
       
  2743     if (ret == CY_AS_ERROR_SUCCESS)
       
  2744     {
       
  2745         if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
       
  2746             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  2747         else
       
  2748             ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
       
  2749     }
       
  2750 
       
  2751     node->cb_p((CyAsDeviceHandle)dev_p, ret, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
       
  2752     CyAsRemoveCBNode(dev_p->func_cbs_usb) ;
       
  2753 
       
  2754     CyAsLLDestroyRequest(dev_p, rqt) ;
       
  2755     CyAsLLDestroyResponse(dev_p, resp) ;
       
  2756     CyAsDeviceClearAckDelayed(dev_p) ;
       
  2757 }
       
  2758 
       
  2759 static CyAsReturnStatus_t
       
  2760 CyAsUsbAckSetupPacket(CyAsDeviceHandle handle,
       
  2761                       CyAsFunctionCallback      cb,
       
  2762                       uint32_t client)
       
  2763 {
       
  2764     CyAsReturnStatus_t ret ;
       
  2765     CyAsLLRequestResponse *req_p ;
       
  2766     CyAsLLRequestResponse *reply_p ;
       
  2767     CyAsFuncCBNode* cbnode ;
       
  2768 
       
  2769     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  2770     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2771         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2772 
       
  2773     ret = IsUsbActive(dev_p) ;
       
  2774     if (ret != CY_AS_ERROR_SUCCESS)
       
  2775         return ret ;
       
  2776 
       
  2777     if (CyAsDeviceIsInCallback(dev_p) && cb == 0)
       
  2778         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  2779 
       
  2780     CyAsHalAssert(cb != 0) ;
       
  2781 
       
  2782     cbnode = CyAsCreateFuncCBNode(cb, client);
       
  2783     if( cbnode == 0)
       
  2784         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2785 
       
  2786     req_p = CyAsLLCreateRequest(dev_p, 0, CY_RQT_USB_RQT_CONTEXT, 2) ;
       
  2787     if (req_p == 0)
       
  2788         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2789 
       
  2790     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2791     if(reply_p == 0)
       
  2792     {
       
  2793         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2794         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2795     }
       
  2796 
       
  2797     CyAsLLInitRequest(req_p, CY_RQT_ACK_SETUP_PACKET, CY_RQT_USB_RQT_CONTEXT, 1) ;
       
  2798     CyAsLLInitResponse(reply_p, 1) ;
       
  2799 
       
  2800     req_p->flags |= CY_AS_REQUEST_RESPONSE_EX ;
       
  2801 
       
  2802     CyAsInsertCBNode(dev_p->func_cbs_usb, cbnode) ;
       
  2803 
       
  2804     ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, CyAsUsbAckCallback) ;
       
  2805 
       
  2806     return ret ;
       
  2807 }
       
  2808 
       
  2809 /*
       
  2810  * Flush all data in logical EP that is being NAK-ed or Stall-ed,
       
  2811  * so that this does not continue to block data on other LEPs that
       
  2812  * use the same physical EP.
       
  2813  */
       
  2814 static void
       
  2815 CyAsUsbFlushLogicalEP(
       
  2816         CyAsDevice *dev_p,
       
  2817         uint16_t    ep)
       
  2818 {
       
  2819     uint16_t addr, val, count ;
       
  2820 
       
  2821     addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ;
       
  2822     val  = CyAsHalReadRegister(dev_p->tag, addr) ;
       
  2823 
       
  2824     while (val)
       
  2825     {
       
  2826         count = ((val & 0xFFF) + 1) / 2 ;
       
  2827         while (count--)
       
  2828         {
       
  2829             val = CyAsHalReadRegister(dev_p->tag, ep) ;
       
  2830         }
       
  2831 
       
  2832         CyAsHalWriteRegister(dev_p->tag, addr, 0) ;
       
  2833         val = CyAsHalReadRegister(dev_p->tag, addr) ;
       
  2834     }
       
  2835 }
       
  2836 
       
  2837 static CyAsReturnStatus_t
       
  2838 CyAsUsbNakStallRequest(CyAsDeviceHandle handle,
       
  2839                        CyAsEndPointNumber_t ep,
       
  2840                        uint16_t request,
       
  2841                        CyBool state,
       
  2842                        CyAsUsbFunctionCallback cb,
       
  2843                        CyAsFunctionCallback fcb,
       
  2844                        uint32_t client)
       
  2845 {
       
  2846     CyAsReturnStatus_t ret ;
       
  2847     CyAsLLRequestResponse *req_p , *reply_p ;
       
  2848     uint16_t data ;
       
  2849 
       
  2850     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  2851     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  2852         return CY_AS_ERROR_INVALID_HANDLE ;
       
  2853 
       
  2854     if(cb)
       
  2855         CyAsHalAssert(fcb == 0) ;
       
  2856     if(fcb)
       
  2857         CyAsHalAssert(cb == 0) ;
       
  2858 
       
  2859     ret = IsUsbActive(dev_p) ;
       
  2860     if (ret != CY_AS_ERROR_SUCCESS)
       
  2861         return ret ;
       
  2862 
       
  2863     if (CyAsDeviceIsInCallback(dev_p) && cb == 0 && fcb == 0)
       
  2864         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  2865 
       
  2866     req_p = CyAsLLCreateRequest(dev_p, request, CY_RQT_USB_RQT_CONTEXT, 2) ;
       
  2867     if (req_p == 0)
       
  2868         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2869 
       
  2870     /* A single status word response type */
       
  2871     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  2872     if (reply_p == 0)
       
  2873     {
       
  2874         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2875         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2876     }
       
  2877 
       
  2878     /* Set the endpoint */
       
  2879     data = (uint8_t)ep ;
       
  2880     CyAsLLRequestResponse_SetWord(req_p, 0, data) ;
       
  2881 
       
  2882     /* Set stall state to stalled */
       
  2883     CyAsLLRequestResponse_SetWord(req_p, 1, (uint8_t)state) ;
       
  2884 
       
  2885     if (cb || fcb)
       
  2886     {
       
  2887         void * cbnode ;
       
  2888         CyAsCBQueue* queue ;
       
  2889         if(cb)
       
  2890         {
       
  2891             cbnode = CyAsCreateUsbFuncCBNode(cb, client) ;
       
  2892             queue = dev_p->usb_func_cbs ;
       
  2893         }
       
  2894         else
       
  2895         {
       
  2896             cbnode = CyAsCreateFuncCBNode(fcb, client) ;
       
  2897             queue = dev_p->func_cbs_usb ;
       
  2898             req_p->flags |= CY_AS_REQUEST_RESPONSE_EX ;
       
  2899         }
       
  2900 
       
  2901         if(cbnode == 0)
       
  2902         {
       
  2903             ret = CY_AS_ERROR_OUT_OF_MEMORY ;
       
  2904             goto destroy ;
       
  2905         }
       
  2906         else
       
  2907             CyAsInsertCBNode(queue, cbnode) ;
       
  2908 
       
  2909 
       
  2910         if (CyAsDeviceIsSetupPacket(dev_p))
       
  2911         {
       
  2912             /* No Ack is needed on a stall request on EP0 */
       
  2913             if ((state == CyTrue) && (ep == 0))
       
  2914             {
       
  2915                 CyAsDeviceSetEp0Stalled(dev_p) ;
       
  2916             }
       
  2917             else
       
  2918             {
       
  2919                 CyAsDeviceSetAckDelayed(dev_p) ;
       
  2920                 req_p->flags |= CY_AS_REQUEST_RESPONSE_DELAY_ACK ;
       
  2921             }
       
  2922         }
       
  2923 
       
  2924         ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, CyAsUsbFuncCallback) ;
       
  2925         if (ret != CY_AS_ERROR_SUCCESS)
       
  2926         {
       
  2927             if (req_p->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
       
  2928                 CyAsDeviceRemAckDelayed(dev_p) ;
       
  2929             CyAsRemoveCBTailNode(queue) ;
       
  2930 
       
  2931             goto destroy ;
       
  2932         }
       
  2933     }
       
  2934     else
       
  2935     {
       
  2936         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  2937         if (ret != CY_AS_ERROR_SUCCESS)
       
  2938             goto destroy ;
       
  2939 
       
  2940         if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
       
  2941         {
       
  2942             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  2943             goto destroy ;
       
  2944         }
       
  2945 
       
  2946         ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  2947 
       
  2948         if ((ret == CY_AS_ERROR_SUCCESS) && (request == CY_RQT_STALL_ENDPOINT))
       
  2949         {
       
  2950             if ((ep > 1) && (state != 0) && (dev_p->usb_config[ep].dir == CyAsUsbOut))
       
  2951                 CyAsUsbFlushLogicalEP(dev_p, ep) ;
       
  2952         }
       
  2953 
       
  2954 destroy:
       
  2955         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2956         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  2957     }
       
  2958 
       
  2959     return ret ;
       
  2960 }
       
  2961 
       
  2962 static CyAsReturnStatus_t
       
  2963 MyHandleResponseGetStall(CyAsDevice* dev_p,
       
  2964                          CyAsLLRequestResponse *req_p,
       
  2965                          CyAsLLRequestResponse *reply_p,
       
  2966                          CyBool *state_p)
       
  2967 {
       
  2968     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  2969     uint8_t code = CyAsLLRequestResponse_GetCode(reply_p) ;
       
  2970 
       
  2971     if (code == CY_RESP_SUCCESS_FAILURE)
       
  2972     {
       
  2973         ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  2974         goto destroy ;
       
  2975     }
       
  2976     else if (code != CY_RESP_ENDPOINT_STALL)
       
  2977     {
       
  2978         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  2979         goto destroy ;
       
  2980     }
       
  2981 
       
  2982     *state_p = (CyBool)CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  2983     ret = CY_AS_ERROR_SUCCESS ;
       
  2984 
       
  2985 
       
  2986 destroy :
       
  2987         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  2988         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  2989 
       
  2990         return ret ;
       
  2991 }
       
  2992 
       
  2993 static CyAsReturnStatus_t
       
  2994 MyHandleResponseGetNak(CyAsDevice* dev_p,
       
  2995                        CyAsLLRequestResponse *req_p,
       
  2996                        CyAsLLRequestResponse *reply_p,
       
  2997                        CyBool *state_p)
       
  2998 {
       
  2999     CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
       
  3000     uint8_t code = CyAsLLRequestResponse_GetCode(reply_p) ;
       
  3001 
       
  3002     if (code == CY_RESP_SUCCESS_FAILURE)
       
  3003     {
       
  3004         ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  3005         goto destroy ;
       
  3006     }
       
  3007     else if (code != CY_RESP_ENDPOINT_NAK)
       
  3008     {
       
  3009         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  3010         goto destroy ;
       
  3011     }
       
  3012 
       
  3013     *state_p = (CyBool)CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  3014     ret = CY_AS_ERROR_SUCCESS ;
       
  3015 
       
  3016 
       
  3017 destroy :
       
  3018         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3019         CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  3020 
       
  3021         return ret ;
       
  3022 }
       
  3023 
       
  3024 static CyAsReturnStatus_t
       
  3025 CyAsUsbGetNakStall(CyAsDeviceHandle handle,
       
  3026                    CyAsEndPointNumber_t ep,
       
  3027                    uint16_t request,
       
  3028                    uint16_t response,
       
  3029                    CyBool *state_p,
       
  3030                    CyAsFunctionCallback cb,
       
  3031                    uint32_t client)
       
  3032 {
       
  3033     CyAsReturnStatus_t ret ;
       
  3034     CyAsLLRequestResponse *req_p , *reply_p ;
       
  3035     uint16_t data ;
       
  3036 
       
  3037     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3038 
       
  3039     (void)response ;
       
  3040 
       
  3041     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3042         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3043 
       
  3044     ret = IsUsbActive(dev_p) ;
       
  3045     if (ret != CY_AS_ERROR_SUCCESS)
       
  3046         return ret ;
       
  3047 
       
  3048     if (CyAsDeviceIsInCallback(dev_p) && !cb)
       
  3049         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  3050 
       
  3051     req_p = CyAsLLCreateRequest(dev_p, request, CY_RQT_USB_RQT_CONTEXT, 1) ;
       
  3052     if (req_p == 0)
       
  3053         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3054 
       
  3055     /* Set the endpoint */
       
  3056     data = (uint8_t)ep ;
       
  3057     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)ep) ;
       
  3058 
       
  3059     /* A single status word response type */
       
  3060     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  3061     if (reply_p == 0)
       
  3062     {
       
  3063         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3064         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3065     }
       
  3066 
       
  3067     if(cb == 0)
       
  3068     {
       
  3069         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  3070         if (ret != CY_AS_ERROR_SUCCESS)
       
  3071             goto destroy ;
       
  3072 
       
  3073         if(request == CY_RQT_GET_STALL)
       
  3074             return MyHandleResponseGetStall(dev_p, req_p, reply_p, state_p) ;
       
  3075         else
       
  3076             return MyHandleResponseGetNak(dev_p, req_p, reply_p, state_p) ;
       
  3077 
       
  3078     }
       
  3079     else
       
  3080     {
       
  3081         CyAsFunctCBType type ;
       
  3082 
       
  3083         if(request == CY_RQT_GET_STALL)
       
  3084             type = CY_FUNCT_CB_USB_GETSTALL ;
       
  3085         else
       
  3086             type = CY_FUNCT_CB_USB_GETNAK ;
       
  3087 
       
  3088         ret = CyAsMiscSendRequest(dev_p, cb, client, type,
       
  3089             state_p, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  3090             CyAsUsbFuncCallback) ;
       
  3091 
       
  3092         if (ret != CY_AS_ERROR_SUCCESS)
       
  3093             goto destroy ;
       
  3094 
       
  3095         return ret ;
       
  3096     }
       
  3097 
       
  3098 destroy:
       
  3099     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3100     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  3101 
       
  3102     return ret ;
       
  3103 }
       
  3104 
       
  3105 CyAsReturnStatus_t
       
  3106 CyAsUsbSetNak(CyAsDeviceHandle handle,
       
  3107                 CyAsEndPointNumber_t ep,
       
  3108                 CyAsFunctionCallback cb,
       
  3109                 uint32_t client)
       
  3110 {
       
  3111     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3112     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3113         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3114 
       
  3115     /*
       
  3116     * We send the firmware the EP# with the appropriate direction bit, regardless
       
  3117     * of what the user gave us.
       
  3118     */
       
  3119     ep &= 0x0f ;
       
  3120     if (dev_p->usb_config[ep].dir == CyAsUsbIn)
       
  3121         ep |= 0x80 ;
       
  3122 
       
  3123         if(dev_p->mtp_count > 0)
       
  3124                 return CY_AS_ERROR_NOT_VALID_IN_MTP ;
       
  3125 
       
  3126     return CyAsUsbNakStallRequest(handle, ep, CY_RQT_ENDPOINT_SET_NAK, CyTrue, 0, cb, client) ;
       
  3127 }
       
  3128 
       
  3129 
       
  3130 CyAsReturnStatus_t
       
  3131 CyAsUsbClearNak(CyAsDeviceHandle handle,
       
  3132                   CyAsEndPointNumber_t ep,
       
  3133                   CyAsFunctionCallback cb,
       
  3134                   uint32_t client)
       
  3135 {
       
  3136     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3137     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3138         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3139 
       
  3140     /*
       
  3141     * We send the firmware the EP# with the appropriate direction bit, regardless
       
  3142     * of what the user gave us.
       
  3143     */
       
  3144     ep &= 0x0f ;
       
  3145     if (dev_p->usb_config[ep].dir == CyAsUsbIn)
       
  3146         ep |= 0x80 ;
       
  3147 
       
  3148         if(dev_p->mtp_count > 0)
       
  3149                 return CY_AS_ERROR_NOT_VALID_IN_MTP ;
       
  3150 
       
  3151     return CyAsUsbNakStallRequest(handle, ep, CY_RQT_ENDPOINT_SET_NAK, CyFalse, 0, cb, client) ;
       
  3152 }
       
  3153 
       
  3154 CyAsReturnStatus_t
       
  3155 CyAsUsbGetNak(CyAsDeviceHandle handle,
       
  3156                 CyAsEndPointNumber_t ep,
       
  3157                 CyBool *nak_p,
       
  3158                 CyAsFunctionCallback cb,
       
  3159                 uint32_t client)
       
  3160 {
       
  3161     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3162     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3163         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3164 
       
  3165     /*
       
  3166     * We send the firmware the EP# with the appropriate direction bit, regardless
       
  3167     * of what the user gave us.
       
  3168     */
       
  3169     ep &= 0x0f ;
       
  3170     if (dev_p->usb_config[ep].dir == CyAsUsbIn)
       
  3171         ep |= 0x80 ;
       
  3172 
       
  3173         if(dev_p->mtp_count > 0)
       
  3174                 return CY_AS_ERROR_NOT_VALID_IN_MTP ;
       
  3175 
       
  3176     return CyAsUsbGetNakStall(handle, ep, CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK, nak_p, cb, client ) ;
       
  3177 }
       
  3178 
       
  3179 
       
  3180 CyAsReturnStatus_t
       
  3181 CyAsUsbSetStall(CyAsDeviceHandle handle,
       
  3182                   CyAsEndPointNumber_t ep,
       
  3183                   CyAsFunctionCallback cb,
       
  3184                   uint32_t client)
       
  3185 {
       
  3186     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3187     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3188         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3189 
       
  3190     /*
       
  3191     * We send the firmware the EP# with the appropriate direction bit, regardless
       
  3192     * of what the user gave us.
       
  3193     */
       
  3194     ep &= 0x0f ;
       
  3195     if (dev_p->usb_config[ep].dir == CyAsUsbIn)
       
  3196         ep |= 0x80 ;
       
  3197 
       
  3198     if(dev_p->mtp_turbo_active)
       
  3199         return CY_AS_ERROR_NOT_VALID_DURING_MTP ;
       
  3200 
       
  3201     return CyAsUsbNakStallRequest(handle, ep, CY_RQT_STALL_ENDPOINT, CyTrue, 0, cb, client) ;
       
  3202 }
       
  3203 
       
  3204 CyAsReturnStatus_t
       
  3205 CyAsUsbClearStall(CyAsDeviceHandle handle,
       
  3206                     CyAsEndPointNumber_t ep,
       
  3207                     CyAsFunctionCallback cb,
       
  3208                     uint32_t client)
       
  3209 {
       
  3210     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3211     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3212         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3213 
       
  3214     /*
       
  3215     * We send the firmware the EP# with the appropriate direction bit, regardless
       
  3216     * of what the user gave us.
       
  3217     */
       
  3218     ep &= 0x0f ;
       
  3219     if (dev_p->usb_config[ep].dir == CyAsUsbIn)
       
  3220         ep |= 0x80 ;
       
  3221 
       
  3222     if(dev_p->mtp_turbo_active)
       
  3223         return CY_AS_ERROR_NOT_VALID_DURING_MTP ;
       
  3224 
       
  3225     return CyAsUsbNakStallRequest(handle, ep, CY_RQT_STALL_ENDPOINT, CyFalse, 0, cb, client) ;
       
  3226 }
       
  3227 
       
  3228 CyAsReturnStatus_t
       
  3229 CyAsUsbGetStall(CyAsDeviceHandle handle,
       
  3230                   CyAsEndPointNumber_t ep,
       
  3231                   CyBool *stall_p,
       
  3232                   CyAsFunctionCallback cb,
       
  3233                   uint32_t client)
       
  3234 {
       
  3235     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3236     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3237         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3238 
       
  3239     /*
       
  3240     * We send the firmware the EP# with the appropriate direction bit, regardless
       
  3241     * of what the user gave us.
       
  3242     */
       
  3243     ep &= 0x0f ;
       
  3244     if (dev_p->usb_config[ep].dir == CyAsUsbIn)
       
  3245         ep |= 0x80 ;
       
  3246 
       
  3247     if(dev_p->mtp_turbo_active)
       
  3248         return CY_AS_ERROR_NOT_VALID_DURING_MTP ;
       
  3249 
       
  3250     return CyAsUsbGetNakStall(handle, ep, CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client) ;
       
  3251 }
       
  3252 
       
  3253 CyAsReturnStatus_t
       
  3254 CyAsUsbSignalRemoteWakeup(CyAsDeviceHandle handle,
       
  3255         CyAsFunctionCallback cb,
       
  3256         uint32_t client)
       
  3257 {
       
  3258     CyAsReturnStatus_t ret ;
       
  3259     CyAsLLRequestResponse *req_p , *reply_p ;
       
  3260 
       
  3261     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3262     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3263         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3264 
       
  3265     ret = IsUsbActive(dev_p) ;
       
  3266     if (ret != CY_AS_ERROR_SUCCESS)
       
  3267         return ret ;
       
  3268 
       
  3269     if (CyAsDeviceIsInCallback(dev_p))
       
  3270         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  3271 
       
  3272     if (dev_p->usb_last_event != CyAsEventUsbSuspend)
       
  3273         return CY_AS_ERROR_NOT_IN_SUSPEND ;
       
  3274 
       
  3275     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_USB_REMOTE_WAKEUP, CY_RQT_USB_RQT_CONTEXT, 0) ;
       
  3276     if (req_p == 0)
       
  3277         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3278 
       
  3279     /* A single status word response type */
       
  3280     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  3281     if (reply_p == 0)
       
  3282     {
       
  3283         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3284         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3285     }
       
  3286 
       
  3287     if (cb == 0)
       
  3288     {
       
  3289         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  3290         if (ret != CY_AS_ERROR_SUCCESS)
       
  3291             goto destroy ;
       
  3292 
       
  3293         if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SUCCESS_FAILURE)
       
  3294             ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  3295         else
       
  3296             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  3297     }
       
  3298     else
       
  3299     {
       
  3300         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP,
       
  3301             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  3302             CyAsUsbFuncCallback) ;
       
  3303 
       
  3304         if (ret != CY_AS_ERROR_SUCCESS)
       
  3305             goto destroy ;
       
  3306         return ret ;
       
  3307     }
       
  3308 
       
  3309 destroy:
       
  3310     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3311     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  3312 
       
  3313     return ret ;
       
  3314 }
       
  3315 
       
  3316 CyAsReturnStatus_t
       
  3317 CyAsUsbSetMSReportThreshold(CyAsDeviceHandle handle,
       
  3318         uint32_t wr_sectors,
       
  3319         uint32_t rd_sectors,
       
  3320         CyAsFunctionCallback cb,
       
  3321         uint32_t client)
       
  3322 {
       
  3323     CyAsReturnStatus_t ret ;
       
  3324     CyAsLLRequestResponse *req_p , *reply_p ;
       
  3325 
       
  3326     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3327     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3328         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3329 
       
  3330     ret = IsUsbActive(dev_p) ;
       
  3331     if (ret != CY_AS_ERROR_SUCCESS)
       
  3332         return ret ;
       
  3333 
       
  3334     if ((cb == 0) && (CyAsDeviceIsInCallback(dev_p)))
       
  3335         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  3336 
       
  3337     /* Check if the firmware version supports this feature. */
       
  3338     if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] == (1 << CyAsMediaNand)))
       
  3339         return CY_AS_ERROR_NOT_SUPPORTED ;
       
  3340 
       
  3341     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_USB_STORAGE_MONITOR, CY_RQT_USB_RQT_CONTEXT, 4) ;
       
  3342     if (req_p == 0)
       
  3343         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3344 
       
  3345     /* A single status word response type */
       
  3346     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  3347     if (reply_p == 0)
       
  3348     {
       
  3349         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3350         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3351     }
       
  3352 
       
  3353     /* Set the read and write count parameters into the request structure. */
       
  3354     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((wr_sectors >> 16) & 0xFFFF)) ;
       
  3355     CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)(wr_sectors & 0xFFFF)) ;
       
  3356     CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)((rd_sectors >> 16) & 0xFFFF)) ;
       
  3357     CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)(rd_sectors & 0xFFFF)) ;
       
  3358 
       
  3359     if (cb == 0)
       
  3360     {
       
  3361         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  3362         if (ret != CY_AS_ERROR_SUCCESS)
       
  3363             goto destroy ;
       
  3364 
       
  3365         if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SUCCESS_FAILURE)
       
  3366             ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  3367         else
       
  3368             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  3369     }
       
  3370     else
       
  3371     {
       
  3372         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD,
       
  3373             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  3374             CyAsUsbFuncCallback) ;
       
  3375 
       
  3376         if (ret != CY_AS_ERROR_SUCCESS)
       
  3377             goto destroy ;
       
  3378         return ret ;
       
  3379     }
       
  3380 
       
  3381 destroy:
       
  3382     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3383     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  3384 
       
  3385     return ret ;
       
  3386 }
       
  3387 
       
  3388 CyAsReturnStatus_t
       
  3389 CyAsUsbSelectMSPartitions (
       
  3390         CyAsDeviceHandle        handle,
       
  3391         CyAsBusNumber_t         bus,
       
  3392         uint32_t                device,
       
  3393         CyAsUsbMSType_t         type,
       
  3394         CyAsFunctionCallback    cb,
       
  3395         uint32_t                client)
       
  3396 {
       
  3397     CyAsReturnStatus_t ret ;
       
  3398     CyAsLLRequestResponse *req_p , *reply_p ;
       
  3399     uint16_t val ;
       
  3400 
       
  3401     CyAsDevice *dev_p = (CyAsDevice *)handle ;
       
  3402     if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
       
  3403         return CY_AS_ERROR_INVALID_HANDLE ;
       
  3404 
       
  3405     ret = IsUsbActive(dev_p) ;
       
  3406     if (ret != CY_AS_ERROR_SUCCESS)
       
  3407         return ret ;
       
  3408 
       
  3409     /* This API has to be made before SetEnumConfig is called. */
       
  3410     if (dev_p->usb_config[0].enabled)
       
  3411         return CY_AS_ERROR_INVALID_CALL_SEQUENCE ;
       
  3412 
       
  3413     if ((cb == 0) && (CyAsDeviceIsInCallback(dev_p)))
       
  3414         return CY_AS_ERROR_INVALID_IN_CALLBACK ;
       
  3415 
       
  3416     req_p = CyAsLLCreateRequest(dev_p, CY_RQT_MS_PARTITION_SELECT, CY_RQT_USB_RQT_CONTEXT, 2) ;
       
  3417     if (req_p == 0)
       
  3418         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3419 
       
  3420     /* A single status word response type */
       
  3421     reply_p = CyAsLLCreateResponse(dev_p, 1) ;
       
  3422     if (reply_p == 0)
       
  3423     {
       
  3424         CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3425         return CY_AS_ERROR_OUT_OF_MEMORY ;
       
  3426     }
       
  3427 
       
  3428     /* Set the read and write count parameters into the request structure. */
       
  3429     CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((bus << 8) | device)) ;
       
  3430 
       
  3431     val = 0 ;
       
  3432     if ((type == CyAsUsbMSUnit0) || (type == CyAsUsbMSBoth))
       
  3433         val |= 1 ;
       
  3434     if ((type == CyAsUsbMSUnit1) || (type == CyAsUsbMSBoth))
       
  3435         val |= (1 << 8) ;
       
  3436 
       
  3437     CyAsLLRequestResponse_SetWord(req_p, 1, val) ;
       
  3438 
       
  3439     if (cb == 0)
       
  3440     {
       
  3441         ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
       
  3442         if (ret != CY_AS_ERROR_SUCCESS)
       
  3443             goto destroy ;
       
  3444 
       
  3445         if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SUCCESS_FAILURE)
       
  3446             ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
       
  3447         else
       
  3448             ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  3449     }
       
  3450     else
       
  3451     {
       
  3452         ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_NODATA,
       
  3453             0, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
       
  3454             CyAsUsbFuncCallback) ;
       
  3455 
       
  3456         if (ret != CY_AS_ERROR_SUCCESS)
       
  3457             goto destroy ;
       
  3458         return ret ;
       
  3459     }
       
  3460 
       
  3461 destroy:
       
  3462     CyAsLLDestroyRequest(dev_p, req_p) ;
       
  3463     CyAsLLDestroyResponse(dev_p, reply_p) ;
       
  3464 
       
  3465     return ret ;
       
  3466 }
       
  3467 
       
  3468 static void
       
  3469 CyAsUsbFuncCallback(
       
  3470                     CyAsDevice *dev_p,
       
  3471                     uint8_t context,
       
  3472                     CyAsLLRequestResponse *rqt,
       
  3473                     CyAsLLRequestResponse *resp,
       
  3474                     CyAsReturnStatus_t stat)
       
  3475 {
       
  3476     CyAsUsbFuncCBNode*  node = (CyAsUsbFuncCBNode*)dev_p->usb_func_cbs->head_p ;
       
  3477     CyAsFuncCBNode*     fnode = (CyAsFuncCBNode*)dev_p->func_cbs_usb->head_p ;
       
  3478     CyAsReturnStatus_t  ret = CY_AS_ERROR_SUCCESS ;
       
  3479 
       
  3480     CyAsDeviceHandle    h = (CyAsDeviceHandle)dev_p ;
       
  3481     CyBool              delayed_ack = (rqt->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK) == CY_AS_REQUEST_RESPONSE_DELAY_ACK;
       
  3482     CyBool              exRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) == CY_AS_REQUEST_RESPONSE_EX ;
       
  3483     CyBool              msRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) == CY_AS_REQUEST_RESPONSE_MS ;
       
  3484     uint8_t             code ;
       
  3485     uint8_t             ep, state ;
       
  3486 
       
  3487     if(!exRequest && !msRequest)
       
  3488     {
       
  3489         CyAsHalAssert(dev_p->usb_func_cbs->count != 0) ;
       
  3490         CyAsHalAssert(dev_p->usb_func_cbs->type == CYAS_USB_FUNC_CB) ;
       
  3491     }
       
  3492     else
       
  3493     {
       
  3494         CyAsHalAssert(dev_p->func_cbs_usb->count != 0) ;
       
  3495         CyAsHalAssert(dev_p->func_cbs_usb->type == CYAS_FUNC_CB) ;
       
  3496     }
       
  3497 
       
  3498     (void)context ;
       
  3499 
       
  3500     /* The Handlers are responsible for Deleting the rqt and resp when
       
  3501      * they are finished
       
  3502      */
       
  3503     code = CyAsLLRequestResponse_GetCode(rqt) ;
       
  3504     switch(code)
       
  3505     {
       
  3506     case CY_RQT_START_USB:
       
  3507         ret = MyHandleResponseUsbStart(dev_p, rqt, resp, stat) ;
       
  3508         break ;
       
  3509     case CY_RQT_STOP_USB:
       
  3510         ret = MyHandleResponseUsbStop(dev_p, rqt, resp, stat) ;
       
  3511         break ;
       
  3512     case CY_RQT_SET_CONNECT_STATE:
       
  3513         if(!CyAsLLRequestResponse_GetWord(rqt, 0))
       
  3514             ret = MyHandleResponseDisconnect(dev_p, rqt, resp, stat) ;
       
  3515         else
       
  3516             ret = MyHandleResponseConnect(dev_p, rqt, resp, stat) ;
       
  3517         break ;
       
  3518     case CY_RQT_GET_CONNECT_STATE:
       
  3519         break ;
       
  3520     case CY_RQT_SET_USB_CONFIG:
       
  3521         ret = MyHandleResponseSetEnumConfig(dev_p, rqt, resp) ;
       
  3522         break ;
       
  3523     case CY_RQT_GET_USB_CONFIG:
       
  3524         CyAsHalAssert(fnode->data != 0) ;
       
  3525         ret = MyHandleResponseGetEnumConfig(dev_p, rqt, resp, fnode->data) ;
       
  3526         break ;
       
  3527     case CY_RQT_STALL_ENDPOINT:
       
  3528         ep    = (uint8_t)CyAsLLRequestResponse_GetWord(rqt, 0) ;
       
  3529         state = (uint8_t)CyAsLLRequestResponse_GetWord(rqt, 1) ;
       
  3530         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3531         if ((ret == CY_AS_ERROR_SUCCESS) && (ep > 1) && (state != 0) && (dev_p->usb_config[ep].dir == CyAsUsbOut))
       
  3532             CyAsUsbFlushLogicalEP(dev_p, ep) ;
       
  3533         break ;
       
  3534     case CY_RQT_GET_STALL:
       
  3535         CyAsHalAssert(fnode->data != 0) ;
       
  3536         ret = MyHandleResponseGetStall(dev_p, rqt, resp, (CyBool*)fnode->data) ;
       
  3537         break ;
       
  3538     case CY_RQT_SET_DESCRIPTOR:
       
  3539         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3540         break ;
       
  3541     case CY_RQT_GET_DESCRIPTOR:
       
  3542         CyAsHalAssert(fnode->data != 0) ;
       
  3543         ret = MyHandleResponseGetDescriptor(dev_p, rqt, resp, (CyAsGetDescriptorData*)fnode->data) ;
       
  3544         break;
       
  3545     case CY_RQT_SET_USB_CONFIG_REGISTERS:
       
  3546         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3547         if (ret == CY_AS_ERROR_SUCCESS)
       
  3548             ret = CyAsUsbSetupDma(dev_p) ;
       
  3549         break ;
       
  3550     case CY_RQT_ENDPOINT_SET_NAK:
       
  3551         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3552         break ;
       
  3553     case CY_RQT_GET_ENDPOINT_NAK:
       
  3554         CyAsHalAssert(fnode->data != 0) ;
       
  3555         ret = MyHandleResponseGetNak(dev_p, rqt, resp, (CyBool*)fnode->data) ;
       
  3556         break ;
       
  3557     case CY_RQT_ACK_SETUP_PACKET:
       
  3558         break ;
       
  3559     case CY_RQT_USB_REMOTE_WAKEUP:
       
  3560         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3561         break ;
       
  3562     case CY_RQT_CLEAR_DESCRIPTORS:
       
  3563         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3564         break ;
       
  3565     case CY_RQT_USB_STORAGE_MONITOR:
       
  3566         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3567         break ;
       
  3568     case CY_RQT_MS_PARTITION_SELECT:
       
  3569         ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
       
  3570         break ;
       
  3571     default:
       
  3572         ret = CY_AS_ERROR_INVALID_RESPONSE ;
       
  3573         CyAsHalAssert(CyFalse) ;
       
  3574         break ;
       
  3575     }
       
  3576 
       
  3577     /*
       
  3578      * If the low level layer returns a direct error, use the corresponding error code.
       
  3579      * If not, use the error code based on the response from firmware.
       
  3580      */
       
  3581     if (stat == CY_AS_ERROR_SUCCESS)
       
  3582         stat = ret ;
       
  3583 
       
  3584     if(exRequest || msRequest)
       
  3585     {
       
  3586         fnode->cb_p((CyAsDeviceHandle)dev_p, stat, fnode->client_data, (CyAsFunctCBType)fnode->dataType, fnode->data) ;
       
  3587         CyAsRemoveCBNode(dev_p->func_cbs_usb) ;
       
  3588     }
       
  3589     else
       
  3590     {
       
  3591         node->cb_p((CyAsDeviceHandle)dev_p, stat, node->client_data) ;
       
  3592         CyAsRemoveCBNode(dev_p->usb_func_cbs) ;
       
  3593     }
       
  3594 
       
  3595     if(delayed_ack)
       
  3596     {
       
  3597         CyAsHalAssert(CyAsDeviceIsAckDelayed(dev_p)) ;
       
  3598         CyAsDeviceRemAckDelayed(dev_p) ;
       
  3599 
       
  3600         /*
       
  3601          * Send the ACK if required.
       
  3602          */
       
  3603         if (!CyAsDeviceIsAckDelayed(dev_p))
       
  3604             CyAsUsbAckSetupPacket(h, UsbAckCallback, 0) ;
       
  3605     }
       
  3606 }
       
  3607 
       
  3608 /* This includes the implementation of the deprecated functions for backward
       
  3609  * compatibility
       
  3610  */
       
  3611 #include "cyasusb_dep_impl.h"
       
  3612 
       
  3613 /*[]*/