summaryrefslogtreecommitdiff
path: root/drivers/staging/westbridge/astoria/api/src/cyasusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/westbridge/astoria/api/src/cyasusb.c')
-rw-r--r--drivers/staging/westbridge/astoria/api/src/cyasusb.c3740
1 files changed, 0 insertions, 3740 deletions
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasusb.c b/drivers/staging/westbridge/astoria/api/src/cyasusb.c
deleted file mode 100644
index 1b55e611191e..000000000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasusb.c
+++ /dev/null
@@ -1,3740 +0,0 @@
-/* Cypress West Bridge API source file (cyasusb.c)
-## ===========================
-## 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/cyasusb.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyaslep2pep.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-#include "../../include/linux/westbridge/cyasstorage.h"
-
-static cy_as_return_status_t
-cy_as_usb_ack_setup_packet(
- /* Handle to the West Bridge device */
- cy_as_device_handle handle,
- /* The callback if async call */
- cy_as_function_callback cb,
- /* Client supplied data */
- uint32_t client
- );
-
-static void
-cy_as_usb_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 ret);
-/*
-* Reset the USB EP0 state
-*/
-static void
-cy_as_usb_reset_e_p0_state(cy_as_device *dev_p)
-{
- cy_as_log_debug_message(6, "cy_as_usb_reset_e_p0_state called");
-
- cy_as_device_clear_ack_delayed(dev_p);
- cy_as_device_clear_setup_packet(dev_p);
- if (cy_as_device_is_usb_async_pending(dev_p, 0))
- cy_as_usb_cancel_async((cy_as_device_handle)dev_p, 0);
-
- dev_p->usb_pending_buffer = 0;
-}
-
-/*
-* External function to map logical endpoints to physical endpoints
-*/
-static cy_as_return_status_t
-is_usb_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->usb_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
-usb_ack_callback(cy_as_device_handle h,
- cy_as_return_status_t status,
- uint32_t client,
- cy_as_funct_c_b_type type,
- void *data)
-{
- cy_as_device *dev_p = (cy_as_device *)h;
-
- (void)client;
- (void)status;
- (void)data;
-
- cy_as_hal_assert(type == CY_FUNCT_CB_NODATA);
-
- if (dev_p->usb_pending_buffer) {
- cy_as_usb_io_callback cb;
-
- cb = dev_p->usb_cb[0];
- dev_p->usb_cb[0] = 0;
- cy_as_device_clear_usb_async_pending(dev_p, 0);
- if (cb)
- cb(h, 0, dev_p->usb_pending_size,
- dev_p->usb_pending_buffer, dev_p->usb_error);
-
- dev_p->usb_pending_buffer = 0;
- }
-
- cy_as_device_clear_setup_packet(dev_p);
-}
-
-static void
-my_usb_request_callback_usb_event(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p)
-{
- uint16_t ev;
- uint16_t val;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
- ev = cy_as_ll_request_response__get_word(req_p, 0);
- switch (ev) {
- case 0: /* Reserved */
- cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
- CY_AS_ERROR_INVALID_REQUEST, 0);
- break;
-
- case 1: /* Reserved */
- cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
- CY_AS_ERROR_INVALID_REQUEST, 0);
- break;
-
- case 2: /* USB Suspend */
- dev_p->usb_last_event = cy_as_event_usb_suspend;
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h, cy_as_event_usb_suspend, 0);
- else if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h, cy_as_event_usb_suspend, 0);
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- break;
-
- case 3: /* USB Resume */
- dev_p->usb_last_event = cy_as_event_usb_resume;
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h, cy_as_event_usb_resume, 0);
- else if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h, cy_as_event_usb_resume, 0);
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- break;
-
- case 4: /* USB Reset */
- /*
- * if we get a USB reset, the USB host did not understand
- * our response or we timed out for some reason. reset
- * our internal state to be ready for another set of
- * enumeration based requests.
- */
- if (cy_as_device_is_ack_delayed(dev_p))
- cy_as_usb_reset_e_p0_state(dev_p);
-
- dev_p->usb_last_event = cy_as_event_usb_reset;
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h, cy_as_event_usb_reset, 0);
- else if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h, cy_as_event_usb_reset, 0);
-
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- cy_as_device_clear_usb_high_speed(dev_p);
- cy_as_usb_set_dma_sizes(dev_p);
- dev_p->usb_max_tx_size = 0x40;
- cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
- break;
-
- case 5: /* USB Set Configuration */
- /* The configuration to set */
- val = cy_as_ll_request_response__get_word(req_p, 1);
- dev_p->usb_last_event = cy_as_event_usb_set_config;
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_set_config, &val);
- else if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h,
- cy_as_event_usb_set_config, &val);
-
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- break;
-
- case 6: /* USB Speed change */
- /* Connect speed */
- val = cy_as_ll_request_response__get_word(req_p, 1);
- dev_p->usb_last_event = cy_as_event_usb_speed_change;
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_speed_change, &val);
- else if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h,
- cy_as_event_usb_speed_change, &val);
-
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- cy_as_device_set_usb_high_speed(dev_p);
- cy_as_usb_set_dma_sizes(dev_p);
- dev_p->usb_max_tx_size = 0x200;
- cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x200);
- break;
-
- case 7: /* USB Clear Feature */
- /* EP Number */
- val = cy_as_ll_request_response__get_word(req_p, 1);
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_clear_feature, &val);
- if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h,
- cy_as_event_usb_clear_feature, &val);
-
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- break;
-
- default:
- cy_as_hal_print_message("invalid event type\n");
- cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
- CY_RESP_USB_INVALID_EVENT, sizeof(ev), &ev);
- break;
- }
-}
-
-static void
-my_usb_request_callback_usb_data(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p)
-{
- cy_as_end_point_number_t ep;
- uint8_t type;
- uint16_t len;
- uint16_t val;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
- val = cy_as_ll_request_response__get_word(req_p, 0);
- ep = (cy_as_end_point_number_t)((val >> 13) & 0x01);
- len = (val & 0x1ff);
-
- cy_as_hal_assert(len <= 64);
- cy_as_ll_request_response__unpack(req_p,
- 1, len, dev_p->usb_ep_data);
-
- type = (uint8_t)((val >> 14) & 0x03);
- if (type == 0) {
- if (cy_as_device_is_ack_delayed(dev_p)) {
- /*
- * A setup packet has arrived while we are
- * processing a previous setup packet. reset
- * our state with respect to EP0 to be ready
- * to process the new packet.
- */
- cy_as_usb_reset_e_p0_state(dev_p);
- }
-
- if (len != 8)
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT,
- CY_AS_ERROR_INVALID_REQUEST, 0);
- else {
- cy_as_device_clear_ep0_stalled(dev_p);
- cy_as_device_set_setup_packet(dev_p);
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT,
- CY_AS_ERROR_SUCCESS, 0);
-
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_setup_packet,
- dev_p->usb_ep_data);
- else
- dev_p->usb_event_cb(h,
- cy_as_event_usb_setup_packet,
- dev_p->usb_ep_data);
-
- if ((!cy_as_device_is_ack_delayed(dev_p)) &&
- (!cy_as_device_is_ep0_stalled(dev_p)))
- cy_as_usb_ack_setup_packet(h,
- usb_ack_callback, 0);
- }
- } else if (type == 2) {
- if (len != 0)
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT,
- CY_AS_ERROR_INVALID_REQUEST, 0);
- else {
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_status_packet, 0);
- else
- dev_p->usb_event_cb(h,
- cy_as_event_usb_status_packet, 0);
-
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT,
- CY_AS_ERROR_SUCCESS, 0);
- }
- } else if (type == 1) {
- /*
- * we need to hand the data associated with these
- * endpoints to the DMA module.
- */
- cy_as_dma_received_data(dev_p, ep, len, dev_p->usb_ep_data);
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
- }
-}
-
-static void
-my_usb_request_callback_inquiry(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p)
-{
- cy_as_usb_inquiry_data_dep cbdata;
- cy_as_usb_inquiry_data cbdata_ms;
- void *data;
- uint16_t val;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
- uint8_t def_inq_data[64];
- uint8_t evpd;
- uint8_t codepage;
- cy_bool updated;
- uint16_t length;
-
- cy_as_bus_number_t bus;
- uint32_t device;
- cy_as_media_type media;
-
- val = cy_as_ll_request_response__get_word(req_p, 0);
- bus = cy_as_storage_get_bus_from_address(val);
- device = cy_as_storage_get_device_from_address(val);
- media = cy_as_storage_get_media_from_address(val);
-
- val = cy_as_ll_request_response__get_word(req_p, 1);
- evpd = (uint8_t)((val >> 8) & 0x01);
- codepage = (uint8_t)(val & 0xff);
-
- length = cy_as_ll_request_response__get_word(req_p, 2);
- data = (void *)def_inq_data;
-
- updated = cy_false;
-
- if (dev_p->usb_event_cb_ms) {
- cbdata_ms.bus = bus;
- cbdata_ms.device = device;
- cbdata_ms.updated = updated;
- cbdata_ms.evpd = evpd;
- cbdata_ms.codepage = codepage;
- cbdata_ms.length = length;
- cbdata_ms.data = data;
-
- cy_as_hal_assert(cbdata_ms.length <= sizeof(def_inq_data));
- cy_as_ll_request_response__unpack(req_p,
- 3, cbdata_ms.length, cbdata_ms.data);
-
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_inquiry_before, &cbdata_ms);
-
- updated = cbdata_ms.updated;
- data = cbdata_ms.data;
- length = cbdata_ms.length;
- } else if (dev_p->usb_event_cb) {
- cbdata.media = media;
- cbdata.updated = updated;
- cbdata.evpd = evpd;
- cbdata.codepage = codepage;
- cbdata.length = length;
- cbdata.data = data;
-
- cy_as_hal_assert(cbdata.length <=
- sizeof(def_inq_data));
- cy_as_ll_request_response__unpack(req_p, 3,
- cbdata.length, cbdata.data);
-
- dev_p->usb_event_cb(h,
- cy_as_event_usb_inquiry_before, &cbdata);
-
- updated = cbdata.updated;
- data = cbdata.data;
- length = cbdata.length;
- }
-
- if (updated && length > 192)
- cy_as_hal_print_message("an inquiry result from a "
- "cy_as_event_usb_inquiry_before event "
- "was greater than 192 bytes.");
-
- /* Now send the reply with the data back
- * to the West Bridge device */
- if (updated && length <= 192) {
- /*
- * the callback function modified the inquiry
- * data, ship the data back to the west bridge firmware.
- */
- cy_as_ll_send_data_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT,
- CY_RESP_INQUIRY_DATA, length, data);
- } else {
- /*
- * the callback did not modify the data, just acknowledge
- * that we processed the request
- */
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1);
- }
-
- if (dev_p->usb_event_cb_ms)
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_inquiry_after, &cbdata_ms);
- else if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h,
- cy_as_event_usb_inquiry_after, &cbdata);
-}
-
-static void
-my_usb_request_callback_start_stop(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p)
-{
- cy_as_bus_number_t bus;
- cy_as_media_type media;
- uint32_t device;
- uint16_t val;
-
- if (dev_p->usb_event_cb_ms || dev_p->usb_event_cb) {
- cy_bool loej;
- cy_bool start;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
- val = cy_as_ll_request_response__get_word(req_p, 0);
- bus = cy_as_storage_get_bus_from_address(val);
- device = cy_as_storage_get_device_from_address(val);
- media = cy_as_storage_get_media_from_address(val);
-
- val = cy_as_ll_request_response__get_word(req_p, 1);
- loej = (val & 0x02) ? cy_true : cy_false;
- start = (val & 0x01) ? cy_true : cy_false;
-
- if (dev_p->usb_event_cb_ms) {
- cy_as_usb_start_stop_data cbdata_ms;
-
- cbdata_ms.bus = bus;
- cbdata_ms.device = device;
- cbdata_ms.loej = loej;
- cbdata_ms.start = start;
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_start_stop, &cbdata_ms);
-
- } else if (dev_p->usb_event_cb) {
- cy_as_usb_start_stop_data_dep cbdata;
-
- cbdata.media = media;
- cbdata.loej = loej;
- cbdata.start = start;
- dev_p->usb_event_cb(h,
- cy_as_event_usb_start_stop, &cbdata);
- }
- }
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1);
-}
-
-static void
-my_usb_request_callback_uknown_c_b_w(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p)
-{
- uint16_t val;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
- uint8_t buf[16];
-
- uint8_t response[4];
- uint16_t reqlen;
- void *request;
- uint8_t status;
- uint8_t key;
- uint8_t asc;
- uint8_t ascq;
-
- val = cy_as_ll_request_response__get_word(req_p, 0);
- /* Failed by default */
- status = 1;
- /* Invalid command */
- key = 0x05;
- /* Invalid command */
- asc = 0x20;
- /* Invalid command */
- ascq = 0x00;
- reqlen = cy_as_ll_request_response__get_word(req_p, 1);
- request = buf;
-
- cy_as_hal_assert(reqlen <= sizeof(buf));
- cy_as_ll_request_response__unpack(req_p, 2, reqlen, request);
-
- if (dev_p->usb_event_cb_ms) {
- cy_as_usb_unknown_command_data cbdata_ms;
- cbdata_ms.bus = cy_as_storage_get_bus_from_address(val);
- cbdata_ms.device =
- cy_as_storage_get_device_from_address(val);
- cbdata_ms.reqlen = reqlen;
- cbdata_ms.request = request;
- cbdata_ms.status = status;
- cbdata_ms.key = key;
- cbdata_ms.asc = asc;
- cbdata_ms.ascq = ascq;
-
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_unknown_storage, &cbdata_ms);
- status = cbdata_ms.status;
- key = cbdata_ms.key;
- asc = cbdata_ms.asc;
- ascq = cbdata_ms.ascq;
- } else if (dev_p->usb_event_cb) {
- cy_as_usb_unknown_command_data_dep cbdata;
- cbdata.media =
- cy_as_storage_get_media_from_address(val);
- cbdata.reqlen = reqlen;
- cbdata.request = request;
- cbdata.status = status;
- cbdata.key = key;
- cbdata.asc = asc;
- cbdata.ascq = ascq;
-
- dev_p->usb_event_cb(h,
- cy_as_event_usb_unknown_storage, &cbdata);
- status = cbdata.status;
- key = cbdata.key;
- asc = cbdata.asc;
- ascq = cbdata.ascq;
- }
-
- response[0] = status;
- response[1] = key;
- response[2] = asc;
- response[3] = ascq;
- cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
- CY_RESP_UNKNOWN_SCSI_COMMAND, sizeof(response), response);
-}
-
-static void
-my_usb_request_callback_m_s_c_progress(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p)
-{
- uint16_t val1, val2;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
- if ((dev_p->usb_event_cb) || (dev_p->usb_event_cb_ms)) {
- cy_as_m_s_c_progress_data cbdata;
-
- val1 = cy_as_ll_request_response__get_word(req_p, 0);
- val2 = cy_as_ll_request_response__get_word(req_p, 1);
- cbdata.wr_count = (uint32_t)((val1 << 16) | val2);
-
- val1 = cy_as_ll_request_response__get_word(req_p, 2);
- val2 = cy_as_ll_request_response__get_word(req_p, 3);
- cbdata.rd_count = (uint32_t)((val1 << 16) | val2);
-
- if (dev_p->usb_event_cb)
- dev_p->usb_event_cb(h,
- cy_as_event_usb_m_s_c_progress, &cbdata);
- else
- dev_p->usb_event_cb_ms(h,
- cy_as_event_usb_m_s_c_progress, &cbdata);
- }
-
- cy_as_ll_send_status_response(dev_p,
- CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-}
-
-/*
-* This function processes the requests delivered from the
-* firmware within the West Bridge device that are delivered
-* in the USB context. These requests generally are EP0 and
-* EP1 related requests or USB events.
-*/
-static void
-my_usb_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;
- uint8_t code = cy_as_ll_request_response__get_code(req_p);
-
- (void)resp_p;
- (void)context;
- (void)ret;
-
- switch (code) {
- case CY_RQT_USB_EVENT:
- my_usb_request_callback_usb_event(dev_p, req_p);
- break;
-
- case CY_RQT_USB_EP_DATA:
- dev_p->usb_last_event = cy_as_event_usb_setup_packet;
- my_usb_request_callback_usb_data(dev_p, req_p);
- break;
-
- case CY_RQT_SCSI_INQUIRY_COMMAND:
- dev_p->usb_last_event = cy_as_event_usb_inquiry_after;
- my_usb_request_callback_inquiry(dev_p, req_p);
- break;
-
- case CY_RQT_SCSI_START_STOP_COMMAND:
- dev_p->usb_last_event = cy_as_event_usb_start_stop;
- my_usb_request_callback_start_stop(dev_p, req_p);
- break;
-
- case CY_RQT_SCSI_UNKNOWN_COMMAND:
- dev_p->usb_last_event = cy_as_event_usb_unknown_storage;
- my_usb_request_callback_uknown_c_b_w(dev_p, req_p);
- break;
-
- case CY_RQT_USB_ACTIVITY_UPDATE:
- dev_p->usb_last_event = cy_as_event_usb_m_s_c_progress;
- my_usb_request_callback_m_s_c_progress(dev_p, req_p);
- break;
-
- default:
- cy_as_hal_print_message("invalid request "
- "received on USB context\n");
- val = req_p->box0;
- cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
- CY_RESP_INVALID_REQUEST, sizeof(val), &val);
- break;
- }
-}
-
-static cy_as_return_status_t
-my_handle_response_usb_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;
-
- /*
- * mark EP 0 and EP1 as 64 byte endpoints
- */
- cy_as_dma_set_max_dma_size(dev_p, 0, 64);
- cy_as_dma_set_max_dma_size(dev_p, 1, 64);
-
- dev_p->usb_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_destroy_c_b_queue(dev_p->usb_func_cbs);
- cy_as_ll_register_request_callback(dev_p,
- CY_RQT_USB_RQT_CONTEXT, 0);
- }
-
- cy_as_device_clear_u_s_s_pending(dev_p);
-
- return ret;
-
-}
-
-/*
-* This function starts the USB stack. The stack is reference
-* counted so if the stack is already started, this function
-* just increments the count. If the stack has not been started,
-* a start request is sent to the West Bridge device.
-*
-* Note: Starting the USB stack does not cause the USB signals
-* to be connected to the USB pins. To do this and therefore
-* initiate enumeration, CyAsUsbConnect() must be called.
-*/
-cy_as_return_status_t
-cy_as_usb_start(cy_as_device_handle handle,
- 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;
-
- cy_as_log_debug_message(6, "cy_as_usb_start called");
-
- 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_u_s_s_pending(dev_p))
- return CY_AS_ERROR_STARTSTOP_PENDING;
-
- cy_as_device_set_u_s_s_pending(dev_p);
-
- if (dev_p->usb_count == 0) {
- /*
- * since we are just starting the stack,
- * mark USB as not connected to the remote host
- */
- cy_as_device_clear_usb_connected(dev_p);
- dev_p->usb_phy_config = 0;
-
- /* Queue for 1.0 Async Requests, kept for
- * backwards compatibility */
- dev_p->usb_func_cbs = cy_as_create_c_b_queue(CYAS_USB_FUNC_CB);
- if (dev_p->usb_func_cbs == 0) {
- cy_as_device_clear_u_s_s_pending(dev_p);
- return CY_AS_ERROR_OUT_OF_MEMORY;
- }
-
- /* Reset the EP0 state */
- cy_as_usb_reset_e_p0_state(dev_p);
-
- /*
- * we register here because 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_USB_RQT_CONTEXT, my_usb_request_callback);
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_START_USB, CY_RQT_USB_RQT_CONTEXT, 0);
- if (req_p == 0) {
- cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
- dev_p->usb_func_cbs = 0;
- cy_as_device_clear_u_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_destroy_c_b_queue(dev_p->usb_func_cbs);
- dev_p->usb_func_cbs = 0;
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_device_clear_u_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_usb_start(dev_p,
- req_p, reply_p, ret);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb,
- client, CY_FUNCT_CB_USB_START, 0,
- dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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->usb_count++;
- if (cb)
- cb(handle, ret, client, CY_FUNCT_CB_USB_START, 0);
- }
-
- cy_as_device_clear_u_s_s_pending(dev_p);
-
- return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_start);
-
-void
-cy_as_usb_reset(cy_as_device *dev_p)
-{
- int i;
-
- cy_as_device_clear_usb_connected(dev_p);
-
- for (i = 0; i < sizeof(dev_p->usb_config) /
- sizeof(dev_p->usb_config[0]); i++) {
- /*
- * cancel all pending USB read/write operations, as it is
- * possible that the USB stack comes up in a different
- * configuration with a different set of endpoints.
- */
- if (cy_as_device_is_usb_async_pending(dev_p, i))
- cy_as_usb_cancel_async(dev_p,
- (cy_as_end_point_number_t)i);
-
- dev_p->usb_cb[i] = 0;
- dev_p->usb_config[i].enabled = cy_false;
- }
-
- dev_p->usb_phy_config = 0;
-}
-
-/*
- * This function does all the API side clean-up associated
- * with CyAsUsbStop, without any communication with firmware.
- * This needs to be done when the device is being reset while
- * the USB stack is active.
- */
-void
-cy_as_usb_cleanup(cy_as_device *dev_p)
-{
- if (dev_p->usb_count) {
- cy_as_usb_reset_e_p0_state(dev_p);
- cy_as_usb_reset(dev_p);
- cy_as_hal_mem_set(dev_p->usb_config, 0,
- sizeof(dev_p->usb_config));
- cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
-
- dev_p->usb_count = 0;
- }
-}
-
-static cy_as_return_status_t
-my_handle_response_usb_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 successfully shutdown the stack, so
- * decrement to make the count zero.
- */
- cy_as_usb_cleanup(dev_p);
-
-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_USB_RQT_CONTEXT, 0);
-
- cy_as_device_clear_u_s_s_pending(dev_p);
-
- return ret;
-}
-
-/*
-* This function stops the USB stack. The USB stack is reference
-* counted so first is reference count is decremented. If the
-* reference count is then zero, a request is sent to the West
-* Bridge device to stop the USB stack on the West Bridge device.
-*/
-cy_as_return_status_t
-cy_as_usb_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_usb_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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_usb_connected(dev_p))
- return CY_AS_ERROR_USB_CONNECTED;
-
- if (cy_as_device_is_in_callback(dev_p))
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- if (cy_as_device_is_u_s_s_pending(dev_p))
- return CY_AS_ERROR_STARTSTOP_PENDING;
-
- cy_as_device_set_u_s_s_pending(dev_p);
-
- if (dev_p->usb_count == 1) {
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_USB,
- CY_RQT_USB_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_usb_stop(dev_p,
- req_p, reply_p, ret);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_STOP, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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->usb_count > 1) {
- /*
- * reset all LE_ps to inactive state, after cleaning
- * up any pending async read/write calls.
- */
- cy_as_usb_reset(dev_p);
- dev_p->usb_count--;
-
- if (cb)
- cb(handle, ret, client, CY_FUNCT_CB_USB_STOP, 0);
- }
-
- cy_as_device_clear_u_s_s_pending(dev_p);
-
- return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_stop);
-
-/*
-* This function registers a callback to be called when
-* USB events are processed
-*/
-cy_as_return_status_t
-cy_as_usb_register_callback(cy_as_device_handle handle,
- cy_as_usb_event_callback callback)
-{
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_register_callback called");
-
- 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;
-
- dev_p->usb_event_cb = NULL;
- dev_p->usb_event_cb_ms = callback;
- return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_register_callback);
-
-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;
- else
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
- 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_connect(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)
- cy_as_device_set_usb_connected(dev_p);
-
-destroy:
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
-
- return ret;
-}
-
-
-/*
-* This method asks the West Bridge device to connect the
-* internal USB D+ and D- signals to the USB pins, thus
-* starting the enumeration processes if the external pins
-* are connected to a USB host. If the external pins are
-* not connected to a USB host, enumeration will begin as soon
-* as the USB pins are connected to a host.
-*/
-cy_as_return_status_t
-cy_as_usb_connect(cy_as_device_handle handle,
- 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;
-
- cy_as_log_debug_message(6, "cy_as_usb_connect 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_usb_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;
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* 1 = Connect request */
- cy_as_ll_request_response__set_word(req_p, 0, 1);
-
- /* 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);
- 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_connect(dev_p, req_p, reply_p, ret);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_CONNECT, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_connect);
-
-static cy_as_return_status_t
-my_handle_response_disconnect(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)
- cy_as_device_clear_usb_connected(dev_p);
-
-destroy:
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
-
- return ret;
-}
-/*
-* This method forces a disconnect of the D+ and D- pins
-* external to the West Bridge device from the D+ and D-
-* signals internally, effectively disconnecting the West
-* Bridge device from any connected USB host.
-*/
-cy_as_return_status_t
-cy_as_usb_disconnect(cy_as_device_handle handle,
- 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;
-
- cy_as_log_debug_message(6, "cy_as_usb_disconnect 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_usb_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_usb_connected(dev_p))
- return CY_AS_ERROR_USB_NOT_CONNECTED;
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- cy_as_ll_request_response__set_word(req_p, 0, 0);
-
- /* Reserve space for the reply, the reply
- * data will not exceed two bytes */
- 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;
-
- return my_handle_response_disconnect(dev_p,
- req_p, reply_p, ret);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_DISCONNECT, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_disconnect);
-
-static cy_as_return_status_t
-my_handle_response_set_enum_config(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);
-
- if (ret == CY_AS_ERROR_SUCCESS) {
- /*
- * we configured the west bridge device and
- * enumeration is going to happen on the P port
- * processor. now we must enable endpoint zero
- */
- cy_as_usb_end_point_config config;
-
- config.dir = cy_as_usb_in_out;
- config.type = cy_as_usb_control;
- config.enabled = cy_true;
-
- ret = cy_as_usb_set_end_point_config((cy_as_device_handle *)
- dev_p, 0, &config);
- }
-
-destroy:
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
-
- return ret;
-}
-
-/*
-* This method sets how the USB is enumerated and should
-* be called before the CyAsUsbConnect() is called.
-*/
-static cy_as_return_status_t
-my_usb_set_enum_config(cy_as_device *dev_p,
- uint8_t bus_mask,
- uint8_t media_mask,
- cy_bool use_antioch_enumeration,
- uint8_t mass_storage_interface,
- uint8_t mtp_interface,
- cy_bool mass_storage_callbacks,
- 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_log_debug_message(6, "cy_as_usb_set_enum_config called");
-
- if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
- return CY_AS_ERROR_INVALID_HANDLE;
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_usb_connected(dev_p))
- return CY_AS_ERROR_USB_CONNECTED;
-
- if (cy_as_device_is_in_callback(dev_p))
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- /* if we are using MTP firmware: */
- if (dev_p->is_mtp_firmware == 1) {
- /* we cannot enumerate MSC */
- if (mass_storage_interface != 0)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- if (bus_mask == 0) {
- if (mtp_interface != 0)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
- } else if (bus_mask == 2) {
- /* enable EP 1 as it will be used */
- cy_as_dma_enable_end_point(dev_p, 1, cy_true,
- cy_as_direction_in);
- dev_p->usb_config[1].enabled = cy_true;
- dev_p->usb_config[1].dir = cy_as_usb_in;
- dev_p->usb_config[1].type = cy_as_usb_int;
- } else {
- return CY_AS_ERROR_INVALID_CONFIGURATION;
- }
- /* if we are not using MTP firmware, we cannot enumerate MTP */
- } else if (mtp_interface != 0)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- /*
- * if we are not enumerating mass storage, we should
- * not be providing an interface number.
- */
- if (bus_mask == 0 && mass_storage_interface != 0)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- /*
- * if we are going to use mtp_interface, bus mask must be 2.
- */
- if (mtp_interface != 0 && bus_mask != 2)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_SET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 4);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* Marshal the structure */
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)((media_mask << 8) | bus_mask));
- cy_as_ll_request_response__set_word(req_p, 1,
- (uint16_t)use_antioch_enumeration);
- cy_as_ll_request_response__set_word(req_p, 2,
- dev_p->is_mtp_firmware ? mtp_interface :
- mass_storage_interface);
- cy_as_ll_request_response__set_word(req_p, 3,
- (uint16_t)mass_storage_callbacks);
-
- /* 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);
- 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_set_enum_config(dev_p,
- req_p, reply_p);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_SETENUMCONFIG, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-
-/*
- * This method sets how the USB is enumerated and should
- * be called before the CyAsUsbConnect() is called.
- */
-cy_as_return_status_t
-cy_as_usb_set_enum_config(cy_as_device_handle handle,
- cy_as_usb_enum_control *config_p,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_device *dev_p = (cy_as_device *)handle;
- uint8_t bus_mask, media_mask;
- uint32_t bus, device;
- cy_as_return_status_t ret;
-
- 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if ((cy_as_device_is_in_callback(dev_p)) && (cb != 0))
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- /* Since we are mapping the media types to bus with NAND to 0
- * and the rest to 1, and we are only allowing for enumerating
- * all the devices on a bus we just scan the array for any
- * positions where there a device is enabled and mark the bus
- * to be enumerated.
- */
- bus_mask = 0;
- media_mask = 0;
- for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
- for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++) {
- if (config_p->devices_to_enumerate[bus][device] ==
- cy_true) {
- bus_mask |= (0x01 << bus);
- media_mask |= dev_p->media_supported[bus];
- media_mask |= dev_p->media_supported[bus];
- }
- }
- }
-
- return my_usb_set_enum_config(dev_p, bus_mask, media_mask,
- config_p->antioch_enumeration,
- config_p->mass_storage_interface,
- config_p->mtp_interface,
- config_p->mass_storage_callbacks,
- cb,
- client
- );
-}
-EXPORT_SYMBOL(cy_as_usb_set_enum_config);
-
-static cy_as_return_status_t
-my_handle_response_get_enum_config(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p,
- cy_as_ll_request_response *reply_p,
- void *config_p)
-{
- cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
- uint16_t val;
- uint8_t bus_mask;
- uint32_t bus;
-
- if (cy_as_ll_request_response__get_code(reply_p) !=
- CY_RESP_USB_CONFIG) {
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- goto destroy;
- }
-
- /* Marshal the reply */
- if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
- uint32_t device;
- cy_bool state;
- cy_as_usb_enum_control *ms_config_p =
- (cy_as_usb_enum_control *)config_p;
-
- bus_mask = (uint8_t)
- (cy_as_ll_request_response__get_word
- (reply_p, 0) & 0xFF);
- for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
- if (bus_mask & (1 << bus))
- state = cy_true;
- else
- state = cy_false;
-
- for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES;
- device++)
- ms_config_p->devices_to_enumerate[bus][device]
- = state;
- }
-
- ms_config_p->antioch_enumeration =
- (cy_bool)cy_as_ll_request_response__get_word
- (reply_p, 1);
-
- val = cy_as_ll_request_response__get_word(reply_p, 2);
- if (dev_p->is_mtp_firmware) {
- ms_config_p->mass_storage_interface = 0;
- ms_config_p->mtp_interface = (uint8_t)(val & 0xFF);
- } else {
- ms_config_p->mass_storage_interface =
- (uint8_t)(val & 0xFF);
- ms_config_p->mtp_interface = 0;
- }
- ms_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
-
- /*
- * firmware returns an invalid interface number for mass storage,
- * if mass storage is not enabled. this needs to be converted to
- * zero to match the input configuration.
- */
- if (bus_mask == 0) {
- if (dev_p->is_mtp_firmware)
- ms_config_p->mtp_interface = 0;
- else
- ms_config_p->mass_storage_interface = 0;
- }
- } else {
- cy_as_usb_enum_control_dep *ex_config_p =
- (cy_as_usb_enum_control_dep *)config_p;
-
- ex_config_p->enum_mass_storage = (uint8_t)
- ((cy_as_ll_request_response__get_word
- (reply_p, 0) >> 8) & 0xFF);
- ex_config_p->antioch_enumeration = (cy_bool)
- cy_as_ll_request_response__get_word(reply_p, 1);
-
- val = cy_as_ll_request_response__get_word(reply_p, 2);
- ex_config_p->mass_storage_interface = (uint8_t)(val & 0xFF);
- ex_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
-
- /*
- * firmware returns an invalid interface number for mass
- * storage, if mass storage is not enabled. this needs to
- * be converted to zero to match the input configuration.
- */
- if (ex_config_p->enum_mass_storage == 0)
- ex_config_p->mass_storage_interface = 0;
- }
-
-destroy:
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
-
- return ret;
-}
-
-/*
-* This sets up the request for the enumerateion configuration
-* information, based on if the request is from the old pre-1.2
-* functions.
-*/
-static cy_as_return_status_t
-my_usb_get_enum_config(cy_as_device_handle handle,
- uint16_t req_flags,
- void *config_p,
- 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;
-
- cy_as_log_debug_message(6, "cy_as_usb_get_enum_config 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_usb_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;
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_GET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 0);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* Reserve space for the reply, the reply data
- * will not exceed two bytes */
- reply_p = cy_as_ll_create_response(dev_p, 3);
- 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;
-
- /* we need to know the type of request to
- * know how to manage the data */
- req_p->flags |= req_flags;
- return my_handle_response_get_enum_config(dev_p,
- req_p, reply_p, config_p);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_GETENUMCONFIG, config_p,
- dev_p->func_cbs_usb, req_flags, req_p, reply_p,
- cy_as_usb_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;
-}
-
-/*
- * This method returns the enumerateion configuration information
- * from the West Bridge device. Generally this is not used by
- * client software but is provided mostly for debug information.
- * We want a method to read all state information from the device.
- */
-cy_as_return_status_t
-cy_as_usb_get_enum_config(cy_as_device_handle handle,
- cy_as_usb_enum_control *config_p,
- cy_as_function_callback cb,
- uint32_t client)
-{
- return my_usb_get_enum_config(handle,
- CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_get_enum_config);
-
-/*
-* This method sets the USB descriptor for a given entity.
-*/
-cy_as_return_status_t
-cy_as_usb_set_descriptor(cy_as_device_handle handle,
- cy_as_usb_desc_type type,
- uint8_t index,
- void *desc_p,
- uint16_t length,
- 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;
- uint16_t pktlen;
-
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_set_descriptor 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_usb_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 (length > CY_AS_MAX_USB_DESCRIPTOR_SIZE)
- return CY_AS_ERROR_INVALID_DESCRIPTOR;
-
- pktlen = (uint16_t)length / 2;
- if (length % 2)
- pktlen++;
- pktlen += 2; /* 1 for type, 1 for length */
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_DESCRIPTOR,
- CY_RQT_USB_RQT_CONTEXT, (uint16_t)pktlen);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)((uint8_t)type | (index << 8)));
- cy_as_ll_request_response__set_word(req_p, 1,
- (uint16_t)length);
- cy_as_ll_request_response__pack(req_p, 2, length, desc_p);
-
- 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;
-
- return my_handle_response_no_data(dev_p, req_p, reply_p);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_SETDESCRIPTOR, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_set_descriptor);
-
-/*
- * This method clears all descriptors that were previously
- * stored on the West Bridge through CyAsUsbSetDescriptor calls.
- */
-cy_as_return_status_t
-cy_as_usb_clear_descriptors(cy_as_device_handle handle,
- 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;
-
- cy_as_log_debug_message(6, "cy_as_usb_clear_descriptors 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if ((cy_as_device_is_in_callback(dev_p)) && (cb == 0))
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_CLEAR_DESCRIPTORS, CY_RQT_USB_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;
-
- return my_handle_response_no_data(dev_p, req_p, reply_p);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_CLEARDESCRIPTORS, 0,
- dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_clear_descriptors);
-
-static cy_as_return_status_t
-my_handle_response_get_descriptor(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p,
- cy_as_ll_request_response *reply_p,
- cy_as_get_descriptor_data *data)
-{
- cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
- uint32_t retlen;
-
- if (cy_as_ll_request_response__get_code(reply_p) ==
- CY_RESP_SUCCESS_FAILURE) {
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
- goto destroy;
- } else if (cy_as_ll_request_response__get_code(reply_p) !=
- CY_RESP_USB_DESCRIPTOR) {
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- goto destroy;
- }
-
- retlen = cy_as_ll_request_response__get_word(reply_p, 0);
- if (retlen > data->length) {
- ret = CY_AS_ERROR_INVALID_SIZE;
- goto destroy;
- }
-
- ret = CY_AS_ERROR_SUCCESS;
- cy_as_ll_request_response__unpack(reply_p, 1,
- retlen, data->desc_p);
-
-destroy:
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
-
- return ret;
-}
-
-/*
-* This method retreives the USB descriptor for a given type.
-*/
-cy_as_return_status_t
-cy_as_usb_get_descriptor(cy_as_device_handle handle,
- cy_as_usb_desc_type type,
- uint8_t index,
- cy_as_get_descriptor_data *data,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
-
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_get_descriptor 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_usb_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;
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_GET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, 1);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)((uint8_t)type | (index << 8)));
-
- /* Add one for the length field */
- reply_p = cy_as_ll_create_response(dev_p,
- CY_AS_MAX_USB_DESCRIPTOR_SIZE + 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;
-
- return my_handle_response_get_descriptor(dev_p,
- req_p, reply_p, data);
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_GETDESCRIPTOR, data,
- dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p,
- reply_p, cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_get_descriptor);
-
-cy_as_return_status_t
-cy_as_usb_set_physical_configuration(cy_as_device_handle handle,
- uint8_t config)
-{
- cy_as_return_status_t ret;
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6,
- "cy_as_usb_set_physical_configuration 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_usb_connected(dev_p))
- return CY_AS_ERROR_USB_CONNECTED;
-
- if (config < 1 || config > 12)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- dev_p->usb_phy_config = config;
-
- return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_set_physical_configuration);
-
-static cy_bool
-is_physical_valid(uint8_t config, cy_as_end_point_number_t ep)
-{
- static uint8_t validmask[12] = {
- 0x0f, /* Config 1 - 1, 2, 3, 4 */
- 0x07, /* Config 2 - 1, 2, 3 */
- 0x07, /* Config 3 - 1, 2, 3 */
- 0x0d, /* Config 4 - 1, 3, 4 */
- 0x05, /* Config 5 - 1, 3 */
- 0x05, /* Config 6 - 1, 3 */
- 0x0d, /* Config 7 - 1, 3, 4 */
- 0x05, /* Config 8 - 1, 3 */
- 0x05, /* Config 9 - 1, 3 */
- 0x0d, /* Config 10 - 1, 3, 4 */
- 0x09, /* Config 11 - 1, 4 */
- 0x01 /* Config 12 - 1 */
- };
-
- return (validmask[config - 1] & (1 << (ep - 1))) ? cy_true : cy_false;
-}
-
-/*
-* This method sets the configuration for an endpoint
-*/
-cy_as_return_status_t
-cy_as_usb_set_end_point_config(cy_as_device_handle handle,
- cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
-{
- cy_as_return_status_t ret;
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_set_end_point_config 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_usb_connected(dev_p))
- return CY_AS_ERROR_USB_CONNECTED;
-
- if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- if (ep == 0) {
- /* Endpoint 0 must be 64 byte, dir IN/OUT,
- * and control type */
- if (config_p->dir != cy_as_usb_in_out ||
- config_p->type != cy_as_usb_control)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
- } else if (ep == 1) {
- if ((dev_p->is_mtp_firmware == 1) &&
- (dev_p->usb_config[1].enabled == cy_true)) {
- return CY_AS_ERROR_INVALID_ENDPOINT;
- }
-
- /*
- * EP1 can only be used either as an OUT ep, or as an IN ep.
- */
- if ((config_p->type == cy_as_usb_control) ||
- (config_p->type == cy_as_usb_iso) ||
- (config_p->dir == cy_as_usb_in_out))
- return CY_AS_ERROR_INVALID_CONFIGURATION;
- } else {
- if (config_p->dir == cy_as_usb_in_out ||
- config_p->type == cy_as_usb_control)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- if (!is_physical_valid(dev_p->usb_phy_config,
- config_p->physical))
- return CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT;
-
- /*
- * ISO endpoints must be on E_ps 3, 5, 7 or 9 as
- * they need to align directly with the underlying
- * physical endpoint.
- */
- if (config_p->type == cy_as_usb_iso) {
- if (ep != 3 && ep != 5 && ep != 7 && ep != 9)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- if (ep == 3 && config_p->physical != 1)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- if (ep == 5 && config_p->physical != 2)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- if (ep == 7 && config_p->physical != 3)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
-
- if (ep == 9 && config_p->physical != 4)
- return CY_AS_ERROR_INVALID_CONFIGURATION;
- }
- }
-
- /* Store the configuration information until a
- * CyAsUsbCommitConfig is done */
- dev_p->usb_config[ep] = *config_p;
-
- /* If the endpoint is enabled, enable DMA associated
- * with the endpoint */
- /*
- * we make some assumptions that we check here. we assume
- * that the direction fields for the DMA module are the same
- * values as the direction values for the USB module.
- */
- cy_as_hal_assert((int)cy_as_usb_in == (int)cy_as_direction_in);
- cy_as_hal_assert((int)cy_as_usb_out == (int)cy_as_direction_out);
- cy_as_hal_assert((int)cy_as_usb_in_out == (int)cy_as_direction_in_out);
-
- return cy_as_dma_enable_end_point(dev_p, ep,
- config_p->enabled, (cy_as_dma_direction)config_p->dir);
-}
-EXPORT_SYMBOL(cy_as_usb_set_end_point_config);
-
-cy_as_return_status_t
-cy_as_usb_get_end_point_config(cy_as_device_handle handle,
- cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
-{
- cy_as_return_status_t ret;
-
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_get_end_point_config 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- *config_p = dev_p->usb_config[ep];
-
- return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_get_end_point_config);
-
-/*
-* Commit the configuration of the various endpoints to the hardware.
-*/
-cy_as_return_status_t
-cy_as_usb_commit_config(cy_as_device_handle handle,
- cy_as_function_callback cb,
- uint32_t client)
-{
- uint32_t i;
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
- cy_as_device *dev_p;
- uint16_t data;
-
- cy_as_log_debug_message(6, "cy_as_usb_commit_config 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_usb_connected(dev_p))
- return CY_AS_ERROR_USB_CONNECTED;
-
- if (cy_as_device_is_in_callback(dev_p))
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- /*
- * this performs the mapping based on informatation that was
- * previously stored on the device about the various endpoints
- * and how they are configured. the output of this mapping is
- * setting the the 14 register values contained in usb_lepcfg
- * and usb_pepcfg
- */
- ret = cy_as_usb_map_logical2_physical(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- /*
- * now, package the information about the various logical and
- * physical endpoint configuration registers and send it
- * across to the west bridge device.
- */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_SET_USB_CONFIG_REGISTERS, CY_RQT_USB_RQT_CONTEXT, 8);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- cy_as_hal_print_message("USB configuration: %d\n",
- dev_p->usb_phy_config);
- cy_as_hal_print_message("EP1OUT: 0x%02x EP1IN: 0x%02x\n",
- dev_p->usb_ep1cfg[0], dev_p->usb_ep1cfg[1]);
- cy_as_hal_print_message("PEP registers: 0x%02x 0x%02x 0x%02x 0x%02x\n",
- dev_p->usb_pepcfg[0], dev_p->usb_pepcfg[1],
- dev_p->usb_pepcfg[2], dev_p->usb_pepcfg[3]);
-
- cy_as_hal_print_message("LEP registers: 0x%02x 0x%02x 0x%02x "
- "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
- dev_p->usb_lepcfg[0], dev_p->usb_lepcfg[1],
- dev_p->usb_lepcfg[2], dev_p->usb_lepcfg[3],
- dev_p->usb_lepcfg[4], dev_p->usb_lepcfg[5],
- dev_p->usb_lepcfg[6], dev_p->usb_lepcfg[7],
- dev_p->usb_lepcfg[8], dev_p->usb_lepcfg[9]);
-
- /* Write the EP1OUTCFG and EP1INCFG data in the first word. */
- data = (uint16_t)((dev_p->usb_ep1cfg[0] << 8) |
- dev_p->usb_ep1cfg[1]);
- cy_as_ll_request_response__set_word(req_p, 0, data);
-
- /* Write the PEP CFG data in the next 2 words */
- for (i = 0; i < 4; i += 2) {
- data = (uint16_t)((dev_p->usb_pepcfg[i] << 8) |
- dev_p->usb_pepcfg[i + 1]);
- cy_as_ll_request_response__set_word(req_p,
- 1 + i / 2, data);
- }
-
- /* Write the LEP CFG data in the next 5 words */
- for (i = 0; i < 10; i += 2) {
- data = (uint16_t)((dev_p->usb_lepcfg[i] << 8) |
- dev_p->usb_lepcfg[i + 1]);
- cy_as_ll_request_response__set_word(req_p,
- 3 + i / 2, data);
- }
-
- /* A single status word response type */
- 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)
- ret = cy_as_usb_setup_dma(dev_p);
-
- return ret;
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_COMMITCONFIG, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_commit_config);
-
-static void
-sync_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)
-{
- (void)ep;
- (void)buf_p;
-
- dev_p->usb_error = err;
- dev_p->usb_actual_cnt = size;
-}
-
-static void
-async_read_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_log_debug_message(6,
- "async_read_request_callback called");
-
- h = (cy_as_device_handle)dev_p;
-
- if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
- dev_p->usb_pending_buffer = buf_p;
- dev_p->usb_pending_size = size;
- dev_p->usb_error = err;
- cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
- } else {
- cy_as_usb_io_callback cb;
-
- cb = dev_p->usb_cb[ep];
- dev_p->usb_cb[ep] = 0;
- cy_as_device_clear_usb_async_pending(dev_p, ep);
- if (cb)
- cb(h, ep, size, buf_p, err);
- }
-}
-
-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_log_debug_message(6,
- "async_write_request_callback called");
-
- h = (cy_as_device_handle)dev_p;
-
- if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
- dev_p->usb_pending_buffer = buf_p;
- dev_p->usb_pending_size = size;
- dev_p->usb_error = err;
-
- /* The west bridge protocol generates ZLPs as required. */
- cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
- } else {
- cy_as_usb_io_callback cb;
-
- cb = dev_p->usb_cb[ep];
- dev_p->usb_cb[ep] = 0;
-
- cy_as_device_clear_usb_async_pending(dev_p, ep);
- if (cb)
- cb(h, ep, size, buf_p, err);
- }
-}
-
-static void
-my_turbo_rqt_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)
-{
- uint8_t code;
-
- (void)context;
- (void)stat;
-
- /* 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_TURBO_SWITCH_ENDPOINT:
- cy_as_hal_assert(stat == CY_AS_ERROR_SUCCESS);
- cy_as_ll_destroy_request(dev_p, rqt);
- cy_as_ll_destroy_response(dev_p, resp);
- break;
- default:
- cy_as_hal_assert(cy_false);
- break;
- }
-}
-
-/* Send a mailbox request to prepare the endpoint for switching */
-static cy_as_return_status_t
-my_send_turbo_switch(cy_as_device *dev_p, uint32_t size, cy_bool pktread)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
-
- /* Create the request to send to the West Bridge device */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_TURBO_SWITCH_ENDPOINT, CY_RQT_TUR_RQT_CONTEXT, 3);
- if (req_p == 0)
- 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);
- return CY_AS_ERROR_OUT_OF_MEMORY;
- }
-
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)pktread);
- cy_as_ll_request_response__set_word(req_p, 1,
- (uint16_t)((size >> 16) & 0xFFFF));
- cy_as_ll_request_response__set_word(req_p, 2,
- (uint16_t)(size & 0xFFFF));
-
- ret = cy_as_ll_send_request(dev_p, req_p,
- reply_p, cy_false, my_turbo_rqt_callback);
- if (ret != CY_AS_ERROR_SUCCESS) {
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_request(dev_p, reply_p);
- return ret;
- }
-
- return CY_AS_ERROR_SUCCESS;
-}
-
-cy_as_return_status_t
-cy_as_usb_read_data(cy_as_device_handle handle,
- cy_as_end_point_number_t ep, cy_bool pktread,
- uint32_t dsize, uint32_t *dataread, void *data)
-{
- cy_as_return_status_t ret;
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_read_data 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_usb_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 (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* EP2 is available for reading when MTP is active */
- if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* If the endpoint is disabled, we cannot
- * write data to the endpoint */
- if (!dev_p->usb_config[ep].enabled)
- return CY_AS_ERROR_ENDPOINT_DISABLED;
-
- if (dev_p->usb_config[ep].dir != cy_as_usb_out)
- return CY_AS_ERROR_USB_BAD_DIRECTION;
-
- ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
- pktread, cy_true, sync_request_callback);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (ep == CY_AS_MTP_READ_ENDPOINT) {
- ret = my_send_turbo_switch(dev_p, dsize, pktread);
- if (ret != CY_AS_ERROR_SUCCESS) {
- cy_as_dma_cancel(dev_p, ep, ret);
- return ret;
- }
-
- ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
- } else {
- ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
- }
-
- ret = dev_p->usb_error;
- *dataread = dev_p->usb_actual_cnt;
-
- return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_read_data);
-
-cy_as_return_status_t
-cy_as_usb_read_data_async(cy_as_device_handle handle,
- cy_as_end_point_number_t ep, cy_bool pktread,
- uint32_t dsize, void *data, cy_as_usb_io_callback cb)
-{
- cy_as_return_status_t ret;
- uint32_t mask;
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_read_data_async 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* EP2 is available for reading when MTP is active */
- if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* If the endpoint is disabled, we cannot
- * write data to the endpoint */
- if (!dev_p->usb_config[ep].enabled)
- return CY_AS_ERROR_ENDPOINT_DISABLED;
-
- if (dev_p->usb_config[ep].dir != cy_as_usb_out &&
- dev_p->usb_config[ep].dir != cy_as_usb_in_out)
- return CY_AS_ERROR_USB_BAD_DIRECTION;
-
- /*
- * since async operations can be triggered by interrupt
- * code, we must insure that we do not get multiple async
- * operations going at one time and protect this test and
- * set operation from interrupts.
- */
- mask = cy_as_hal_disable_interrupts();
- if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
- cy_as_hal_enable_interrupts(mask);
- return CY_AS_ERROR_ASYNC_PENDING;
- }
- cy_as_device_set_usb_async_pending(dev_p, ep);
-
- /*
- * if this is for EP0, we set this bit to delay the
- * ACK response until after this read has completed.
- */
- if (ep == 0)
- cy_as_device_set_ack_delayed(dev_p);
-
- cy_as_hal_enable_interrupts(mask);
-
- cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
- dev_p->usb_cb[ep] = cb;
-
- ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
- pktread, cy_true, async_read_request_callback);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (ep == CY_AS_MTP_READ_ENDPOINT) {
- ret = my_send_turbo_switch(dev_p, dsize, pktread);
- if (ret != CY_AS_ERROR_SUCCESS) {
- cy_as_dma_cancel(dev_p, ep, ret);
- return ret;
- }
- } else {
- /* Kick start the queue if it is not running */
- cy_as_dma_kick_start(dev_p, ep);
- }
- return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_read_data_async);
-
-cy_as_return_status_t
-cy_as_usb_write_data(cy_as_device_handle handle,
- cy_as_end_point_number_t ep, uint32_t dsize, void *data)
-{
- cy_as_return_status_t ret;
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_write_data 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_usb_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 (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* EP6 is available for writing when MTP is active */
- if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* If the endpoint is disabled, we cannot
- * write data to the endpoint */
- if (!dev_p->usb_config[ep].enabled)
- return CY_AS_ERROR_ENDPOINT_DISABLED;
-
- if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
- dev_p->usb_config[ep].dir != cy_as_usb_in_out)
- return CY_AS_ERROR_USB_BAD_DIRECTION;
-
- /* Write on Turbo endpoint */
- if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
- cy_as_ll_request_response *req_p, *reply_p;
-
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
- CY_RQT_TUR_RQT_CONTEXT, 3);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- cy_as_ll_request_response__set_word(req_p,
- 0, 0x0006); /* EP number to use. */
- cy_as_ll_request_response__set_word(req_p,
- 1, (uint16_t)((dsize >> 16) & 0xFFFF));
- cy_as_ll_request_response__set_word(req_p,
- 2, (uint16_t)(dsize & 0xFFFF));
-
- /* 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);
- return CY_AS_ERROR_OUT_OF_MEMORY;
- }
-
- if (dsize) {
- ret = cy_as_dma_queue_request(dev_p,
- ep, data, dsize, cy_false,
- cy_false, sync_request_callback);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
- }
-
- ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
- if (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;
- else
- ret = cy_as_ll_request_response__get_word
- (reply_p, 0);
- }
-
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
-
- if (ret != CY_AS_ERROR_SUCCESS) {
- if (dsize)
- cy_as_dma_cancel(dev_p, ep, ret);
- return ret;
- }
-
- /* If this is a zero-byte write, firmware will
- * handle it. there is no need to do any work here.
- */
- if (!dsize)
- return CY_AS_ERROR_SUCCESS;
- } else {
- ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
- cy_false, cy_false, sync_request_callback);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
- }
-
- if (ep != CY_AS_MTP_WRITE_ENDPOINT)
- ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
- else
- ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
-
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- ret = dev_p->usb_error;
- return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_write_data);
-
-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_usb_io_callback cb;
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
- 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 this was a zero byte transfer request, we can
- * call the callback from here. */
- if ((cy_as_ll_request_response__get_word(rqt, 1) == 0) &&
- (cy_as_ll_request_response__get_word(rqt, 2) == 0)) {
- cb = dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT];
- dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] = 0;
- cy_as_device_clear_usb_async_pending(dev_p,
- CY_AS_MTP_WRITE_ENDPOINT);
- if (cb)
- cb(h, CY_AS_MTP_WRITE_ENDPOINT, 0, 0, ret);
-
- goto destroy;
- }
-
- if (ret != CY_AS_ERROR_SUCCESS) {
- /* Firmware failed the request. Cancel the DMA transfer. */
- cy_as_dma_cancel(dev_p, 0x06, CY_AS_ERROR_CANCELED);
- dev_p->usb_cb[0x06] = 0;
- cy_as_device_clear_usb_async_pending(dev_p, 0x06);
- }
-
-destroy:
- cy_as_ll_destroy_response(dev_p, resp);
- cy_as_ll_destroy_request(dev_p, rqt);
-}
-
-cy_as_return_status_t
-cy_as_usb_write_data_async(cy_as_device_handle handle,
- cy_as_end_point_number_t ep, uint32_t dsize, void *data,
- cy_bool spacket, cy_as_usb_io_callback cb)
-{
- uint32_t mask;
- cy_as_return_status_t ret;
- cy_as_device *dev_p;
-
- cy_as_log_debug_message(6, "cy_as_usb_write_data_async 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_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* EP6 is available for writing when MTP is active */
- if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
- return CY_AS_ERROR_INVALID_ENDPOINT;
-
- /* If the endpoint is disabled, we cannot
- * write data to the endpoint */
- if (!dev_p->usb_config[ep].enabled)
- return CY_AS_ERROR_ENDPOINT_DISABLED;
-
- if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
- dev_p->usb_config[ep].dir != cy_as_usb_in_out)
- return CY_AS_ERROR_USB_BAD_DIRECTION;
-
- /*
- * since async operations can be triggered by interrupt
- * code, we must insure that we do not get multiple
- * async operations going at one time and
- * protect this test and set operation from interrupts.
- */
- mask = cy_as_hal_disable_interrupts();
- if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
- cy_as_hal_enable_interrupts(mask);
- return CY_AS_ERROR_ASYNC_PENDING;
- }
-
- cy_as_device_set_usb_async_pending(dev_p, ep);
-
- if (ep == 0)
- cy_as_device_set_ack_delayed(dev_p);
-
- cy_as_hal_enable_interrupts(mask);
-
- cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
- dev_p->usb_cb[ep] = cb;
- dev_p->usb_spacket[ep] = spacket;
-
- /* Write on Turbo endpoint */
- if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
- cy_as_ll_request_response *req_p, *reply_p;
-
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
- CY_RQT_TUR_RQT_CONTEXT, 3);
-
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- cy_as_ll_request_response__set_word(req_p, 0,
- 0x0006); /* EP number to use. */
- cy_as_ll_request_response__set_word(req_p, 1,
- (uint16_t)((dsize >> 16) & 0xFFFF));
- cy_as_ll_request_response__set_word(req_p, 2,
- (uint16_t)(dsize & 0xFFFF));
-
- /* 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);
- return CY_AS_ERROR_OUT_OF_MEMORY;
- }
-
- if (dsize) {
- ret = cy_as_dma_queue_request(dev_p, ep, data,
- dsize, cy_false, cy_false,
- async_write_request_callback);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
- }
-
- ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
- cy_false, mtp_write_callback);
- if (ret != CY_AS_ERROR_SUCCESS) {
- if (dsize)
- cy_as_dma_cancel(dev_p, ep, ret);
- return ret;
- }
-
- /* Firmware will handle a zero byte transfer
- * without any DMA transfers. */
- if (!dsize)
- return CY_AS_ERROR_SUCCESS;
- } else {
- ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
- 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 */
- if (ep != CY_AS_MTP_WRITE_ENDPOINT)
- cy_as_dma_kick_start(dev_p, ep);
-
- return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_write_data_async);
-
-static void
-my_usb_cancel_async_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)
-{
- uint8_t ep;
- (void)context;
-
- ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
- 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);
- }
-
- cy_as_ll_destroy_request(dev_p, rqt);
- cy_as_ll_destroy_response(dev_p, resp);
-
- if (ret == CY_AS_ERROR_SUCCESS) {
- cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
- dev_p->usb_cb[ep] = 0;
- cy_as_device_clear_usb_async_pending(dev_p, ep);
- }
-}
-
-cy_as_return_status_t
-cy_as_usb_cancel_async(cy_as_device_handle handle,
- cy_as_end_point_number_t ep)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p, *reply_p;
-
- 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;
-
- ep &= 0x7F; /* Remove the direction bit. */
- if (!cy_as_device_is_usb_async_pending(dev_p, ep))
- return CY_AS_ERROR_ASYNC_NOT_PENDING;
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_in_suspend_mode(dev_p))
- return CY_AS_ERROR_IN_SUSPEND;
-
- if ((ep == CY_AS_MTP_WRITE_ENDPOINT) ||
- (ep == CY_AS_MTP_READ_ENDPOINT)) {
- /* Need firmware support for the cancel operation. */
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_CANCEL_ASYNC_TRANSFER,
- 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;
- }
-
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)ep);
-
- ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
- cy_false, my_usb_cancel_async_callback);
-
- if (ret != CY_AS_ERROR_SUCCESS) {
- cy_as_ll_destroy_request(dev_p, req_p);
- cy_as_ll_destroy_response(dev_p, reply_p);
- return ret;
- }
- } else {
- ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- dev_p->usb_cb[ep] = 0;
- cy_as_device_clear_usb_async_pending(dev_p, ep);
- }
-
- return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_cancel_async);
-
-static void
-cy_as_usb_ack_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_func_c_b_node *node = (cy_as_func_c_b_node *)
- dev_p->func_cbs_usb->head_p;
-
- (void)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);
- }
-
- node->cb_p((cy_as_device_handle)dev_p, ret,
- node->client_data, node->data_type, node->data);
- cy_as_remove_c_b_node(dev_p->func_cbs_usb);
-
- cy_as_ll_destroy_request(dev_p, rqt);
- cy_as_ll_destroy_response(dev_p, resp);
- cy_as_device_clear_ack_delayed(dev_p);
-}
-
-static cy_as_return_status_t
-cy_as_usb_ack_setup_packet(cy_as_device_handle handle,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p;
- cy_as_ll_request_response *reply_p;
- cy_as_func_c_b_node *cbnode;
-
- 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;
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_in_callback(dev_p) && cb == 0)
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- cy_as_hal_assert(cb != 0);
-
- cbnode = cy_as_create_func_c_b_node(cb, client);
- if (cbnode == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- req_p = cy_as_ll_create_request(dev_p, 0,
- CY_RQT_USB_RQT_CONTEXT, 2);
- 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;
- }
-
- cy_as_ll_init_request(req_p, CY_RQT_ACK_SETUP_PACKET,
- CY_RQT_USB_RQT_CONTEXT, 1);
- cy_as_ll_init_response(reply_p, 1);
-
- req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
-
- cy_as_insert_c_b_node(dev_p->func_cbs_usb, cbnode);
-
- ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
- cy_false, cy_as_usb_ack_callback);
-
- return ret;
-}
-
-/*
- * Flush all data in logical EP that is being NAK-ed or
- * Stall-ed, so that this does not continue to block data
- * on other LEPs that use the same physical EP.
- */
-static void
-cy_as_usb_flush_logical_e_p(
- cy_as_device *dev_p,
- uint16_t ep)
-{
- uint16_t addr, val, count;
-
- addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
- val = cy_as_hal_read_register(dev_p->tag, addr);
-
- while (val) {
- count = ((val & 0xFFF) + 1) / 2;
- while (count--)
- val = cy_as_hal_read_register(dev_p->tag, ep);
-
- cy_as_hal_write_register(dev_p->tag, addr, 0);
- val = cy_as_hal_read_register(dev_p->tag, addr);
- }
-}
-
-static cy_as_return_status_t
-cy_as_usb_nak_stall_request(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- uint16_t request,
- cy_bool state,
- cy_as_usb_function_callback cb,
- cy_as_function_callback fcb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
- uint16_t data;
-
- 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 (cb)
- cy_as_hal_assert(fcb == 0);
- if (fcb)
- cy_as_hal_assert(cb == 0);
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_in_callback(dev_p) && cb == 0 && fcb == 0)
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- req_p = cy_as_ll_create_request(dev_p,
- request, CY_RQT_USB_RQT_CONTEXT, 2);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* A single status word response type */
- 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;
- }
-
- /* Set the endpoint */
- data = (uint8_t)ep;
- cy_as_ll_request_response__set_word(req_p, 0, data);
-
- /* Set stall state to stalled */
- cy_as_ll_request_response__set_word(req_p, 1, (uint8_t)state);
-
- if (cb || fcb) {
- void *cbnode;
- cy_as_c_b_queue *queue;
- if (cb) {
- cbnode = cy_as_create_usb_func_c_b_node(cb, client);
- queue = dev_p->usb_func_cbs;
- } else {
- cbnode = cy_as_create_func_c_b_node(fcb, client);
- queue = dev_p->func_cbs_usb;
- req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
- }
-
- if (cbnode == 0) {
- ret = CY_AS_ERROR_OUT_OF_MEMORY;
- goto destroy;
- } else
- cy_as_insert_c_b_node(queue, cbnode);
-
-
- if (cy_as_device_is_setup_packet(dev_p)) {
- /* No Ack is needed on a stall request on EP0 */
- if ((state == cy_true) && (ep == 0)) {
- cy_as_device_set_ep0_stalled(dev_p);
- } else {
- cy_as_device_set_ack_delayed(dev_p);
- req_p->flags |=
- CY_AS_REQUEST_RESPONSE_DELAY_ACK;
- }
- }
-
- ret = cy_as_ll_send_request(dev_p, req_p,
- reply_p, cy_false, cy_as_usb_func_callback);
- if (ret != CY_AS_ERROR_SUCCESS) {
- if (req_p->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
- cy_as_device_rem_ack_delayed(dev_p);
- cy_as_remove_c_b_tail_node(queue);
-
- goto destroy;
- }
- } else {
- ret = cy_as_ll_send_request_wait_reply(dev_p,
- req_p, reply_p);
- 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) &&
- (request == CY_RQT_STALL_ENDPOINT)) {
- if ((ep > 1) && (state != 0) &&
- (dev_p->usb_config[ep].dir == cy_as_usb_out))
- cy_as_usb_flush_logical_e_p(dev_p, ep);
- }
-
-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_get_stall(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p,
- cy_as_ll_request_response *reply_p,
- cy_bool *state_p)
-{
- cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
- uint8_t code = cy_as_ll_request_response__get_code(reply_p);
-
- if (code == CY_RESP_SUCCESS_FAILURE) {
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
- goto destroy;
- } else if (code != CY_RESP_ENDPOINT_STALL) {
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- goto destroy;
- }
-
- *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
- ret = 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;
-}
-
-static cy_as_return_status_t
-my_handle_response_get_nak(cy_as_device *dev_p,
- cy_as_ll_request_response *req_p,
- cy_as_ll_request_response *reply_p,
- cy_bool *state_p)
-{
- cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
- uint8_t code = cy_as_ll_request_response__get_code(reply_p);
-
- if (code == CY_RESP_SUCCESS_FAILURE) {
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
- goto destroy;
- } else if (code != CY_RESP_ENDPOINT_NAK) {
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- goto destroy;
- }
-
- *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
- ret = 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;
-}
-
-static cy_as_return_status_t
-cy_as_usb_get_nak_stall(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- uint16_t request,
- uint16_t response,
- cy_bool *state_p,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
- uint16_t data;
-
- cy_as_device *dev_p = (cy_as_device *)handle;
-
- (void)response;
-
- if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
- return CY_AS_ERROR_INVALID_HANDLE;
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if (cy_as_device_is_in_callback(dev_p) && !cb)
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- req_p = cy_as_ll_create_request(dev_p, request,
- CY_RQT_USB_RQT_CONTEXT, 1);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* Set the endpoint */
- data = (uint8_t)ep;
- cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)ep);
-
- /* A single status word response type */
- 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;
-
- if (request == CY_RQT_GET_STALL)
- return my_handle_response_get_stall(dev_p,
- req_p, reply_p, state_p);
- else
- return my_handle_response_get_nak(dev_p,
- req_p, reply_p, state_p);
-
- } else {
- cy_as_funct_c_b_type type;
-
- if (request == CY_RQT_GET_STALL)
- type = CY_FUNCT_CB_USB_GETSTALL;
- else
- type = CY_FUNCT_CB_USB_GETNAK;
-
- ret = cy_as_misc_send_request(dev_p, cb, client, type,
- state_p, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
- req_p, reply_p, cy_as_usb_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_usb_set_nak(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- cy_as_function_callback cb,
- uint32_t client)
-{
- 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;
-
- /*
- * we send the firmware the EP# with the appropriate direction
- * bit, regardless of what the user gave us.
- */
- ep &= 0x0f;
- if (dev_p->usb_config[ep].dir == cy_as_usb_in)
- ep |= 0x80;
-
- if (dev_p->mtp_count > 0)
- return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
- return cy_as_usb_nak_stall_request(handle, ep,
- CY_RQT_ENDPOINT_SET_NAK, cy_true, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_set_nak);
-
-cy_as_return_status_t
-cy_as_usb_clear_nak(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- cy_as_function_callback cb,
- uint32_t client)
-{
- 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;
-
- /*
- * we send the firmware the EP# with the appropriate
- * direction bit, regardless of what the user gave us.
- */
- ep &= 0x0f;
- if (dev_p->usb_config[ep].dir == cy_as_usb_in)
- ep |= 0x80;
-
- if (dev_p->mtp_count > 0)
- return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
- return cy_as_usb_nak_stall_request(handle, ep,
- CY_RQT_ENDPOINT_SET_NAK, cy_false, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_clear_nak);
-
-cy_as_return_status_t
-cy_as_usb_get_nak(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- cy_bool *nak_p,
- cy_as_function_callback cb,
- uint32_t client)
-{
- 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;
-
- /*
- * we send the firmware the EP# with the appropriate
- * direction bit, regardless of what the user gave us.
- */
- ep &= 0x0f;
- if (dev_p->usb_config[ep].dir == cy_as_usb_in)
- ep |= 0x80;
-
- if (dev_p->mtp_count > 0)
- return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
- return cy_as_usb_get_nak_stall(handle, ep,
- CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK,
- nak_p, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_get_nak);
-
-cy_as_return_status_t
-cy_as_usb_set_stall(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- cy_as_function_callback cb,
- uint32_t client)
-{
- 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;
-
- /*
- * we send the firmware the EP# with the appropriate
- * direction bit, regardless of what the user gave us.
- */
- ep &= 0x0f;
- if (dev_p->usb_config[ep].dir == cy_as_usb_in)
- ep |= 0x80;
-
- if (dev_p->mtp_turbo_active)
- return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
- return cy_as_usb_nak_stall_request(handle, ep,
- CY_RQT_STALL_ENDPOINT, cy_true, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_set_stall);
-
-cy_as_return_status_t
-cy_as_usb_clear_stall(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- cy_as_function_callback cb,
- uint32_t client)
-{
- 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;
-
- /*
- * we send the firmware the EP# with the appropriate
- * direction bit, regardless of what the user gave us.
- */
- ep &= 0x0f;
- if (dev_p->usb_config[ep].dir == cy_as_usb_in)
- ep |= 0x80;
-
- if (dev_p->mtp_turbo_active)
- return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
- return cy_as_usb_nak_stall_request(handle, ep,
- CY_RQT_STALL_ENDPOINT, cy_false, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_clear_stall);
-
-cy_as_return_status_t
-cy_as_usb_get_stall(cy_as_device_handle handle,
- cy_as_end_point_number_t ep,
- cy_bool *stall_p,
- cy_as_function_callback cb,
- uint32_t client)
-{
- 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;
-
- /*
- * we send the firmware the EP# with the appropriate
- * direction bit, regardless of what the user gave us.
- */
- ep &= 0x0f;
- if (dev_p->usb_config[ep].dir == cy_as_usb_in)
- ep |= 0x80;
-
- if (dev_p->mtp_turbo_active)
- return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
- return cy_as_usb_get_nak_stall(handle, ep,
- CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_get_stall);
-
-cy_as_return_status_t
-cy_as_usb_signal_remote_wakeup(cy_as_device_handle handle,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
-
- 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;
-
- ret = is_usb_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 (dev_p->usb_last_event != cy_as_event_usb_suspend)
- return CY_AS_ERROR_NOT_IN_SUSPEND;
-
- req_p = cy_as_ll_create_request(dev_p,
- CY_RQT_USB_REMOTE_WAKEUP, CY_RQT_USB_RQT_CONTEXT, 0);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* A single status word response type */
- 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;
-
- if (cy_as_ll_request_response__get_code(reply_p) ==
- CY_RESP_SUCCESS_FAILURE)
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
- else
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP, 0,
- dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p,
- reply_p, cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_signal_remote_wakeup);
-
-cy_as_return_status_t
-cy_as_usb_set_m_s_report_threshold(cy_as_device_handle handle,
- uint32_t wr_sectors,
- uint32_t rd_sectors,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
-
- 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;
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
- return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
- /* Check if the firmware version supports this feature. */
- if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] ==
- (1 << cy_as_media_nand)))
- return CY_AS_ERROR_NOT_SUPPORTED;
-
- req_p = cy_as_ll_create_request(dev_p, CY_RQT_USB_STORAGE_MONITOR,
- CY_RQT_USB_RQT_CONTEXT, 4);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* A single status word response type */
- 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;
- }
-
- /* Set the read and write count parameters into
- * the request structure. */
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)((wr_sectors >> 16) & 0xFFFF));
- cy_as_ll_request_response__set_word(req_p, 1,
- (uint16_t)(wr_sectors & 0xFFFF));
- cy_as_ll_request_response__set_word(req_p, 2,
- (uint16_t)((rd_sectors >> 16) & 0xFFFF));
- cy_as_ll_request_response__set_word(req_p, 3,
- (uint16_t)(rd_sectors & 0xFFFF));
-
- 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;
-
- if (cy_as_ll_request_response__get_code(reply_p) ==
- CY_RESP_SUCCESS_FAILURE)
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
- else
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD, 0,
- dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
- req_p, reply_p, cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_set_m_s_report_threshold);
-
-cy_as_return_status_t
-cy_as_usb_select_m_s_partitions(
- cy_as_device_handle handle,
- cy_as_bus_number_t bus,
- uint32_t device,
- cy_as_usb_m_s_type_t type,
- cy_as_function_callback cb,
- uint32_t client)
-{
- cy_as_return_status_t ret;
- cy_as_ll_request_response *req_p , *reply_p;
- uint16_t val;
-
- 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;
-
- ret = is_usb_active(dev_p);
- if (ret != CY_AS_ERROR_SUCCESS)
- return ret;
-
- /* This API has to be made before SetEnumConfig is called. */
- if (dev_p->usb_config[0].enabled)
- return CY_AS_ERROR_INVALID_CALL_SEQUENCE;
-
- if ((cb == 0) && (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_MS_PARTITION_SELECT,
- CY_RQT_USB_RQT_CONTEXT, 2);
- if (req_p == 0)
- return CY_AS_ERROR_OUT_OF_MEMORY;
-
- /* A single status word response type */
- 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;
- }
-
- /* Set the read and write count parameters into
- * the request structure. */
- cy_as_ll_request_response__set_word(req_p, 0,
- (uint16_t)((bus << 8) | device));
-
- val = 0;
- if ((type == cy_as_usb_m_s_unit0) || (type == cy_as_usb_m_s_both))
- val |= 1;
- if ((type == cy_as_usb_m_s_unit1) || (type == cy_as_usb_m_s_both))
- val |= (1 << 8);
-
- cy_as_ll_request_response__set_word(req_p, 1, val);
-
- 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;
-
- if (cy_as_ll_request_response__get_code(reply_p) ==
- CY_RESP_SUCCESS_FAILURE)
- ret = cy_as_ll_request_response__get_word(reply_p, 0);
- else
- ret = CY_AS_ERROR_INVALID_RESPONSE;
- } else {
- ret = cy_as_misc_send_request(dev_p, cb, client,
- CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_usb,
- CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
- cy_as_usb_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;
-}
-EXPORT_SYMBOL(cy_as_usb_select_m_s_partitions);
-
-static void
-cy_as_usb_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_usb_func_c_b_node* node = (cy_as_usb_func_c_b_node *)
- dev_p->usb_func_cbs->head_p;
- cy_as_func_c_b_node* fnode = (cy_as_func_c_b_node *)
- dev_p->func_cbs_usb->head_p;
- cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
- cy_as_device_handle h = (cy_as_device_handle)dev_p;
- cy_bool delayed_ack = (rqt->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
- == CY_AS_REQUEST_RESPONSE_DELAY_ACK;
- cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
- == CY_AS_REQUEST_RESPONSE_EX;
- cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
- == CY_AS_REQUEST_RESPONSE_MS;
- uint8_t code;
- uint8_t ep, state;
-
- if (!ex_request && !ms_request) {
- cy_as_hal_assert(dev_p->usb_func_cbs->count != 0);
- cy_as_hal_assert(dev_p->usb_func_cbs->type ==
- CYAS_USB_FUNC_CB);
- } else {
- cy_as_hal_assert(dev_p->func_cbs_usb->count != 0);
- cy_as_hal_assert(dev_p->func_cbs_usb->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_USB:
- ret = my_handle_response_usb_start(dev_p, rqt, resp, stat);
- break;
- case CY_RQT_STOP_USB:
- ret = my_handle_response_usb_stop(dev_p, rqt, resp, stat);
- break;
- case CY_RQT_SET_CONNECT_STATE:
- if (!cy_as_ll_request_response__get_word(rqt, 0))
- ret = my_handle_response_disconnect(
- dev_p, rqt, resp, stat);
- else
- ret = my_handle_response_connect(
- dev_p, rqt, resp, stat);
- break;
- case CY_RQT_GET_CONNECT_STATE:
- break;
- case CY_RQT_SET_USB_CONFIG:
- ret = my_handle_response_set_enum_config(dev_p, rqt, resp);
- break;
- case CY_RQT_GET_USB_CONFIG:
- cy_as_hal_assert(fnode->data != 0);
- ret = my_handle_response_get_enum_config(dev_p,
- rqt, resp, fnode->data);
- break;
- case CY_RQT_STALL_ENDPOINT:
- ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
- state = (uint8_t)cy_as_ll_request_response__get_word(rqt, 1);
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- if ((ret == CY_AS_ERROR_SUCCESS) && (ep > 1) && (state != 0)
- && (dev_p->usb_config[ep].dir == cy_as_usb_out))
- cy_as_usb_flush_logical_e_p(dev_p, ep);
- break;
- case CY_RQT_GET_STALL:
- cy_as_hal_assert(fnode->data != 0);
- ret = my_handle_response_get_stall(dev_p,
- rqt, resp, (cy_bool *)fnode->data);
- break;
- case CY_RQT_SET_DESCRIPTOR:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- break;
- case CY_RQT_GET_DESCRIPTOR:
- cy_as_hal_assert(fnode->data != 0);
- ret = my_handle_response_get_descriptor(dev_p,
- rqt, resp, (cy_as_get_descriptor_data *)fnode->data);
- break;
- case CY_RQT_SET_USB_CONFIG_REGISTERS:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- if (ret == CY_AS_ERROR_SUCCESS)
- ret = cy_as_usb_setup_dma(dev_p);
- break;
- case CY_RQT_ENDPOINT_SET_NAK:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- break;
- case CY_RQT_GET_ENDPOINT_NAK:
- cy_as_hal_assert(fnode->data != 0);
- ret = my_handle_response_get_nak(dev_p,
- rqt, resp, (cy_bool *)fnode->data);
- break;
- case CY_RQT_ACK_SETUP_PACKET:
- break;
- case CY_RQT_USB_REMOTE_WAKEUP:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- break;
- case CY_RQT_CLEAR_DESCRIPTORS:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- break;
- case CY_RQT_USB_STORAGE_MONITOR:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- break;
- case CY_RQT_MS_PARTITION_SELECT:
- ret = my_handle_response_no_data(dev_p, rqt, resp);
- 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 (ex_request || ms_request) {
- fnode->cb_p((cy_as_device_handle)dev_p, stat,
- fnode->client_data, fnode->data_type, fnode->data);
- cy_as_remove_c_b_node(dev_p->func_cbs_usb);
- } else {
- node->cb_p((cy_as_device_handle)dev_p, stat,
- node->client_data);
- cy_as_remove_c_b_node(dev_p->usb_func_cbs);
- }
-
- if (delayed_ack) {
- cy_as_hal_assert(cy_as_device_is_ack_delayed(dev_p));
- cy_as_device_rem_ack_delayed(dev_p);
-
- /*
- * send the ACK if required.
- */
- if (!cy_as_device_is_ack_delayed(dev_p))
- cy_as_usb_ack_setup_packet(h,
- usb_ack_callback, 0);
- }
-}
-
-
-/*[]*/