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