/* Cypress West Bridge API header file (cyasmtp.h)
## ===========================
## Copyright (C) 2010  Cypress Semiconductor
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor
## Boston, MA  02110-1301, USA.
## ===========================
*/

#include "../../include/linux/westbridge/cyashal.h"
#include "../../include/linux/westbridge/cyasmtp.h"
#include "../../include/linux/westbridge/cyaserr.h"
#include "../../include/linux/westbridge/cyasdma.h"
#include "../../include/linux/westbridge/cyaslowlevel.h"

static void
cy_as_mtp_func_callback(cy_as_device *dev_p,
					uint8_t context,
					cy_as_ll_request_response *rqt,
					cy_as_ll_request_response *resp,
					cy_as_return_status_t stat);

static cy_as_return_status_t
is_mtp_active(cy_as_device *dev_p)
{
	if (!cy_as_device_is_configured(dev_p))
		return CY_AS_ERROR_NOT_CONFIGURED;

	if (!cy_as_device_is_firmware_loaded(dev_p))
		return CY_AS_ERROR_NO_FIRMWARE;

	if (dev_p->mtp_count == 0)
		return CY_AS_ERROR_NOT_RUNNING;

	if (cy_as_device_is_in_suspend_mode(dev_p))
		return CY_AS_ERROR_IN_SUSPEND;

	return CY_AS_ERROR_SUCCESS;
}

static void
my_mtp_request_callback(cy_as_device *dev_p,
					 uint8_t context,
					 cy_as_ll_request_response *req_p,
					 cy_as_ll_request_response *resp_p,
					 cy_as_return_status_t ret)
{
	uint16_t val, ev, status;
	uint16_t mtp_datalen = 0;
	uint32_t bytecount_l, bytecount_h;
	cy_as_mtp_send_object_complete_data send_obj_data;
	cy_as_mtp_get_object_complete_data  get_obj_data;
	cy_as_dma_end_point *ep_p;

	uint8_t code = cy_as_ll_request_response__get_code(req_p);

	(void)resp_p;
	(void)context;
	(void)ret;

	switch (code) {
	case CY_RQT_MTP_EVENT:
		val = cy_as_ll_request_response__get_word(req_p, 0);
		/* MSB indicates status of read/write */
		status = (val >> 8) & 0xFF;
		/* event type */
		ev =   val & 0xFF;
		switch (ev) {
		case 0: /* SendObject Complete */
			{
				bytecount_l =
					cy_as_ll_request_response__get_word
					(req_p, 1);
				bytecount_h =
					cy_as_ll_request_response__get_word
					(req_p, 2);
				send_obj_data.byte_count =
					(bytecount_h << 16) | bytecount_l;

				send_obj_data.status = status;

				/* use the byte count again */
				bytecount_l =
					cy_as_ll_request_response__get_word
					(req_p, 3);
				bytecount_h =
					cy_as_ll_request_response__get_word
					(req_p, 4);
				send_obj_data.transaction_id =
					(bytecount_h << 16) | bytecount_l;

				dev_p->mtp_turbo_active = cy_false;

				if (dev_p->mtp_event_cb)
					dev_p->mtp_event_cb(
					(cy_as_device_handle) dev_p,
					cy_as_mtp_send_object_complete,
						&send_obj_data);
			}
			break;

		case 1: /* GetObject Complete */
			{
				bytecount_l =
					cy_as_ll_request_response__get_word
					(req_p, 1);
				bytecount_h =
					cy_as_ll_request_response__get_word
					(req_p, 2);

				get_obj_data.byte_count =
					(bytecount_h << 16) | bytecount_l;

				get_obj_data.status = status;

				dev_p->mtp_turbo_active = cy_false;

				if (dev_p->mtp_event_cb)
					dev_p->mtp_event_cb(
					(cy_as_device_handle) dev_p,
					cy_as_mtp_get_object_complete,
					&get_obj_data);
			}
			break;

		case 2: /* BlockTable Needed */
			{
				if (dev_p->mtp_event_cb)
					dev_p->mtp_event_cb(
					(cy_as_device_handle) dev_p,
					cy_as_mtp_block_table_needed, 0);
			}
			break;
		default:
			cy_as_hal_print_message("invalid event type\n");
			cy_as_ll_send_data_response(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 =
				cy_as_ll_request_response__get_word(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. */
			cy_as_hal_assert(ep_p->queue_p != 0);

			/* Put the len in ep data information in
			 * dmaqueue and kick start the queue */
			cy_as_hal_assert(ep_p->queue_p->size >= mtp_datalen);

			if (mtp_datalen == 0) {
				cy_as_dma_completed_callback(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
				 * cy_as_dma_kick_start 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.
				 */
				cy_as_dma_end_point_set_stopped(ep_p);

				/* Kick start the queue if it is not running */
				cy_as_dma_kick_start(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.
			 */
			cy_as_ll_send_status_response(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);
			cy_as_hal_assert(ep_p->queue_p != 0);

			cy_as_dma_end_point_set_stopped(ep_p);
			cy_as_dma_kick_start(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
		}
		break;

	default:
		cy_as_hal_print_message("invalid request received "
				"on TUR context\n");
		val = req_p->box0;
		cy_as_ll_send_data_response(dev_p, CY_RQT_TUR_RQT_CONTEXT,
			CY_RESP_INVALID_REQUEST, sizeof(val), &val);
		break;
	}
}

static cy_as_return_status_t
my_handle_response_no_data(cy_as_device *dev_p,
			cy_as_ll_request_response *req_p,
			cy_as_ll_request_response *reply_p)
{
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;

	if (cy_as_ll_request_response__get_code(reply_p) !=
		CY_RESP_SUCCESS_FAILURE) {
		ret = CY_AS_ERROR_INVALID_RESPONSE;
		goto destroy;
	}

	ret = cy_as_ll_request_response__get_word(reply_p, 0);

destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}

static cy_as_return_status_t
my_handle_response_mtp_start(cy_as_device *dev_p,
			cy_as_ll_request_response *req_p,
			cy_as_ll_request_response *reply_p,
			cy_as_return_status_t ret)
{
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;

	if (cy_as_ll_request_response__get_code(reply_p) !=
		CY_RESP_SUCCESS_FAILURE) {
		ret = CY_AS_ERROR_INVALID_RESPONSE;
		goto destroy;
	}

	ret = cy_as_ll_request_response__get_word(reply_p, 0);
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;

	dev_p->mtp_count++;

	cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_READ_ENDPOINT,
		cy_true, cy_as_direction_out);
	dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].enabled = cy_true;
	dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].dir = cy_as_usb_out;
	dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].type = cy_as_usb_bulk;

	cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_WRITE_ENDPOINT,
		cy_true, cy_as_direction_in);
	dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].enabled = cy_true;
	dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].dir = cy_as_usb_in;
	dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].type = cy_as_usb_bulk;

	/* Packet size is 512 bytes */
	cy_as_dma_set_max_dma_size(dev_p, 0x02, 0x0200);
	/* Packet size is 64 bytes until a switch to high speed happens.*/
	cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);

destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	if (ret != CY_AS_ERROR_SUCCESS)
		cy_as_ll_register_request_callback(dev_p,
			CY_RQT_TUR_RQT_CONTEXT, 0);

	cy_as_device_clear_m_s_s_pending(dev_p);

	return ret;
}


cy_as_return_status_t
cy_as_mtp_start(cy_as_device_handle handle,
			 cy_as_mtp_event_callback event_c_b,
			 cy_as_function_callback cb,
			 uint32_t client
			)
{
	cy_as_ll_request_response *req_p, *reply_p;
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
	cy_as_device *dev_p;

	dev_p = (cy_as_device *)handle;
	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	if (!cy_as_device_is_configured(dev_p))
		return CY_AS_ERROR_NOT_CONFIGURED;

	if (!cy_as_device_is_firmware_loaded(dev_p))
		return CY_AS_ERROR_NO_FIRMWARE;

	if (cy_as_device_is_in_suspend_mode(dev_p))
		return CY_AS_ERROR_IN_SUSPEND;

	if (cy_as_device_is_in_callback(dev_p))
		return CY_AS_ERROR_INVALID_IN_CALLBACK;

	if (cy_as_device_is_m_s_s_pending(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;

	cy_as_device_set_m_s_s_pending(dev_p);

	if (dev_p->mtp_count == 0) {

		dev_p->mtp_event_cb = event_c_b;
		/*
		* we register here becuase the start request may cause
		* events to occur before the response to the start request.
		*/
		cy_as_ll_register_request_callback(dev_p,
			CY_RQT_TUR_RQT_CONTEXT, my_mtp_request_callback);

		/* Create the request to send to the West Bridge device */
		req_p = cy_as_ll_create_request(dev_p,
			CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0);
		if (req_p == 0) {
			cy_as_device_clear_m_s_s_pending(dev_p);
			return CY_AS_ERROR_OUT_OF_MEMORY;
		}

		/* Reserve space for the reply, the reply data will
		 * not exceed one word */
		reply_p = cy_as_ll_create_response(dev_p, 1);
		if (reply_p == 0) {
			cy_as_ll_destroy_request(dev_p, req_p);
			cy_as_device_clear_m_s_s_pending(dev_p);
			return CY_AS_ERROR_OUT_OF_MEMORY;
		}

		if (cb == 0) {
			ret = cy_as_ll_send_request_wait_reply(dev_p,
				req_p, reply_p);
			if (ret != CY_AS_ERROR_SUCCESS)
				goto destroy;

			return my_handle_response_mtp_start(dev_p, req_p,
				reply_p, ret);
		} else {
			ret = cy_as_misc_send_request(dev_p, cb, client,
				CY_FUNCT_CB_MTP_START, 0, dev_p->func_cbs_mtp,
				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
				cy_as_mtp_func_callback);

			if (ret != CY_AS_ERROR_SUCCESS)
				goto destroy;

			return ret;
		}

destroy:
		cy_as_ll_destroy_request(dev_p, req_p);
		cy_as_ll_destroy_response(dev_p, reply_p);
	} else {
		dev_p->mtp_count++;
		if (cb)
			cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0);
	}

	cy_as_device_clear_m_s_s_pending(dev_p);

	return ret;
}

static cy_as_return_status_t
my_handle_response_mtp_stop(cy_as_device *dev_p,
			cy_as_ll_request_response *req_p,
			cy_as_ll_request_response *reply_p,
			cy_as_return_status_t ret)
{
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;

	if (cy_as_ll_request_response__get_code(reply_p) !=
		CY_RESP_SUCCESS_FAILURE) {
		ret = CY_AS_ERROR_INVALID_RESPONSE;
		goto destroy;
	}

	ret = cy_as_ll_request_response__get_word(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:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	if (ret != CY_AS_ERROR_SUCCESS)
		cy_as_ll_register_request_callback(dev_p,
			CY_RQT_TUR_RQT_CONTEXT, 0);

	cy_as_device_clear_m_s_s_pending(dev_p);

	return ret;
}

cy_as_return_status_t
cy_as_mtp_stop(cy_as_device_handle handle,
			cy_as_function_callback cb,
			uint32_t client
			)
{
	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;

	cy_as_device *dev_p;

	cy_as_log_debug_message(6, "cy_as_mtp_stop called");

	dev_p = (cy_as_device *)handle;
	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	ret = is_mtp_active(dev_p);
	if (ret != CY_AS_ERROR_SUCCESS)
		return ret;

	if (cy_as_device_is_in_callback(dev_p))
		return CY_AS_ERROR_INVALID_IN_CALLBACK;

	if (cy_as_device_is_m_s_s_pending(dev_p))
		return CY_AS_ERROR_STARTSTOP_PENDING;

	cy_as_device_set_m_s_s_pending(dev_p);

	if (dev_p->mtp_count == 1) {
		/* Create the request to send to the West
		 * Bridge device */
		req_p = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
		if (reply_p == 0) {
			ret = CY_AS_ERROR_OUT_OF_MEMORY;
			goto destroy;
		}

		if (cb == 0) {
			ret = cy_as_ll_send_request_wait_reply(dev_p,
				req_p, reply_p);
			if (ret != CY_AS_ERROR_SUCCESS)
				goto destroy;

			return my_handle_response_mtp_stop(dev_p, req_p,
					reply_p, ret);
		} else {
			ret = cy_as_misc_send_request(dev_p, cb, client,
				CY_FUNCT_CB_MTP_STOP, 0, dev_p->func_cbs_mtp,
				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
				cy_as_mtp_func_callback);

			if (ret != CY_AS_ERROR_SUCCESS)
				goto destroy;

			return ret;
		}

destroy:
		cy_as_ll_destroy_request(dev_p, req_p);
		cy_as_ll_destroy_response(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);
	}

	cy_as_device_clear_m_s_s_pending(dev_p);

	return ret;
}

static void
mtp_write_callback(
		cy_as_device *dev_p,
		uint8_t context,
		cy_as_ll_request_response *rqt,
		cy_as_ll_request_response *resp,
		cy_as_return_status_t ret)
{
	cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);

	if (ret == CY_AS_ERROR_SUCCESS) {
		if (cy_as_ll_request_response__get_code(resp) !=
			CY_RESP_SUCCESS_FAILURE)
			ret = CY_AS_ERROR_INVALID_RESPONSE;
		else
			ret = cy_as_ll_request_response__get_word(resp, 0);
	}

	if (ret != CY_AS_ERROR_SUCCESS) {
		/* Firmware failed the request. Cancel the DMA transfer. */
		cy_as_dma_cancel(dev_p, 0x04, CY_AS_ERROR_CANCELED);
		cy_as_device_clear_storage_async_pending(dev_p);
	}

	cy_as_ll_destroy_response(dev_p, resp);
	cy_as_ll_destroy_request(dev_p, rqt);
}

static void
async_write_request_callback(cy_as_device *dev_p,
	cy_as_end_point_number_t ep, void *buf_p, uint32_t size,
	cy_as_return_status_t err)
{
	cy_as_device_handle h;
	cy_as_function_callback cb;

	(void)size;
	(void)buf_p;
	(void)ep;


	cy_as_log_debug_message(6, "async_write_request_callback called");

	h = (cy_as_device_handle)dev_p;

	cb = dev_p->mtp_cb;
	dev_p->mtp_cb = 0;

	cy_as_device_clear_storage_async_pending(dev_p);

	if (cb)
		cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0);

}

