From 78f23926dff9c8587d510fa4d746e77a8ad9410d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 Jul 2011 04:53:56 +0200 Subject: Staging: delete westbridge code It's been stagnant for a while with out much forward progress for a variety of different reasons. So remove it for now. It can be reverted at any time if development picks back up again. Acked-by: David Cross Signed-off-by: Greg Kroah-Hartman --- .../staging/westbridge/astoria/api/src/cyasusb.c | 3740 -------------------- 1 file changed, 3740 deletions(-) delete mode 100644 drivers/staging/westbridge/astoria/api/src/cyasusb.c (limited to 'drivers/staging/westbridge/astoria/api/src/cyasusb.c') 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 1b55e611191..00000000000 --- 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); - } -} - - -/*[]*/ -- cgit v1.2.3