omap3530/beagle_drivers/wb/api/src/cyasmtp.c
changeset 27 117faf51deac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/wb/api/src/cyasmtp.c	Wed Mar 03 13:10:32 2010 +0000
@@ -0,0 +1,1073 @@
+/* Cypress West Bridge API header file (cyasmtp.h)
+## ===========================
+##
+##  Copyright Cypress Semiconductor Corporation, 2006-2009,
+##  All Rights Reserved
+##  UNPUBLISHED, LICENSED SOFTWARE.
+##
+##  CONFIDENTIAL AND PROPRIETARY INFORMATION
+##  WHICH IS THE PROPERTY OF CYPRESS.
+##
+##  Use of this file is governed
+##  by the license agreement included in the file
+##
+##     <install>/license/license.txt
+##
+##  where <install> is the Cypress software
+##  installation root directory path.
+##
+## ===========================
+*/
+
+#include "cyashal.h"
+#include "cyasmtp.h"
+#include "cyaserr.h"
+#include "cyasdma.h"
+#include "cyaslowlevel.h"
+
+static void
+CyAsMTPFuncCallback(CyAsDevice *dev_p,
+                    uint8_t context,
+                    CyAsLLRequestResponse *rqt,
+                    CyAsLLRequestResponse *resp,
+                    CyAsReturnStatus_t stat) ;
+
+static CyAsReturnStatus_t
+IsMTPActive(CyAsDevice *dev_p)
+{
+    if (!CyAsDeviceIsConfigured(dev_p))
+        return CY_AS_ERROR_NOT_CONFIGURED ;
+
+    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+        return CY_AS_ERROR_NO_FIRMWARE ;
+
+    if (dev_p->mtp_count == 0)
+        return CY_AS_ERROR_NOT_RUNNING ;
+
+    if (CyAsDeviceIsInSuspendMode(dev_p))
+        return CY_AS_ERROR_IN_SUSPEND ;
+
+    return CY_AS_ERROR_SUCCESS ;
+}
+
+static void
+MyMtpRequestCallback(CyAsDevice *dev_p,
+                     uint8_t context,
+                     CyAsLLRequestResponse *req_p,
+                     CyAsLLRequestResponse *resp_p,
+                     CyAsReturnStatus_t ret)
+{
+    uint16_t val, ev, status ;
+    uint16_t mtp_datalen = 0 ;
+    uint32_t bytecount_l, bytecount_h ;
+    CyAsMTPSendObjectCompleteData sendObjData ;
+    CyAsMTPGetObjectCompleteData  getObjData ;
+    CyAsDmaEndPoint *ep_p ;
+
+    uint8_t code = CyAsLLRequestResponse_GetCode(req_p) ;
+
+    (void)resp_p ;
+    (void)context ;
+    (void)ret ;
+
+    switch(code)
+    {
+    case CY_RQT_MTP_EVENT:
+        val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
+        status = (val >> 8) & 0xFF ; /* MSB indicates status of read/write */
+        ev =   val & 0xFF ; /* event type */
+        switch(ev)
+        {
+        case 0: /* SendObject Complete */
+            {
+                bytecount_l = CyAsLLRequestResponse_GetWord(req_p, 1) ;
+                bytecount_h = CyAsLLRequestResponse_GetWord(req_p, 2) ;
+                sendObjData.byte_count = (bytecount_h << 16) | bytecount_l ;
+
+                sendObjData.status = status ;
+
+                /* use the byte count again */
+                bytecount_l = CyAsLLRequestResponse_GetWord(req_p, 3) ;
+                bytecount_h = CyAsLLRequestResponse_GetWord(req_p, 4) ;
+                sendObjData.transaction_id = (bytecount_h << 16) | bytecount_l ;
+
+                dev_p->mtp_turbo_active = CyFalse ;
+
+                if (dev_p->mtp_event_cb)
+                    dev_p->mtp_event_cb((CyAsDeviceHandle)dev_p,  CyAsMTPSendObjectComplete,
+                                        &sendObjData) ;
+            }
+            break ;
+
+        case 1: /* GetObject Complete */
+            {
+                bytecount_l = CyAsLLRequestResponse_GetWord(req_p, 1) ;
+                bytecount_h = CyAsLLRequestResponse_GetWord(req_p, 2) ;
+
+                getObjData.byte_count = (bytecount_h << 16) | bytecount_l ;
+                getObjData.status = status ;
+
+                dev_p->mtp_turbo_active = CyFalse ;
+
+                if (dev_p->mtp_event_cb)
+                    dev_p->mtp_event_cb((CyAsDeviceHandle)dev_p,  CyAsMTPGetObjectComplete,
+                                        &getObjData);
+            }
+            break ;
+
+        case 2: /* BlockTable Needed */
+            {
+                if (dev_p->mtp_event_cb)
+                    dev_p->mtp_event_cb((CyAsDeviceHandle)dev_p,  CyAsMTPBlockTableNeeded, 0);
+            }
+            break ;
+        default:
+            CyAsHalPrintMessage("Invalid event type\n") ;
+            CyAsLLSendDataResponse(dev_p, CY_RQT_TUR_RQT_CONTEXT, CY_RESP_MTP_INVALID_EVENT, sizeof(ev), &ev) ;
+            break ;
+        }
+        break ;
+
+    case CY_RQT_TURBO_CMD_FROM_HOST:
+        {
+            mtp_datalen = CyAsLLRequestResponse_GetWord(req_p, 1) ;
+
+            /* Get the endpoint pointer based on the endpoint number */
+            ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_READ_ENDPOINT) ;
+
+            /* The event should arrive only after the DMA operation has been queued. */
+            CyAsHalAssert(ep_p->queue_p != 0) ;
+
+            /* Put the len in ep data information in dmaqueue and kick start the queue */
+            CyAsHalAssert(ep_p->queue_p->size >= mtp_datalen) ;
+
+            if (mtp_datalen == 0)
+            {
+                CyAsDmaCompletedCallback(dev_p->tag, CY_AS_MTP_READ_ENDPOINT, 0, CY_AS_ERROR_SUCCESS) ;
+            }
+            else
+            {
+                ep_p->maxhwdata = mtp_datalen ;
+
+                /*
+                 * Make sure that the DMA status for this EP is not running, so that
+                 * the call to CyAsDmaKickStart gets this transfer going.
+                 * Note: In MTP mode, we never leave a DMA transfer of greater than one
+                 * packet running. So, it is okay to override the status here and start
+                 * the next packet transfer.
+                 */
+                CyAsDmaEndPointSetStopped(ep_p) ;
+
+                /* Kick start the queue if it is not running */
+                CyAsDmaKickStart(dev_p, CY_AS_MTP_READ_ENDPOINT) ;
+            }
+        }
+        break ;
+
+    case CY_RQT_TURBO_START_WRITE_DMA:
+        {
+            /*
+             * Now that the firmware is ready to receive the next packet of data, start
+             * the corresponding DMA transfer.  First, ensure that a DMA operation is still
+             * pending in the queue for the write endpoint.
+             */
+            CyAsLLSendStatusResponse(dev_p, CY_RQT_TUR_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+
+            ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_WRITE_ENDPOINT) ;
+            CyAsHalAssert (ep_p->queue_p != 0) ;
+
+            CyAsDmaEndPointSetStopped(ep_p) ;
+            CyAsDmaKickStart(dev_p, CY_AS_MTP_WRITE_ENDPOINT) ;
+        }
+        break ;
+
+    default:
+        CyAsHalPrintMessage("Invalid request received on TUR context\n") ;
+        val = req_p->box0 ;
+        CyAsLLSendDataResponse(dev_p, CY_RQT_TUR_RQT_CONTEXT, CY_RESP_INVALID_REQUEST, sizeof(val), &val) ;
+        break ;
+    }
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseNoData(CyAsDevice* dev_p,
+                         CyAsLLRequestResponse *req_p,
+                         CyAsLLRequestResponse *reply_p)
+{
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+    {
+        ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        goto destroy ;
+    }
+
+    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+
+destroy :
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseMTPStart(CyAsDevice* dev_p,
+                         CyAsLLRequestResponse *req_p,
+                         CyAsLLRequestResponse *reply_p,
+                         CyAsReturnStatus_t ret)
+{
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+    {
+        ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        goto destroy ;
+    }
+
+    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+    dev_p->mtp_count++ ;
+
+    CyAsDmaEnableEndPoint(dev_p, CY_AS_MTP_READ_ENDPOINT, CyTrue, CyAsDirectionOut) ;
+    dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].enabled = CyTrue ;
+    dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].dir = CyAsUsbOut ;
+    dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].type = CyAsUsbBulk ;
+
+    CyAsDmaEnableEndPoint(dev_p, CY_AS_MTP_WRITE_ENDPOINT, CyTrue, CyAsDirectionIn) ;
+    dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].enabled = CyTrue ;
+    dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].dir = CyAsUsbIn ;
+    dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].type = CyAsUsbBulk ;
+
+    CyAsDmaSetMaxDmaSize(dev_p, 0x02, 0x0200) ; /* Packet size is 512 bytes */
+    CyAsDmaSetMaxDmaSize(dev_p, 0x06, 0x40) ;   /* Packet size is 64 bytes until a switch to high speed happens. */
+
+destroy :
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    if (ret != CY_AS_ERROR_SUCCESS)
+        CyAsLLRegisterRequestCallback(dev_p, CY_RQT_TUR_RQT_CONTEXT, 0) ;
+
+    CyAsDeviceClearMSSPending(dev_p) ;
+
+    return ret ;
+}
+
+
+CyAsReturnStatus_t
+CyAsMTPStart(CyAsDeviceHandle handle,
+             CyAsMTPEventCallback eventCB,
+             CyAsFunctionCallback cb,
+             uint32_t client
+             )
+{
+    CyAsLLRequestResponse *req_p, *reply_p ;
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+    CyAsDevice* dev_p ;
+
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    if (!CyAsDeviceIsConfigured(dev_p))
+        return CY_AS_ERROR_NOT_CONFIGURED ;
+
+    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+        return CY_AS_ERROR_NO_FIRMWARE ;
+
+    if (CyAsDeviceIsInSuspendMode(dev_p))
+        return CY_AS_ERROR_IN_SUSPEND ;
+
+    if (CyAsDeviceIsInCallback(dev_p))
+        return CY_AS_ERROR_INVALID_IN_CALLBACK ;
+
+    if(CyAsDeviceIsMSSPending(dev_p))
+        return CY_AS_ERROR_STARTSTOP_PENDING ;
+
+    if (dev_p->storage_count == 0)
+        return CY_AS_ERROR_NOT_RUNNING ;
+
+    if (dev_p->usb_count == 0)
+        return CY_AS_ERROR_NOT_RUNNING ;
+
+    if (dev_p->is_mtp_firmware == 0)
+        return CY_AS_ERROR_NOT_SUPPORTED ;
+
+    CyAsDeviceSetMSSPending(dev_p) ;
+
+    if (dev_p->mtp_count == 0)
+    {
+
+        dev_p->mtp_event_cb = eventCB ;
+        /*
+        * We register here becuase the start request may cause events to occur before the
+        * response to the start request.
+        */
+        CyAsLLRegisterRequestCallback(dev_p, CY_RQT_TUR_RQT_CONTEXT, MyMtpRequestCallback) ;
+
+        /* Create the request to send to the West Bridge device */
+        req_p = CyAsLLCreateRequest(dev_p, CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0) ;
+        if (req_p == 0)
+        {
+            CyAsDeviceClearMSSPending(dev_p) ;
+            return CY_AS_ERROR_OUT_OF_MEMORY ;
+        }
+
+        /* Reserve space for the reply, the reply data will not exceed one word */
+        reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+        if (reply_p == 0)
+        {
+            CyAsLLDestroyRequest(dev_p, req_p) ;
+            CyAsDeviceClearMSSPending(dev_p) ;
+            return CY_AS_ERROR_OUT_OF_MEMORY ;
+        }
+
+        if(cb == 0)
+        {
+            ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+            if (ret != CY_AS_ERROR_SUCCESS)
+                goto destroy ;
+
+            return MyHandleResponseMTPStart(dev_p, req_p, reply_p, ret) ;
+        }
+        else
+        {
+            ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MTP_START,
+                0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+                CyAsMTPFuncCallback) ;
+
+            if (ret != CY_AS_ERROR_SUCCESS)
+                goto destroy ;
+
+            return ret ;
+        }
+
+destroy:
+        CyAsLLDestroyRequest(dev_p, req_p) ;
+        CyAsLLDestroyResponse(dev_p, reply_p) ;
+    }
+    else
+    {
+        dev_p->mtp_count++ ;
+        if (cb)
+            cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0) ;
+    }
+
+    CyAsDeviceClearMSSPending(dev_p) ;
+
+    return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseMTPStop(CyAsDevice* dev_p,
+                        CyAsLLRequestResponse *req_p,
+                        CyAsLLRequestResponse *reply_p,
+                        CyAsReturnStatus_t ret)
+{
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+    {
+        ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        goto destroy ;
+    }
+
+    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+    /*
+    * We sucessfully shutdown the stack, so decrement to make the count
+    * zero.
+    */
+    dev_p->mtp_count-- ;
+
+destroy :
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    if (ret != CY_AS_ERROR_SUCCESS)
+        CyAsLLRegisterRequestCallback(dev_p, CY_RQT_TUR_RQT_CONTEXT, 0) ;
+
+    CyAsDeviceClearMSSPending(dev_p) ;
+
+    return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMTPStop(CyAsDeviceHandle handle,
+            CyAsFunctionCallback cb,
+            uint32_t client
+            )
+{
+    CyAsLLRequestResponse *req_p = 0, *reply_p = 0 ;
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+    CyAsDevice*dev_p ;
+
+    CyAsLogDebugMessage(6, "CyAsMTPStop called") ;
+
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    ret = IsMTPActive(dev_p) ;
+    if (ret != CY_AS_ERROR_SUCCESS)
+        return ret ;
+
+    if (CyAsDeviceIsInCallback(dev_p))
+        return CY_AS_ERROR_INVALID_IN_CALLBACK ;
+
+    if(CyAsDeviceIsMSSPending(dev_p))
+        return CY_AS_ERROR_STARTSTOP_PENDING ;
+
+    CyAsDeviceSetMSSPending(dev_p) ;
+
+    if (dev_p->mtp_count == 1)
+    {
+        /* Create the request to send to the West Bridge device */
+        req_p = CyAsLLCreateRequest(dev_p, CY_RQT_STOP_MTP, CY_RQT_TUR_RQT_CONTEXT, 0) ;
+        if (req_p == 0)
+        {
+            ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+            goto destroy ;
+        }
+
+        /* Reserve space for the reply, the reply data will not exceed one word */
+        reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+        if (reply_p == 0)
+        {
+            ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+            goto destroy ;
+        }
+
+        if(cb == 0)
+        {
+            ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+            if (ret != CY_AS_ERROR_SUCCESS)
+                goto destroy ;
+
+            return MyHandleResponseMTPStop(dev_p, req_p, reply_p, ret) ;
+        }
+        else
+        {
+            ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MTP_STOP,
+                0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+                CyAsMTPFuncCallback) ;
+
+            if (ret != CY_AS_ERROR_SUCCESS)
+                goto destroy ;
+
+            return ret ;
+        }
+
+destroy:
+        CyAsLLDestroyRequest(dev_p, req_p) ;
+        CyAsLLDestroyResponse(dev_p, reply_p) ;
+    }
+    else if (dev_p->mtp_count > 1)
+    {
+
+        dev_p->mtp_count-- ;
+
+        if (cb)
+            cb(handle, ret, client, CY_FUNCT_CB_MTP_STOP, 0) ;
+    }
+
+    CyAsDeviceClearMSSPending(dev_p) ;
+
+    return ret ;
+}
+
+static void
+MtpWriteCallback(
+        CyAsDevice *dev_p,
+        uint8_t context,
+        CyAsLLRequestResponse *rqt,
+        CyAsLLRequestResponse *resp,
+        CyAsReturnStatus_t ret)
+{
+    CyAsHalAssert(context == CY_RQT_TUR_RQT_CONTEXT) ;
+
+    if (ret == CY_AS_ERROR_SUCCESS)
+    {
+        if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
+            ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        else
+            ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
+    }
+
+    if (ret != CY_AS_ERROR_SUCCESS)
+    {
+        /* Firmware failed the request. Cancel the DMA transfer. */
+        CyAsDmaCancel(dev_p, 0x04, CY_AS_ERROR_CANCELED) ;
+        CyAsDeviceClearStorageAsyncPending(dev_p) ;
+    }
+
+    CyAsLLDestroyResponse(dev_p, resp) ;
+    CyAsLLDestroyRequest(dev_p, rqt) ;
+}
+
+static void
+AsyncWriteRequestCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
+{
+    CyAsDeviceHandle h ;
+    CyAsFunctionCallback cb ;
+
+    (void)size ;
+    (void)buf_p ;
+    (void)ep ;
+
+
+    CyAsLogDebugMessage(6, "AsyncWriteRequestCallback called") ;
+
+    h = (CyAsDeviceHandle)dev_p ;
+
+    cb = dev_p->mtp_cb ;
+    dev_p->mtp_cb = 0 ;
+
+    CyAsDeviceClearStorageAsyncPending(dev_p) ;
+
+    if (cb)
+        cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0) ;
+
+}
+
+static void
+SyncMTPCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
+{
+    (void)ep ;
+    (void)buf_p ;
+    (void)size ;
+
+    dev_p->mtp_error = err ;
+}
+
+static CyAsReturnStatus_t
+CyAsMTPOperation(CyAsDevice *dev_p,
+                 CyAsMTPBlockTable* blk_table,
+                 uint32_t num_bytes,
+                 uint32_t transaction_id,
+                 CyAsFunctionCallback cb,
+                 uint32_t client,
+                 uint8_t rqttype
+                 )
+{
+    CyAsLLRequestResponse *req_p = 0, *reply_p = 0 ;
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+    uint32_t mask = 0 ;
+    CyAsFunctCBType mtp_cb_op = (CyAsFunctCBType)0 ;
+    uint16_t size = 2 ;
+
+        if(dev_p->mtp_count == 0)
+                return CY_AS_ERROR_NOT_RUNNING ;
+
+    if (rqttype == CY_RQT_INIT_SEND_OBJECT)
+    {
+        mtp_cb_op = CY_FUNCT_CB_MTP_INIT_SEND_OBJECT ;
+        dev_p->mtp_turbo_active = CyTrue ;
+    }
+    else if (rqttype == CY_RQT_INIT_GET_OBJECT)
+    {
+        mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT ;
+        dev_p->mtp_turbo_active = CyTrue ;
+    }
+    else
+        mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE ;
+
+    ret = IsMTPActive(dev_p) ;
+    if (ret != CY_AS_ERROR_SUCCESS)
+        return ret ;
+
+    if (CY_RQT_INIT_GET_OBJECT == rqttype)
+    {
+        size = 4 ;
+    }
+    /* Create the request to send to the West Bridge device */
+    req_p = CyAsLLCreateRequest(dev_p, rqttype, CY_RQT_TUR_RQT_CONTEXT, size) ;
+    if (req_p == 0)
+    {
+        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+        goto destroy ;
+    }
+
+    /* Reserve space for the reply, the reply data will not exceed one word */
+    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+    if (reply_p == 0)
+    {
+        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+        goto destroy ;
+    }
+
+    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)(num_bytes & 0xFFFF)) ;
+    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((num_bytes >> 16) & 0xFFFF)) ;
+
+    /* If it is GET_OBJECT, send transaction id as well */
+    if (CY_RQT_INIT_GET_OBJECT == rqttype)
+    {
+        CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(transaction_id & 0xFFFF)) ;
+        CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((transaction_id >> 16) & 0xFFFF)) ;
+    }
+
+    if(cb == 0)
+    {
+        /* Queue the DMA request for block table write */
+        ret = CyAsDmaQueueRequest(dev_p, 4, blk_table, sizeof(CyAsMTPBlockTable), CyFalse, CyFalse, SyncMTPCallback) ;
+
+        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+        {
+            CyAsDmaCancel(dev_p, 4, CY_AS_ERROR_CANCELED) ;
+            CyAsDeviceClearStorageAsyncPending(dev_p) ;
+
+            goto destroy ;
+        }
+
+        ret = CyAsDmaDrainQueue(dev_p, 4, CyTrue) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        ret = dev_p->mtp_error ;
+        goto destroy ;
+    }
+    else
+    {
+#if 0
+        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MTP_INIT_SEND_OBJECT,
+            0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+            CyAsMTPFuncCallback) ;
+
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+#endif
+
+        /* Protection from interrupt driven code */
+        /* since we are using storage EP4 check if any storage activity is pending */
+        mask = CyAsHalDisableInterrupts() ;
+        if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
+        {
+            CyAsHalEnableInterrupts(mask) ;
+            return CY_AS_ERROR_ASYNC_PENDING ;
+        }
+        CyAsDeviceSetStorageAsyncPending(dev_p) ;
+        CyAsHalEnableInterrupts(mask) ;
+
+        dev_p->mtp_cb     = cb ;
+        dev_p->mtp_client = client ;
+        dev_p->mtp_op     = mtp_cb_op ;
+
+        ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, MtpWriteCallback) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        ret = CyAsDmaQueueRequest(dev_p, 4, blk_table, sizeof(CyAsMTPBlockTable), CyFalse, CyFalse, AsyncWriteRequestCallback) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+            return ret ;
+
+        /* Kick start the queue if it is not running */
+        CyAsDmaKickStart(dev_p, 4) ;
+
+        return CY_AS_ERROR_SUCCESS ;
+    }
+
+destroy:
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMTPInitSendObject(CyAsDeviceHandle handle,
+                      CyAsMTPBlockTable* blk_table,
+                      uint32_t num_bytes,
+                      CyAsFunctionCallback cb,
+                      uint32_t client
+                      )
+{
+    CyAsDevice* dev_p ;
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    return CyAsMTPOperation(dev_p, blk_table, num_bytes, 0, cb, client, CY_RQT_INIT_SEND_OBJECT) ;
+
+}
+
+CyAsReturnStatus_t
+CyAsMTPInitGetObject(CyAsDeviceHandle handle,
+                     CyAsMTPBlockTable* blk_table,
+                     uint32_t num_bytes,
+                     uint32_t transaction_id,
+                     CyAsFunctionCallback cb,
+                     uint32_t client
+                     )
+{
+    CyAsDevice* dev_p ;
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    return CyAsMTPOperation(dev_p, blk_table, num_bytes, transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT) ;
+
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseCancelSendObject(CyAsDevice* dev_p,
+                                 CyAsLLRequestResponse *req_p,
+                                 CyAsLLRequestResponse *reply_p,
+                                 CyAsReturnStatus_t ret)
+{
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+    {
+        ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        goto destroy ;
+    }
+
+    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+
+destroy :
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMTPCancelSendObject(CyAsDeviceHandle handle,
+                        CyAsFunctionCallback cb,
+                        uint32_t client
+                        )
+{
+    CyAsLLRequestResponse *req_p = 0, *reply_p = 0 ;
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+    CyAsDevice*dev_p ;
+
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+        if(dev_p->mtp_count == 0)
+                return CY_AS_ERROR_NOT_RUNNING ;
+
+    /* Create the request to send to the West Bridge device */
+    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CANCEL_SEND_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0) ;
+    if (req_p == 0)
+    {
+        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+        goto destroy ;
+    }
+
+    /* Reserve space for the reply, the reply data will not exceed one word */
+    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+    if (reply_p == 0)
+    {
+        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+        goto destroy ;
+    }
+
+    if(cb == 0)
+    {
+        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        return MyHandleResponseCancelSendObject(dev_p, req_p, reply_p, ret) ;
+    }
+    else
+    {
+        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT,
+            0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+            CyAsMTPFuncCallback) ;
+
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        return ret ;
+    }
+
+destroy :
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseCancelGetObject(CyAsDevice* dev_p,
+                                CyAsLLRequestResponse *req_p,
+                                CyAsLLRequestResponse *reply_p,
+                                CyAsReturnStatus_t ret)
+{
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+    {
+        ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        goto destroy ;
+    }
+
+    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+    if (ret != CY_AS_ERROR_SUCCESS)
+        goto destroy ;
+
+
+destroy :
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMTPCancelGetObject(CyAsDeviceHandle handle,
+                       CyAsFunctionCallback cb,
+                       uint32_t client
+                       )
+{
+    CyAsLLRequestResponse *req_p = 0, *reply_p = 0 ;
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+    CyAsDevice*dev_p ;
+
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+        if(dev_p->mtp_count == 0)
+                return CY_AS_ERROR_NOT_RUNNING ;
+
+    /* Create the request to send to the West Bridge device */
+    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CANCEL_GET_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0) ;
+    if (req_p == 0)
+    {
+        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+        goto destroy ;
+    }
+
+    /* Reserve space for the reply, the reply data will not exceed one word */
+    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+    if (reply_p == 0)
+    {
+        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+        goto destroy ;
+    }
+
+    if(cb == 0)
+    {
+        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        return MyHandleResponseCancelGetObject(dev_p, req_p, reply_p, ret) ;
+    }
+    else
+    {
+        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT,
+            0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+            CyAsMTPFuncCallback) ;
+
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        return ret ;
+    }
+
+destroy:
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMTPSendBlockTable(CyAsDeviceHandle handle,
+                      CyAsMTPBlockTable* blk_table,
+                      CyAsFunctionCallback cb,
+                      uint32_t client
+                      )
+{
+    CyAsDevice* dev_p ;
+    dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    return CyAsMTPOperation(dev_p, blk_table, 0, 0, cb, client, CY_RQT_SEND_BLOCK_TABLE) ;
+}
+
+static void
+CyAsMTPFuncCallback(CyAsDevice *dev_p,
+                    uint8_t context,
+                    CyAsLLRequestResponse *rqt,
+                    CyAsLLRequestResponse *resp,
+                    CyAsReturnStatus_t stat)
+{
+    CyAsFuncCBNode*     node = (CyAsFuncCBNode*)dev_p->func_cbs_mtp->head_p ;
+    CyAsReturnStatus_t  ret = CY_AS_ERROR_SUCCESS ;
+    uint8_t             code ;
+    CyBool delay_callback = CyFalse ;
+
+    CyAsHalAssert(dev_p->func_cbs_mtp->count != 0) ;
+    CyAsHalAssert(dev_p->func_cbs_mtp->type == CYAS_FUNC_CB) ;
+
+    (void)context ;
+
+    /* The Handlers are responsible for Deleting the rqt and resp when
+    * they are finished
+    */
+    code = CyAsLLRequestResponse_GetCode(rqt) ;
+    switch(code)
+    {
+    case CY_RQT_START_MTP:
+        ret = MyHandleResponseMTPStart(dev_p, rqt, resp, stat) ;
+        break ;
+    case CY_RQT_STOP_MTP:
+        ret = MyHandleResponseMTPStop(dev_p, rqt, resp, stat) ;
+        break ;
+#if 0
+    case CY_RQT_INIT_SEND_OBJECT:
+        ret = MyHandleResponseInitSendObject(dev_p, rqt, resp, stat, CyTrue) ;
+        delay_callback = CyTrue ;
+        break ;
+#endif
+    case CY_RQT_CANCEL_SEND_OBJECT:
+        ret = MyHandleResponseCancelSendObject(dev_p, rqt, resp, stat) ;
+        break ;
+#if 0
+    case CY_RQT_INIT_GET_OBJECT:
+        ret = MyHandleResponseInitGetObject(dev_p, rqt, resp, stat, CyTrue) ;
+        delay_callback = CyTrue ;
+        break ;
+#endif
+    case CY_RQT_CANCEL_GET_OBJECT:
+        ret = MyHandleResponseCancelGetObject(dev_p, rqt, resp, stat) ;
+        break ;
+#if 0
+    case CY_RQT_SEND_BLOCK_TABLE:
+        ret = MyHandleResponseSendBlockTable(dev_p, rqt, resp, stat, CyTrue) ;
+        delay_callback = CyTrue ;
+        break ;
+#endif
+    case CY_RQT_ENABLE_USB_PATH:
+        ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+        if (ret == CY_AS_ERROR_SUCCESS)
+            dev_p->is_storage_only_mode = CyFalse ;
+        break ;
+    default:
+        ret = CY_AS_ERROR_INVALID_RESPONSE ;
+        CyAsHalAssert(CyFalse) ;
+        break ;
+    }
+
+    /*
+    * If the low level layer returns a direct error, use the corresponding error code.
+    * If not, use the error code based on the response from firmware.
+    */
+    if (stat == CY_AS_ERROR_SUCCESS)
+        stat = ret ;
+
+    if(!delay_callback)
+    {
+        node->cb_p((CyAsDeviceHandle)dev_p, stat, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
+        CyAsRemoveCBNode(dev_p->func_cbs_mtp) ;
+    }
+}
+
+CyAsReturnStatus_t
+CyAsMTPStorageOnlyStart(CyAsDeviceHandle handle)
+{
+    CyAsDevice *dev_p = (CyAsDevice *)handle ;
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    if (!CyAsDeviceIsConfigured(dev_p))
+        return CY_AS_ERROR_NOT_CONFIGURED ;
+
+    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+        return CY_AS_ERROR_NO_FIRMWARE ;
+
+    if (dev_p->storage_count == 0)
+        return CY_AS_ERROR_NOT_RUNNING ;
+
+    dev_p->is_storage_only_mode = CyTrue ;
+    return CY_AS_ERROR_SUCCESS ;
+}
+
+CyAsReturnStatus_t
+CyAsMTPStorageOnlyStop(CyAsDeviceHandle handle,
+                        CyAsFunctionCallback cb,
+                        uint32_t client)
+{
+    CyAsDevice *dev_p = (CyAsDevice *)handle ;
+    CyAsLLRequestResponse *req_p, *reply_p ;
+    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+        return CY_AS_ERROR_INVALID_HANDLE ;
+
+    if (!CyAsDeviceIsConfigured(dev_p))
+        return CY_AS_ERROR_NOT_CONFIGURED ;
+
+    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+        return CY_AS_ERROR_NO_FIRMWARE ;
+
+    if (dev_p->storage_count == 0)
+        return CY_AS_ERROR_NOT_RUNNING ;
+
+    if (dev_p->is_storage_only_mode == CyFalse)
+        return CY_AS_ERROR_SUCCESS ;
+
+    if (CyAsDeviceIsInCallback(dev_p))
+        return CY_AS_ERROR_INVALID_IN_CALLBACK ;
+
+    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ENABLE_USB_PATH, CY_RQT_TUR_RQT_CONTEXT, 1) ;
+    if (req_p == 0)
+        return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+    if (reply_p == 0)
+    {
+        CyAsLLDestroyRequest(dev_p, req_p) ;
+        return CY_AS_ERROR_OUT_OF_MEMORY ;
+    }
+
+    if(cb == 0)
+    {
+        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        ret = MyHandleResponseNoData(dev_p, req_p, reply_p) ;
+        if (ret == CY_AS_ERROR_SUCCESS)
+            dev_p->is_storage_only_mode = CyFalse ;
+        return ret ;
+    }
+    else
+    {
+        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY,
+            0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+            CyAsMTPFuncCallback) ;
+
+        if (ret != CY_AS_ERROR_SUCCESS)
+            goto destroy ;
+
+        return ret ;
+    }
+
+destroy:
+    CyAsLLDestroyRequest(dev_p, req_p) ;
+    CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+    return ret ;
+}