static void
sync_mtp_callback(cy_as_device *dev_p, cy_as_end_point_number_t ep,
	void *buf_p, uint32_t size, cy_as_return_status_t err)
{
	(void)ep;
	(void)buf_p;
	(void)size;

	dev_p->mtp_error = err;
}

static cy_as_return_status_t
cy_as_mtp_operation(cy_as_device *dev_p,
				 cy_as_mtp_block_table *blk_table,
				 uint32_t num_bytes,
				 uint32_t transaction_id,
				 cy_as_function_callback cb,
				 uint32_t client,
				 uint8_t rqttype
				)
{
	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
	uint32_t mask = 0;
	cy_as_funct_c_b_type mtp_cb_op = 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 = cy_true;
	} else if (rqttype == CY_RQT_INIT_GET_OBJECT) {
		mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT;
		dev_p->mtp_turbo_active = cy_true;
	} else
		mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE;

	ret = is_mtp_active(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 = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
	if (reply_p == 0) {
		ret = CY_AS_ERROR_OUT_OF_MEMORY;
		goto destroy;
	}

	cy_as_ll_request_response__set_word(req_p, 0,
		(uint16_t)(num_bytes & 0xFFFF));
	cy_as_ll_request_response__set_word(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) {
		cy_as_ll_request_response__set_word(req_p, 2,
			(uint16_t)(transaction_id & 0xFFFF));
		cy_as_ll_request_response__set_word(req_p, 3,
			(uint16_t)((transaction_id >> 16) & 0xFFFF));
	}

	if (cb == 0) {
		/* Queue the DMA request for block table write */
		ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
			sizeof(cy_as_mtp_block_table), cy_false,
			cy_false, sync_mtp_callback);

		ret = cy_as_ll_send_request_wait_reply(dev_p,
			req_p, reply_p);
		if (ret != CY_AS_ERROR_SUCCESS) {
			cy_as_dma_cancel(dev_p, 4, CY_AS_ERROR_CANCELED);
			cy_as_device_clear_storage_async_pending(dev_p);

			goto destroy;
		}

		ret = cy_as_dma_drain_queue(dev_p, 4, cy_true);
		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		ret = dev_p->mtp_error;
		goto destroy;
	} else {
#if 0
		ret = cy_as_misc_send_request(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, cy_as_mtp_func_callback);

		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 = cy_as_hal_disable_interrupts();
		if ((cy_as_device_is_storage_async_pending(dev_p)) ||
			(dev_p->storage_wait)) {
			cy_as_hal_enable_interrupts(mask);
			return CY_AS_ERROR_ASYNC_PENDING;
		}
		cy_as_device_set_storage_async_pending(dev_p);
		cy_as_hal_enable_interrupts(mask);

		dev_p->mtp_cb	 = cb;
		dev_p->mtp_client = client;
		dev_p->mtp_op	 = mtp_cb_op;

		ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
			cy_false, mtp_write_callback);
		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
			sizeof(cy_as_mtp_block_table), cy_false, cy_false,
			async_write_request_callback);
		if (ret != CY_AS_ERROR_SUCCESS)
			return ret;

		/* Kick start the queue if it is not running */
		cy_as_dma_kick_start(dev_p, 4);

		return CY_AS_ERROR_SUCCESS;
	}

destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}

cy_as_return_status_t
cy_as_mtp_init_send_object(cy_as_device_handle handle,
					  cy_as_mtp_block_table *blk_table,
					  uint32_t num_bytes,
					  cy_as_function_callback cb,
					  uint32_t client
					 )
{
	cy_as_device *dev_p;
	dev_p = (cy_as_device *)handle;
	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	return cy_as_mtp_operation(dev_p, blk_table, num_bytes, 0, cb,
		client, CY_RQT_INIT_SEND_OBJECT);

}

cy_as_return_status_t
cy_as_mtp_init_get_object(cy_as_device_handle handle,
					 cy_as_mtp_block_table *blk_table,
					 uint32_t num_bytes,
					 uint32_t transaction_id,
					 cy_as_function_callback cb,
					 uint32_t client
					)
{
	cy_as_device *dev_p;
	dev_p = (cy_as_device *)handle;
	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	return cy_as_mtp_operation(dev_p, blk_table, num_bytes,
		transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT);

}

static cy_as_return_status_t
my_handle_response_cancel_send_object(cy_as_device *dev_p,
			cy_as_ll_request_response *req_p,
			cy_as_ll_request_response *reply_p,
			cy_as_return_status_t ret)
{
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;

	if (cy_as_ll_request_response__get_code(reply_p) !=
		CY_RESP_SUCCESS_FAILURE) {
		ret = CY_AS_ERROR_INVALID_RESPONSE;
		goto destroy;
	}

	ret = cy_as_ll_request_response__get_word(reply_p, 0);
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;


destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}

