1 /* Cypress West Bridge API source file (cyasusb.c)
2 ## ===========================
3 ## Copyright (C) 2010 Cypress Semiconductor
5 ## This program is free software; you can redistribute it and/or
6 ## modify it under the terms of the GNU General Public License
7 ## as published by the Free Software Foundation; either version 2
8 ## of the License, or (at your option) any later version.
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; if not, write to the Free Software
17 ## Foundation, Inc., 51 Franklin Street, Fifth Floor
18 ## Boston, MA 02110-1301, USA.
19 ## ===========================
22 #include "../../include/linux/westbridge/cyashal.h"
23 #include "../../include/linux/westbridge/cyasusb.h"
24 #include "../../include/linux/westbridge/cyaserr.h"
25 #include "../../include/linux/westbridge/cyasdma.h"
26 #include "../../include/linux/westbridge/cyaslowlevel.h"
27 #include "../../include/linux/westbridge/cyaslep2pep.h"
28 #include "../../include/linux/westbridge/cyasregs.h"
29 #include "../../include/linux/westbridge/cyasstorage.h"
31 static cy_as_return_status_t
32 cy_as_usb_ack_setup_packet(
33 /* Handle to the West Bridge device */
34 cy_as_device_handle handle,
35 /* The callback if async call */
36 cy_as_function_callback cb,
37 /* Client supplied data */
42 cy_as_usb_func_callback(
45 cy_as_ll_request_response *rqt,
46 cy_as_ll_request_response *resp,
47 cy_as_return_status_t ret);
49 * Reset the USB EP0 state
52 cy_as_usb_reset_e_p0_state(cy_as_device *dev_p)
54 cy_as_log_debug_message(6, "cy_as_usb_reset_e_p0_state called");
56 cy_as_device_clear_ack_delayed(dev_p);
57 cy_as_device_clear_setup_packet(dev_p);
58 if (cy_as_device_is_usb_async_pending(dev_p, 0))
59 cy_as_usb_cancel_async((cy_as_device_handle)dev_p, 0);
61 dev_p->usb_pending_buffer = 0;
65 * External function to map logical endpoints to physical endpoints
67 static cy_as_return_status_t
68 is_usb_active(cy_as_device *dev_p)
70 if (!cy_as_device_is_configured(dev_p))
71 return CY_AS_ERROR_NOT_CONFIGURED;
73 if (!cy_as_device_is_firmware_loaded(dev_p))
74 return CY_AS_ERROR_NO_FIRMWARE;
76 if (dev_p->usb_count == 0)
77 return CY_AS_ERROR_NOT_RUNNING;
79 if (cy_as_device_is_in_suspend_mode(dev_p))
80 return CY_AS_ERROR_IN_SUSPEND;
82 return CY_AS_ERROR_SUCCESS;
86 usb_ack_callback(cy_as_device_handle h,
87 cy_as_return_status_t status,
89 cy_as_funct_c_b_type type,
92 cy_as_device *dev_p = (cy_as_device *)h;
98 cy_as_hal_assert(type == CY_FUNCT_CB_NODATA);
100 if (dev_p->usb_pending_buffer) {
101 cy_as_usb_io_callback cb;
103 cb = dev_p->usb_cb[0];
104 dev_p->usb_cb[0] = 0;
105 cy_as_device_clear_usb_async_pending(dev_p, 0);
107 cb(h, 0, dev_p->usb_pending_size,
108 dev_p->usb_pending_buffer, dev_p->usb_error);
110 dev_p->usb_pending_buffer = 0;
113 cy_as_device_clear_setup_packet(dev_p);
117 my_usb_request_callback_usb_event(cy_as_device *dev_p,
118 cy_as_ll_request_response *req_p)
122 cy_as_device_handle h = (cy_as_device_handle)dev_p;
124 ev = cy_as_ll_request_response__get_word(req_p, 0);
126 case 0: /* Reserved */
127 cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
128 CY_AS_ERROR_INVALID_REQUEST, 0);
131 case 1: /* Reserved */
132 cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
133 CY_AS_ERROR_INVALID_REQUEST, 0);
136 case 2: /* USB Suspend */
137 dev_p->usb_last_event = cy_as_event_usb_suspend;
138 if (dev_p->usb_event_cb_ms)
139 dev_p->usb_event_cb_ms(h, cy_as_event_usb_suspend, 0);
140 else if (dev_p->usb_event_cb)
141 dev_p->usb_event_cb(h, cy_as_event_usb_suspend, 0);
142 cy_as_ll_send_status_response(dev_p,
143 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
146 case 3: /* USB Resume */
147 dev_p->usb_last_event = cy_as_event_usb_resume;
148 if (dev_p->usb_event_cb_ms)
149 dev_p->usb_event_cb_ms(h, cy_as_event_usb_resume, 0);
150 else if (dev_p->usb_event_cb)
151 dev_p->usb_event_cb(h, cy_as_event_usb_resume, 0);
152 cy_as_ll_send_status_response(dev_p,
153 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
156 case 4: /* USB Reset */
158 * if we get a USB reset, the USB host did not understand
159 * our response or we timed out for some reason. reset
160 * our internal state to be ready for another set of
161 * enumeration based requests.
163 if (cy_as_device_is_ack_delayed(dev_p))
164 cy_as_usb_reset_e_p0_state(dev_p);
166 dev_p->usb_last_event = cy_as_event_usb_reset;
167 if (dev_p->usb_event_cb_ms)
168 dev_p->usb_event_cb_ms(h, cy_as_event_usb_reset, 0);
169 else if (dev_p->usb_event_cb)
170 dev_p->usb_event_cb(h, cy_as_event_usb_reset, 0);
172 cy_as_ll_send_status_response(dev_p,
173 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
174 cy_as_device_clear_usb_high_speed(dev_p);
175 cy_as_usb_set_dma_sizes(dev_p);
176 dev_p->usb_max_tx_size = 0x40;
177 cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
180 case 5: /* USB Set Configuration */
181 /* The configuration to set */
182 val = cy_as_ll_request_response__get_word(req_p, 1);
183 dev_p->usb_last_event = cy_as_event_usb_set_config;
184 if (dev_p->usb_event_cb_ms)
185 dev_p->usb_event_cb_ms(h,
186 cy_as_event_usb_set_config, &val);
187 else if (dev_p->usb_event_cb)
188 dev_p->usb_event_cb(h,
189 cy_as_event_usb_set_config, &val);
191 cy_as_ll_send_status_response(dev_p,
192 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
195 case 6: /* USB Speed change */
197 val = cy_as_ll_request_response__get_word(req_p, 1);
198 dev_p->usb_last_event = cy_as_event_usb_speed_change;
199 if (dev_p->usb_event_cb_ms)
200 dev_p->usb_event_cb_ms(h,
201 cy_as_event_usb_speed_change, &val);
202 else if (dev_p->usb_event_cb)
203 dev_p->usb_event_cb(h,
204 cy_as_event_usb_speed_change, &val);
206 cy_as_ll_send_status_response(dev_p,
207 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
208 cy_as_device_set_usb_high_speed(dev_p);
209 cy_as_usb_set_dma_sizes(dev_p);
210 dev_p->usb_max_tx_size = 0x200;
211 cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x200);
214 case 7: /* USB Clear Feature */
216 val = cy_as_ll_request_response__get_word(req_p, 1);
217 if (dev_p->usb_event_cb_ms)
218 dev_p->usb_event_cb_ms(h,
219 cy_as_event_usb_clear_feature, &val);
220 if (dev_p->usb_event_cb)
221 dev_p->usb_event_cb(h,
222 cy_as_event_usb_clear_feature, &val);
224 cy_as_ll_send_status_response(dev_p,
225 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
229 cy_as_hal_print_message("invalid event type\n");
230 cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
231 CY_RESP_USB_INVALID_EVENT, sizeof(ev), &ev);
237 my_usb_request_callback_usb_data(cy_as_device *dev_p,
238 cy_as_ll_request_response *req_p)
240 cy_as_end_point_number_t ep;
244 cy_as_device_handle h = (cy_as_device_handle)dev_p;
246 val = cy_as_ll_request_response__get_word(req_p, 0);
247 ep = (cy_as_end_point_number_t)((val >> 13) & 0x01);
250 cy_as_hal_assert(len <= 64);
251 cy_as_ll_request_response__unpack(req_p,
252 1, len, dev_p->usb_ep_data);
254 type = (uint8_t)((val >> 14) & 0x03);
256 if (cy_as_device_is_ack_delayed(dev_p)) {
258 * A setup packet has arrived while we are
259 * processing a previous setup packet. reset
260 * our state with respect to EP0 to be ready
261 * to process the new packet.
263 cy_as_usb_reset_e_p0_state(dev_p);
267 cy_as_ll_send_status_response(dev_p,
268 CY_RQT_USB_RQT_CONTEXT,
269 CY_AS_ERROR_INVALID_REQUEST, 0);
271 cy_as_device_clear_ep0_stalled(dev_p);
272 cy_as_device_set_setup_packet(dev_p);
273 cy_as_ll_send_status_response(dev_p,
274 CY_RQT_USB_RQT_CONTEXT,
275 CY_AS_ERROR_SUCCESS, 0);
277 if (dev_p->usb_event_cb_ms)
278 dev_p->usb_event_cb_ms(h,
279 cy_as_event_usb_setup_packet,
282 dev_p->usb_event_cb(h,
283 cy_as_event_usb_setup_packet,
286 if ((!cy_as_device_is_ack_delayed(dev_p)) &&
287 (!cy_as_device_is_ep0_stalled(dev_p)))
288 cy_as_usb_ack_setup_packet(h,
289 usb_ack_callback, 0);
291 } else if (type == 2) {
293 cy_as_ll_send_status_response(dev_p,
294 CY_RQT_USB_RQT_CONTEXT,
295 CY_AS_ERROR_INVALID_REQUEST, 0);
297 if (dev_p->usb_event_cb_ms)
298 dev_p->usb_event_cb_ms(h,
299 cy_as_event_usb_status_packet, 0);
301 dev_p->usb_event_cb(h,
302 cy_as_event_usb_status_packet, 0);
304 cy_as_ll_send_status_response(dev_p,
305 CY_RQT_USB_RQT_CONTEXT,
306 CY_AS_ERROR_SUCCESS, 0);
308 } else if (type == 1) {
310 * we need to hand the data associated with these
311 * endpoints to the DMA module.
313 cy_as_dma_received_data(dev_p, ep, len, dev_p->usb_ep_data);
314 cy_as_ll_send_status_response(dev_p,
315 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
320 my_usb_request_callback_inquiry(cy_as_device *dev_p,
321 cy_as_ll_request_response *req_p)
323 cy_as_usb_inquiry_data_dep cbdata;
324 cy_as_usb_inquiry_data cbdata_ms;
327 cy_as_device_handle h = (cy_as_device_handle)dev_p;
328 uint8_t def_inq_data[64];
334 cy_as_bus_number_t bus;
336 cy_as_media_type media;
338 val = cy_as_ll_request_response__get_word(req_p, 0);
339 bus = cy_as_storage_get_bus_from_address(val);
340 device = cy_as_storage_get_device_from_address(val);
341 media = cy_as_storage_get_media_from_address(val);
343 val = cy_as_ll_request_response__get_word(req_p, 1);
344 evpd = (uint8_t)((val >> 8) & 0x01);
345 codepage = (uint8_t)(val & 0xff);
347 length = cy_as_ll_request_response__get_word(req_p, 2);
348 data = (void *)def_inq_data;
352 if (dev_p->usb_event_cb_ms) {
354 cbdata_ms.device = device;
355 cbdata_ms.updated = updated;
356 cbdata_ms.evpd = evpd;
357 cbdata_ms.codepage = codepage;
358 cbdata_ms.length = length;
359 cbdata_ms.data = data;
361 cy_as_hal_assert(cbdata_ms.length <= sizeof(def_inq_data));
362 cy_as_ll_request_response__unpack(req_p,
363 3, cbdata_ms.length, cbdata_ms.data);
365 dev_p->usb_event_cb_ms(h,
366 cy_as_event_usb_inquiry_before, &cbdata_ms);
368 updated = cbdata_ms.updated;
369 data = cbdata_ms.data;
370 length = cbdata_ms.length;
371 } else if (dev_p->usb_event_cb) {
372 cbdata.media = media;
373 cbdata.updated = updated;
375 cbdata.codepage = codepage;
376 cbdata.length = length;
379 cy_as_hal_assert(cbdata.length <=
380 sizeof(def_inq_data));
381 cy_as_ll_request_response__unpack(req_p, 3,
382 cbdata.length, cbdata.data);
384 dev_p->usb_event_cb(h,
385 cy_as_event_usb_inquiry_before, &cbdata);
387 updated = cbdata.updated;
389 length = cbdata.length;
392 if (updated && length > 192)
393 cy_as_hal_print_message("an inquiry result from a "
394 "cy_as_event_usb_inquiry_before event "
395 "was greater than 192 bytes.");
397 /* Now send the reply with the data back
398 * to the West Bridge device */
399 if (updated && length <= 192) {
401 * the callback function modified the inquiry
402 * data, ship the data back to the west bridge firmware.
404 cy_as_ll_send_data_response(dev_p,
405 CY_RQT_USB_RQT_CONTEXT,
406 CY_RESP_INQUIRY_DATA, length, data);
409 * the callback did not modify the data, just acknowledge
410 * that we processed the request
412 cy_as_ll_send_status_response(dev_p,
413 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1);
416 if (dev_p->usb_event_cb_ms)
417 dev_p->usb_event_cb_ms(h,
418 cy_as_event_usb_inquiry_after, &cbdata_ms);
419 else if (dev_p->usb_event_cb)
420 dev_p->usb_event_cb(h,
421 cy_as_event_usb_inquiry_after, &cbdata);
425 my_usb_request_callback_start_stop(cy_as_device *dev_p,
426 cy_as_ll_request_response *req_p)
428 cy_as_bus_number_t bus;
429 cy_as_media_type media;
433 if (dev_p->usb_event_cb_ms || dev_p->usb_event_cb) {
436 cy_as_device_handle h = (cy_as_device_handle)dev_p;
438 val = cy_as_ll_request_response__get_word(req_p, 0);
439 bus = cy_as_storage_get_bus_from_address(val);
440 device = cy_as_storage_get_device_from_address(val);
441 media = cy_as_storage_get_media_from_address(val);
443 val = cy_as_ll_request_response__get_word(req_p, 1);
444 loej = (val & 0x02) ? cy_true : cy_false;
445 start = (val & 0x01) ? cy_true : cy_false;
447 if (dev_p->usb_event_cb_ms) {
448 cy_as_usb_start_stop_data cbdata_ms;
451 cbdata_ms.device = device;
452 cbdata_ms.loej = loej;
453 cbdata_ms.start = start;
454 dev_p->usb_event_cb_ms(h,
455 cy_as_event_usb_start_stop, &cbdata_ms);
457 } else if (dev_p->usb_event_cb) {
458 cy_as_usb_start_stop_data_dep cbdata;
460 cbdata.media = media;
462 cbdata.start = start;
463 dev_p->usb_event_cb(h,
464 cy_as_event_usb_start_stop, &cbdata);
467 cy_as_ll_send_status_response(dev_p,
468 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1);
472 my_usb_request_callback_uknown_c_b_w(cy_as_device *dev_p,
473 cy_as_ll_request_response *req_p)
476 cy_as_device_handle h = (cy_as_device_handle)dev_p;
487 val = cy_as_ll_request_response__get_word(req_p, 0);
488 /* Failed by default */
490 /* Invalid command */
492 /* Invalid command */
494 /* Invalid command */
496 reqlen = cy_as_ll_request_response__get_word(req_p, 1);
499 cy_as_hal_assert(reqlen <= sizeof(buf));
500 cy_as_ll_request_response__unpack(req_p, 2, reqlen, request);
502 if (dev_p->usb_event_cb_ms) {
503 cy_as_usb_unknown_command_data cbdata_ms;
504 cbdata_ms.bus = cy_as_storage_get_bus_from_address(val);
506 cy_as_storage_get_device_from_address(val);
507 cbdata_ms.reqlen = reqlen;
508 cbdata_ms.request = request;
509 cbdata_ms.status = status;
512 cbdata_ms.ascq = ascq;
514 dev_p->usb_event_cb_ms(h,
515 cy_as_event_usb_unknown_storage, &cbdata_ms);
516 status = cbdata_ms.status;
519 ascq = cbdata_ms.ascq;
520 } else if (dev_p->usb_event_cb) {
521 cy_as_usb_unknown_command_data_dep cbdata;
523 cy_as_storage_get_media_from_address(val);
524 cbdata.reqlen = reqlen;
525 cbdata.request = request;
526 cbdata.status = status;
531 dev_p->usb_event_cb(h,
532 cy_as_event_usb_unknown_storage, &cbdata);
533 status = cbdata.status;
539 response[0] = status;
543 cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
544 CY_RESP_UNKNOWN_SCSI_COMMAND, sizeof(response), response);
548 my_usb_request_callback_m_s_c_progress(cy_as_device *dev_p,
549 cy_as_ll_request_response *req_p)
552 cy_as_device_handle h = (cy_as_device_handle)dev_p;
554 if ((dev_p->usb_event_cb) || (dev_p->usb_event_cb_ms)) {
555 cy_as_m_s_c_progress_data cbdata;
557 val1 = cy_as_ll_request_response__get_word(req_p, 0);
558 val2 = cy_as_ll_request_response__get_word(req_p, 1);
559 cbdata.wr_count = (uint32_t)((val1 << 16) | val2);
561 val1 = cy_as_ll_request_response__get_word(req_p, 2);
562 val2 = cy_as_ll_request_response__get_word(req_p, 3);
563 cbdata.rd_count = (uint32_t)((val1 << 16) | val2);
565 if (dev_p->usb_event_cb)
566 dev_p->usb_event_cb(h,
567 cy_as_event_usb_m_s_c_progress, &cbdata);
569 dev_p->usb_event_cb_ms(h,
570 cy_as_event_usb_m_s_c_progress, &cbdata);
573 cy_as_ll_send_status_response(dev_p,
574 CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
578 * This function processes the requests delivered from the
579 * firmware within the West Bridge device that are delivered
580 * in the USB context. These requests generally are EP0 and
581 * EP1 related requests or USB events.
584 my_usb_request_callback(cy_as_device *dev_p, uint8_t context,
585 cy_as_ll_request_response *req_p,
586 cy_as_ll_request_response *resp_p,
587 cy_as_return_status_t ret)
590 uint8_t code = cy_as_ll_request_response__get_code(req_p);
597 case CY_RQT_USB_EVENT:
598 my_usb_request_callback_usb_event(dev_p, req_p);
601 case CY_RQT_USB_EP_DATA:
602 dev_p->usb_last_event = cy_as_event_usb_setup_packet;
603 my_usb_request_callback_usb_data(dev_p, req_p);
606 case CY_RQT_SCSI_INQUIRY_COMMAND:
607 dev_p->usb_last_event = cy_as_event_usb_inquiry_after;
608 my_usb_request_callback_inquiry(dev_p, req_p);
611 case CY_RQT_SCSI_START_STOP_COMMAND:
612 dev_p->usb_last_event = cy_as_event_usb_start_stop;
613 my_usb_request_callback_start_stop(dev_p, req_p);
616 case CY_RQT_SCSI_UNKNOWN_COMMAND:
617 dev_p->usb_last_event = cy_as_event_usb_unknown_storage;
618 my_usb_request_callback_uknown_c_b_w(dev_p, req_p);
621 case CY_RQT_USB_ACTIVITY_UPDATE:
622 dev_p->usb_last_event = cy_as_event_usb_m_s_c_progress;
623 my_usb_request_callback_m_s_c_progress(dev_p, req_p);
627 cy_as_hal_print_message("invalid request "
628 "received on USB context\n");
630 cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
631 CY_RESP_INVALID_REQUEST, sizeof(val), &val);
636 static cy_as_return_status_t
637 my_handle_response_usb_start(cy_as_device *dev_p,
638 cy_as_ll_request_response *req_p,
639 cy_as_ll_request_response *reply_p,
640 cy_as_return_status_t ret)
642 if (ret != CY_AS_ERROR_SUCCESS)
645 if (cy_as_ll_request_response__get_code(reply_p) !=
646 CY_RESP_SUCCESS_FAILURE) {
647 ret = CY_AS_ERROR_INVALID_RESPONSE;
651 ret = cy_as_ll_request_response__get_word(reply_p, 0);
652 if (ret != CY_AS_ERROR_SUCCESS)
656 * mark EP 0 and EP1 as 64 byte endpoints
658 cy_as_dma_set_max_dma_size(dev_p, 0, 64);
659 cy_as_dma_set_max_dma_size(dev_p, 1, 64);
664 cy_as_ll_destroy_request(dev_p, req_p);
665 cy_as_ll_destroy_response(dev_p, reply_p);
667 if (ret != CY_AS_ERROR_SUCCESS) {
668 cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
669 cy_as_ll_register_request_callback(dev_p,
670 CY_RQT_USB_RQT_CONTEXT, 0);
673 cy_as_device_clear_u_s_s_pending(dev_p);
680 * This function starts the USB stack. The stack is reference
681 * counted so if the stack is already started, this function
682 * just increments the count. If the stack has not been started,
683 * a start request is sent to the West Bridge device.
685 * Note: Starting the USB stack does not cause the USB signals
686 * to be connected to the USB pins. To do this and therefore
687 * initiate enumeration, CyAsUsbConnect() must be called.
689 cy_as_return_status_t
690 cy_as_usb_start(cy_as_device_handle handle,
691 cy_as_function_callback cb,
694 cy_as_ll_request_response *req_p, *reply_p;
695 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
699 cy_as_log_debug_message(6, "cy_as_usb_start called");
701 dev_p = (cy_as_device *)handle;
702 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
703 return CY_AS_ERROR_INVALID_HANDLE;
705 if (!cy_as_device_is_configured(dev_p))
706 return CY_AS_ERROR_NOT_CONFIGURED;
708 if (!cy_as_device_is_firmware_loaded(dev_p))
709 return CY_AS_ERROR_NO_FIRMWARE;
711 if (cy_as_device_is_in_suspend_mode(dev_p))
712 return CY_AS_ERROR_IN_SUSPEND;
714 if (cy_as_device_is_in_callback(dev_p))
715 return CY_AS_ERROR_INVALID_IN_CALLBACK;
717 if (cy_as_device_is_u_s_s_pending(dev_p))
718 return CY_AS_ERROR_STARTSTOP_PENDING;
720 cy_as_device_set_u_s_s_pending(dev_p);
722 if (dev_p->usb_count == 0) {
724 * since we are just starting the stack,
725 * mark USB as not connected to the remote host
727 cy_as_device_clear_usb_connected(dev_p);
728 dev_p->usb_phy_config = 0;
730 /* Queue for 1.0 Async Requests, kept for
731 * backwards compatibility */
732 dev_p->usb_func_cbs = cy_as_create_c_b_queue(CYAS_USB_FUNC_CB);
733 if (dev_p->usb_func_cbs == 0) {
734 cy_as_device_clear_u_s_s_pending(dev_p);
735 return CY_AS_ERROR_OUT_OF_MEMORY;
738 /* Reset the EP0 state */
739 cy_as_usb_reset_e_p0_state(dev_p);
742 * we register here becuase the start request may cause
743 * events to occur before the response to the start request.
745 cy_as_ll_register_request_callback(dev_p,
746 CY_RQT_USB_RQT_CONTEXT, my_usb_request_callback);
748 /* Create the request to send to the West Bridge device */
749 req_p = cy_as_ll_create_request(dev_p,
750 CY_RQT_START_USB, CY_RQT_USB_RQT_CONTEXT, 0);
752 cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
753 dev_p->usb_func_cbs = 0;
754 cy_as_device_clear_u_s_s_pending(dev_p);
755 return CY_AS_ERROR_OUT_OF_MEMORY;
758 /* Reserve space for the reply, the reply data
759 * will not exceed one word */
760 reply_p = cy_as_ll_create_response(dev_p, 1);
762 cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
763 dev_p->usb_func_cbs = 0;
764 cy_as_ll_destroy_request(dev_p, req_p);
765 cy_as_device_clear_u_s_s_pending(dev_p);
766 return CY_AS_ERROR_OUT_OF_MEMORY;
770 ret = cy_as_ll_send_request_wait_reply(dev_p,
772 if (ret != CY_AS_ERROR_SUCCESS)
775 return my_handle_response_usb_start(dev_p,
776 req_p, reply_p, ret);
778 ret = cy_as_misc_send_request(dev_p, cb,
779 client, CY_FUNCT_CB_USB_START, 0,
781 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
782 cy_as_usb_func_callback);
784 if (ret != CY_AS_ERROR_SUCCESS)
791 cy_as_ll_destroy_request(dev_p, req_p);
792 cy_as_ll_destroy_response(dev_p, reply_p);
796 cb(handle, ret, client, CY_FUNCT_CB_USB_START, 0);
799 cy_as_device_clear_u_s_s_pending(dev_p);
805 cy_as_usb_reset(cy_as_device *dev_p)
809 cy_as_device_clear_usb_connected(dev_p);
811 for (i = 0; i < sizeof(dev_p->usb_config) /
812 sizeof(dev_p->usb_config[0]); i++) {
814 * cancel all pending USB read/write operations, as it is
815 * possible that the USB stack comes up in a different
816 * configuration with a different set of endpoints.
818 if (cy_as_device_is_usb_async_pending(dev_p, i))
819 cy_as_usb_cancel_async(dev_p,
820 (cy_as_end_point_number_t)i);
822 dev_p->usb_cb[i] = 0;
823 dev_p->usb_config[i].enabled = cy_false;
826 dev_p->usb_phy_config = 0;
830 * This function does all the API side clean-up associated
831 * with CyAsUsbStop, without any communication with firmware.
832 * This needs to be done when the device is being reset while
833 * the USB stack is active.
836 cy_as_usb_cleanup(cy_as_device *dev_p)
838 if (dev_p->usb_count) {
839 cy_as_usb_reset_e_p0_state(dev_p);
840 cy_as_usb_reset(dev_p);
841 cy_as_hal_mem_set(dev_p->usb_config, 0,
842 sizeof(dev_p->usb_config));
843 cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
845 dev_p->usb_count = 0;
849 static cy_as_return_status_t
850 my_handle_response_usb_stop(cy_as_device *dev_p,
851 cy_as_ll_request_response *req_p,
852 cy_as_ll_request_response *reply_p,
853 cy_as_return_status_t ret)
855 if (ret != CY_AS_ERROR_SUCCESS)
858 if (cy_as_ll_request_response__get_code(reply_p) !=
859 CY_RESP_SUCCESS_FAILURE) {
860 ret = CY_AS_ERROR_INVALID_RESPONSE;
864 ret = cy_as_ll_request_response__get_word(reply_p, 0);
865 if (ret != CY_AS_ERROR_SUCCESS)
869 * we sucessfully shutdown the stack, so
870 * decrement to make the count zero.
872 cy_as_usb_cleanup(dev_p);
875 cy_as_ll_destroy_request(dev_p, req_p);
876 cy_as_ll_destroy_response(dev_p, reply_p);
878 if (ret != CY_AS_ERROR_SUCCESS)
879 cy_as_ll_register_request_callback(dev_p,
880 CY_RQT_USB_RQT_CONTEXT, 0);
882 cy_as_device_clear_u_s_s_pending(dev_p);
888 * This function stops the USB stack. The USB stack is reference
889 * counted so first is reference count is decremented. If the
890 * reference count is then zero, a request is sent to the West
891 * Bridge device to stop the USB stack on the West Bridge device.
893 cy_as_return_status_t
894 cy_as_usb_stop(cy_as_device_handle handle,
895 cy_as_function_callback cb,
898 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
899 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
903 cy_as_log_debug_message(6, "cy_as_usb_stop called");
905 dev_p = (cy_as_device *)handle;
906 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
907 return CY_AS_ERROR_INVALID_HANDLE;
909 ret = is_usb_active(dev_p);
910 if (ret != CY_AS_ERROR_SUCCESS)
913 if (cy_as_device_is_usb_connected(dev_p))
914 return CY_AS_ERROR_USB_CONNECTED;
916 if (cy_as_device_is_in_callback(dev_p))
917 return CY_AS_ERROR_INVALID_IN_CALLBACK;
919 if (cy_as_device_is_u_s_s_pending(dev_p))
920 return CY_AS_ERROR_STARTSTOP_PENDING;
922 cy_as_device_set_u_s_s_pending(dev_p);
924 if (dev_p->usb_count == 1) {
925 /* Create the request to send to the West Bridge device */
926 req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_USB,
927 CY_RQT_USB_RQT_CONTEXT, 0);
929 ret = CY_AS_ERROR_OUT_OF_MEMORY;
933 /* Reserve space for the reply, the reply data will not
935 reply_p = cy_as_ll_create_response(dev_p, 1);
937 ret = CY_AS_ERROR_OUT_OF_MEMORY;
942 ret = cy_as_ll_send_request_wait_reply(dev_p,
944 if (ret != CY_AS_ERROR_SUCCESS)
947 return my_handle_response_usb_stop(dev_p,
948 req_p, reply_p, ret);
950 ret = cy_as_misc_send_request(dev_p, cb, client,
951 CY_FUNCT_CB_USB_STOP, 0, dev_p->func_cbs_usb,
952 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
953 cy_as_usb_func_callback);
955 if (ret != CY_AS_ERROR_SUCCESS)
962 cy_as_ll_destroy_request(dev_p, req_p);
963 cy_as_ll_destroy_response(dev_p, reply_p);
964 } else if (dev_p->usb_count > 1) {
966 * reset all LE_ps to inactive state, after cleaning
967 * up any pending async read/write calls.
969 cy_as_usb_reset(dev_p);
973 cb(handle, ret, client, CY_FUNCT_CB_USB_STOP, 0);
976 cy_as_device_clear_u_s_s_pending(dev_p);
982 * This function registers a callback to be called when
983 * USB events are processed
985 cy_as_return_status_t
986 cy_as_usb_register_callback(cy_as_device_handle handle,
987 cy_as_usb_event_callback callback)
991 cy_as_log_debug_message(6, "cy_as_usb_register_callback called");
993 dev_p = (cy_as_device *)handle;
994 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
995 return CY_AS_ERROR_INVALID_HANDLE;
997 if (!cy_as_device_is_configured(dev_p))
998 return CY_AS_ERROR_NOT_CONFIGURED;
1000 if (!cy_as_device_is_firmware_loaded(dev_p))
1001 return CY_AS_ERROR_NO_FIRMWARE;
1003 dev_p->usb_event_cb = NULL;
1004 dev_p->usb_event_cb_ms = callback;
1005 return CY_AS_ERROR_SUCCESS;
1009 static cy_as_return_status_t
1010 my_handle_response_no_data(cy_as_device *dev_p,
1011 cy_as_ll_request_response *req_p,
1012 cy_as_ll_request_response *reply_p)
1014 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1016 if (cy_as_ll_request_response__get_code(reply_p) !=
1017 CY_RESP_SUCCESS_FAILURE)
1018 ret = CY_AS_ERROR_INVALID_RESPONSE;
1020 ret = cy_as_ll_request_response__get_word(reply_p, 0);
1022 cy_as_ll_destroy_request(dev_p, req_p);
1023 cy_as_ll_destroy_response(dev_p, reply_p);
1028 static cy_as_return_status_t
1029 my_handle_response_connect(cy_as_device *dev_p,
1030 cy_as_ll_request_response *req_p,
1031 cy_as_ll_request_response *reply_p,
1032 cy_as_return_status_t ret)
1034 if (ret != CY_AS_ERROR_SUCCESS)
1037 if (cy_as_ll_request_response__get_code(reply_p) !=
1038 CY_RESP_SUCCESS_FAILURE) {
1039 ret = CY_AS_ERROR_INVALID_RESPONSE;
1043 ret = cy_as_ll_request_response__get_word(reply_p, 0);
1044 if (ret == CY_AS_ERROR_SUCCESS)
1045 cy_as_device_set_usb_connected(dev_p);
1048 cy_as_ll_destroy_request(dev_p, req_p);
1049 cy_as_ll_destroy_response(dev_p, reply_p);
1056 * This method asks the West Bridge device to connect the
1057 * internal USB D+ and D- signals to the USB pins, thus
1058 * starting the enumeration processes if the external pins
1059 * are connnected to a USB host. If the external pins are
1060 * not connect to a USB host, enumeration will begin as soon
1061 * as the USB pins are connected to a host.
1063 cy_as_return_status_t
1064 cy_as_usb_connect(cy_as_device_handle handle,
1065 cy_as_function_callback cb,
1068 cy_as_ll_request_response *req_p , *reply_p;
1069 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1071 cy_as_device *dev_p;
1073 cy_as_log_debug_message(6, "cy_as_usb_connect called");
1075 dev_p = (cy_as_device *)handle;
1076 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1077 return CY_AS_ERROR_INVALID_HANDLE;
1079 ret = is_usb_active(dev_p);
1080 if (ret != CY_AS_ERROR_SUCCESS)
1083 if (cy_as_device_is_in_callback(dev_p))
1084 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1086 /* Create the request to send to the West Bridge device */
1087 req_p = cy_as_ll_create_request(dev_p,
1088 CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1);
1090 return CY_AS_ERROR_OUT_OF_MEMORY;
1092 /* 1 = Connect request */
1093 cy_as_ll_request_response__set_word(req_p, 0, 1);
1095 /* Reserve space for the reply, the reply
1096 * data will not exceed one word */
1097 reply_p = cy_as_ll_create_response(dev_p, 1);
1099 cy_as_ll_destroy_request(dev_p, req_p);
1100 return CY_AS_ERROR_OUT_OF_MEMORY;
1104 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1105 if (ret != CY_AS_ERROR_SUCCESS)
1108 return my_handle_response_connect(dev_p, req_p, reply_p, ret);
1110 ret = cy_as_misc_send_request(dev_p, cb, client,
1111 CY_FUNCT_CB_USB_CONNECT, 0, dev_p->func_cbs_usb,
1112 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1113 cy_as_usb_func_callback);
1115 if (ret != CY_AS_ERROR_SUCCESS)
1122 cy_as_ll_destroy_request(dev_p, req_p);
1123 cy_as_ll_destroy_response(dev_p, reply_p);
1128 static cy_as_return_status_t
1129 my_handle_response_disconnect(cy_as_device *dev_p,
1130 cy_as_ll_request_response *req_p,
1131 cy_as_ll_request_response *reply_p,
1132 cy_as_return_status_t ret)
1134 if (ret != CY_AS_ERROR_SUCCESS)
1137 if (cy_as_ll_request_response__get_code(reply_p) !=
1138 CY_RESP_SUCCESS_FAILURE) {
1139 ret = CY_AS_ERROR_INVALID_RESPONSE;
1143 ret = cy_as_ll_request_response__get_word(reply_p, 0);
1144 if (ret == CY_AS_ERROR_SUCCESS)
1145 cy_as_device_clear_usb_connected(dev_p);
1148 cy_as_ll_destroy_request(dev_p, req_p);
1149 cy_as_ll_destroy_response(dev_p, reply_p);
1154 * This method forces a disconnect of the D+ and D- pins
1155 * external to the West Bridge device from the D+ and D-
1156 * signals internally, effectively disconnecting the West
1157 * Bridge device from any connected USB host.
1159 cy_as_return_status_t
1160 cy_as_usb_disconnect(cy_as_device_handle handle,
1161 cy_as_function_callback cb,
1164 cy_as_ll_request_response *req_p , *reply_p;
1165 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1167 cy_as_device *dev_p;
1169 cy_as_log_debug_message(6, "cy_as_usb_disconnect called");
1171 dev_p = (cy_as_device *)handle;
1172 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1173 return CY_AS_ERROR_INVALID_HANDLE;
1175 ret = is_usb_active(dev_p);
1176 if (ret != CY_AS_ERROR_SUCCESS)
1179 if (cy_as_device_is_in_callback(dev_p))
1180 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1182 if (!cy_as_device_is_usb_connected(dev_p))
1183 return CY_AS_ERROR_USB_NOT_CONNECTED;
1185 /* Create the request to send to the West Bridge device */
1186 req_p = cy_as_ll_create_request(dev_p,
1187 CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1);
1189 return CY_AS_ERROR_OUT_OF_MEMORY;
1191 cy_as_ll_request_response__set_word(req_p, 0, 0);
1193 /* Reserve space for the reply, the reply
1194 * data will not exceed two bytes */
1195 reply_p = cy_as_ll_create_response(dev_p, 1);
1197 cy_as_ll_destroy_request(dev_p, req_p);
1198 return CY_AS_ERROR_OUT_OF_MEMORY;
1202 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1203 if (ret != CY_AS_ERROR_SUCCESS)
1206 return my_handle_response_disconnect(dev_p,
1207 req_p, reply_p, ret);
1209 ret = cy_as_misc_send_request(dev_p, cb, client,
1210 CY_FUNCT_CB_USB_DISCONNECT, 0, dev_p->func_cbs_usb,
1211 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1212 cy_as_usb_func_callback);
1214 if (ret != CY_AS_ERROR_SUCCESS)
1220 cy_as_ll_destroy_request(dev_p, req_p);
1221 cy_as_ll_destroy_response(dev_p, reply_p);
1226 static cy_as_return_status_t
1227 my_handle_response_set_enum_config(cy_as_device *dev_p,
1228 cy_as_ll_request_response *req_p,
1229 cy_as_ll_request_response *reply_p)
1231 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1233 if (cy_as_ll_request_response__get_code(reply_p) !=
1234 CY_RESP_SUCCESS_FAILURE) {
1235 ret = CY_AS_ERROR_INVALID_RESPONSE;
1239 ret = cy_as_ll_request_response__get_word(reply_p, 0);
1241 if (ret == CY_AS_ERROR_SUCCESS) {
1243 * we configured the west bridge device and
1244 * enumeration is going to happen on the P port
1245 * processor. now we must enable endpoint zero
1247 cy_as_usb_end_point_config config;
1249 config.dir = cy_as_usb_in_out;
1250 config.type = cy_as_usb_control;
1251 config.enabled = cy_true;
1253 ret = cy_as_usb_set_end_point_config((cy_as_device_handle *)
1258 cy_as_ll_destroy_request(dev_p, req_p);
1259 cy_as_ll_destroy_response(dev_p, reply_p);
1265 * This method sets how the USB is enumerated and should
1266 * be called before the CyAsUsbConnect() is called.
1268 static cy_as_return_status_t
1269 my_usb_set_enum_config(cy_as_device *dev_p,
1272 cy_bool use_antioch_enumeration,
1273 uint8_t mass_storage_interface,
1274 uint8_t mtp_interface,
1275 cy_bool mass_storage_callbacks,
1276 cy_as_function_callback cb,
1279 cy_as_ll_request_response *req_p , *reply_p;
1280 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1282 cy_as_log_debug_message(6, "cy_as_usb_set_enum_config called");
1284 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1285 return CY_AS_ERROR_INVALID_HANDLE;
1287 ret = is_usb_active(dev_p);
1288 if (ret != CY_AS_ERROR_SUCCESS)
1291 if (cy_as_device_is_usb_connected(dev_p))
1292 return CY_AS_ERROR_USB_CONNECTED;
1294 if (cy_as_device_is_in_callback(dev_p))
1295 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1297 /* if we are using MTP firmware: */
1298 if (dev_p->is_mtp_firmware == 1) {
1299 /* we cannot enumerate MSC */
1300 if (mass_storage_interface != 0)
1301 return CY_AS_ERROR_INVALID_CONFIGURATION;
1303 if (bus_mask == 0) {
1304 if (mtp_interface != 0)
1305 return CY_AS_ERROR_INVALID_CONFIGURATION;
1306 } else if (bus_mask == 2) {
1307 /* enable EP 1 as it will be used */
1308 cy_as_dma_enable_end_point(dev_p, 1, cy_true,
1309 cy_as_direction_in);
1310 dev_p->usb_config[1].enabled = cy_true;
1311 dev_p->usb_config[1].dir = cy_as_usb_in;
1312 dev_p->usb_config[1].type = cy_as_usb_int;
1314 return CY_AS_ERROR_INVALID_CONFIGURATION;
1316 /* if we are not using MTP firmware, we cannot enumerate MTP */
1317 } else if (mtp_interface != 0)
1318 return CY_AS_ERROR_INVALID_CONFIGURATION;
1321 * if we are not enumerating mass storage, we should
1322 * not be providing an interface number.
1324 if (bus_mask == 0 && mass_storage_interface != 0)
1325 return CY_AS_ERROR_INVALID_CONFIGURATION;
1328 * if we are going to use mtp_interface, bus mask must be 2.
1330 if (mtp_interface != 0 && bus_mask != 2)
1331 return CY_AS_ERROR_INVALID_CONFIGURATION;
1334 /* Create the request to send to the West Bridge device */
1335 req_p = cy_as_ll_create_request(dev_p,
1336 CY_RQT_SET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 4);
1338 return CY_AS_ERROR_OUT_OF_MEMORY;
1340 /* Marshal the structure */
1341 cy_as_ll_request_response__set_word(req_p, 0,
1342 (uint16_t)((media_mask << 8) | bus_mask));
1343 cy_as_ll_request_response__set_word(req_p, 1,
1344 (uint16_t)use_antioch_enumeration);
1345 cy_as_ll_request_response__set_word(req_p, 2,
1346 dev_p->is_mtp_firmware ? mtp_interface :
1347 mass_storage_interface);
1348 cy_as_ll_request_response__set_word(req_p, 3,
1349 (uint16_t)mass_storage_callbacks);
1351 /* Reserve space for the reply, the reply
1352 * data will not exceed one word */
1353 reply_p = cy_as_ll_create_response(dev_p, 1);
1355 cy_as_ll_destroy_request(dev_p, req_p);
1356 return CY_AS_ERROR_OUT_OF_MEMORY;
1361 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1362 if (ret != CY_AS_ERROR_SUCCESS)
1365 return my_handle_response_set_enum_config(dev_p,
1368 ret = cy_as_misc_send_request(dev_p, cb, client,
1369 CY_FUNCT_CB_USB_SETENUMCONFIG, 0, dev_p->func_cbs_usb,
1370 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1371 cy_as_usb_func_callback);
1373 if (ret != CY_AS_ERROR_SUCCESS)
1380 cy_as_ll_destroy_request(dev_p, req_p);
1381 cy_as_ll_destroy_response(dev_p, reply_p);
1387 * This method sets how the USB is enumerated and should
1388 * be called before the CyAsUsbConnect() is called.
1390 cy_as_return_status_t
1391 cy_as_usb_set_enum_config(cy_as_device_handle handle,
1392 cy_as_usb_enum_control *config_p,
1393 cy_as_function_callback cb,
1396 cy_as_device *dev_p = (cy_as_device *)handle;
1397 uint8_t bus_mask, media_mask;
1398 uint32_t bus, device;
1399 cy_as_return_status_t ret;
1401 dev_p = (cy_as_device *)handle;
1402 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1403 return CY_AS_ERROR_INVALID_HANDLE;
1405 ret = is_usb_active(dev_p);
1406 if (ret != CY_AS_ERROR_SUCCESS)
1409 if ((cy_as_device_is_in_callback(dev_p)) && (cb != 0))
1410 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1412 /* Since we are mapping the media types to bus with NAND to 0
1413 * and the rest to 1, and we are only allowing for enumerating
1414 * all the devices on a bus we just scan the array for any
1415 * positions where there a device is enabled and mark the bus
1420 for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
1421 for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++) {
1422 if (config_p->devices_to_enumerate[bus][device] ==
1424 bus_mask |= (0x01 << bus);
1425 media_mask |= dev_p->media_supported[bus];
1426 media_mask |= dev_p->media_supported[bus];
1431 return my_usb_set_enum_config(dev_p, bus_mask, media_mask,
1432 config_p->antioch_enumeration,
1433 config_p->mass_storage_interface,
1434 config_p->mtp_interface,
1435 config_p->mass_storage_callbacks,
1442 static cy_as_return_status_t
1443 my_handle_response_get_enum_config(cy_as_device *dev_p,
1444 cy_as_ll_request_response *req_p,
1445 cy_as_ll_request_response *reply_p,
1448 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1453 if (cy_as_ll_request_response__get_code(reply_p) !=
1454 CY_RESP_USB_CONFIG) {
1455 ret = CY_AS_ERROR_INVALID_RESPONSE;
1459 /* Marshal the reply */
1460 if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
1463 cy_as_usb_enum_control *ms_config_p =
1464 (cy_as_usb_enum_control *)config_p;
1466 bus_mask = (uint8_t)
1467 (cy_as_ll_request_response__get_word
1468 (reply_p, 0) & 0xFF);
1469 for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
1470 if (bus_mask & (1 << bus))
1475 for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES;
1477 ms_config_p->devices_to_enumerate[bus][device]
1481 ms_config_p->antioch_enumeration =
1482 (cy_bool)cy_as_ll_request_response__get_word
1485 val = cy_as_ll_request_response__get_word(reply_p, 2);
1486 if (dev_p->is_mtp_firmware) {
1487 ms_config_p->mass_storage_interface = 0;
1488 ms_config_p->mtp_interface = (uint8_t)(val & 0xFF);
1490 ms_config_p->mass_storage_interface =
1491 (uint8_t)(val & 0xFF);
1492 ms_config_p->mtp_interface = 0;
1494 ms_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
1497 * firmware returns an invalid interface number for mass storage,
1498 * if mass storage is not enabled. this needs to be converted to
1499 * zero to match the input configuration.
1501 if (bus_mask == 0) {
1502 if (dev_p->is_mtp_firmware)
1503 ms_config_p->mtp_interface = 0;
1505 ms_config_p->mass_storage_interface = 0;
1508 cy_as_usb_enum_control_dep *ex_config_p =
1509 (cy_as_usb_enum_control_dep *)config_p;
1511 ex_config_p->enum_mass_storage = (uint8_t)
1512 ((cy_as_ll_request_response__get_word
1513 (reply_p, 0) >> 8) & 0xFF);
1514 ex_config_p->antioch_enumeration = (cy_bool)
1515 cy_as_ll_request_response__get_word(reply_p, 1);
1517 val = cy_as_ll_request_response__get_word(reply_p, 2);
1518 ex_config_p->mass_storage_interface = (uint8_t)(val & 0xFF);
1519 ex_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
1522 * firmware returns an invalid interface number for mass
1523 * storage, if mass storage is not enabled. this needs to
1524 * be converted to zero to match the input configuration.
1526 if (ex_config_p->enum_mass_storage == 0)
1527 ex_config_p->mass_storage_interface = 0;
1531 cy_as_ll_destroy_request(dev_p, req_p);
1532 cy_as_ll_destroy_response(dev_p, reply_p);
1538 * This sets up the request for the enumerateion configuration
1539 * information, based on if the request is from the old pre-1.2
1542 static cy_as_return_status_t
1543 my_usb_get_enum_config(cy_as_device_handle handle,
1546 cy_as_function_callback cb,
1549 cy_as_ll_request_response *req_p , *reply_p;
1550 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1552 cy_as_device *dev_p;
1554 cy_as_log_debug_message(6, "cy_as_usb_get_enum_config called");
1556 dev_p = (cy_as_device *)handle;
1557 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1558 return CY_AS_ERROR_INVALID_HANDLE;
1560 ret = is_usb_active(dev_p);
1561 if (ret != CY_AS_ERROR_SUCCESS)
1564 if (cy_as_device_is_in_callback(dev_p))
1565 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1567 /* Create the request to send to the West Bridge device */
1568 req_p = cy_as_ll_create_request(dev_p,
1569 CY_RQT_GET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 0);
1571 return CY_AS_ERROR_OUT_OF_MEMORY;
1573 /* Reserve space for the reply, the reply data
1574 * will not exceed two bytes */
1575 reply_p = cy_as_ll_create_response(dev_p, 3);
1577 cy_as_ll_destroy_request(dev_p, req_p);
1578 return CY_AS_ERROR_OUT_OF_MEMORY;
1582 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1583 if (ret != CY_AS_ERROR_SUCCESS)
1586 /* we need to know the type of request to
1587 * know how to manage the data */
1588 req_p->flags |= req_flags;
1589 return my_handle_response_get_enum_config(dev_p,
1590 req_p, reply_p, config_p);
1592 ret = cy_as_misc_send_request(dev_p, cb, client,
1593 CY_FUNCT_CB_USB_GETENUMCONFIG, config_p,
1594 dev_p->func_cbs_usb, req_flags, req_p, reply_p,
1595 cy_as_usb_func_callback);
1597 if (ret != CY_AS_ERROR_SUCCESS)
1604 cy_as_ll_destroy_request(dev_p, req_p);
1605 cy_as_ll_destroy_response(dev_p, reply_p);
1611 * This method returns the enumerateion configuration information
1612 * from the West Bridge device. Generally this is not used by
1613 * client software but is provided mostly for debug information.
1614 * We want a method to read all state information from the device.
1616 cy_as_return_status_t
1617 cy_as_usb_get_enum_config(cy_as_device_handle handle,
1618 cy_as_usb_enum_control *config_p,
1619 cy_as_function_callback cb,
1622 return my_usb_get_enum_config(handle,
1623 CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client);
1628 * This method sets the USB descriptor for a given entity.
1630 cy_as_return_status_t
1631 cy_as_usb_set_descriptor(cy_as_device_handle handle,
1632 cy_as_usb_desc_type type,
1636 cy_as_function_callback cb,
1639 cy_as_ll_request_response *req_p , *reply_p;
1640 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1643 cy_as_device *dev_p;
1645 cy_as_log_debug_message(6, "cy_as_usb_set_descriptor called");
1647 dev_p = (cy_as_device *)handle;
1648 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1649 return CY_AS_ERROR_INVALID_HANDLE;
1651 ret = is_usb_active(dev_p);
1652 if (ret != CY_AS_ERROR_SUCCESS)
1655 if (cy_as_device_is_in_callback(dev_p))
1656 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1658 if (length > CY_AS_MAX_USB_DESCRIPTOR_SIZE)
1659 return CY_AS_ERROR_INVALID_DESCRIPTOR;
1661 pktlen = (uint16_t)length / 2;
1664 pktlen += 2; /* 1 for type, 1 for length */
1666 /* Create the request to send to the West Bridge device */
1667 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_DESCRIPTOR,
1668 CY_RQT_USB_RQT_CONTEXT, (uint16_t)pktlen);
1670 return CY_AS_ERROR_OUT_OF_MEMORY;
1672 cy_as_ll_request_response__set_word(req_p, 0,
1673 (uint16_t)((uint8_t)type | (index << 8)));
1674 cy_as_ll_request_response__set_word(req_p, 1,
1676 cy_as_ll_request_response__pack(req_p, 2, length, desc_p);
1678 reply_p = cy_as_ll_create_response(dev_p, 1);
1680 cy_as_ll_destroy_request(dev_p, req_p);
1681 return CY_AS_ERROR_OUT_OF_MEMORY;
1685 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1686 if (ret != CY_AS_ERROR_SUCCESS)
1689 return my_handle_response_no_data(dev_p, req_p, reply_p);
1691 ret = cy_as_misc_send_request(dev_p, cb, client,
1692 CY_FUNCT_CB_USB_SETDESCRIPTOR, 0, dev_p->func_cbs_usb,
1693 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1694 cy_as_usb_func_callback);
1696 if (ret != CY_AS_ERROR_SUCCESS)
1703 cy_as_ll_destroy_request(dev_p, req_p);
1704 cy_as_ll_destroy_response(dev_p, reply_p);
1710 * This method clears all descriptors that were previously
1711 * stored on the West Bridge through CyAsUsbSetDescriptor calls.
1713 cy_as_return_status_t
1714 cy_as_usb_clear_descriptors(cy_as_device_handle handle,
1715 cy_as_function_callback cb,
1718 cy_as_ll_request_response *req_p , *reply_p;
1719 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1721 cy_as_device *dev_p;
1723 cy_as_log_debug_message(6, "cy_as_usb_clear_descriptors called");
1725 dev_p = (cy_as_device *)handle;
1726 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1727 return CY_AS_ERROR_INVALID_HANDLE;
1729 ret = is_usb_active(dev_p);
1730 if (ret != CY_AS_ERROR_SUCCESS)
1733 if ((cy_as_device_is_in_callback(dev_p)) && (cb == 0))
1734 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1736 /* Create the request to send to the West Bridge device */
1737 req_p = cy_as_ll_create_request(dev_p,
1738 CY_RQT_CLEAR_DESCRIPTORS, CY_RQT_USB_RQT_CONTEXT, 1);
1740 return CY_AS_ERROR_OUT_OF_MEMORY;
1742 reply_p = cy_as_ll_create_response(dev_p, 1);
1744 cy_as_ll_destroy_request(dev_p, req_p);
1745 return CY_AS_ERROR_OUT_OF_MEMORY;
1750 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1751 if (ret != CY_AS_ERROR_SUCCESS)
1754 return my_handle_response_no_data(dev_p, req_p, reply_p);
1756 ret = cy_as_misc_send_request(dev_p, cb, client,
1757 CY_FUNCT_CB_USB_CLEARDESCRIPTORS, 0,
1758 dev_p->func_cbs_usb,
1759 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1760 cy_as_usb_func_callback);
1762 if (ret != CY_AS_ERROR_SUCCESS)
1769 cy_as_ll_destroy_request(dev_p, req_p);
1770 cy_as_ll_destroy_response(dev_p, reply_p);
1775 static cy_as_return_status_t
1776 my_handle_response_get_descriptor(cy_as_device *dev_p,
1777 cy_as_ll_request_response *req_p,
1778 cy_as_ll_request_response *reply_p,
1779 cy_as_get_descriptor_data *data)
1781 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1784 if (cy_as_ll_request_response__get_code(reply_p) ==
1785 CY_RESP_SUCCESS_FAILURE) {
1786 ret = cy_as_ll_request_response__get_word(reply_p, 0);
1788 } else if (cy_as_ll_request_response__get_code(reply_p) !=
1789 CY_RESP_USB_DESCRIPTOR) {
1790 ret = CY_AS_ERROR_INVALID_RESPONSE;
1794 retlen = cy_as_ll_request_response__get_word(reply_p, 0);
1795 if (retlen > data->length) {
1796 ret = CY_AS_ERROR_INVALID_SIZE;
1800 ret = CY_AS_ERROR_SUCCESS;
1801 cy_as_ll_request_response__unpack(reply_p, 1,
1802 retlen, data->desc_p);
1805 cy_as_ll_destroy_request(dev_p, req_p);
1806 cy_as_ll_destroy_response(dev_p, reply_p);
1812 * This method retreives the USB descriptor for a given type.
1814 cy_as_return_status_t
1815 cy_as_usb_get_descriptor(cy_as_device_handle handle,
1816 cy_as_usb_desc_type type,
1818 cy_as_get_descriptor_data *data,
1819 cy_as_function_callback cb,
1822 cy_as_return_status_t ret;
1823 cy_as_ll_request_response *req_p , *reply_p;
1825 cy_as_device *dev_p;
1827 cy_as_log_debug_message(6, "cy_as_usb_get_descriptor called");
1829 dev_p = (cy_as_device *)handle;
1830 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1831 return CY_AS_ERROR_INVALID_HANDLE;
1833 ret = is_usb_active(dev_p);
1834 if (ret != CY_AS_ERROR_SUCCESS)
1837 if (cy_as_device_is_in_callback(dev_p))
1838 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1840 /* Create the request to send to the West Bridge device */
1841 req_p = cy_as_ll_create_request(dev_p,
1842 CY_RQT_GET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, 1);
1844 return CY_AS_ERROR_OUT_OF_MEMORY;
1846 cy_as_ll_request_response__set_word(req_p, 0,
1847 (uint16_t)((uint8_t)type | (index << 8)));
1849 /* Add one for the length field */
1850 reply_p = cy_as_ll_create_response(dev_p,
1851 CY_AS_MAX_USB_DESCRIPTOR_SIZE + 1);
1853 cy_as_ll_destroy_request(dev_p, req_p);
1854 return CY_AS_ERROR_OUT_OF_MEMORY;
1858 ret = cy_as_ll_send_request_wait_reply(
1859 dev_p, req_p, reply_p);
1860 if (ret != CY_AS_ERROR_SUCCESS)
1863 return my_handle_response_get_descriptor(dev_p,
1864 req_p, reply_p, data);
1866 ret = cy_as_misc_send_request(dev_p, cb, client,
1867 CY_FUNCT_CB_USB_GETDESCRIPTOR, data,
1868 dev_p->func_cbs_usb,
1869 CY_AS_REQUEST_RESPONSE_EX, req_p,
1870 reply_p, cy_as_usb_func_callback);
1872 if (ret != CY_AS_ERROR_SUCCESS)
1879 cy_as_ll_destroy_request(dev_p, req_p);
1880 cy_as_ll_destroy_response(dev_p, reply_p);
1885 cy_as_return_status_t
1886 cy_as_usb_set_physical_configuration(cy_as_device_handle handle,
1889 cy_as_return_status_t ret;
1890 cy_as_device *dev_p;
1892 cy_as_log_debug_message(6,
1893 "cy_as_usb_set_physical_configuration called");
1895 dev_p = (cy_as_device *)handle;
1896 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1897 return CY_AS_ERROR_INVALID_HANDLE;
1899 ret = is_usb_active(dev_p);
1900 if (ret != CY_AS_ERROR_SUCCESS)
1903 if (cy_as_device_is_usb_connected(dev_p))
1904 return CY_AS_ERROR_USB_CONNECTED;
1906 if (config < 1 || config > 12)
1907 return CY_AS_ERROR_INVALID_CONFIGURATION;
1909 dev_p->usb_phy_config = config;
1911 return CY_AS_ERROR_SUCCESS;
1915 is_physical_valid(uint8_t config, cy_as_end_point_number_t ep)
1917 static uint8_t validmask[12] = {
1918 0x0f, /* Config 1 - 1, 2, 3, 4 */
1919 0x07, /* Config 2 - 1, 2, 3 */
1920 0x07, /* Config 3 - 1, 2, 3 */
1921 0x0d, /* Config 4 - 1, 3, 4 */
1922 0x05, /* Config 5 - 1, 3 */
1923 0x05, /* Config 6 - 1, 3 */
1924 0x0d, /* Config 7 - 1, 3, 4 */
1925 0x05, /* Config 8 - 1, 3 */
1926 0x05, /* Config 9 - 1, 3 */
1927 0x0d, /* Config 10 - 1, 3, 4 */
1928 0x09, /* Config 11 - 1, 4 */
1929 0x01 /* Config 12 - 1 */
1932 return (validmask[config - 1] & (1 << (ep - 1))) ? cy_true : cy_false;
1936 * This method sets the configuration for an endpoint
1938 cy_as_return_status_t
1939 cy_as_usb_set_end_point_config(cy_as_device_handle handle,
1940 cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
1942 cy_as_return_status_t ret;
1943 cy_as_device *dev_p;
1945 cy_as_log_debug_message(6, "cy_as_usb_set_end_point_config called");
1947 dev_p = (cy_as_device *)handle;
1948 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1949 return CY_AS_ERROR_INVALID_HANDLE;
1951 ret = is_usb_active(dev_p);
1952 if (ret != CY_AS_ERROR_SUCCESS)
1955 if (cy_as_device_is_usb_connected(dev_p))
1956 return CY_AS_ERROR_USB_CONNECTED;
1958 if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
1959 return CY_AS_ERROR_INVALID_ENDPOINT;
1962 /* Endpoint 0 must be 64 byte, dir IN/OUT,
1963 * and control type */
1964 if (config_p->dir != cy_as_usb_in_out ||
1965 config_p->type != cy_as_usb_control)
1966 return CY_AS_ERROR_INVALID_CONFIGURATION;
1967 } else if (ep == 1) {
1968 if ((dev_p->is_mtp_firmware == 1) &&
1969 (dev_p->usb_config[1].enabled == cy_true)) {
1970 return CY_AS_ERROR_INVALID_ENDPOINT;
1974 * EP1 can only be used either as an OUT ep, or as an IN ep.
1976 if ((config_p->type == cy_as_usb_control) ||
1977 (config_p->type == cy_as_usb_iso) ||
1978 (config_p->dir == cy_as_usb_in_out))
1979 return CY_AS_ERROR_INVALID_CONFIGURATION;
1981 if (config_p->dir == cy_as_usb_in_out ||
1982 config_p->type == cy_as_usb_control)
1983 return CY_AS_ERROR_INVALID_CONFIGURATION;
1985 if (!is_physical_valid(dev_p->usb_phy_config,
1986 config_p->physical))
1987 return CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT;
1990 * ISO endpoints must be on E_ps 3, 5, 7 or 9 as
1991 * they need to align directly with the underlying
1992 * physical endpoint.
1994 if (config_p->type == cy_as_usb_iso) {
1995 if (ep != 3 && ep != 5 && ep != 7 && ep != 9)
1996 return CY_AS_ERROR_INVALID_CONFIGURATION;
1998 if (ep == 3 && config_p->physical != 1)
1999 return CY_AS_ERROR_INVALID_CONFIGURATION;
2001 if (ep == 5 && config_p->physical != 2)
2002 return CY_AS_ERROR_INVALID_CONFIGURATION;
2004 if (ep == 7 && config_p->physical != 3)
2005 return CY_AS_ERROR_INVALID_CONFIGURATION;
2007 if (ep == 9 && config_p->physical != 4)
2008 return CY_AS_ERROR_INVALID_CONFIGURATION;
2012 /* Store the configuration information until a
2013 * CyAsUsbCommitConfig is done */
2014 dev_p->usb_config[ep] = *config_p;
2016 /* If the endpoint is enabled, enable DMA associated
2017 * with the endpoint */
2019 * we make some assumptions that we check here. we assume
2020 * that the direction fields for the DMA module are the same
2021 * values as the direction values for the USB module.
2023 cy_as_hal_assert((int)cy_as_usb_in == (int)cy_as_direction_in);
2024 cy_as_hal_assert((int)cy_as_usb_out == (int)cy_as_direction_out);
2025 cy_as_hal_assert((int)cy_as_usb_in_out == (int)cy_as_direction_in_out);
2027 return cy_as_dma_enable_end_point(dev_p, ep,
2028 config_p->enabled, (cy_as_dma_direction)config_p->dir);
2031 cy_as_return_status_t
2032 cy_as_usb_get_end_point_config(cy_as_device_handle handle,
2033 cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
2035 cy_as_return_status_t ret;
2037 cy_as_device *dev_p;
2039 cy_as_log_debug_message(6, "cy_as_usb_get_end_point_config called");
2041 dev_p = (cy_as_device *)handle;
2042 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2043 return CY_AS_ERROR_INVALID_HANDLE;
2045 ret = is_usb_active(dev_p);
2046 if (ret != CY_AS_ERROR_SUCCESS)
2049 if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
2050 return CY_AS_ERROR_INVALID_ENDPOINT;
2052 *config_p = dev_p->usb_config[ep];
2054 return CY_AS_ERROR_SUCCESS;
2058 * Commit the configuration of the various endpoints to the hardware.
2060 cy_as_return_status_t
2061 cy_as_usb_commit_config(cy_as_device_handle handle,
2062 cy_as_function_callback cb,
2066 cy_as_return_status_t ret;
2067 cy_as_ll_request_response *req_p , *reply_p;
2068 cy_as_device *dev_p;
2071 cy_as_log_debug_message(6, "cy_as_usb_commit_config called");
2073 dev_p = (cy_as_device *)handle;
2074 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2075 return CY_AS_ERROR_INVALID_HANDLE;
2077 ret = is_usb_active(dev_p);
2078 if (ret != CY_AS_ERROR_SUCCESS)
2081 if (cy_as_device_is_usb_connected(dev_p))
2082 return CY_AS_ERROR_USB_CONNECTED;
2084 if (cy_as_device_is_in_callback(dev_p))
2085 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2088 * this performs the mapping based on informatation that was
2089 * previously stored on the device about the various endpoints
2090 * and how they are configured. the output of this mapping is
2091 * setting the the 14 register values contained in usb_lepcfg
2094 ret = cy_as_usb_map_logical2_physical(dev_p);
2095 if (ret != CY_AS_ERROR_SUCCESS)
2099 * now, package the information about the various logical and
2100 * physical endpoint configuration registers and send it
2101 * across to the west bridge device.
2103 req_p = cy_as_ll_create_request(dev_p,
2104 CY_RQT_SET_USB_CONFIG_REGISTERS, CY_RQT_USB_RQT_CONTEXT, 8);
2106 return CY_AS_ERROR_OUT_OF_MEMORY;
2108 cy_as_hal_print_message("USB configuration: %d\n",
2109 dev_p->usb_phy_config);
2110 cy_as_hal_print_message("EP1OUT: 0x%02x EP1IN: 0x%02x\n",
2111 dev_p->usb_ep1cfg[0], dev_p->usb_ep1cfg[1]);
2112 cy_as_hal_print_message("PEP registers: 0x%02x 0x%02x 0x%02x 0x%02x\n",
2113 dev_p->usb_pepcfg[0], dev_p->usb_pepcfg[1],
2114 dev_p->usb_pepcfg[2], dev_p->usb_pepcfg[3]);
2116 cy_as_hal_print_message("LEP registers: 0x%02x 0x%02x 0x%02x "
2117 "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
2118 dev_p->usb_lepcfg[0], dev_p->usb_lepcfg[1],
2119 dev_p->usb_lepcfg[2], dev_p->usb_lepcfg[3],
2120 dev_p->usb_lepcfg[4], dev_p->usb_lepcfg[5],
2121 dev_p->usb_lepcfg[6], dev_p->usb_lepcfg[7],
2122 dev_p->usb_lepcfg[8], dev_p->usb_lepcfg[9]);
2124 /* Write the EP1OUTCFG and EP1INCFG data in the first word. */
2125 data = (uint16_t)((dev_p->usb_ep1cfg[0] << 8) |
2126 dev_p->usb_ep1cfg[1]);
2127 cy_as_ll_request_response__set_word(req_p, 0, data);
2129 /* Write the PEP CFG data in the next 2 words */
2130 for (i = 0; i < 4; i += 2) {
2131 data = (uint16_t)((dev_p->usb_pepcfg[i] << 8) |
2132 dev_p->usb_pepcfg[i + 1]);
2133 cy_as_ll_request_response__set_word(req_p,
2137 /* Write the LEP CFG data in the next 5 words */
2138 for (i = 0; i < 10; i += 2) {
2139 data = (uint16_t)((dev_p->usb_lepcfg[i] << 8) |
2140 dev_p->usb_lepcfg[i + 1]);
2141 cy_as_ll_request_response__set_word(req_p,
2145 /* A single status word response type */
2146 reply_p = cy_as_ll_create_response(dev_p, 1);
2148 cy_as_ll_destroy_request(dev_p, req_p);
2149 return CY_AS_ERROR_OUT_OF_MEMORY;
2153 ret = cy_as_ll_send_request_wait_reply(dev_p,
2155 if (ret != CY_AS_ERROR_SUCCESS)
2158 ret = my_handle_response_no_data(dev_p,
2161 if (ret == CY_AS_ERROR_SUCCESS)
2162 ret = cy_as_usb_setup_dma(dev_p);
2166 ret = cy_as_misc_send_request(dev_p, cb, client,
2167 CY_FUNCT_CB_USB_COMMITCONFIG, 0, dev_p->func_cbs_usb,
2168 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
2169 cy_as_usb_func_callback);
2171 if (ret != CY_AS_ERROR_SUCCESS)
2178 cy_as_ll_destroy_request(dev_p, req_p);
2179 cy_as_ll_destroy_response(dev_p, reply_p);
2185 sync_request_callback(cy_as_device *dev_p,
2186 cy_as_end_point_number_t ep, void *buf_p,
2187 uint32_t size, cy_as_return_status_t err)
2192 dev_p->usb_error = err;
2193 dev_p->usb_actual_cnt = size;
2197 async_read_request_callback(cy_as_device *dev_p,
2198 cy_as_end_point_number_t ep, void *buf_p,
2199 uint32_t size, cy_as_return_status_t err)
2201 cy_as_device_handle h;
2203 cy_as_log_debug_message(6,
2204 "async_read_request_callback called");
2206 h = (cy_as_device_handle)dev_p;
2208 if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
2209 dev_p->usb_pending_buffer = buf_p;
2210 dev_p->usb_pending_size = size;
2211 dev_p->usb_error = err;
2212 cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
2214 cy_as_usb_io_callback cb;
2216 cb = dev_p->usb_cb[ep];
2217 dev_p->usb_cb[ep] = 0;
2218 cy_as_device_clear_usb_async_pending(dev_p, ep);
2220 cb(h, ep, size, buf_p, err);
2225 async_write_request_callback(cy_as_device *dev_p,
2226 cy_as_end_point_number_t ep, void *buf_p,
2227 uint32_t size, cy_as_return_status_t err)
2229 cy_as_device_handle h;
2231 cy_as_log_debug_message(6,
2232 "async_write_request_callback called");
2234 h = (cy_as_device_handle)dev_p;
2236 if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
2237 dev_p->usb_pending_buffer = buf_p;
2238 dev_p->usb_pending_size = size;
2239 dev_p->usb_error = err;
2241 /* The west bridge protocol generates ZLPs as required. */
2242 cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
2244 cy_as_usb_io_callback cb;
2246 cb = dev_p->usb_cb[ep];
2247 dev_p->usb_cb[ep] = 0;
2249 cy_as_device_clear_usb_async_pending(dev_p, ep);
2251 cb(h, ep, size, buf_p, err);
2256 my_turbo_rqt_callback(cy_as_device *dev_p,
2258 cy_as_ll_request_response *rqt,
2259 cy_as_ll_request_response *resp,
2260 cy_as_return_status_t stat)
2267 /* The Handlers are responsible for Deleting the rqt and resp when
2270 code = cy_as_ll_request_response__get_code(rqt);
2272 case CY_RQT_TURBO_SWITCH_ENDPOINT:
2273 cy_as_hal_assert(stat == CY_AS_ERROR_SUCCESS);
2274 cy_as_ll_destroy_request(dev_p, rqt);
2275 cy_as_ll_destroy_response(dev_p, resp);
2278 cy_as_hal_assert(cy_false);
2283 /* Send a mailbox request to prepare the endpoint for switching */
2284 static cy_as_return_status_t
2285 my_send_turbo_switch(cy_as_device *dev_p, uint32_t size, cy_bool pktread)
2287 cy_as_return_status_t ret;
2288 cy_as_ll_request_response *req_p , *reply_p;
2290 /* Create the request to send to the West Bridge device */
2291 req_p = cy_as_ll_create_request(dev_p,
2292 CY_RQT_TURBO_SWITCH_ENDPOINT, CY_RQT_TUR_RQT_CONTEXT, 3);
2294 return CY_AS_ERROR_OUT_OF_MEMORY;
2296 /* Reserve space for the reply, the reply data will
2297 * not exceed one word */
2298 reply_p = cy_as_ll_create_response(dev_p, 1);
2300 cy_as_ll_destroy_request(dev_p, req_p);
2301 return CY_AS_ERROR_OUT_OF_MEMORY;
2304 cy_as_ll_request_response__set_word(req_p, 0,
2306 cy_as_ll_request_response__set_word(req_p, 1,
2307 (uint16_t)((size >> 16) & 0xFFFF));
2308 cy_as_ll_request_response__set_word(req_p, 2,
2309 (uint16_t)(size & 0xFFFF));
2311 ret = cy_as_ll_send_request(dev_p, req_p,
2312 reply_p, cy_false, my_turbo_rqt_callback);
2313 if (ret != CY_AS_ERROR_SUCCESS) {
2314 cy_as_ll_destroy_request(dev_p, req_p);
2315 cy_as_ll_destroy_request(dev_p, reply_p);
2319 return CY_AS_ERROR_SUCCESS;
2322 cy_as_return_status_t
2323 cy_as_usb_read_data(cy_as_device_handle handle,
2324 cy_as_end_point_number_t ep, cy_bool pktread,
2325 uint32_t dsize, uint32_t *dataread, void *data)
2327 cy_as_return_status_t ret;
2328 cy_as_device *dev_p;
2330 cy_as_log_debug_message(6, "cy_as_usb_read_data called");
2332 dev_p = (cy_as_device *)handle;
2333 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2334 return CY_AS_ERROR_INVALID_HANDLE;
2336 ret = is_usb_active(dev_p);
2337 if (ret != CY_AS_ERROR_SUCCESS)
2340 if (cy_as_device_is_in_callback(dev_p))
2341 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2343 if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
2344 return CY_AS_ERROR_INVALID_ENDPOINT;
2346 /* EP2 is available for reading when MTP is active */
2347 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
2348 return CY_AS_ERROR_INVALID_ENDPOINT;
2350 /* If the endpoint is disabled, we cannot
2351 * write data to the endpoint */
2352 if (!dev_p->usb_config[ep].enabled)
2353 return CY_AS_ERROR_ENDPOINT_DISABLED;
2355 if (dev_p->usb_config[ep].dir != cy_as_usb_out)
2356 return CY_AS_ERROR_USB_BAD_DIRECTION;
2358 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2359 pktread, cy_true, sync_request_callback);
2360 if (ret != CY_AS_ERROR_SUCCESS)
2363 if (ep == CY_AS_MTP_READ_ENDPOINT) {
2364 ret = my_send_turbo_switch(dev_p, dsize, pktread);
2365 if (ret != CY_AS_ERROR_SUCCESS) {
2366 cy_as_dma_cancel(dev_p, ep, ret);
2370 ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
2371 if (ret != CY_AS_ERROR_SUCCESS)
2374 ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
2375 if (ret != CY_AS_ERROR_SUCCESS)
2379 ret = dev_p->usb_error;
2380 *dataread = dev_p->usb_actual_cnt;
2385 cy_as_return_status_t
2386 cy_as_usb_read_data_async(cy_as_device_handle handle,
2387 cy_as_end_point_number_t ep, cy_bool pktread,
2388 uint32_t dsize, void *data, cy_as_usb_io_callback cb)
2390 cy_as_return_status_t ret;
2392 cy_as_device *dev_p;
2394 cy_as_log_debug_message(6, "cy_as_usb_read_data_async called");
2396 dev_p = (cy_as_device *)handle;
2397 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2398 return CY_AS_ERROR_INVALID_HANDLE;
2400 ret = is_usb_active(dev_p);
2401 if (ret != CY_AS_ERROR_SUCCESS)
2404 if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
2405 return CY_AS_ERROR_INVALID_ENDPOINT;
2407 /* EP2 is available for reading when MTP is active */
2408 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
2409 return CY_AS_ERROR_INVALID_ENDPOINT;
2411 /* If the endpoint is disabled, we cannot
2412 * write data to the endpoint */
2413 if (!dev_p->usb_config[ep].enabled)
2414 return CY_AS_ERROR_ENDPOINT_DISABLED;
2416 if (dev_p->usb_config[ep].dir != cy_as_usb_out &&
2417 dev_p->usb_config[ep].dir != cy_as_usb_in_out)
2418 return CY_AS_ERROR_USB_BAD_DIRECTION;
2421 * since async operations can be triggered by interrupt
2422 * code, we must insure that we do not get multiple async
2423 * operations going at one time and protect this test and
2424 * set operation from interrupts.
2426 mask = cy_as_hal_disable_interrupts();
2427 if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
2428 cy_as_hal_enable_interrupts(mask);
2429 return CY_AS_ERROR_ASYNC_PENDING;
2431 cy_as_device_set_usb_async_pending(dev_p, ep);
2434 * if this is for EP0, we set this bit to delay the
2435 * ACK response until after this read has completed.
2438 cy_as_device_set_ack_delayed(dev_p);
2440 cy_as_hal_enable_interrupts(mask);
2442 cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
2443 dev_p->usb_cb[ep] = cb;
2445 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2446 pktread, cy_true, async_read_request_callback);
2447 if (ret != CY_AS_ERROR_SUCCESS)
2450 if (ep == CY_AS_MTP_READ_ENDPOINT) {
2451 ret = my_send_turbo_switch(dev_p, dsize, pktread);
2452 if (ret != CY_AS_ERROR_SUCCESS) {
2453 cy_as_dma_cancel(dev_p, ep, ret);
2457 /* Kick start the queue if it is not running */
2458 cy_as_dma_kick_start(dev_p, ep);
2463 cy_as_return_status_t
2464 cy_as_usb_write_data(cy_as_device_handle handle,
2465 cy_as_end_point_number_t ep, uint32_t dsize, void *data)
2467 cy_as_return_status_t ret;
2468 cy_as_device *dev_p;
2470 cy_as_log_debug_message(6, "cy_as_usb_write_data called");
2472 dev_p = (cy_as_device *)handle;
2473 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2474 return CY_AS_ERROR_INVALID_HANDLE;
2476 ret = is_usb_active(dev_p);
2477 if (ret != CY_AS_ERROR_SUCCESS)
2480 if (cy_as_device_is_in_callback(dev_p))
2481 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2483 if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
2484 return CY_AS_ERROR_INVALID_ENDPOINT;
2486 /* EP6 is available for writing when MTP is active */
2487 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
2488 return CY_AS_ERROR_INVALID_ENDPOINT;
2490 /* If the endpoint is disabled, we cannot
2491 * write data to the endpoint */
2492 if (!dev_p->usb_config[ep].enabled)
2493 return CY_AS_ERROR_ENDPOINT_DISABLED;
2495 if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
2496 dev_p->usb_config[ep].dir != cy_as_usb_in_out)
2497 return CY_AS_ERROR_USB_BAD_DIRECTION;
2499 /* Write on Turbo endpoint */
2500 if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
2501 cy_as_ll_request_response *req_p, *reply_p;
2503 req_p = cy_as_ll_create_request(dev_p,
2504 CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
2505 CY_RQT_TUR_RQT_CONTEXT, 3);
2507 return CY_AS_ERROR_OUT_OF_MEMORY;
2509 cy_as_ll_request_response__set_word(req_p,
2510 0, 0x0006); /* EP number to use. */
2511 cy_as_ll_request_response__set_word(req_p,
2512 1, (uint16_t)((dsize >> 16) & 0xFFFF));
2513 cy_as_ll_request_response__set_word(req_p,
2514 2, (uint16_t)(dsize & 0xFFFF));
2516 /* Reserve space for the reply, the reply data
2517 * will not exceed one word */
2518 reply_p = cy_as_ll_create_response(dev_p, 1);
2520 cy_as_ll_destroy_request(dev_p, req_p);
2521 return CY_AS_ERROR_OUT_OF_MEMORY;
2525 ret = cy_as_dma_queue_request(dev_p,
2526 ep, data, dsize, cy_false,
2527 cy_false, sync_request_callback);
2528 if (ret != CY_AS_ERROR_SUCCESS)
2532 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2533 if (ret == CY_AS_ERROR_SUCCESS) {
2534 if (cy_as_ll_request_response__get_code(reply_p) !=
2535 CY_RESP_SUCCESS_FAILURE)
2536 ret = CY_AS_ERROR_INVALID_RESPONSE;
2538 ret = cy_as_ll_request_response__get_word
2542 cy_as_ll_destroy_request(dev_p, req_p);
2543 cy_as_ll_destroy_response(dev_p, reply_p);
2545 if (ret != CY_AS_ERROR_SUCCESS) {
2547 cy_as_dma_cancel(dev_p, ep, ret);
2551 /* If this is a zero-byte write, firmware will
2552 * handle it. there is no need to do any work here.
2555 return CY_AS_ERROR_SUCCESS;
2557 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2558 cy_false, cy_false, sync_request_callback);
2559 if (ret != CY_AS_ERROR_SUCCESS)
2563 if (ep != CY_AS_MTP_WRITE_ENDPOINT)
2564 ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
2566 ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
2568 if (ret != CY_AS_ERROR_SUCCESS)
2571 ret = dev_p->usb_error;
2577 cy_as_device *dev_p,
2579 cy_as_ll_request_response *rqt,
2580 cy_as_ll_request_response *resp,
2581 cy_as_return_status_t ret)
2583 cy_as_usb_io_callback cb;
2584 cy_as_device_handle h = (cy_as_device_handle)dev_p;
2586 cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
2588 if (ret == CY_AS_ERROR_SUCCESS) {
2589 if (cy_as_ll_request_response__get_code(resp) !=
2590 CY_RESP_SUCCESS_FAILURE)
2591 ret = CY_AS_ERROR_INVALID_RESPONSE;
2593 ret = cy_as_ll_request_response__get_word(resp, 0);
2596 /* If this was a zero byte transfer request, we can
2597 * call the callback from here. */
2598 if ((cy_as_ll_request_response__get_word(rqt, 1) == 0) &&
2599 (cy_as_ll_request_response__get_word(rqt, 2) == 0)) {
2600 cb = dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT];
2601 dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] = 0;
2602 cy_as_device_clear_usb_async_pending(dev_p,
2603 CY_AS_MTP_WRITE_ENDPOINT);
2605 cb(h, CY_AS_MTP_WRITE_ENDPOINT, 0, 0, ret);
2610 if (ret != CY_AS_ERROR_SUCCESS) {
2611 /* Firmware failed the request. Cancel the DMA transfer. */
2612 cy_as_dma_cancel(dev_p, 0x06, CY_AS_ERROR_CANCELED);
2613 dev_p->usb_cb[0x06] = 0;
2614 cy_as_device_clear_usb_async_pending(dev_p, 0x06);
2618 cy_as_ll_destroy_response(dev_p, resp);
2619 cy_as_ll_destroy_request(dev_p, rqt);
2622 cy_as_return_status_t
2623 cy_as_usb_write_data_async(cy_as_device_handle handle,
2624 cy_as_end_point_number_t ep, uint32_t dsize, void *data,
2625 cy_bool spacket, cy_as_usb_io_callback cb)
2628 cy_as_return_status_t ret;
2629 cy_as_device *dev_p;
2631 cy_as_log_debug_message(6, "cy_as_usb_write_data_async called");
2633 dev_p = (cy_as_device *)handle;
2634 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2635 return CY_AS_ERROR_INVALID_HANDLE;
2637 ret = is_usb_active(dev_p);
2638 if (ret != CY_AS_ERROR_SUCCESS)
2641 if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
2642 return CY_AS_ERROR_INVALID_ENDPOINT;
2644 /* EP6 is available for writing when MTP is active */
2645 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
2646 return CY_AS_ERROR_INVALID_ENDPOINT;
2648 /* If the endpoint is disabled, we cannot
2649 * write data to the endpoint */
2650 if (!dev_p->usb_config[ep].enabled)
2651 return CY_AS_ERROR_ENDPOINT_DISABLED;
2653 if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
2654 dev_p->usb_config[ep].dir != cy_as_usb_in_out)
2655 return CY_AS_ERROR_USB_BAD_DIRECTION;
2658 * since async operations can be triggered by interrupt
2659 * code, we must insure that we do not get multiple
2660 * async operations going at one time and
2661 * protect this test and set operation from interrupts.
2663 mask = cy_as_hal_disable_interrupts();
2664 if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
2665 cy_as_hal_enable_interrupts(mask);
2666 return CY_AS_ERROR_ASYNC_PENDING;
2669 cy_as_device_set_usb_async_pending(dev_p, ep);
2672 cy_as_device_set_ack_delayed(dev_p);
2674 cy_as_hal_enable_interrupts(mask);
2676 cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
2677 dev_p->usb_cb[ep] = cb;
2678 dev_p->usb_spacket[ep] = spacket;
2680 /* Write on Turbo endpoint */
2681 if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
2682 cy_as_ll_request_response *req_p, *reply_p;
2684 req_p = cy_as_ll_create_request(dev_p,
2685 CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
2686 CY_RQT_TUR_RQT_CONTEXT, 3);
2689 return CY_AS_ERROR_OUT_OF_MEMORY;
2691 cy_as_ll_request_response__set_word(req_p, 0,
2692 0x0006); /* EP number to use. */
2693 cy_as_ll_request_response__set_word(req_p, 1,
2694 (uint16_t)((dsize >> 16) & 0xFFFF));
2695 cy_as_ll_request_response__set_word(req_p, 2,
2696 (uint16_t)(dsize & 0xFFFF));
2698 /* Reserve space for the reply, the reply data
2699 * will not exceed one word */
2700 reply_p = cy_as_ll_create_response(dev_p, 1);
2702 cy_as_ll_destroy_request(dev_p, req_p);
2703 return CY_AS_ERROR_OUT_OF_MEMORY;
2707 ret = cy_as_dma_queue_request(dev_p, ep, data,
2708 dsize, cy_false, cy_false,
2709 async_write_request_callback);
2710 if (ret != CY_AS_ERROR_SUCCESS)
2714 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
2715 cy_false, mtp_write_callback);
2716 if (ret != CY_AS_ERROR_SUCCESS) {
2718 cy_as_dma_cancel(dev_p, ep, ret);
2722 /* Firmware will handle a zero byte transfer
2723 * without any DMA transfers. */
2725 return CY_AS_ERROR_SUCCESS;
2727 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2728 cy_false, cy_false, async_write_request_callback);
2729 if (ret != CY_AS_ERROR_SUCCESS)
2733 /* Kick start the queue if it is not running */
2734 if (ep != CY_AS_MTP_WRITE_ENDPOINT)
2735 cy_as_dma_kick_start(dev_p, ep);
2737 return CY_AS_ERROR_SUCCESS;
2741 my_usb_cancel_async_callback(
2742 cy_as_device *dev_p,
2744 cy_as_ll_request_response *rqt,
2745 cy_as_ll_request_response *resp,
2746 cy_as_return_status_t ret)
2751 ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
2752 if (ret == CY_AS_ERROR_SUCCESS) {
2753 if (cy_as_ll_request_response__get_code(resp) !=
2754 CY_RESP_SUCCESS_FAILURE)
2755 ret = CY_AS_ERROR_INVALID_RESPONSE;
2757 ret = cy_as_ll_request_response__get_word(resp, 0);
2760 cy_as_ll_destroy_request(dev_p, rqt);
2761 cy_as_ll_destroy_response(dev_p, resp);
2763 if (ret == CY_AS_ERROR_SUCCESS) {
2764 cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
2765 dev_p->usb_cb[ep] = 0;
2766 cy_as_device_clear_usb_async_pending(dev_p, ep);
2770 cy_as_return_status_t
2771 cy_as_usb_cancel_async(cy_as_device_handle handle,
2772 cy_as_end_point_number_t ep)
2774 cy_as_return_status_t ret;
2775 cy_as_ll_request_response *req_p, *reply_p;
2777 cy_as_device *dev_p = (cy_as_device *)handle;
2778 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2779 return CY_AS_ERROR_INVALID_HANDLE;
2781 ep &= 0x7F; /* Remove the direction bit. */
2782 if (!cy_as_device_is_usb_async_pending(dev_p, ep))
2783 return CY_AS_ERROR_ASYNC_NOT_PENDING;
2785 ret = is_usb_active(dev_p);
2786 if (ret != CY_AS_ERROR_SUCCESS)
2789 if (cy_as_device_is_in_suspend_mode(dev_p))
2790 return CY_AS_ERROR_IN_SUSPEND;
2792 if ((ep == CY_AS_MTP_WRITE_ENDPOINT) ||
2793 (ep == CY_AS_MTP_READ_ENDPOINT)) {
2794 /* Need firmware support for the cancel operation. */
2795 req_p = cy_as_ll_create_request(dev_p,
2796 CY_RQT_CANCEL_ASYNC_TRANSFER,
2797 CY_RQT_TUR_RQT_CONTEXT, 1);
2800 return CY_AS_ERROR_OUT_OF_MEMORY;
2802 reply_p = cy_as_ll_create_response(dev_p, 1);
2804 cy_as_ll_destroy_request(dev_p, req_p);
2805 return CY_AS_ERROR_OUT_OF_MEMORY;
2808 cy_as_ll_request_response__set_word(req_p, 0,
2811 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
2812 cy_false, my_usb_cancel_async_callback);
2814 if (ret != CY_AS_ERROR_SUCCESS) {
2815 cy_as_ll_destroy_request(dev_p, req_p);
2816 cy_as_ll_destroy_response(dev_p, reply_p);
2820 ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
2821 if (ret != CY_AS_ERROR_SUCCESS)
2824 dev_p->usb_cb[ep] = 0;
2825 cy_as_device_clear_usb_async_pending(dev_p, ep);
2828 return CY_AS_ERROR_SUCCESS;
2832 cy_as_usb_ack_callback(
2833 cy_as_device *dev_p,
2835 cy_as_ll_request_response *rqt,
2836 cy_as_ll_request_response *resp,
2837 cy_as_return_status_t ret)
2839 cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
2840 dev_p->func_cbs_usb->head_p;
2844 if (ret == CY_AS_ERROR_SUCCESS) {
2845 if (cy_as_ll_request_response__get_code(resp) !=
2846 CY_RESP_SUCCESS_FAILURE)
2847 ret = CY_AS_ERROR_INVALID_RESPONSE;
2849 ret = cy_as_ll_request_response__get_word(resp, 0);
2852 node->cb_p((cy_as_device_handle)dev_p, ret,
2853 node->client_data, node->data_type, node->data);
2854 cy_as_remove_c_b_node(dev_p->func_cbs_usb);
2856 cy_as_ll_destroy_request(dev_p, rqt);
2857 cy_as_ll_destroy_response(dev_p, resp);
2858 cy_as_device_clear_ack_delayed(dev_p);
2861 static cy_as_return_status_t
2862 cy_as_usb_ack_setup_packet(cy_as_device_handle handle,
2863 cy_as_function_callback cb,
2866 cy_as_return_status_t ret;
2867 cy_as_ll_request_response *req_p;
2868 cy_as_ll_request_response *reply_p;
2869 cy_as_func_c_b_node *cbnode;
2871 cy_as_device *dev_p = (cy_as_device *)handle;
2872 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2873 return CY_AS_ERROR_INVALID_HANDLE;
2875 ret = is_usb_active(dev_p);
2876 if (ret != CY_AS_ERROR_SUCCESS)
2879 if (cy_as_device_is_in_callback(dev_p) && cb == 0)
2880 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2882 cy_as_hal_assert(cb != 0);
2884 cbnode = cy_as_create_func_c_b_node(cb, client);
2886 return CY_AS_ERROR_OUT_OF_MEMORY;
2888 req_p = cy_as_ll_create_request(dev_p, 0,
2889 CY_RQT_USB_RQT_CONTEXT, 2);
2891 return CY_AS_ERROR_OUT_OF_MEMORY;
2893 reply_p = cy_as_ll_create_response(dev_p, 1);
2895 cy_as_ll_destroy_request(dev_p, req_p);
2896 return CY_AS_ERROR_OUT_OF_MEMORY;
2899 cy_as_ll_init_request(req_p, CY_RQT_ACK_SETUP_PACKET,
2900 CY_RQT_USB_RQT_CONTEXT, 1);
2901 cy_as_ll_init_response(reply_p, 1);
2903 req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
2905 cy_as_insert_c_b_node(dev_p->func_cbs_usb, cbnode);
2907 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
2908 cy_false, cy_as_usb_ack_callback);
2914 * Flush all data in logical EP that is being NAK-ed or
2915 * Stall-ed, so that this does not continue to block data
2916 * on other LEPs that use the same physical EP.
2919 cy_as_usb_flush_logical_e_p(
2920 cy_as_device *dev_p,
2923 uint16_t addr, val, count;
2925 addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
2926 val = cy_as_hal_read_register(dev_p->tag, addr);
2929 count = ((val & 0xFFF) + 1) / 2;
2931 val = cy_as_hal_read_register(dev_p->tag, ep);
2933 cy_as_hal_write_register(dev_p->tag, addr, 0);
2934 val = cy_as_hal_read_register(dev_p->tag, addr);
2938 static cy_as_return_status_t
2939 cy_as_usb_nak_stall_request(cy_as_device_handle handle,
2940 cy_as_end_point_number_t ep,
2943 cy_as_usb_function_callback cb,
2944 cy_as_function_callback fcb,
2947 cy_as_return_status_t ret;
2948 cy_as_ll_request_response *req_p , *reply_p;
2951 cy_as_device *dev_p = (cy_as_device *)handle;
2952 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2953 return CY_AS_ERROR_INVALID_HANDLE;
2956 cy_as_hal_assert(fcb == 0);
2958 cy_as_hal_assert(cb == 0);
2960 ret = is_usb_active(dev_p);
2961 if (ret != CY_AS_ERROR_SUCCESS)
2964 if (cy_as_device_is_in_callback(dev_p) && cb == 0 && fcb == 0)
2965 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2967 req_p = cy_as_ll_create_request(dev_p,
2968 request, CY_RQT_USB_RQT_CONTEXT, 2);
2970 return CY_AS_ERROR_OUT_OF_MEMORY;
2972 /* A single status word response type */
2973 reply_p = cy_as_ll_create_response(dev_p, 1);
2975 cy_as_ll_destroy_request(dev_p, req_p);
2976 return CY_AS_ERROR_OUT_OF_MEMORY;
2979 /* Set the endpoint */
2981 cy_as_ll_request_response__set_word(req_p, 0, data);
2983 /* Set stall state to stalled */
2984 cy_as_ll_request_response__set_word(req_p, 1, (uint8_t)state);
2988 cy_as_c_b_queue *queue;
2990 cbnode = cy_as_create_usb_func_c_b_node(cb, client);
2991 queue = dev_p->usb_func_cbs;
2993 cbnode = cy_as_create_func_c_b_node(fcb, client);
2994 queue = dev_p->func_cbs_usb;
2995 req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
2999 ret = CY_AS_ERROR_OUT_OF_MEMORY;
3002 cy_as_insert_c_b_node(queue, cbnode);
3005 if (cy_as_device_is_setup_packet(dev_p)) {
3006 /* No Ack is needed on a stall request on EP0 */
3007 if ((state == cy_true) && (ep == 0)) {
3008 cy_as_device_set_ep0_stalled(dev_p);
3010 cy_as_device_set_ack_delayed(dev_p);
3012 CY_AS_REQUEST_RESPONSE_DELAY_ACK;
3016 ret = cy_as_ll_send_request(dev_p, req_p,
3017 reply_p, cy_false, cy_as_usb_func_callback);
3018 if (ret != CY_AS_ERROR_SUCCESS) {
3019 if (req_p->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
3020 cy_as_device_rem_ack_delayed(dev_p);
3021 cy_as_remove_c_b_tail_node(queue);
3026 ret = cy_as_ll_send_request_wait_reply(dev_p,
3028 if (ret != CY_AS_ERROR_SUCCESS)
3031 if (cy_as_ll_request_response__get_code(reply_p) !=
3032 CY_RESP_SUCCESS_FAILURE) {
3033 ret = CY_AS_ERROR_INVALID_RESPONSE;
3037 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3039 if ((ret == CY_AS_ERROR_SUCCESS) &&
3040 (request == CY_RQT_STALL_ENDPOINT)) {
3041 if ((ep > 1) && (state != 0) &&
3042 (dev_p->usb_config[ep].dir == cy_as_usb_out))
3043 cy_as_usb_flush_logical_e_p(dev_p, ep);
3047 cy_as_ll_destroy_request(dev_p, req_p);
3048 cy_as_ll_destroy_response(dev_p, reply_p);
3054 static cy_as_return_status_t
3055 my_handle_response_get_stall(cy_as_device *dev_p,
3056 cy_as_ll_request_response *req_p,
3057 cy_as_ll_request_response *reply_p,
3060 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3061 uint8_t code = cy_as_ll_request_response__get_code(reply_p);
3063 if (code == CY_RESP_SUCCESS_FAILURE) {
3064 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3066 } else if (code != CY_RESP_ENDPOINT_STALL) {
3067 ret = CY_AS_ERROR_INVALID_RESPONSE;
3071 *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
3072 ret = CY_AS_ERROR_SUCCESS;
3076 cy_as_ll_destroy_request(dev_p, req_p);
3077 cy_as_ll_destroy_response(dev_p, reply_p);
3082 static cy_as_return_status_t
3083 my_handle_response_get_nak(cy_as_device *dev_p,
3084 cy_as_ll_request_response *req_p,
3085 cy_as_ll_request_response *reply_p,
3088 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3089 uint8_t code = cy_as_ll_request_response__get_code(reply_p);
3091 if (code == CY_RESP_SUCCESS_FAILURE) {
3092 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3094 } else if (code != CY_RESP_ENDPOINT_NAK) {
3095 ret = CY_AS_ERROR_INVALID_RESPONSE;
3099 *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
3100 ret = CY_AS_ERROR_SUCCESS;
3104 cy_as_ll_destroy_request(dev_p, req_p);
3105 cy_as_ll_destroy_response(dev_p, reply_p);
3110 static cy_as_return_status_t
3111 cy_as_usb_get_nak_stall(cy_as_device_handle handle,
3112 cy_as_end_point_number_t ep,
3116 cy_as_function_callback cb,
3119 cy_as_return_status_t ret;
3120 cy_as_ll_request_response *req_p , *reply_p;
3123 cy_as_device *dev_p = (cy_as_device *)handle;
3127 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3128 return CY_AS_ERROR_INVALID_HANDLE;
3130 ret = is_usb_active(dev_p);
3131 if (ret != CY_AS_ERROR_SUCCESS)
3134 if (cy_as_device_is_in_callback(dev_p) && !cb)
3135 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3137 req_p = cy_as_ll_create_request(dev_p, request,
3138 CY_RQT_USB_RQT_CONTEXT, 1);
3140 return CY_AS_ERROR_OUT_OF_MEMORY;
3142 /* Set the endpoint */
3144 cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)ep);
3146 /* A single status word response type */
3147 reply_p = cy_as_ll_create_response(dev_p, 1);
3149 cy_as_ll_destroy_request(dev_p, req_p);
3150 return CY_AS_ERROR_OUT_OF_MEMORY;
3154 ret = cy_as_ll_send_request_wait_reply(dev_p,
3156 if (ret != CY_AS_ERROR_SUCCESS)
3159 if (request == CY_RQT_GET_STALL)
3160 return my_handle_response_get_stall(dev_p,
3161 req_p, reply_p, state_p);
3163 return my_handle_response_get_nak(dev_p,
3164 req_p, reply_p, state_p);
3167 cy_as_funct_c_b_type type;
3169 if (request == CY_RQT_GET_STALL)
3170 type = CY_FUNCT_CB_USB_GETSTALL;
3172 type = CY_FUNCT_CB_USB_GETNAK;
3174 ret = cy_as_misc_send_request(dev_p, cb, client, type,
3175 state_p, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
3176 req_p, reply_p, cy_as_usb_func_callback);
3178 if (ret != CY_AS_ERROR_SUCCESS)
3185 cy_as_ll_destroy_request(dev_p, req_p);
3186 cy_as_ll_destroy_response(dev_p, reply_p);
3191 cy_as_return_status_t
3192 cy_as_usb_set_nak(cy_as_device_handle handle,
3193 cy_as_end_point_number_t ep,
3194 cy_as_function_callback cb,
3197 cy_as_device *dev_p = (cy_as_device *)handle;
3198 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3199 return CY_AS_ERROR_INVALID_HANDLE;
3202 * we send the firmware the EP# with the appropriate direction
3203 * bit, regardless of what the user gave us.
3206 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3209 if (dev_p->mtp_count > 0)
3210 return CY_AS_ERROR_NOT_VALID_IN_MTP;
3212 return cy_as_usb_nak_stall_request(handle, ep,
3213 CY_RQT_ENDPOINT_SET_NAK, cy_true, 0, cb, client);
3217 cy_as_return_status_t
3218 cy_as_usb_clear_nak(cy_as_device_handle handle,
3219 cy_as_end_point_number_t ep,
3220 cy_as_function_callback cb,
3223 cy_as_device *dev_p = (cy_as_device *)handle;
3224 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3225 return CY_AS_ERROR_INVALID_HANDLE;
3228 * we send the firmware the EP# with the appropriate
3229 * direction bit, regardless of what the user gave us.
3232 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3235 if (dev_p->mtp_count > 0)
3236 return CY_AS_ERROR_NOT_VALID_IN_MTP;
3238 return cy_as_usb_nak_stall_request(handle, ep,
3239 CY_RQT_ENDPOINT_SET_NAK, cy_false, 0, cb, client);
3242 cy_as_return_status_t
3243 cy_as_usb_get_nak(cy_as_device_handle handle,
3244 cy_as_end_point_number_t ep,
3246 cy_as_function_callback cb,
3249 cy_as_device *dev_p = (cy_as_device *)handle;
3250 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3251 return CY_AS_ERROR_INVALID_HANDLE;
3254 * we send the firmware the EP# with the appropriate
3255 * direction bit, regardless of what the user gave us.
3258 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3261 if (dev_p->mtp_count > 0)
3262 return CY_AS_ERROR_NOT_VALID_IN_MTP;
3264 return cy_as_usb_get_nak_stall(handle, ep,
3265 CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK,
3270 cy_as_return_status_t
3271 cy_as_usb_set_stall(cy_as_device_handle handle,
3272 cy_as_end_point_number_t ep,
3273 cy_as_function_callback cb,
3276 cy_as_device *dev_p = (cy_as_device *)handle;
3277 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3278 return CY_AS_ERROR_INVALID_HANDLE;
3281 * we send the firmware the EP# with the appropriate
3282 * direction bit, regardless of what the user gave us.
3285 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3288 if (dev_p->mtp_turbo_active)
3289 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
3291 return cy_as_usb_nak_stall_request(handle, ep,
3292 CY_RQT_STALL_ENDPOINT, cy_true, 0, cb, client);
3295 cy_as_return_status_t
3296 cy_as_usb_clear_stall(cy_as_device_handle handle,
3297 cy_as_end_point_number_t ep,
3298 cy_as_function_callback cb,
3301 cy_as_device *dev_p = (cy_as_device *)handle;
3302 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3303 return CY_AS_ERROR_INVALID_HANDLE;
3306 * we send the firmware the EP# with the appropriate
3307 * direction bit, regardless of what the user gave us.
3310 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3313 if (dev_p->mtp_turbo_active)
3314 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
3316 return cy_as_usb_nak_stall_request(handle, ep,
3317 CY_RQT_STALL_ENDPOINT, cy_false, 0, cb, client);
3320 cy_as_return_status_t
3321 cy_as_usb_get_stall(cy_as_device_handle handle,
3322 cy_as_end_point_number_t ep,
3324 cy_as_function_callback cb,
3327 cy_as_device *dev_p = (cy_as_device *)handle;
3328 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3329 return CY_AS_ERROR_INVALID_HANDLE;
3332 * we send the firmware the EP# with the appropriate
3333 * direction bit, regardless of what the user gave us.
3336 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3339 if (dev_p->mtp_turbo_active)
3340 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
3342 return cy_as_usb_get_nak_stall(handle, ep,
3343 CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client);
3346 cy_as_return_status_t
3347 cy_as_usb_signal_remote_wakeup(cy_as_device_handle handle,
3348 cy_as_function_callback cb,
3351 cy_as_return_status_t ret;
3352 cy_as_ll_request_response *req_p , *reply_p;
3354 cy_as_device *dev_p = (cy_as_device *)handle;
3355 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3356 return CY_AS_ERROR_INVALID_HANDLE;
3358 ret = is_usb_active(dev_p);
3359 if (ret != CY_AS_ERROR_SUCCESS)
3362 if (cy_as_device_is_in_callback(dev_p))
3363 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3365 if (dev_p->usb_last_event != cy_as_event_usb_suspend)
3366 return CY_AS_ERROR_NOT_IN_SUSPEND;
3368 req_p = cy_as_ll_create_request(dev_p,
3369 CY_RQT_USB_REMOTE_WAKEUP, CY_RQT_USB_RQT_CONTEXT, 0);
3371 return CY_AS_ERROR_OUT_OF_MEMORY;
3373 /* A single status word response type */
3374 reply_p = cy_as_ll_create_response(dev_p, 1);
3376 cy_as_ll_destroy_request(dev_p, req_p);
3377 return CY_AS_ERROR_OUT_OF_MEMORY;
3381 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3382 if (ret != CY_AS_ERROR_SUCCESS)
3385 if (cy_as_ll_request_response__get_code(reply_p) ==
3386 CY_RESP_SUCCESS_FAILURE)
3387 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3389 ret = CY_AS_ERROR_INVALID_RESPONSE;
3391 ret = cy_as_misc_send_request(dev_p, cb, client,
3392 CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP, 0,
3393 dev_p->func_cbs_usb,
3394 CY_AS_REQUEST_RESPONSE_EX, req_p,
3395 reply_p, cy_as_usb_func_callback);
3397 if (ret != CY_AS_ERROR_SUCCESS)
3403 cy_as_ll_destroy_request(dev_p, req_p);
3404 cy_as_ll_destroy_response(dev_p, reply_p);
3409 cy_as_return_status_t
3410 cy_as_usb_set_m_s_report_threshold(cy_as_device_handle handle,
3411 uint32_t wr_sectors,
3412 uint32_t rd_sectors,
3413 cy_as_function_callback cb,
3416 cy_as_return_status_t ret;
3417 cy_as_ll_request_response *req_p , *reply_p;
3419 cy_as_device *dev_p = (cy_as_device *)handle;
3420 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3421 return CY_AS_ERROR_INVALID_HANDLE;
3423 ret = is_usb_active(dev_p);
3424 if (ret != CY_AS_ERROR_SUCCESS)
3427 if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
3428 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3430 /* Check if the firmware version supports this feature. */
3431 if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] ==
3432 (1 << cy_as_media_nand)))
3433 return CY_AS_ERROR_NOT_SUPPORTED;
3435 req_p = cy_as_ll_create_request(dev_p, CY_RQT_USB_STORAGE_MONITOR,
3436 CY_RQT_USB_RQT_CONTEXT, 4);
3438 return CY_AS_ERROR_OUT_OF_MEMORY;
3440 /* A single status word response type */
3441 reply_p = cy_as_ll_create_response(dev_p, 1);
3443 cy_as_ll_destroy_request(dev_p, req_p);
3444 return CY_AS_ERROR_OUT_OF_MEMORY;
3447 /* Set the read and write count parameters into
3448 * the request structure. */
3449 cy_as_ll_request_response__set_word(req_p, 0,
3450 (uint16_t)((wr_sectors >> 16) & 0xFFFF));
3451 cy_as_ll_request_response__set_word(req_p, 1,
3452 (uint16_t)(wr_sectors & 0xFFFF));
3453 cy_as_ll_request_response__set_word(req_p, 2,
3454 (uint16_t)((rd_sectors >> 16) & 0xFFFF));
3455 cy_as_ll_request_response__set_word(req_p, 3,
3456 (uint16_t)(rd_sectors & 0xFFFF));
3459 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3460 if (ret != CY_AS_ERROR_SUCCESS)
3463 if (cy_as_ll_request_response__get_code(reply_p) ==
3464 CY_RESP_SUCCESS_FAILURE)
3465 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3467 ret = CY_AS_ERROR_INVALID_RESPONSE;
3469 ret = cy_as_misc_send_request(dev_p, cb, client,
3470 CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD, 0,
3471 dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
3472 req_p, reply_p, cy_as_usb_func_callback);
3474 if (ret != CY_AS_ERROR_SUCCESS)
3480 cy_as_ll_destroy_request(dev_p, req_p);
3481 cy_as_ll_destroy_response(dev_p, reply_p);
3486 cy_as_return_status_t
3487 cy_as_usb_select_m_s_partitions(
3488 cy_as_device_handle handle,
3489 cy_as_bus_number_t bus,
3491 cy_as_usb_m_s_type_t type,
3492 cy_as_function_callback cb,
3495 cy_as_return_status_t ret;
3496 cy_as_ll_request_response *req_p , *reply_p;
3499 cy_as_device *dev_p = (cy_as_device *)handle;
3500 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3501 return CY_AS_ERROR_INVALID_HANDLE;
3503 ret = is_usb_active(dev_p);
3504 if (ret != CY_AS_ERROR_SUCCESS)
3507 /* This API has to be made before SetEnumConfig is called. */
3508 if (dev_p->usb_config[0].enabled)
3509 return CY_AS_ERROR_INVALID_CALL_SEQUENCE;
3511 if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
3512 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3514 req_p = cy_as_ll_create_request(dev_p, CY_RQT_MS_PARTITION_SELECT,
3515 CY_RQT_USB_RQT_CONTEXT, 2);
3517 return CY_AS_ERROR_OUT_OF_MEMORY;
3519 /* A single status word response type */
3520 reply_p = cy_as_ll_create_response(dev_p, 1);
3522 cy_as_ll_destroy_request(dev_p, req_p);
3523 return CY_AS_ERROR_OUT_OF_MEMORY;
3526 /* Set the read and write count parameters into
3527 * the request structure. */
3528 cy_as_ll_request_response__set_word(req_p, 0,
3529 (uint16_t)((bus << 8) | device));
3532 if ((type == cy_as_usb_m_s_unit0) || (type == cy_as_usb_m_s_both))
3534 if ((type == cy_as_usb_m_s_unit1) || (type == cy_as_usb_m_s_both))
3537 cy_as_ll_request_response__set_word(req_p, 1, val);
3540 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3541 if (ret != CY_AS_ERROR_SUCCESS)
3544 if (cy_as_ll_request_response__get_code(reply_p) ==
3545 CY_RESP_SUCCESS_FAILURE)
3546 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3548 ret = CY_AS_ERROR_INVALID_RESPONSE;
3550 ret = cy_as_misc_send_request(dev_p, cb, client,
3551 CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_usb,
3552 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
3553 cy_as_usb_func_callback);
3555 if (ret != CY_AS_ERROR_SUCCESS)
3561 cy_as_ll_destroy_request(dev_p, req_p);
3562 cy_as_ll_destroy_response(dev_p, reply_p);
3568 cy_as_usb_func_callback(
3569 cy_as_device *dev_p,
3571 cy_as_ll_request_response *rqt,
3572 cy_as_ll_request_response *resp,
3573 cy_as_return_status_t stat)
3575 cy_as_usb_func_c_b_node* node = (cy_as_usb_func_c_b_node *)
3576 dev_p->usb_func_cbs->head_p;
3577 cy_as_func_c_b_node* fnode = (cy_as_func_c_b_node *)
3578 dev_p->func_cbs_usb->head_p;
3579 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3581 cy_as_device_handle h = (cy_as_device_handle)dev_p;
3582 cy_bool delayed_ack = (rqt->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
3583 == CY_AS_REQUEST_RESPONSE_DELAY_ACK;
3584 cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
3585 == CY_AS_REQUEST_RESPONSE_EX;
3586 cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
3587 == CY_AS_REQUEST_RESPONSE_MS;
3591 if (!ex_request && !ms_request) {
3592 cy_as_hal_assert(dev_p->usb_func_cbs->count != 0);
3593 cy_as_hal_assert(dev_p->usb_func_cbs->type ==
3596 cy_as_hal_assert(dev_p->func_cbs_usb->count != 0);
3597 cy_as_hal_assert(dev_p->func_cbs_usb->type == CYAS_FUNC_CB);
3602 /* The Handlers are responsible for Deleting the rqt and resp when
3605 code = cy_as_ll_request_response__get_code(rqt);
3607 case CY_RQT_START_USB:
3608 ret = my_handle_response_usb_start(dev_p, rqt, resp, stat);
3610 case CY_RQT_STOP_USB:
3611 ret = my_handle_response_usb_stop(dev_p, rqt, resp, stat);
3613 case CY_RQT_SET_CONNECT_STATE:
3614 if (!cy_as_ll_request_response__get_word(rqt, 0))
3615 ret = my_handle_response_disconnect(
3616 dev_p, rqt, resp, stat);
3618 ret = my_handle_response_connect(
3619 dev_p, rqt, resp, stat);
3621 case CY_RQT_GET_CONNECT_STATE:
3623 case CY_RQT_SET_USB_CONFIG:
3624 ret = my_handle_response_set_enum_config(dev_p, rqt, resp);
3626 case CY_RQT_GET_USB_CONFIG:
3627 cy_as_hal_assert(fnode->data != 0);
3628 ret = my_handle_response_get_enum_config(dev_p,
3629 rqt, resp, fnode->data);
3631 case CY_RQT_STALL_ENDPOINT:
3632 ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
3633 state = (uint8_t)cy_as_ll_request_response__get_word(rqt, 1);
3634 ret = my_handle_response_no_data(dev_p, rqt, resp);
3635 if ((ret == CY_AS_ERROR_SUCCESS) && (ep > 1) && (state != 0)
3636 && (dev_p->usb_config[ep].dir == cy_as_usb_out))
3637 cy_as_usb_flush_logical_e_p(dev_p, ep);
3639 case CY_RQT_GET_STALL:
3640 cy_as_hal_assert(fnode->data != 0);
3641 ret = my_handle_response_get_stall(dev_p,
3642 rqt, resp, (cy_bool *)fnode->data);
3644 case CY_RQT_SET_DESCRIPTOR:
3645 ret = my_handle_response_no_data(dev_p, rqt, resp);
3647 case CY_RQT_GET_DESCRIPTOR:
3648 cy_as_hal_assert(fnode->data != 0);
3649 ret = my_handle_response_get_descriptor(dev_p,
3650 rqt, resp, (cy_as_get_descriptor_data *)fnode->data);
3652 case CY_RQT_SET_USB_CONFIG_REGISTERS:
3653 ret = my_handle_response_no_data(dev_p, rqt, resp);
3654 if (ret == CY_AS_ERROR_SUCCESS)
3655 ret = cy_as_usb_setup_dma(dev_p);
3657 case CY_RQT_ENDPOINT_SET_NAK:
3658 ret = my_handle_response_no_data(dev_p, rqt, resp);
3660 case CY_RQT_GET_ENDPOINT_NAK:
3661 cy_as_hal_assert(fnode->data != 0);
3662 ret = my_handle_response_get_nak(dev_p,
3663 rqt, resp, (cy_bool *)fnode->data);
3665 case CY_RQT_ACK_SETUP_PACKET:
3667 case CY_RQT_USB_REMOTE_WAKEUP:
3668 ret = my_handle_response_no_data(dev_p, rqt, resp);
3670 case CY_RQT_CLEAR_DESCRIPTORS:
3671 ret = my_handle_response_no_data(dev_p, rqt, resp);
3673 case CY_RQT_USB_STORAGE_MONITOR:
3674 ret = my_handle_response_no_data(dev_p, rqt, resp);
3676 case CY_RQT_MS_PARTITION_SELECT:
3677 ret = my_handle_response_no_data(dev_p, rqt, resp);
3680 ret = CY_AS_ERROR_INVALID_RESPONSE;
3681 cy_as_hal_assert(cy_false);
3686 * if the low level layer returns a direct error, use
3687 * the corresponding error code. if not, use the error
3688 * code based on the response from firmware.
3690 if (stat == CY_AS_ERROR_SUCCESS)
3693 if (ex_request || ms_request) {
3694 fnode->cb_p((cy_as_device_handle)dev_p, stat,
3695 fnode->client_data, fnode->data_type, fnode->data);
3696 cy_as_remove_c_b_node(dev_p->func_cbs_usb);
3698 node->cb_p((cy_as_device_handle)dev_p, stat,
3700 cy_as_remove_c_b_node(dev_p->usb_func_cbs);
3704 cy_as_hal_assert(cy_as_device_is_ack_delayed(dev_p));
3705 cy_as_device_rem_ack_delayed(dev_p);
3708 * send the ACK if required.
3710 if (!cy_as_device_is_ack_delayed(dev_p))
3711 cy_as_usb_ack_setup_packet(h,
3712 usb_ack_callback, 0);