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
1421 for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
1422 for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++) {
1423 if (config_p->devices_to_enumerate[bus][device] ==
1425 bus_mask |= (0x01 << bus);
1426 media_mask |= dev_p->media_supported[bus];
1427 media_mask |= dev_p->media_supported[bus];
1432 return my_usb_set_enum_config(dev_p, bus_mask, media_mask,
1433 config_p->antioch_enumeration,
1434 config_p->mass_storage_interface,
1435 config_p->mtp_interface,
1436 config_p->mass_storage_callbacks,
1443 static cy_as_return_status_t
1444 my_handle_response_get_enum_config(cy_as_device *dev_p,
1445 cy_as_ll_request_response *req_p,
1446 cy_as_ll_request_response *reply_p,
1449 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1454 if (cy_as_ll_request_response__get_code(reply_p) !=
1455 CY_RESP_USB_CONFIG) {
1456 ret = CY_AS_ERROR_INVALID_RESPONSE;
1460 /* Marshal the reply */
1461 if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
1464 cy_as_usb_enum_control *ms_config_p =
1465 (cy_as_usb_enum_control *)config_p;
1467 bus_mask = (uint8_t)
1468 (cy_as_ll_request_response__get_word
1469 (reply_p, 0) & 0xFF);
1470 for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
1471 if (bus_mask & (1 << bus))
1476 for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES;
1478 ms_config_p->devices_to_enumerate[bus][device]
1482 ms_config_p->antioch_enumeration =
1483 (cy_bool)cy_as_ll_request_response__get_word
1486 val = cy_as_ll_request_response__get_word(reply_p, 2);
1487 if (dev_p->is_mtp_firmware) {
1488 ms_config_p->mass_storage_interface = 0;
1489 ms_config_p->mtp_interface = (uint8_t)(val & 0xFF);
1491 ms_config_p->mass_storage_interface =
1492 (uint8_t)(val & 0xFF);
1493 ms_config_p->mtp_interface = 0;
1495 ms_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
1498 * firmware returns an invalid interface number for mass storage,
1499 * if mass storage is not enabled. this needs to be converted to
1500 * zero to match the input configuration.
1502 if (bus_mask == 0) {
1503 if (dev_p->is_mtp_firmware)
1504 ms_config_p->mtp_interface = 0;
1506 ms_config_p->mass_storage_interface = 0;
1509 cy_as_usb_enum_control_dep *ex_config_p =
1510 (cy_as_usb_enum_control_dep *)config_p;
1512 ex_config_p->enum_mass_storage = (uint8_t)
1513 ((cy_as_ll_request_response__get_word
1514 (reply_p, 0) >> 8) & 0xFF);
1515 ex_config_p->antioch_enumeration = (cy_bool)
1516 cy_as_ll_request_response__get_word(reply_p, 1);
1518 val = cy_as_ll_request_response__get_word(reply_p, 2);
1519 ex_config_p->mass_storage_interface = (uint8_t)(val & 0xFF);
1520 ex_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
1523 * firmware returns an invalid interface number for mass
1524 * storage, if mass storage is not enabled. this needs to
1525 * be converted to zero to match the input configuration.
1527 if (ex_config_p->enum_mass_storage == 0)
1528 ex_config_p->mass_storage_interface = 0;
1532 cy_as_ll_destroy_request(dev_p, req_p);
1533 cy_as_ll_destroy_response(dev_p, reply_p);
1539 * This sets up the request for the enumerateion configuration
1540 * information, based on if the request is from the old pre-1.2
1543 static cy_as_return_status_t
1544 my_usb_get_enum_config(cy_as_device_handle handle,
1547 cy_as_function_callback cb,
1550 cy_as_ll_request_response *req_p , *reply_p;
1551 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1553 cy_as_device *dev_p;
1555 cy_as_log_debug_message(6, "cy_as_usb_get_enum_config called");
1557 dev_p = (cy_as_device *)handle;
1558 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1559 return CY_AS_ERROR_INVALID_HANDLE;
1561 ret = is_usb_active(dev_p);
1562 if (ret != CY_AS_ERROR_SUCCESS)
1565 if (cy_as_device_is_in_callback(dev_p))
1566 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1568 /* Create the request to send to the West Bridge device */
1569 req_p = cy_as_ll_create_request(dev_p,
1570 CY_RQT_GET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 0);
1572 return CY_AS_ERROR_OUT_OF_MEMORY;
1574 /* Reserve space for the reply, the reply data
1575 * will not exceed two bytes */
1576 reply_p = cy_as_ll_create_response(dev_p, 3);
1578 cy_as_ll_destroy_request(dev_p, req_p);
1579 return CY_AS_ERROR_OUT_OF_MEMORY;
1583 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1584 if (ret != CY_AS_ERROR_SUCCESS)
1587 /* we need to know the type of request to
1588 * know how to manage the data */
1589 req_p->flags |= req_flags;
1590 return my_handle_response_get_enum_config(dev_p,
1591 req_p, reply_p, config_p);
1593 ret = cy_as_misc_send_request(dev_p, cb, client,
1594 CY_FUNCT_CB_USB_GETENUMCONFIG, config_p,
1595 dev_p->func_cbs_usb, req_flags, req_p, reply_p,
1596 cy_as_usb_func_callback);
1598 if (ret != CY_AS_ERROR_SUCCESS)
1605 cy_as_ll_destroy_request(dev_p, req_p);
1606 cy_as_ll_destroy_response(dev_p, reply_p);
1612 * This method returns the enumerateion configuration information
1613 * from the West Bridge device. Generally this is not used by
1614 * client software but is provided mostly for debug information.
1615 * We want a method to read all state information from the device.
1617 cy_as_return_status_t
1618 cy_as_usb_get_enum_config(cy_as_device_handle handle,
1619 cy_as_usb_enum_control *config_p,
1620 cy_as_function_callback cb,
1623 return my_usb_get_enum_config(handle,
1624 CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client);
1629 * This method sets the USB descriptor for a given entity.
1631 cy_as_return_status_t
1632 cy_as_usb_set_descriptor(cy_as_device_handle handle,
1633 cy_as_usb_desc_type type,
1637 cy_as_function_callback cb,
1640 cy_as_ll_request_response *req_p , *reply_p;
1641 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1644 cy_as_device *dev_p;
1646 cy_as_log_debug_message(6, "cy_as_usb_set_descriptor called");
1648 dev_p = (cy_as_device *)handle;
1649 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1650 return CY_AS_ERROR_INVALID_HANDLE;
1652 ret = is_usb_active(dev_p);
1653 if (ret != CY_AS_ERROR_SUCCESS)
1656 if (cy_as_device_is_in_callback(dev_p))
1657 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1659 if (length > CY_AS_MAX_USB_DESCRIPTOR_SIZE)
1660 return CY_AS_ERROR_INVALID_DESCRIPTOR;
1662 pktlen = (uint16_t)length / 2;
1665 pktlen += 2; /* 1 for type, 1 for length */
1667 /* Create the request to send to the West Bridge device */
1668 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_DESCRIPTOR,
1669 CY_RQT_USB_RQT_CONTEXT, (uint16_t)pktlen);
1671 return CY_AS_ERROR_OUT_OF_MEMORY;
1673 cy_as_ll_request_response__set_word(req_p, 0,
1674 (uint16_t)((uint8_t)type | (index << 8)));
1675 cy_as_ll_request_response__set_word(req_p, 1,
1677 cy_as_ll_request_response__pack(req_p, 2, length, desc_p);
1679 reply_p = cy_as_ll_create_response(dev_p, 1);
1681 cy_as_ll_destroy_request(dev_p, req_p);
1682 return CY_AS_ERROR_OUT_OF_MEMORY;
1686 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1687 if (ret != CY_AS_ERROR_SUCCESS)
1690 return my_handle_response_no_data(dev_p, req_p, reply_p);
1692 ret = cy_as_misc_send_request(dev_p, cb, client,
1693 CY_FUNCT_CB_USB_SETDESCRIPTOR, 0, dev_p->func_cbs_usb,
1694 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1695 cy_as_usb_func_callback);
1697 if (ret != CY_AS_ERROR_SUCCESS)
1704 cy_as_ll_destroy_request(dev_p, req_p);
1705 cy_as_ll_destroy_response(dev_p, reply_p);
1711 * This method clears all descriptors that were previously
1712 * stored on the West Bridge through CyAsUsbSetDescriptor calls.
1714 cy_as_return_status_t
1715 cy_as_usb_clear_descriptors(cy_as_device_handle handle,
1716 cy_as_function_callback cb,
1719 cy_as_ll_request_response *req_p , *reply_p;
1720 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1722 cy_as_device *dev_p;
1724 cy_as_log_debug_message(6, "cy_as_usb_clear_descriptors called");
1726 dev_p = (cy_as_device *)handle;
1727 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1728 return CY_AS_ERROR_INVALID_HANDLE;
1730 ret = is_usb_active(dev_p);
1731 if (ret != CY_AS_ERROR_SUCCESS)
1734 if ((cy_as_device_is_in_callback(dev_p)) && (cb == 0))
1735 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1737 /* Create the request to send to the West Bridge device */
1738 req_p = cy_as_ll_create_request(dev_p,
1739 CY_RQT_CLEAR_DESCRIPTORS, CY_RQT_USB_RQT_CONTEXT, 1);
1741 return CY_AS_ERROR_OUT_OF_MEMORY;
1743 reply_p = cy_as_ll_create_response(dev_p, 1);
1745 cy_as_ll_destroy_request(dev_p, req_p);
1746 return CY_AS_ERROR_OUT_OF_MEMORY;
1751 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1752 if (ret != CY_AS_ERROR_SUCCESS)
1755 return my_handle_response_no_data(dev_p, req_p, reply_p);
1757 ret = cy_as_misc_send_request(dev_p, cb, client,
1758 CY_FUNCT_CB_USB_CLEARDESCRIPTORS, 0,
1759 dev_p->func_cbs_usb,
1760 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1761 cy_as_usb_func_callback);
1763 if (ret != CY_AS_ERROR_SUCCESS)
1770 cy_as_ll_destroy_request(dev_p, req_p);
1771 cy_as_ll_destroy_response(dev_p, reply_p);
1776 static cy_as_return_status_t
1777 my_handle_response_get_descriptor(cy_as_device *dev_p,
1778 cy_as_ll_request_response *req_p,
1779 cy_as_ll_request_response *reply_p,
1780 cy_as_get_descriptor_data *data)
1782 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1785 if (cy_as_ll_request_response__get_code(reply_p) ==
1786 CY_RESP_SUCCESS_FAILURE) {
1787 ret = cy_as_ll_request_response__get_word(reply_p, 0);
1789 } else if (cy_as_ll_request_response__get_code(reply_p) !=
1790 CY_RESP_USB_DESCRIPTOR) {
1791 ret = CY_AS_ERROR_INVALID_RESPONSE;
1795 retlen = cy_as_ll_request_response__get_word(reply_p, 0);
1796 if (retlen > data->length) {
1797 ret = CY_AS_ERROR_INVALID_SIZE;
1801 ret = CY_AS_ERROR_SUCCESS;
1802 cy_as_ll_request_response__unpack(reply_p, 1,
1803 retlen, data->desc_p);
1806 cy_as_ll_destroy_request(dev_p, req_p);
1807 cy_as_ll_destroy_response(dev_p, reply_p);
1813 * This method retreives the USB descriptor for a given type.
1815 cy_as_return_status_t
1816 cy_as_usb_get_descriptor(cy_as_device_handle handle,
1817 cy_as_usb_desc_type type,
1819 cy_as_get_descriptor_data *data,
1820 cy_as_function_callback cb,
1823 cy_as_return_status_t ret;
1824 cy_as_ll_request_response *req_p , *reply_p;
1826 cy_as_device *dev_p;
1828 cy_as_log_debug_message(6, "cy_as_usb_get_descriptor called");
1830 dev_p = (cy_as_device *)handle;
1831 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1832 return CY_AS_ERROR_INVALID_HANDLE;
1834 ret = is_usb_active(dev_p);
1835 if (ret != CY_AS_ERROR_SUCCESS)
1838 if (cy_as_device_is_in_callback(dev_p))
1839 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1841 /* Create the request to send to the West Bridge device */
1842 req_p = cy_as_ll_create_request(dev_p,
1843 CY_RQT_GET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, 1);
1845 return CY_AS_ERROR_OUT_OF_MEMORY;
1847 cy_as_ll_request_response__set_word(req_p, 0,
1848 (uint16_t)((uint8_t)type | (index << 8)));
1850 /* Add one for the length field */
1851 reply_p = cy_as_ll_create_response(dev_p,
1852 CY_AS_MAX_USB_DESCRIPTOR_SIZE + 1);
1854 cy_as_ll_destroy_request(dev_p, req_p);
1855 return CY_AS_ERROR_OUT_OF_MEMORY;
1859 ret = cy_as_ll_send_request_wait_reply(
1860 dev_p, req_p, reply_p);
1861 if (ret != CY_AS_ERROR_SUCCESS)
1864 return my_handle_response_get_descriptor(dev_p,
1865 req_p, reply_p, data);
1867 ret = cy_as_misc_send_request(dev_p, cb, client,
1868 CY_FUNCT_CB_USB_GETDESCRIPTOR, data,
1869 dev_p->func_cbs_usb,
1870 CY_AS_REQUEST_RESPONSE_EX, req_p,
1871 reply_p, cy_as_usb_func_callback);
1873 if (ret != CY_AS_ERROR_SUCCESS)
1880 cy_as_ll_destroy_request(dev_p, req_p);
1881 cy_as_ll_destroy_response(dev_p, reply_p);
1886 cy_as_return_status_t
1887 cy_as_usb_set_physical_configuration(cy_as_device_handle handle,
1890 cy_as_return_status_t ret;
1891 cy_as_device *dev_p;
1893 cy_as_log_debug_message(6,
1894 "cy_as_usb_set_physical_configuration called");
1896 dev_p = (cy_as_device *)handle;
1897 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1898 return CY_AS_ERROR_INVALID_HANDLE;
1900 ret = is_usb_active(dev_p);
1901 if (ret != CY_AS_ERROR_SUCCESS)
1904 if (cy_as_device_is_usb_connected(dev_p))
1905 return CY_AS_ERROR_USB_CONNECTED;
1907 if (config < 1 || config > 12)
1908 return CY_AS_ERROR_INVALID_CONFIGURATION;
1910 dev_p->usb_phy_config = config;
1912 return CY_AS_ERROR_SUCCESS;
1916 is_physical_valid(uint8_t config, cy_as_end_point_number_t ep)
1918 static uint8_t validmask[12] = {
1919 0x0f, /* Config 1 - 1, 2, 3, 4 */
1920 0x07, /* Config 2 - 1, 2, 3 */
1921 0x07, /* Config 3 - 1, 2, 3 */
1922 0x0d, /* Config 4 - 1, 3, 4 */
1923 0x05, /* Config 5 - 1, 3 */
1924 0x05, /* Config 6 - 1, 3 */
1925 0x0d, /* Config 7 - 1, 3, 4 */
1926 0x05, /* Config 8 - 1, 3 */
1927 0x05, /* Config 9 - 1, 3 */
1928 0x0d, /* Config 10 - 1, 3, 4 */
1929 0x09, /* Config 11 - 1, 4 */
1930 0x01 /* Config 12 - 1 */
1933 return (validmask[config - 1] & (1 << (ep - 1))) ? cy_true : cy_false;
1937 * This method sets the configuration for an endpoint
1939 cy_as_return_status_t
1940 cy_as_usb_set_end_point_config(cy_as_device_handle handle,
1941 cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
1943 cy_as_return_status_t ret;
1944 cy_as_device *dev_p;
1946 cy_as_log_debug_message(6, "cy_as_usb_set_end_point_config called");
1948 dev_p = (cy_as_device *)handle;
1949 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1950 return CY_AS_ERROR_INVALID_HANDLE;
1952 ret = is_usb_active(dev_p);
1953 if (ret != CY_AS_ERROR_SUCCESS)
1956 if (cy_as_device_is_usb_connected(dev_p))
1957 return CY_AS_ERROR_USB_CONNECTED;
1959 if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
1960 return CY_AS_ERROR_INVALID_ENDPOINT;
1963 /* Endpoint 0 must be 64 byte, dir IN/OUT,
1964 * and control type */
1965 if (config_p->dir != cy_as_usb_in_out ||
1966 config_p->type != cy_as_usb_control)
1967 return CY_AS_ERROR_INVALID_CONFIGURATION;
1968 } else if (ep == 1) {
1969 if ((dev_p->is_mtp_firmware == 1) &&
1970 (dev_p->usb_config[1].enabled == cy_true)) {
1971 return CY_AS_ERROR_INVALID_ENDPOINT;
1975 * EP1 can only be used either as an OUT ep, or as an IN ep.
1977 if ((config_p->type == cy_as_usb_control) ||
1978 (config_p->type == cy_as_usb_iso) ||
1979 (config_p->dir == cy_as_usb_in_out))
1980 return CY_AS_ERROR_INVALID_CONFIGURATION;
1982 if (config_p->dir == cy_as_usb_in_out ||
1983 config_p->type == cy_as_usb_control)
1984 return CY_AS_ERROR_INVALID_CONFIGURATION;
1986 if (!is_physical_valid(dev_p->usb_phy_config,
1987 config_p->physical))
1988 return CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT;
1991 * ISO endpoints must be on E_ps 3, 5, 7 or 9 as
1992 * they need to align directly with the underlying
1993 * physical endpoint.
1995 if (config_p->type == cy_as_usb_iso) {
1996 if (ep != 3 && ep != 5 && ep != 7 && ep != 9)
1997 return CY_AS_ERROR_INVALID_CONFIGURATION;
1999 if (ep == 3 && config_p->physical != 1)
2000 return CY_AS_ERROR_INVALID_CONFIGURATION;
2002 if (ep == 5 && config_p->physical != 2)
2003 return CY_AS_ERROR_INVALID_CONFIGURATION;
2005 if (ep == 7 && config_p->physical != 3)
2006 return CY_AS_ERROR_INVALID_CONFIGURATION;
2008 if (ep == 9 && config_p->physical != 4)
2009 return CY_AS_ERROR_INVALID_CONFIGURATION;
2013 /* Store the configuration information until a
2014 * CyAsUsbCommitConfig is done */
2015 dev_p->usb_config[ep] = *config_p;
2017 /* If the endpoint is enabled, enable DMA associated
2018 * with the endpoint */
2020 * we make some assumptions that we check here. we assume
2021 * that the direction fields for the DMA module are the same
2022 * values as the direction values for the USB module.
2024 cy_as_hal_assert((int)cy_as_usb_in == (int)cy_as_direction_in);
2025 cy_as_hal_assert((int)cy_as_usb_out == (int)cy_as_direction_out);
2026 cy_as_hal_assert((int)cy_as_usb_in_out == (int)cy_as_direction_in_out);
2028 return cy_as_dma_enable_end_point(dev_p, ep,
2029 config_p->enabled, (cy_as_dma_direction)config_p->dir);
2032 cy_as_return_status_t
2033 cy_as_usb_get_end_point_config(cy_as_device_handle handle,
2034 cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
2036 cy_as_return_status_t ret;
2038 cy_as_device *dev_p;
2040 cy_as_log_debug_message(6, "cy_as_usb_get_end_point_config called");
2042 dev_p = (cy_as_device *)handle;
2043 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2044 return CY_AS_ERROR_INVALID_HANDLE;
2046 ret = is_usb_active(dev_p);
2047 if (ret != CY_AS_ERROR_SUCCESS)
2050 if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
2051 return CY_AS_ERROR_INVALID_ENDPOINT;
2053 *config_p = dev_p->usb_config[ep];
2055 return CY_AS_ERROR_SUCCESS;
2059 * Commit the configuration of the various endpoints to the hardware.
2061 cy_as_return_status_t
2062 cy_as_usb_commit_config(cy_as_device_handle handle,
2063 cy_as_function_callback cb,
2067 cy_as_return_status_t ret;
2068 cy_as_ll_request_response *req_p , *reply_p;
2069 cy_as_device *dev_p;
2072 cy_as_log_debug_message(6, "cy_as_usb_commit_config called");
2074 dev_p = (cy_as_device *)handle;
2075 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2076 return CY_AS_ERROR_INVALID_HANDLE;
2078 ret = is_usb_active(dev_p);
2079 if (ret != CY_AS_ERROR_SUCCESS)
2082 if (cy_as_device_is_usb_connected(dev_p))
2083 return CY_AS_ERROR_USB_CONNECTED;
2085 if (cy_as_device_is_in_callback(dev_p))
2086 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2089 * this performs the mapping based on informatation that was
2090 * previously stored on the device about the various endpoints
2091 * and how they are configured. the output of this mapping is
2092 * setting the the 14 register values contained in usb_lepcfg
2095 ret = cy_as_usb_map_logical2_physical(dev_p);
2096 if (ret != CY_AS_ERROR_SUCCESS)
2100 * now, package the information about the various logical and
2101 * physical endpoint configuration registers and send it
2102 * across to the west bridge device.
2104 req_p = cy_as_ll_create_request(dev_p,
2105 CY_RQT_SET_USB_CONFIG_REGISTERS, CY_RQT_USB_RQT_CONTEXT, 8);
2107 return CY_AS_ERROR_OUT_OF_MEMORY;
2109 cy_as_hal_print_message("USB configuration: %d\n",
2110 dev_p->usb_phy_config);
2111 cy_as_hal_print_message("EP1OUT: 0x%02x EP1IN: 0x%02x\n",
2112 dev_p->usb_ep1cfg[0], dev_p->usb_ep1cfg[1]);
2113 cy_as_hal_print_message("PEP registers: 0x%02x 0x%02x 0x%02x 0x%02x\n",
2114 dev_p->usb_pepcfg[0], dev_p->usb_pepcfg[1],
2115 dev_p->usb_pepcfg[2], dev_p->usb_pepcfg[3]);
2117 cy_as_hal_print_message("LEP registers: 0x%02x 0x%02x 0x%02x "
2118 "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
2119 dev_p->usb_lepcfg[0], dev_p->usb_lepcfg[1],
2120 dev_p->usb_lepcfg[2], dev_p->usb_lepcfg[3],
2121 dev_p->usb_lepcfg[4], dev_p->usb_lepcfg[5],
2122 dev_p->usb_lepcfg[6], dev_p->usb_lepcfg[7],
2123 dev_p->usb_lepcfg[8], dev_p->usb_lepcfg[9]);
2125 /* Write the EP1OUTCFG and EP1INCFG data in the first word. */
2126 data = (uint16_t)((dev_p->usb_ep1cfg[0] << 8) |
2127 dev_p->usb_ep1cfg[1]);
2128 cy_as_ll_request_response__set_word(req_p, 0, data);
2130 /* Write the PEP CFG data in the next 2 words */
2131 for (i = 0; i < 4; i += 2) {
2132 data = (uint16_t)((dev_p->usb_pepcfg[i] << 8) |
2133 dev_p->usb_pepcfg[i + 1]);
2134 cy_as_ll_request_response__set_word(req_p,
2138 /* Write the LEP CFG data in the next 5 words */
2139 for (i = 0; i < 10; i += 2) {
2140 data = (uint16_t)((dev_p->usb_lepcfg[i] << 8) |
2141 dev_p->usb_lepcfg[i + 1]);
2142 cy_as_ll_request_response__set_word(req_p,
2146 /* A single status word response type */
2147 reply_p = cy_as_ll_create_response(dev_p, 1);
2149 cy_as_ll_destroy_request(dev_p, req_p);
2150 return CY_AS_ERROR_OUT_OF_MEMORY;
2154 ret = cy_as_ll_send_request_wait_reply(dev_p,
2156 if (ret != CY_AS_ERROR_SUCCESS)
2159 ret = my_handle_response_no_data(dev_p,
2162 if (ret == CY_AS_ERROR_SUCCESS)
2163 ret = cy_as_usb_setup_dma(dev_p);
2167 ret = cy_as_misc_send_request(dev_p, cb, client,
2168 CY_FUNCT_CB_USB_COMMITCONFIG, 0, dev_p->func_cbs_usb,
2169 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
2170 cy_as_usb_func_callback);
2172 if (ret != CY_AS_ERROR_SUCCESS)
2179 cy_as_ll_destroy_request(dev_p, req_p);
2180 cy_as_ll_destroy_response(dev_p, reply_p);
2186 sync_request_callback(cy_as_device *dev_p,
2187 cy_as_end_point_number_t ep, void *buf_p,
2188 uint32_t size, cy_as_return_status_t err)
2193 dev_p->usb_error = err;
2194 dev_p->usb_actual_cnt = size;
2198 async_read_request_callback(cy_as_device *dev_p,
2199 cy_as_end_point_number_t ep, void *buf_p,
2200 uint32_t size, cy_as_return_status_t err)
2202 cy_as_device_handle h;
2204 cy_as_log_debug_message(6,
2205 "async_read_request_callback called");
2207 h = (cy_as_device_handle)dev_p;
2209 if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
2210 dev_p->usb_pending_buffer = buf_p;
2211 dev_p->usb_pending_size = size;
2212 dev_p->usb_error = err;
2213 cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
2215 cy_as_usb_io_callback cb;
2217 cb = dev_p->usb_cb[ep];
2218 dev_p->usb_cb[ep] = 0;
2219 cy_as_device_clear_usb_async_pending(dev_p, ep);
2221 cb(h, ep, size, buf_p, err);
2226 async_write_request_callback(cy_as_device *dev_p,
2227 cy_as_end_point_number_t ep, void *buf_p,
2228 uint32_t size, cy_as_return_status_t err)
2230 cy_as_device_handle h;
2232 cy_as_log_debug_message(6,
2233 "async_write_request_callback called");
2235 h = (cy_as_device_handle)dev_p;
2237 if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
2238 dev_p->usb_pending_buffer = buf_p;
2239 dev_p->usb_pending_size = size;
2240 dev_p->usb_error = err;
2242 /* The west bridge protocol generates ZLPs as required. */
2243 cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
2245 cy_as_usb_io_callback cb;
2247 cb = dev_p->usb_cb[ep];
2248 dev_p->usb_cb[ep] = 0;
2250 cy_as_device_clear_usb_async_pending(dev_p, ep);
2252 cb(h, ep, size, buf_p, err);
2257 my_turbo_rqt_callback(cy_as_device *dev_p,
2259 cy_as_ll_request_response *rqt,
2260 cy_as_ll_request_response *resp,
2261 cy_as_return_status_t stat)
2268 /* The Handlers are responsible for Deleting the rqt and resp when
2271 code = cy_as_ll_request_response__get_code(rqt);
2273 case CY_RQT_TURBO_SWITCH_ENDPOINT:
2274 cy_as_hal_assert(stat == CY_AS_ERROR_SUCCESS);
2275 cy_as_ll_destroy_request(dev_p, rqt);
2276 cy_as_ll_destroy_response(dev_p, resp);
2279 cy_as_hal_assert(cy_false);
2284 /* Send a mailbox request to prepare the endpoint for switching */
2285 static cy_as_return_status_t
2286 my_send_turbo_switch(cy_as_device *dev_p, uint32_t size, cy_bool pktread)
2288 cy_as_return_status_t ret;
2289 cy_as_ll_request_response *req_p , *reply_p;
2291 /* Create the request to send to the West Bridge device */
2292 req_p = cy_as_ll_create_request(dev_p,
2293 CY_RQT_TURBO_SWITCH_ENDPOINT, CY_RQT_TUR_RQT_CONTEXT, 3);
2295 return CY_AS_ERROR_OUT_OF_MEMORY;
2297 /* Reserve space for the reply, the reply data will
2298 * not exceed one word */
2299 reply_p = cy_as_ll_create_response(dev_p, 1);
2301 cy_as_ll_destroy_request(dev_p, req_p);
2302 return CY_AS_ERROR_OUT_OF_MEMORY;
2305 cy_as_ll_request_response__set_word(req_p, 0,
2307 cy_as_ll_request_response__set_word(req_p, 1,
2308 (uint16_t)((size >> 16) & 0xFFFF));
2309 cy_as_ll_request_response__set_word(req_p, 2,
2310 (uint16_t)(size & 0xFFFF));
2312 ret = cy_as_ll_send_request(dev_p, req_p,
2313 reply_p, cy_false, my_turbo_rqt_callback);
2314 if (ret != CY_AS_ERROR_SUCCESS) {
2315 cy_as_ll_destroy_request(dev_p, req_p);
2316 cy_as_ll_destroy_request(dev_p, reply_p);
2320 return CY_AS_ERROR_SUCCESS;
2323 cy_as_return_status_t
2324 cy_as_usb_read_data(cy_as_device_handle handle,
2325 cy_as_end_point_number_t ep, cy_bool pktread,
2326 uint32_t dsize, uint32_t *dataread, void *data)
2328 cy_as_return_status_t ret;
2329 cy_as_device *dev_p;
2331 cy_as_log_debug_message(6, "cy_as_usb_read_data called");
2333 dev_p = (cy_as_device *)handle;
2334 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2335 return CY_AS_ERROR_INVALID_HANDLE;
2337 ret = is_usb_active(dev_p);
2338 if (ret != CY_AS_ERROR_SUCCESS)
2341 if (cy_as_device_is_in_callback(dev_p))
2342 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2344 if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
2345 return CY_AS_ERROR_INVALID_ENDPOINT;
2347 /* EP2 is available for reading when MTP is active */
2348 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
2349 return CY_AS_ERROR_INVALID_ENDPOINT;
2351 /* If the endpoint is disabled, we cannot
2352 * write data to the endpoint */
2353 if (!dev_p->usb_config[ep].enabled)
2354 return CY_AS_ERROR_ENDPOINT_DISABLED;
2356 if (dev_p->usb_config[ep].dir != cy_as_usb_out)
2357 return CY_AS_ERROR_USB_BAD_DIRECTION;
2359 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2360 pktread, cy_true, sync_request_callback);
2361 if (ret != CY_AS_ERROR_SUCCESS)
2364 if (ep == CY_AS_MTP_READ_ENDPOINT) {
2365 ret = my_send_turbo_switch(dev_p, dsize, pktread);
2366 if (ret != CY_AS_ERROR_SUCCESS) {
2367 cy_as_dma_cancel(dev_p, ep, ret);
2371 ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
2372 if (ret != CY_AS_ERROR_SUCCESS)
2375 ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
2376 if (ret != CY_AS_ERROR_SUCCESS)
2380 ret = dev_p->usb_error;
2381 *dataread = dev_p->usb_actual_cnt;
2386 cy_as_return_status_t
2387 cy_as_usb_read_data_async(cy_as_device_handle handle,
2388 cy_as_end_point_number_t ep, cy_bool pktread,
2389 uint32_t dsize, void *data, cy_as_usb_io_callback cb)
2391 cy_as_return_status_t ret;
2393 cy_as_device *dev_p;
2395 cy_as_log_debug_message(6, "cy_as_usb_read_data_async called");
2397 dev_p = (cy_as_device *)handle;
2398 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2399 return CY_AS_ERROR_INVALID_HANDLE;
2401 ret = is_usb_active(dev_p);
2402 if (ret != CY_AS_ERROR_SUCCESS)
2405 if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
2406 return CY_AS_ERROR_INVALID_ENDPOINT;
2408 /* EP2 is available for reading when MTP is active */
2409 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
2410 return CY_AS_ERROR_INVALID_ENDPOINT;
2412 /* If the endpoint is disabled, we cannot
2413 * write data to the endpoint */
2414 if (!dev_p->usb_config[ep].enabled)
2415 return CY_AS_ERROR_ENDPOINT_DISABLED;
2417 if (dev_p->usb_config[ep].dir != cy_as_usb_out &&
2418 dev_p->usb_config[ep].dir != cy_as_usb_in_out)
2419 return CY_AS_ERROR_USB_BAD_DIRECTION;
2422 * since async operations can be triggered by interrupt
2423 * code, we must insure that we do not get multiple async
2424 * operations going at one time and protect this test and
2425 * set operation from interrupts.
2427 mask = cy_as_hal_disable_interrupts();
2428 if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
2429 cy_as_hal_enable_interrupts(mask);
2430 return CY_AS_ERROR_ASYNC_PENDING;
2432 cy_as_device_set_usb_async_pending(dev_p, ep);
2435 * if this is for EP0, we set this bit to delay the
2436 * ACK response until after this read has completed.
2439 cy_as_device_set_ack_delayed(dev_p);
2441 cy_as_hal_enable_interrupts(mask);
2443 cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
2444 dev_p->usb_cb[ep] = cb;
2446 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2447 pktread, cy_true, async_read_request_callback);
2448 if (ret != CY_AS_ERROR_SUCCESS)
2451 if (ep == CY_AS_MTP_READ_ENDPOINT) {
2452 ret = my_send_turbo_switch(dev_p, dsize, pktread);
2453 if (ret != CY_AS_ERROR_SUCCESS) {
2454 cy_as_dma_cancel(dev_p, ep, ret);
2458 /* Kick start the queue if it is not running */
2459 cy_as_dma_kick_start(dev_p, ep);
2464 cy_as_return_status_t
2465 cy_as_usb_write_data(cy_as_device_handle handle,
2466 cy_as_end_point_number_t ep, uint32_t dsize, void *data)
2468 cy_as_return_status_t ret;
2469 cy_as_device *dev_p;
2471 cy_as_log_debug_message(6, "cy_as_usb_write_data called");
2473 dev_p = (cy_as_device *)handle;
2474 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2475 return CY_AS_ERROR_INVALID_HANDLE;
2477 ret = is_usb_active(dev_p);
2478 if (ret != CY_AS_ERROR_SUCCESS)
2481 if (cy_as_device_is_in_callback(dev_p))
2482 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2484 if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
2485 return CY_AS_ERROR_INVALID_ENDPOINT;
2487 /* EP6 is available for writing when MTP is active */
2488 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
2489 return CY_AS_ERROR_INVALID_ENDPOINT;
2491 /* If the endpoint is disabled, we cannot
2492 * write data to the endpoint */
2493 if (!dev_p->usb_config[ep].enabled)
2494 return CY_AS_ERROR_ENDPOINT_DISABLED;
2496 if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
2497 dev_p->usb_config[ep].dir != cy_as_usb_in_out)
2498 return CY_AS_ERROR_USB_BAD_DIRECTION;
2500 /* Write on Turbo endpoint */
2501 if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
2502 cy_as_ll_request_response *req_p, *reply_p;
2504 req_p = cy_as_ll_create_request(dev_p,
2505 CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
2506 CY_RQT_TUR_RQT_CONTEXT, 3);
2508 return CY_AS_ERROR_OUT_OF_MEMORY;
2510 cy_as_ll_request_response__set_word(req_p,
2511 0, 0x0006); /* EP number to use. */
2512 cy_as_ll_request_response__set_word(req_p,
2513 1, (uint16_t)((dsize >> 16) & 0xFFFF));
2514 cy_as_ll_request_response__set_word(req_p,
2515 2, (uint16_t)(dsize & 0xFFFF));
2517 /* Reserve space for the reply, the reply data
2518 * will not exceed one word */
2519 reply_p = cy_as_ll_create_response(dev_p, 1);
2521 cy_as_ll_destroy_request(dev_p, req_p);
2522 return CY_AS_ERROR_OUT_OF_MEMORY;
2526 ret = cy_as_dma_queue_request(dev_p,
2527 ep, data, dsize, cy_false,
2528 cy_false, sync_request_callback);
2529 if (ret != CY_AS_ERROR_SUCCESS)
2533 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2534 if (ret == CY_AS_ERROR_SUCCESS) {
2535 if (cy_as_ll_request_response__get_code(reply_p) !=
2536 CY_RESP_SUCCESS_FAILURE)
2537 ret = CY_AS_ERROR_INVALID_RESPONSE;
2539 ret = cy_as_ll_request_response__get_word
2543 cy_as_ll_destroy_request(dev_p, req_p);
2544 cy_as_ll_destroy_response(dev_p, reply_p);
2546 if (ret != CY_AS_ERROR_SUCCESS) {
2548 cy_as_dma_cancel(dev_p, ep, ret);
2552 /* If this is a zero-byte write, firmware will
2553 * handle it. there is no need to do any work here.
2556 return CY_AS_ERROR_SUCCESS;
2558 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2559 cy_false, cy_false, sync_request_callback);
2560 if (ret != CY_AS_ERROR_SUCCESS)
2564 if (ep != CY_AS_MTP_WRITE_ENDPOINT)
2565 ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
2567 ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
2569 if (ret != CY_AS_ERROR_SUCCESS)
2572 ret = dev_p->usb_error;
2578 cy_as_device *dev_p,
2580 cy_as_ll_request_response *rqt,
2581 cy_as_ll_request_response *resp,
2582 cy_as_return_status_t ret)
2584 cy_as_usb_io_callback cb;
2585 cy_as_device_handle h = (cy_as_device_handle)dev_p;
2587 cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
2589 if (ret == CY_AS_ERROR_SUCCESS) {
2590 if (cy_as_ll_request_response__get_code(resp) !=
2591 CY_RESP_SUCCESS_FAILURE)
2592 ret = CY_AS_ERROR_INVALID_RESPONSE;
2594 ret = cy_as_ll_request_response__get_word(resp, 0);
2597 /* If this was a zero byte transfer request, we can
2598 * call the callback from here. */
2599 if ((cy_as_ll_request_response__get_word(rqt, 1) == 0) &&
2600 (cy_as_ll_request_response__get_word(rqt, 2) == 0)) {
2601 cb = dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT];
2602 dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] = 0;
2603 cy_as_device_clear_usb_async_pending(dev_p,
2604 CY_AS_MTP_WRITE_ENDPOINT);
2606 cb(h, CY_AS_MTP_WRITE_ENDPOINT, 0, 0, ret);
2611 if (ret != CY_AS_ERROR_SUCCESS) {
2612 /* Firmware failed the request. Cancel the DMA transfer. */
2613 cy_as_dma_cancel(dev_p, 0x06, CY_AS_ERROR_CANCELED);
2614 dev_p->usb_cb[0x06] = 0;
2615 cy_as_device_clear_usb_async_pending(dev_p, 0x06);
2619 cy_as_ll_destroy_response(dev_p, resp);
2620 cy_as_ll_destroy_request(dev_p, rqt);
2623 cy_as_return_status_t
2624 cy_as_usb_write_data_async(cy_as_device_handle handle,
2625 cy_as_end_point_number_t ep, uint32_t dsize, void *data,
2626 cy_bool spacket, cy_as_usb_io_callback cb)
2629 cy_as_return_status_t ret;
2630 cy_as_device *dev_p;
2632 cy_as_log_debug_message(6, "cy_as_usb_write_data_async called");
2634 dev_p = (cy_as_device *)handle;
2635 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2636 return CY_AS_ERROR_INVALID_HANDLE;
2638 ret = is_usb_active(dev_p);
2639 if (ret != CY_AS_ERROR_SUCCESS)
2642 if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
2643 return CY_AS_ERROR_INVALID_ENDPOINT;
2645 /* EP6 is available for writing when MTP is active */
2646 if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
2647 return CY_AS_ERROR_INVALID_ENDPOINT;
2649 /* If the endpoint is disabled, we cannot
2650 * write data to the endpoint */
2651 if (!dev_p->usb_config[ep].enabled)
2652 return CY_AS_ERROR_ENDPOINT_DISABLED;
2654 if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
2655 dev_p->usb_config[ep].dir != cy_as_usb_in_out)
2656 return CY_AS_ERROR_USB_BAD_DIRECTION;
2659 * since async operations can be triggered by interrupt
2660 * code, we must insure that we do not get multiple
2661 * async operations going at one time and
2662 * protect this test and set operation from interrupts.
2664 mask = cy_as_hal_disable_interrupts();
2665 if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
2666 cy_as_hal_enable_interrupts(mask);
2667 return CY_AS_ERROR_ASYNC_PENDING;
2670 cy_as_device_set_usb_async_pending(dev_p, ep);
2673 cy_as_device_set_ack_delayed(dev_p);
2675 cy_as_hal_enable_interrupts(mask);
2677 cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
2678 dev_p->usb_cb[ep] = cb;
2679 dev_p->usb_spacket[ep] = spacket;
2681 /* Write on Turbo endpoint */
2682 if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
2683 cy_as_ll_request_response *req_p, *reply_p;
2685 req_p = cy_as_ll_create_request(dev_p,
2686 CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
2687 CY_RQT_TUR_RQT_CONTEXT, 3);
2690 return CY_AS_ERROR_OUT_OF_MEMORY;
2692 cy_as_ll_request_response__set_word(req_p, 0,
2693 0x0006); /* EP number to use. */
2694 cy_as_ll_request_response__set_word(req_p, 1,
2695 (uint16_t)((dsize >> 16) & 0xFFFF));
2696 cy_as_ll_request_response__set_word(req_p, 2,
2697 (uint16_t)(dsize & 0xFFFF));
2699 /* Reserve space for the reply, the reply data
2700 * will not exceed one word */
2701 reply_p = cy_as_ll_create_response(dev_p, 1);
2703 cy_as_ll_destroy_request(dev_p, req_p);
2704 return CY_AS_ERROR_OUT_OF_MEMORY;
2708 ret = cy_as_dma_queue_request(dev_p, ep, data,
2709 dsize, cy_false, cy_false,
2710 async_write_request_callback);
2711 if (ret != CY_AS_ERROR_SUCCESS)
2715 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
2716 cy_false, mtp_write_callback);
2717 if (ret != CY_AS_ERROR_SUCCESS) {
2719 cy_as_dma_cancel(dev_p, ep, ret);
2723 /* Firmware will handle a zero byte transfer
2724 * without any DMA transfers. */
2726 return CY_AS_ERROR_SUCCESS;
2728 ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
2729 cy_false, cy_false, async_write_request_callback);
2730 if (ret != CY_AS_ERROR_SUCCESS)
2734 /* Kick start the queue if it is not running */
2735 if (ep != CY_AS_MTP_WRITE_ENDPOINT)
2736 cy_as_dma_kick_start(dev_p, ep);
2738 return CY_AS_ERROR_SUCCESS;
2742 my_usb_cancel_async_callback(
2743 cy_as_device *dev_p,
2745 cy_as_ll_request_response *rqt,
2746 cy_as_ll_request_response *resp,
2747 cy_as_return_status_t ret)
2752 ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
2753 if (ret == CY_AS_ERROR_SUCCESS) {
2754 if (cy_as_ll_request_response__get_code(resp) !=
2755 CY_RESP_SUCCESS_FAILURE)
2756 ret = CY_AS_ERROR_INVALID_RESPONSE;
2758 ret = cy_as_ll_request_response__get_word(resp, 0);
2761 cy_as_ll_destroy_request(dev_p, rqt);
2762 cy_as_ll_destroy_response(dev_p, resp);
2764 if (ret == CY_AS_ERROR_SUCCESS) {
2765 cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
2766 dev_p->usb_cb[ep] = 0;
2767 cy_as_device_clear_usb_async_pending(dev_p, ep);
2771 cy_as_return_status_t
2772 cy_as_usb_cancel_async(cy_as_device_handle handle,
2773 cy_as_end_point_number_t ep)
2775 cy_as_return_status_t ret;
2776 cy_as_ll_request_response *req_p, *reply_p;
2778 cy_as_device *dev_p = (cy_as_device *)handle;
2779 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2780 return CY_AS_ERROR_INVALID_HANDLE;
2782 ep &= 0x7F; /* Remove the direction bit. */
2783 if (!cy_as_device_is_usb_async_pending(dev_p, ep))
2784 return CY_AS_ERROR_ASYNC_NOT_PENDING;
2786 ret = is_usb_active(dev_p);
2787 if (ret != CY_AS_ERROR_SUCCESS)
2790 if (cy_as_device_is_in_suspend_mode(dev_p))
2791 return CY_AS_ERROR_IN_SUSPEND;
2793 if ((ep == CY_AS_MTP_WRITE_ENDPOINT) ||
2794 (ep == CY_AS_MTP_READ_ENDPOINT)) {
2795 /* Need firmware support for the cancel operation. */
2796 req_p = cy_as_ll_create_request(dev_p,
2797 CY_RQT_CANCEL_ASYNC_TRANSFER,
2798 CY_RQT_TUR_RQT_CONTEXT, 1);
2801 return CY_AS_ERROR_OUT_OF_MEMORY;
2803 reply_p = cy_as_ll_create_response(dev_p, 1);
2805 cy_as_ll_destroy_request(dev_p, req_p);
2806 return CY_AS_ERROR_OUT_OF_MEMORY;
2809 cy_as_ll_request_response__set_word(req_p, 0,
2812 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
2813 cy_false, my_usb_cancel_async_callback);
2815 if (ret != CY_AS_ERROR_SUCCESS) {
2816 cy_as_ll_destroy_request(dev_p, req_p);
2817 cy_as_ll_destroy_response(dev_p, reply_p);
2821 ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
2822 if (ret != CY_AS_ERROR_SUCCESS)
2825 dev_p->usb_cb[ep] = 0;
2826 cy_as_device_clear_usb_async_pending(dev_p, ep);
2829 return CY_AS_ERROR_SUCCESS;
2833 cy_as_usb_ack_callback(
2834 cy_as_device *dev_p,
2836 cy_as_ll_request_response *rqt,
2837 cy_as_ll_request_response *resp,
2838 cy_as_return_status_t ret)
2840 cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
2841 dev_p->func_cbs_usb->head_p;
2845 if (ret == CY_AS_ERROR_SUCCESS) {
2846 if (cy_as_ll_request_response__get_code(resp) !=
2847 CY_RESP_SUCCESS_FAILURE)
2848 ret = CY_AS_ERROR_INVALID_RESPONSE;
2850 ret = cy_as_ll_request_response__get_word(resp, 0);
2853 node->cb_p((cy_as_device_handle)dev_p, ret,
2854 node->client_data, node->data_type, node->data);
2855 cy_as_remove_c_b_node(dev_p->func_cbs_usb);
2857 cy_as_ll_destroy_request(dev_p, rqt);
2858 cy_as_ll_destroy_response(dev_p, resp);
2859 cy_as_device_clear_ack_delayed(dev_p);
2862 static cy_as_return_status_t
2863 cy_as_usb_ack_setup_packet(cy_as_device_handle handle,
2864 cy_as_function_callback cb,
2867 cy_as_return_status_t ret;
2868 cy_as_ll_request_response *req_p;
2869 cy_as_ll_request_response *reply_p;
2870 cy_as_func_c_b_node *cbnode;
2872 cy_as_device *dev_p = (cy_as_device *)handle;
2873 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2874 return CY_AS_ERROR_INVALID_HANDLE;
2876 ret = is_usb_active(dev_p);
2877 if (ret != CY_AS_ERROR_SUCCESS)
2880 if (cy_as_device_is_in_callback(dev_p) && cb == 0)
2881 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2883 cy_as_hal_assert(cb != 0);
2885 cbnode = cy_as_create_func_c_b_node(cb, client);
2887 return CY_AS_ERROR_OUT_OF_MEMORY;
2889 req_p = cy_as_ll_create_request(dev_p, 0,
2890 CY_RQT_USB_RQT_CONTEXT, 2);
2892 return CY_AS_ERROR_OUT_OF_MEMORY;
2894 reply_p = cy_as_ll_create_response(dev_p, 1);
2896 cy_as_ll_destroy_request(dev_p, req_p);
2897 return CY_AS_ERROR_OUT_OF_MEMORY;
2900 cy_as_ll_init_request(req_p, CY_RQT_ACK_SETUP_PACKET,
2901 CY_RQT_USB_RQT_CONTEXT, 1);
2902 cy_as_ll_init_response(reply_p, 1);
2904 req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
2906 cy_as_insert_c_b_node(dev_p->func_cbs_usb, cbnode);
2908 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
2909 cy_false, cy_as_usb_ack_callback);
2915 * Flush all data in logical EP that is being NAK-ed or
2916 * Stall-ed, so that this does not continue to block data
2917 * on other LEPs that use the same physical EP.
2920 cy_as_usb_flush_logical_e_p(
2921 cy_as_device *dev_p,
2924 uint16_t addr, val, count;
2926 addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
2927 val = cy_as_hal_read_register(dev_p->tag, addr);
2930 count = ((val & 0xFFF) + 1) / 2;
2932 val = cy_as_hal_read_register(dev_p->tag, ep);
2934 cy_as_hal_write_register(dev_p->tag, addr, 0);
2935 val = cy_as_hal_read_register(dev_p->tag, addr);
2939 static cy_as_return_status_t
2940 cy_as_usb_nak_stall_request(cy_as_device_handle handle,
2941 cy_as_end_point_number_t ep,
2944 cy_as_usb_function_callback cb,
2945 cy_as_function_callback fcb,
2948 cy_as_return_status_t ret;
2949 cy_as_ll_request_response *req_p , *reply_p;
2952 cy_as_device *dev_p = (cy_as_device *)handle;
2953 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2954 return CY_AS_ERROR_INVALID_HANDLE;
2957 cy_as_hal_assert(fcb == 0);
2959 cy_as_hal_assert(cb == 0);
2961 ret = is_usb_active(dev_p);
2962 if (ret != CY_AS_ERROR_SUCCESS)
2965 if (cy_as_device_is_in_callback(dev_p) && cb == 0 && fcb == 0)
2966 return CY_AS_ERROR_INVALID_IN_CALLBACK;
2968 req_p = cy_as_ll_create_request(dev_p,
2969 request, CY_RQT_USB_RQT_CONTEXT, 2);
2971 return CY_AS_ERROR_OUT_OF_MEMORY;
2973 /* A single status word response type */
2974 reply_p = cy_as_ll_create_response(dev_p, 1);
2976 cy_as_ll_destroy_request(dev_p, req_p);
2977 return CY_AS_ERROR_OUT_OF_MEMORY;
2980 /* Set the endpoint */
2982 cy_as_ll_request_response__set_word(req_p, 0, data);
2984 /* Set stall state to stalled */
2985 cy_as_ll_request_response__set_word(req_p, 1, (uint8_t)state);
2989 cy_as_c_b_queue *queue;
2991 cbnode = cy_as_create_usb_func_c_b_node(cb, client);
2992 queue = dev_p->usb_func_cbs;
2994 cbnode = cy_as_create_func_c_b_node(fcb, client);
2995 queue = dev_p->func_cbs_usb;
2996 req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
3000 ret = CY_AS_ERROR_OUT_OF_MEMORY;
3003 cy_as_insert_c_b_node(queue, cbnode);
3006 if (cy_as_device_is_setup_packet(dev_p)) {
3007 /* No Ack is needed on a stall request on EP0 */
3008 if ((state == cy_true) && (ep == 0)) {
3009 cy_as_device_set_ep0_stalled(dev_p);
3011 cy_as_device_set_ack_delayed(dev_p);
3013 CY_AS_REQUEST_RESPONSE_DELAY_ACK;
3017 ret = cy_as_ll_send_request(dev_p, req_p,
3018 reply_p, cy_false, cy_as_usb_func_callback);
3019 if (ret != CY_AS_ERROR_SUCCESS) {
3020 if (req_p->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
3021 cy_as_device_rem_ack_delayed(dev_p);
3022 cy_as_remove_c_b_tail_node(queue);
3027 ret = cy_as_ll_send_request_wait_reply(dev_p,
3029 if (ret != CY_AS_ERROR_SUCCESS)
3032 if (cy_as_ll_request_response__get_code(reply_p) !=
3033 CY_RESP_SUCCESS_FAILURE) {
3034 ret = CY_AS_ERROR_INVALID_RESPONSE;
3038 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3040 if ((ret == CY_AS_ERROR_SUCCESS) &&
3041 (request == CY_RQT_STALL_ENDPOINT)) {
3042 if ((ep > 1) && (state != 0) &&
3043 (dev_p->usb_config[ep].dir == cy_as_usb_out))
3044 cy_as_usb_flush_logical_e_p(dev_p, ep);
3048 cy_as_ll_destroy_request(dev_p, req_p);
3049 cy_as_ll_destroy_response(dev_p, reply_p);
3055 static cy_as_return_status_t
3056 my_handle_response_get_stall(cy_as_device *dev_p,
3057 cy_as_ll_request_response *req_p,
3058 cy_as_ll_request_response *reply_p,
3061 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3062 uint8_t code = cy_as_ll_request_response__get_code(reply_p);
3064 if (code == CY_RESP_SUCCESS_FAILURE) {
3065 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3067 } else if (code != CY_RESP_ENDPOINT_STALL) {
3068 ret = CY_AS_ERROR_INVALID_RESPONSE;
3072 *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
3073 ret = CY_AS_ERROR_SUCCESS;
3077 cy_as_ll_destroy_request(dev_p, req_p);
3078 cy_as_ll_destroy_response(dev_p, reply_p);
3083 static cy_as_return_status_t
3084 my_handle_response_get_nak(cy_as_device *dev_p,
3085 cy_as_ll_request_response *req_p,
3086 cy_as_ll_request_response *reply_p,
3089 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3090 uint8_t code = cy_as_ll_request_response__get_code(reply_p);
3092 if (code == CY_RESP_SUCCESS_FAILURE) {
3093 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3095 } else if (code != CY_RESP_ENDPOINT_NAK) {
3096 ret = CY_AS_ERROR_INVALID_RESPONSE;
3100 *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
3101 ret = CY_AS_ERROR_SUCCESS;
3105 cy_as_ll_destroy_request(dev_p, req_p);
3106 cy_as_ll_destroy_response(dev_p, reply_p);
3111 static cy_as_return_status_t
3112 cy_as_usb_get_nak_stall(cy_as_device_handle handle,
3113 cy_as_end_point_number_t ep,
3117 cy_as_function_callback cb,
3120 cy_as_return_status_t ret;
3121 cy_as_ll_request_response *req_p , *reply_p;
3124 cy_as_device *dev_p = (cy_as_device *)handle;
3128 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3129 return CY_AS_ERROR_INVALID_HANDLE;
3131 ret = is_usb_active(dev_p);
3132 if (ret != CY_AS_ERROR_SUCCESS)
3135 if (cy_as_device_is_in_callback(dev_p) && !cb)
3136 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3138 req_p = cy_as_ll_create_request(dev_p, request,
3139 CY_RQT_USB_RQT_CONTEXT, 1);
3141 return CY_AS_ERROR_OUT_OF_MEMORY;
3143 /* Set the endpoint */
3145 cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)ep);
3147 /* A single status word response type */
3148 reply_p = cy_as_ll_create_response(dev_p, 1);
3150 cy_as_ll_destroy_request(dev_p, req_p);
3151 return CY_AS_ERROR_OUT_OF_MEMORY;
3155 ret = cy_as_ll_send_request_wait_reply(dev_p,
3157 if (ret != CY_AS_ERROR_SUCCESS)
3160 if (request == CY_RQT_GET_STALL)
3161 return my_handle_response_get_stall(dev_p,
3162 req_p, reply_p, state_p);
3164 return my_handle_response_get_nak(dev_p,
3165 req_p, reply_p, state_p);
3168 cy_as_funct_c_b_type type;
3170 if (request == CY_RQT_GET_STALL)
3171 type = CY_FUNCT_CB_USB_GETSTALL;
3173 type = CY_FUNCT_CB_USB_GETNAK;
3175 ret = cy_as_misc_send_request(dev_p, cb, client, type,
3176 state_p, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
3177 req_p, reply_p, cy_as_usb_func_callback);
3179 if (ret != CY_AS_ERROR_SUCCESS)
3186 cy_as_ll_destroy_request(dev_p, req_p);
3187 cy_as_ll_destroy_response(dev_p, reply_p);
3192 cy_as_return_status_t
3193 cy_as_usb_set_nak(cy_as_device_handle handle,
3194 cy_as_end_point_number_t ep,
3195 cy_as_function_callback cb,
3198 cy_as_device *dev_p = (cy_as_device *)handle;
3199 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3200 return CY_AS_ERROR_INVALID_HANDLE;
3203 * we send the firmware the EP# with the appropriate direction
3204 * bit, regardless of what the user gave us.
3207 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3210 if (dev_p->mtp_count > 0)
3211 return CY_AS_ERROR_NOT_VALID_IN_MTP;
3213 return cy_as_usb_nak_stall_request(handle, ep,
3214 CY_RQT_ENDPOINT_SET_NAK, cy_true, 0, cb, client);
3218 cy_as_return_status_t
3219 cy_as_usb_clear_nak(cy_as_device_handle handle,
3220 cy_as_end_point_number_t ep,
3221 cy_as_function_callback cb,
3224 cy_as_device *dev_p = (cy_as_device *)handle;
3225 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3226 return CY_AS_ERROR_INVALID_HANDLE;
3229 * we send the firmware the EP# with the appropriate
3230 * direction bit, regardless of what the user gave us.
3233 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3236 if (dev_p->mtp_count > 0)
3237 return CY_AS_ERROR_NOT_VALID_IN_MTP;
3239 return cy_as_usb_nak_stall_request(handle, ep,
3240 CY_RQT_ENDPOINT_SET_NAK, cy_false, 0, cb, client);
3243 cy_as_return_status_t
3244 cy_as_usb_get_nak(cy_as_device_handle handle,
3245 cy_as_end_point_number_t ep,
3247 cy_as_function_callback cb,
3250 cy_as_device *dev_p = (cy_as_device *)handle;
3251 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3252 return CY_AS_ERROR_INVALID_HANDLE;
3255 * we send the firmware the EP# with the appropriate
3256 * direction bit, regardless of what the user gave us.
3259 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3262 if (dev_p->mtp_count > 0)
3263 return CY_AS_ERROR_NOT_VALID_IN_MTP;
3265 return cy_as_usb_get_nak_stall(handle, ep,
3266 CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK,
3271 cy_as_return_status_t
3272 cy_as_usb_set_stall(cy_as_device_handle handle,
3273 cy_as_end_point_number_t ep,
3274 cy_as_function_callback cb,
3277 cy_as_device *dev_p = (cy_as_device *)handle;
3278 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3279 return CY_AS_ERROR_INVALID_HANDLE;
3282 * we send the firmware the EP# with the appropriate
3283 * direction bit, regardless of what the user gave us.
3286 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3289 if (dev_p->mtp_turbo_active)
3290 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
3292 return cy_as_usb_nak_stall_request(handle, ep,
3293 CY_RQT_STALL_ENDPOINT, cy_true, 0, cb, client);
3296 cy_as_return_status_t
3297 cy_as_usb_clear_stall(cy_as_device_handle handle,
3298 cy_as_end_point_number_t ep,
3299 cy_as_function_callback cb,
3302 cy_as_device *dev_p = (cy_as_device *)handle;
3303 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3304 return CY_AS_ERROR_INVALID_HANDLE;
3307 * we send the firmware the EP# with the appropriate
3308 * direction bit, regardless of what the user gave us.
3311 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3314 if (dev_p->mtp_turbo_active)
3315 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
3317 return cy_as_usb_nak_stall_request(handle, ep,
3318 CY_RQT_STALL_ENDPOINT, cy_false, 0, cb, client);
3321 cy_as_return_status_t
3322 cy_as_usb_get_stall(cy_as_device_handle handle,
3323 cy_as_end_point_number_t ep,
3325 cy_as_function_callback cb,
3328 cy_as_device *dev_p = (cy_as_device *)handle;
3329 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3330 return CY_AS_ERROR_INVALID_HANDLE;
3333 * we send the firmware the EP# with the appropriate
3334 * direction bit, regardless of what the user gave us.
3337 if (dev_p->usb_config[ep].dir == cy_as_usb_in)
3340 if (dev_p->mtp_turbo_active)
3341 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
3343 return cy_as_usb_get_nak_stall(handle, ep,
3344 CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client);
3347 cy_as_return_status_t
3348 cy_as_usb_signal_remote_wakeup(cy_as_device_handle handle,
3349 cy_as_function_callback cb,
3352 cy_as_return_status_t ret;
3353 cy_as_ll_request_response *req_p , *reply_p;
3355 cy_as_device *dev_p = (cy_as_device *)handle;
3356 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3357 return CY_AS_ERROR_INVALID_HANDLE;
3359 ret = is_usb_active(dev_p);
3360 if (ret != CY_AS_ERROR_SUCCESS)
3363 if (cy_as_device_is_in_callback(dev_p))
3364 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3366 if (dev_p->usb_last_event != cy_as_event_usb_suspend)
3367 return CY_AS_ERROR_NOT_IN_SUSPEND;
3369 req_p = cy_as_ll_create_request(dev_p,
3370 CY_RQT_USB_REMOTE_WAKEUP, CY_RQT_USB_RQT_CONTEXT, 0);
3372 return CY_AS_ERROR_OUT_OF_MEMORY;
3374 /* A single status word response type */
3375 reply_p = cy_as_ll_create_response(dev_p, 1);
3377 cy_as_ll_destroy_request(dev_p, req_p);
3378 return CY_AS_ERROR_OUT_OF_MEMORY;
3382 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3383 if (ret != CY_AS_ERROR_SUCCESS)
3386 if (cy_as_ll_request_response__get_code(reply_p) ==
3387 CY_RESP_SUCCESS_FAILURE)
3388 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3390 ret = CY_AS_ERROR_INVALID_RESPONSE;
3392 ret = cy_as_misc_send_request(dev_p, cb, client,
3393 CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP, 0,
3394 dev_p->func_cbs_usb,
3395 CY_AS_REQUEST_RESPONSE_EX, req_p,
3396 reply_p, cy_as_usb_func_callback);
3398 if (ret != CY_AS_ERROR_SUCCESS)
3404 cy_as_ll_destroy_request(dev_p, req_p);
3405 cy_as_ll_destroy_response(dev_p, reply_p);
3410 cy_as_return_status_t
3411 cy_as_usb_set_m_s_report_threshold(cy_as_device_handle handle,
3412 uint32_t wr_sectors,
3413 uint32_t rd_sectors,
3414 cy_as_function_callback cb,
3417 cy_as_return_status_t ret;
3418 cy_as_ll_request_response *req_p , *reply_p;
3420 cy_as_device *dev_p = (cy_as_device *)handle;
3421 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3422 return CY_AS_ERROR_INVALID_HANDLE;
3424 ret = is_usb_active(dev_p);
3425 if (ret != CY_AS_ERROR_SUCCESS)
3428 if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
3429 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3431 /* Check if the firmware version supports this feature. */
3432 if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] ==
3433 (1 << cy_as_media_nand)))
3434 return CY_AS_ERROR_NOT_SUPPORTED;
3436 req_p = cy_as_ll_create_request(dev_p, CY_RQT_USB_STORAGE_MONITOR,
3437 CY_RQT_USB_RQT_CONTEXT, 4);
3439 return CY_AS_ERROR_OUT_OF_MEMORY;
3441 /* A single status word response type */
3442 reply_p = cy_as_ll_create_response(dev_p, 1);
3444 cy_as_ll_destroy_request(dev_p, req_p);
3445 return CY_AS_ERROR_OUT_OF_MEMORY;
3448 /* Set the read and write count parameters into
3449 * the request structure. */
3450 cy_as_ll_request_response__set_word(req_p, 0,
3451 (uint16_t)((wr_sectors >> 16) & 0xFFFF));
3452 cy_as_ll_request_response__set_word(req_p, 1,
3453 (uint16_t)(wr_sectors & 0xFFFF));
3454 cy_as_ll_request_response__set_word(req_p, 2,
3455 (uint16_t)((rd_sectors >> 16) & 0xFFFF));
3456 cy_as_ll_request_response__set_word(req_p, 3,
3457 (uint16_t)(rd_sectors & 0xFFFF));
3460 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3461 if (ret != CY_AS_ERROR_SUCCESS)
3464 if (cy_as_ll_request_response__get_code(reply_p) ==
3465 CY_RESP_SUCCESS_FAILURE)
3466 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3468 ret = CY_AS_ERROR_INVALID_RESPONSE;
3470 ret = cy_as_misc_send_request(dev_p, cb, client,
3471 CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD, 0,
3472 dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
3473 req_p, reply_p, cy_as_usb_func_callback);
3475 if (ret != CY_AS_ERROR_SUCCESS)
3481 cy_as_ll_destroy_request(dev_p, req_p);
3482 cy_as_ll_destroy_response(dev_p, reply_p);
3487 cy_as_return_status_t
3488 cy_as_usb_select_m_s_partitions(
3489 cy_as_device_handle handle,
3490 cy_as_bus_number_t bus,
3492 cy_as_usb_m_s_type_t type,
3493 cy_as_function_callback cb,
3496 cy_as_return_status_t ret;
3497 cy_as_ll_request_response *req_p , *reply_p;
3500 cy_as_device *dev_p = (cy_as_device *)handle;
3501 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
3502 return CY_AS_ERROR_INVALID_HANDLE;
3504 ret = is_usb_active(dev_p);
3505 if (ret != CY_AS_ERROR_SUCCESS)
3508 /* This API has to be made before SetEnumConfig is called. */
3509 if (dev_p->usb_config[0].enabled)
3510 return CY_AS_ERROR_INVALID_CALL_SEQUENCE;
3512 if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
3513 return CY_AS_ERROR_INVALID_IN_CALLBACK;
3515 req_p = cy_as_ll_create_request(dev_p, CY_RQT_MS_PARTITION_SELECT,
3516 CY_RQT_USB_RQT_CONTEXT, 2);
3518 return CY_AS_ERROR_OUT_OF_MEMORY;
3520 /* A single status word response type */
3521 reply_p = cy_as_ll_create_response(dev_p, 1);
3523 cy_as_ll_destroy_request(dev_p, req_p);
3524 return CY_AS_ERROR_OUT_OF_MEMORY;
3527 /* Set the read and write count parameters into
3528 * the request structure. */
3529 cy_as_ll_request_response__set_word(req_p, 0,
3530 (uint16_t)((bus << 8) | device));
3533 if ((type == cy_as_usb_m_s_unit0) || (type == cy_as_usb_m_s_both))
3535 if ((type == cy_as_usb_m_s_unit1) || (type == cy_as_usb_m_s_both))
3538 cy_as_ll_request_response__set_word(req_p, 1, val);
3541 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3542 if (ret != CY_AS_ERROR_SUCCESS)
3545 if (cy_as_ll_request_response__get_code(reply_p) ==
3546 CY_RESP_SUCCESS_FAILURE)
3547 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3549 ret = CY_AS_ERROR_INVALID_RESPONSE;
3551 ret = cy_as_misc_send_request(dev_p, cb, client,
3552 CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_usb,
3553 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
3554 cy_as_usb_func_callback);
3556 if (ret != CY_AS_ERROR_SUCCESS)
3562 cy_as_ll_destroy_request(dev_p, req_p);
3563 cy_as_ll_destroy_response(dev_p, reply_p);
3569 cy_as_usb_func_callback(
3570 cy_as_device *dev_p,
3572 cy_as_ll_request_response *rqt,
3573 cy_as_ll_request_response *resp,
3574 cy_as_return_status_t stat)
3576 cy_as_usb_func_c_b_node* node = (cy_as_usb_func_c_b_node *)
3577 dev_p->usb_func_cbs->head_p;
3578 cy_as_func_c_b_node* fnode = (cy_as_func_c_b_node *)
3579 dev_p->func_cbs_usb->head_p;
3580 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3582 cy_as_device_handle h = (cy_as_device_handle)dev_p;
3583 cy_bool delayed_ack = (rqt->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
3584 == CY_AS_REQUEST_RESPONSE_DELAY_ACK;
3585 cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
3586 == CY_AS_REQUEST_RESPONSE_EX;
3587 cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
3588 == CY_AS_REQUEST_RESPONSE_MS;
3592 if (!ex_request && !ms_request) {
3593 cy_as_hal_assert(dev_p->usb_func_cbs->count != 0);
3594 cy_as_hal_assert(dev_p->usb_func_cbs->type ==
3597 cy_as_hal_assert(dev_p->func_cbs_usb->count != 0);
3598 cy_as_hal_assert(dev_p->func_cbs_usb->type == CYAS_FUNC_CB);
3603 /* The Handlers are responsible for Deleting the rqt and resp when
3606 code = cy_as_ll_request_response__get_code(rqt);
3608 case CY_RQT_START_USB:
3609 ret = my_handle_response_usb_start(dev_p, rqt, resp, stat);
3611 case CY_RQT_STOP_USB:
3612 ret = my_handle_response_usb_stop(dev_p, rqt, resp, stat);
3614 case CY_RQT_SET_CONNECT_STATE:
3615 if (!cy_as_ll_request_response__get_word(rqt, 0))
3616 ret = my_handle_response_disconnect(
3617 dev_p, rqt, resp, stat);
3619 ret = my_handle_response_connect(
3620 dev_p, rqt, resp, stat);
3622 case CY_RQT_GET_CONNECT_STATE:
3624 case CY_RQT_SET_USB_CONFIG:
3625 ret = my_handle_response_set_enum_config(dev_p, rqt, resp);
3627 case CY_RQT_GET_USB_CONFIG:
3628 cy_as_hal_assert(fnode->data != 0);
3629 ret = my_handle_response_get_enum_config(dev_p,
3630 rqt, resp, fnode->data);
3632 case CY_RQT_STALL_ENDPOINT:
3633 ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
3634 state = (uint8_t)cy_as_ll_request_response__get_word(rqt, 1);
3635 ret = my_handle_response_no_data(dev_p, rqt, resp);
3636 if ((ret == CY_AS_ERROR_SUCCESS) && (ep > 1) && (state != 0)
3637 && (dev_p->usb_config[ep].dir == cy_as_usb_out))
3638 cy_as_usb_flush_logical_e_p(dev_p, ep);
3640 case CY_RQT_GET_STALL:
3641 cy_as_hal_assert(fnode->data != 0);
3642 ret = my_handle_response_get_stall(dev_p,
3643 rqt, resp, (cy_bool *)fnode->data);
3645 case CY_RQT_SET_DESCRIPTOR:
3646 ret = my_handle_response_no_data(dev_p, rqt, resp);
3648 case CY_RQT_GET_DESCRIPTOR:
3649 cy_as_hal_assert(fnode->data != 0);
3650 ret = my_handle_response_get_descriptor(dev_p,
3651 rqt, resp, (cy_as_get_descriptor_data *)fnode->data);
3653 case CY_RQT_SET_USB_CONFIG_REGISTERS:
3654 ret = my_handle_response_no_data(dev_p, rqt, resp);
3655 if (ret == CY_AS_ERROR_SUCCESS)
3656 ret = cy_as_usb_setup_dma(dev_p);
3658 case CY_RQT_ENDPOINT_SET_NAK:
3659 ret = my_handle_response_no_data(dev_p, rqt, resp);
3661 case CY_RQT_GET_ENDPOINT_NAK:
3662 cy_as_hal_assert(fnode->data != 0);
3663 ret = my_handle_response_get_nak(dev_p,
3664 rqt, resp, (cy_bool *)fnode->data);
3666 case CY_RQT_ACK_SETUP_PACKET:
3668 case CY_RQT_USB_REMOTE_WAKEUP:
3669 ret = my_handle_response_no_data(dev_p, rqt, resp);
3671 case CY_RQT_CLEAR_DESCRIPTORS:
3672 ret = my_handle_response_no_data(dev_p, rqt, resp);
3674 case CY_RQT_USB_STORAGE_MONITOR:
3675 ret = my_handle_response_no_data(dev_p, rqt, resp);
3677 case CY_RQT_MS_PARTITION_SELECT:
3678 ret = my_handle_response_no_data(dev_p, rqt, resp);
3681 ret = CY_AS_ERROR_INVALID_RESPONSE;
3682 cy_as_hal_assert(cy_false);
3687 * if the low level layer returns a direct error, use
3688 * the corresponding error code. if not, use the error
3689 * code based on the response from firmware.
3691 if (stat == CY_AS_ERROR_SUCCESS)
3694 if (ex_request || ms_request) {
3695 fnode->cb_p((cy_as_device_handle)dev_p, stat,
3696 fnode->client_data, fnode->data_type, fnode->data);
3697 cy_as_remove_c_b_node(dev_p->func_cbs_usb);
3699 node->cb_p((cy_as_device_handle)dev_p, stat,
3701 cy_as_remove_c_b_node(dev_p->usb_func_cbs);
3705 cy_as_hal_assert(cy_as_device_is_ack_delayed(dev_p));
3706 cy_as_device_rem_ack_delayed(dev_p);
3709 * send the ACK if required.
3711 if (!cy_as_device_is_ack_delayed(dev_p))
3712 cy_as_usb_ack_setup_packet(h,
3713 usb_ack_callback, 0);