cy_as_return_status_t
cy_as_mtp_cancel_send_object(cy_as_device_handle handle,
						cy_as_function_callback cb,
						uint32_t client
						)
{
	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
	cy_as_device *dev_p;

	dev_p = (cy_as_device *)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 = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
	if (reply_p == 0) {
		ret = CY_AS_ERROR_OUT_OF_MEMORY;
		goto destroy;
	}

	if (cb == 0) {
		ret = cy_as_ll_send_request_wait_reply(dev_p,
			req_p, reply_p);
		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		return my_handle_response_cancel_send_object(dev_p,
			req_p, reply_p, ret);
	} else {
		ret = cy_as_misc_send_request(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, cy_as_mtp_func_callback);

		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		return ret;
	}

destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}

static cy_as_return_status_t
my_handle_response_cancel_get_object(cy_as_device *dev_p,
			cy_as_ll_request_response *req_p,
			cy_as_ll_request_response *reply_p,
			cy_as_return_status_t ret)
{
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;

	if (cy_as_ll_request_response__get_code(reply_p) !=
		CY_RESP_SUCCESS_FAILURE) {
		ret = CY_AS_ERROR_INVALID_RESPONSE;
		goto destroy;
	}

	ret = cy_as_ll_request_response__get_word(reply_p, 0);
	if (ret != CY_AS_ERROR_SUCCESS)
		goto destroy;


destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}

cy_as_return_status_t
cy_as_mtp_cancel_get_object(cy_as_device_handle handle,
					   cy_as_function_callback cb,
					   uint32_t client
					  )
{
	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
	cy_as_device *dev_p;

	dev_p = (cy_as_device *)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 = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
	if (reply_p == 0) {
		ret = CY_AS_ERROR_OUT_OF_MEMORY;
		goto destroy;
	}

	if (cb == 0) {
		ret = cy_as_ll_send_request_wait_reply(dev_p,
			req_p, reply_p);
		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		return my_handle_response_cancel_get_object(dev_p,
			req_p, reply_p, ret);
	} else {
		ret = cy_as_misc_send_request(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,  cy_as_mtp_func_callback);

		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		return ret;
	}

destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}

cy_as_return_status_t
cy_as_mtp_send_block_table(cy_as_device_handle handle,
			cy_as_mtp_block_table *blk_table,
			cy_as_function_callback cb,
			uint32_t client)
{
	cy_as_device *dev_p;
	dev_p = (cy_as_device *)handle;
	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	return cy_as_mtp_operation(dev_p, blk_table, 0, 0, cb,
		client, CY_RQT_SEND_BLOCK_TABLE);
}

static void
cy_as_mtp_func_callback(cy_as_device *dev_p,
					uint8_t context,
					cy_as_ll_request_response *rqt,
					cy_as_ll_request_response *resp,
					cy_as_return_status_t stat)
{
	cy_as_func_c_b_node* node = (cy_as_func_c_b_node *)
					dev_p->func_cbs_mtp->head_p;
	cy_as_return_status_t  ret = CY_AS_ERROR_SUCCESS;
	uint8_t			 code;
	cy_bool delay_callback = cy_false;

	cy_as_hal_assert(dev_p->func_cbs_mtp->count != 0);
	cy_as_hal_assert(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 = cy_as_ll_request_response__get_code(rqt);
	switch (code) {
	case CY_RQT_START_MTP:
		ret = my_handle_response_mtp_start(dev_p, rqt,
			resp, stat);
		break;
	case CY_RQT_STOP_MTP:
		ret = my_handle_response_mtp_stop(dev_p, rqt,
			resp, stat);
		break;
#if 0
	case CY_RQT_INIT_SEND_OBJECT:
		ret = my_handle_response_init_send_object(dev_p,
			rqt, resp, stat, cy_true);
		delay_callback = cy_true;
		break;
#endif
	case CY_RQT_CANCEL_SEND_OBJECT:
		ret = my_handle_response_cancel_send_object(dev_p,
			rqt, resp, stat);
		break;
#if 0
	case CY_RQT_INIT_GET_OBJECT:
		ret = my_handle_response_init_get_object(dev_p,
			rqt, resp, stat, cy_true);
		delay_callback = cy_true;
		break;
#endif
	case CY_RQT_CANCEL_GET_OBJECT:
		ret = my_handle_response_cancel_get_object(dev_p,
			rqt, resp, stat);
		break;
#if 0
	case CY_RQT_SEND_BLOCK_TABLE:
		ret = my_handle_response_send_block_table(dev_p, rqt,
			resp, stat, cy_true);
		delay_callback = cy_true;
		break;
#endif
	case CY_RQT_ENABLE_USB_PATH:
		ret = my_handle_response_no_data(dev_p, rqt, resp);
		if (ret == CY_AS_ERROR_SUCCESS)
			dev_p->is_storage_only_mode = cy_false;
		break;
	default:
		ret = CY_AS_ERROR_INVALID_RESPONSE;
		cy_as_hal_assert(cy_false);
		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((cy_as_device_handle)dev_p, stat, node->client_data,
			node->data_type, node->data);
		cy_as_remove_c_b_node(dev_p->func_cbs_mtp);
	}
}

cy_as_return_status_t
cy_as_mtp_storage_only_start(cy_as_device_handle handle)
{
	cy_as_device *dev_p = (cy_as_device *)handle;
	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	if (!cy_as_device_is_configured(dev_p))
		return CY_AS_ERROR_NOT_CONFIGURED;

	if (!cy_as_device_is_firmware_loaded(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 = cy_true;
	return CY_AS_ERROR_SUCCESS;
}

cy_as_return_status_t
cy_as_mtp_storage_only_stop(cy_as_device_handle handle,
						cy_as_function_callback cb,
						uint32_t client)
{
	cy_as_device *dev_p = (cy_as_device *)handle;
	cy_as_ll_request_response *req_p, *reply_p;
	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;

	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
		return CY_AS_ERROR_INVALID_HANDLE;

	if (!cy_as_device_is_configured(dev_p))
		return CY_AS_ERROR_NOT_CONFIGURED;

	if (!cy_as_device_is_firmware_loaded(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 == cy_false)
		return CY_AS_ERROR_SUCCESS;

	if (cy_as_device_is_in_callback(dev_p))
		return CY_AS_ERROR_INVALID_IN_CALLBACK;

	req_p = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
	if (reply_p == 0) {
		cy_as_ll_destroy_request(dev_p, req_p);
		return CY_AS_ERROR_OUT_OF_MEMORY;
	}

	if (cb == 0) {
		ret = cy_as_ll_send_request_wait_reply(dev_p,
			req_p, reply_p);
		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		ret = my_handle_response_no_data(dev_p, req_p,
			reply_p);
		if (ret == CY_AS_ERROR_SUCCESS)
			dev_p->is_storage_only_mode = cy_false;
		return ret;
	} else {
		ret = cy_as_misc_send_request(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, cy_as_mtp_func_callback);

		if (ret != CY_AS_ERROR_SUCCESS)
			goto destroy;

		return ret;
	}

destroy:
	cy_as_ll_destroy_request(dev_p, req_p);
	cy_as_ll_destroy_response(dev_p, reply_p);

	return ret;
}
