1 /* Cypress West Bridge API header file (cyasmtp.h)
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/cyasmtp.h"
24 #include "../../include/linux/westbridge/cyaserr.h"
25 #include "../../include/linux/westbridge/cyasdma.h"
26 #include "../../include/linux/westbridge/cyaslowlevel.h"
29 cy_as_mtp_func_callback(cy_as_device *dev_p,
31 cy_as_ll_request_response *rqt,
32 cy_as_ll_request_response *resp,
33 cy_as_return_status_t stat);
35 static cy_as_return_status_t
36 is_mtp_active(cy_as_device *dev_p)
38 if (!cy_as_device_is_configured(dev_p))
39 return CY_AS_ERROR_NOT_CONFIGURED;
41 if (!cy_as_device_is_firmware_loaded(dev_p))
42 return CY_AS_ERROR_NO_FIRMWARE;
44 if (dev_p->mtp_count == 0)
45 return CY_AS_ERROR_NOT_RUNNING;
47 if (cy_as_device_is_in_suspend_mode(dev_p))
48 return CY_AS_ERROR_IN_SUSPEND;
50 return CY_AS_ERROR_SUCCESS;
54 my_mtp_request_callback(cy_as_device *dev_p,
56 cy_as_ll_request_response *req_p,
57 cy_as_ll_request_response *resp_p,
58 cy_as_return_status_t ret)
60 uint16_t val, ev, status;
61 uint16_t mtp_datalen = 0;
62 uint32_t bytecount_l, bytecount_h;
63 cy_as_mtp_send_object_complete_data send_obj_data;
64 cy_as_mtp_get_object_complete_data get_obj_data;
65 cy_as_dma_end_point *ep_p;
67 uint8_t code = cy_as_ll_request_response__get_code(req_p);
74 case CY_RQT_MTP_EVENT:
75 val = cy_as_ll_request_response__get_word(req_p, 0);
76 /* MSB indicates status of read/write */
77 status = (val >> 8) & 0xFF;
81 case 0: /* SendObject Complete */
84 cy_as_ll_request_response__get_word
87 cy_as_ll_request_response__get_word
89 send_obj_data.byte_count =
90 (bytecount_h << 16) | bytecount_l;
92 send_obj_data.status = status;
94 /* use the byte count again */
96 cy_as_ll_request_response__get_word
99 cy_as_ll_request_response__get_word
101 send_obj_data.transaction_id =
102 (bytecount_h << 16) | bytecount_l;
104 dev_p->mtp_turbo_active = cy_false;
106 if (dev_p->mtp_event_cb)
108 (cy_as_device_handle) dev_p,
109 cy_as_mtp_send_object_complete,
114 case 1: /* GetObject Complete */
117 cy_as_ll_request_response__get_word
120 cy_as_ll_request_response__get_word
123 get_obj_data.byte_count =
124 (bytecount_h << 16) | bytecount_l;
126 get_obj_data.status = status;
128 dev_p->mtp_turbo_active = cy_false;
130 if (dev_p->mtp_event_cb)
132 (cy_as_device_handle) dev_p,
133 cy_as_mtp_get_object_complete,
138 case 2: /* BlockTable Needed */
140 if (dev_p->mtp_event_cb)
142 (cy_as_device_handle) dev_p,
143 cy_as_mtp_block_table_needed, 0);
147 cy_as_hal_print_message("invalid event type\n");
148 cy_as_ll_send_data_response(dev_p,
149 CY_RQT_TUR_RQT_CONTEXT,
150 CY_RESP_MTP_INVALID_EVENT,
156 case CY_RQT_TURBO_CMD_FROM_HOST:
159 cy_as_ll_request_response__get_word(req_p, 1);
161 /* Get the endpoint pointer based on
162 * the endpoint number */
163 ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_READ_ENDPOINT);
165 /* The event should arrive only after the DMA operation
166 * has been queued. */
167 cy_as_hal_assert(ep_p->queue_p != 0);
169 /* Put the len in ep data information in
170 * dmaqueue and kick start the queue */
171 cy_as_hal_assert(ep_p->queue_p->size >= mtp_datalen);
173 if (mtp_datalen == 0) {
174 cy_as_dma_completed_callback(dev_p->tag,
175 CY_AS_MTP_READ_ENDPOINT, 0,
176 CY_AS_ERROR_SUCCESS);
178 ep_p->maxhwdata = mtp_datalen;
181 * make sure that the DMA status for this
182 * EP is not running, so that the call to
183 * cy_as_dma_kick_start gets this transfer
184 * going. note: in MTP mode, we never leave
185 * a DMA transfer of greater than one packet
186 * running. so, it is okay to override the
187 * status here and start the next packet
190 cy_as_dma_end_point_set_stopped(ep_p);
192 /* Kick start the queue if it is not running */
193 cy_as_dma_kick_start(dev_p,
194 CY_AS_MTP_READ_ENDPOINT);
199 case CY_RQT_TURBO_START_WRITE_DMA:
202 * now that the firmware is ready to receive the
203 * next packet of data, start the corresponding
204 * DMA transfer. first, ensure that a DMA
205 * operation is still pending in the queue for the
208 cy_as_ll_send_status_response(dev_p,
209 CY_RQT_TUR_RQT_CONTEXT,
210 CY_AS_ERROR_SUCCESS, 0);
212 ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
213 cy_as_hal_assert(ep_p->queue_p != 0);
215 cy_as_dma_end_point_set_stopped(ep_p);
216 cy_as_dma_kick_start(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
221 cy_as_hal_print_message("invalid request received "
224 cy_as_ll_send_data_response(dev_p, CY_RQT_TUR_RQT_CONTEXT,
225 CY_RESP_INVALID_REQUEST, sizeof(val), &val);
230 static cy_as_return_status_t
231 my_handle_response_no_data(cy_as_device *dev_p,
232 cy_as_ll_request_response *req_p,
233 cy_as_ll_request_response *reply_p)
235 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
237 if (cy_as_ll_request_response__get_code(reply_p) !=
238 CY_RESP_SUCCESS_FAILURE) {
239 ret = CY_AS_ERROR_INVALID_RESPONSE;
243 ret = cy_as_ll_request_response__get_word(reply_p, 0);
246 cy_as_ll_destroy_request(dev_p, req_p);
247 cy_as_ll_destroy_response(dev_p, reply_p);
252 static cy_as_return_status_t
253 my_handle_response_mtp_start(cy_as_device *dev_p,
254 cy_as_ll_request_response *req_p,
255 cy_as_ll_request_response *reply_p,
256 cy_as_return_status_t ret)
258 if (ret != CY_AS_ERROR_SUCCESS)
261 if (cy_as_ll_request_response__get_code(reply_p) !=
262 CY_RESP_SUCCESS_FAILURE) {
263 ret = CY_AS_ERROR_INVALID_RESPONSE;
267 ret = cy_as_ll_request_response__get_word(reply_p, 0);
268 if (ret != CY_AS_ERROR_SUCCESS)
273 cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_READ_ENDPOINT,
274 cy_true, cy_as_direction_out);
275 dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].enabled = cy_true;
276 dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].dir = cy_as_usb_out;
277 dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].type = cy_as_usb_bulk;
279 cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_WRITE_ENDPOINT,
280 cy_true, cy_as_direction_in);
281 dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].enabled = cy_true;
282 dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].dir = cy_as_usb_in;
283 dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].type = cy_as_usb_bulk;
285 /* Packet size is 512 bytes */
286 cy_as_dma_set_max_dma_size(dev_p, 0x02, 0x0200);
287 /* Packet size is 64 bytes until a switch to high speed happens.*/
288 cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
291 cy_as_ll_destroy_request(dev_p, req_p);
292 cy_as_ll_destroy_response(dev_p, reply_p);
294 if (ret != CY_AS_ERROR_SUCCESS)
295 cy_as_ll_register_request_callback(dev_p,
296 CY_RQT_TUR_RQT_CONTEXT, 0);
298 cy_as_device_clear_m_s_s_pending(dev_p);
304 cy_as_return_status_t
305 cy_as_mtp_start(cy_as_device_handle handle,
306 cy_as_mtp_event_callback event_c_b,
307 cy_as_function_callback cb,
311 cy_as_ll_request_response *req_p, *reply_p;
312 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
315 dev_p = (cy_as_device *)handle;
316 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
317 return CY_AS_ERROR_INVALID_HANDLE;
319 if (!cy_as_device_is_configured(dev_p))
320 return CY_AS_ERROR_NOT_CONFIGURED;
322 if (!cy_as_device_is_firmware_loaded(dev_p))
323 return CY_AS_ERROR_NO_FIRMWARE;
325 if (cy_as_device_is_in_suspend_mode(dev_p))
326 return CY_AS_ERROR_IN_SUSPEND;
328 if (cy_as_device_is_in_callback(dev_p))
329 return CY_AS_ERROR_INVALID_IN_CALLBACK;
331 if (cy_as_device_is_m_s_s_pending(dev_p))
332 return CY_AS_ERROR_STARTSTOP_PENDING;
334 if (dev_p->storage_count == 0)
335 return CY_AS_ERROR_NOT_RUNNING;
337 if (dev_p->usb_count == 0)
338 return CY_AS_ERROR_NOT_RUNNING;
340 if (dev_p->is_mtp_firmware == 0)
341 return CY_AS_ERROR_NOT_SUPPORTED;
343 cy_as_device_set_m_s_s_pending(dev_p);
345 if (dev_p->mtp_count == 0) {
347 dev_p->mtp_event_cb = event_c_b;
349 * we register here becuase the start request may cause
350 * events to occur before the response to the start request.
352 cy_as_ll_register_request_callback(dev_p,
353 CY_RQT_TUR_RQT_CONTEXT, my_mtp_request_callback);
355 /* Create the request to send to the West Bridge device */
356 req_p = cy_as_ll_create_request(dev_p,
357 CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0);
359 cy_as_device_clear_m_s_s_pending(dev_p);
360 return CY_AS_ERROR_OUT_OF_MEMORY;
363 /* Reserve space for the reply, the reply data will
364 * not exceed one word */
365 reply_p = cy_as_ll_create_response(dev_p, 1);
367 cy_as_ll_destroy_request(dev_p, req_p);
368 cy_as_device_clear_m_s_s_pending(dev_p);
369 return CY_AS_ERROR_OUT_OF_MEMORY;
373 ret = cy_as_ll_send_request_wait_reply(dev_p,
375 if (ret != CY_AS_ERROR_SUCCESS)
378 return my_handle_response_mtp_start(dev_p, req_p,
381 ret = cy_as_misc_send_request(dev_p, cb, client,
382 CY_FUNCT_CB_MTP_START, 0, dev_p->func_cbs_mtp,
383 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
384 cy_as_mtp_func_callback);
386 if (ret != CY_AS_ERROR_SUCCESS)
393 cy_as_ll_destroy_request(dev_p, req_p);
394 cy_as_ll_destroy_response(dev_p, reply_p);
398 cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0);
401 cy_as_device_clear_m_s_s_pending(dev_p);
405 EXPORT_SYMBOL(cy_as_mtp_start);
407 static cy_as_return_status_t
408 my_handle_response_mtp_stop(cy_as_device *dev_p,
409 cy_as_ll_request_response *req_p,
410 cy_as_ll_request_response *reply_p,
411 cy_as_return_status_t ret)
413 if (ret != CY_AS_ERROR_SUCCESS)
416 if (cy_as_ll_request_response__get_code(reply_p) !=
417 CY_RESP_SUCCESS_FAILURE) {
418 ret = CY_AS_ERROR_INVALID_RESPONSE;
422 ret = cy_as_ll_request_response__get_word(reply_p, 0);
423 if (ret != CY_AS_ERROR_SUCCESS)
427 * we sucessfully shutdown the stack, so decrement
428 * to make the count zero.
433 cy_as_ll_destroy_request(dev_p, req_p);
434 cy_as_ll_destroy_response(dev_p, reply_p);
436 if (ret != CY_AS_ERROR_SUCCESS)
437 cy_as_ll_register_request_callback(dev_p,
438 CY_RQT_TUR_RQT_CONTEXT, 0);
440 cy_as_device_clear_m_s_s_pending(dev_p);
445 cy_as_return_status_t
446 cy_as_mtp_stop(cy_as_device_handle handle,
447 cy_as_function_callback cb,
451 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
452 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
456 cy_as_log_debug_message(6, "cy_as_mtp_stop called");
458 dev_p = (cy_as_device *)handle;
459 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
460 return CY_AS_ERROR_INVALID_HANDLE;
462 ret = is_mtp_active(dev_p);
463 if (ret != CY_AS_ERROR_SUCCESS)
466 if (cy_as_device_is_in_callback(dev_p))
467 return CY_AS_ERROR_INVALID_IN_CALLBACK;
469 if (cy_as_device_is_m_s_s_pending(dev_p))
470 return CY_AS_ERROR_STARTSTOP_PENDING;
472 cy_as_device_set_m_s_s_pending(dev_p);
474 if (dev_p->mtp_count == 1) {
475 /* Create the request to send to the West
477 req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_MTP,
478 CY_RQT_TUR_RQT_CONTEXT, 0);
480 ret = CY_AS_ERROR_OUT_OF_MEMORY;
484 /* Reserve space for the reply, the reply data will
485 * not exceed one word */
486 reply_p = cy_as_ll_create_response(dev_p, 1);
488 ret = CY_AS_ERROR_OUT_OF_MEMORY;
493 ret = cy_as_ll_send_request_wait_reply(dev_p,
495 if (ret != CY_AS_ERROR_SUCCESS)
498 return my_handle_response_mtp_stop(dev_p, req_p,
501 ret = cy_as_misc_send_request(dev_p, cb, client,
502 CY_FUNCT_CB_MTP_STOP, 0, dev_p->func_cbs_mtp,
503 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
504 cy_as_mtp_func_callback);
506 if (ret != CY_AS_ERROR_SUCCESS)
513 cy_as_ll_destroy_request(dev_p, req_p);
514 cy_as_ll_destroy_response(dev_p, reply_p);
515 } else if (dev_p->mtp_count > 1) {
520 cb(handle, ret, client, CY_FUNCT_CB_MTP_STOP, 0);
523 cy_as_device_clear_m_s_s_pending(dev_p);
532 cy_as_ll_request_response *rqt,
533 cy_as_ll_request_response *resp,
534 cy_as_return_status_t ret)
536 cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
538 if (ret == CY_AS_ERROR_SUCCESS) {
539 if (cy_as_ll_request_response__get_code(resp) !=
540 CY_RESP_SUCCESS_FAILURE)
541 ret = CY_AS_ERROR_INVALID_RESPONSE;
543 ret = cy_as_ll_request_response__get_word(resp, 0);
546 if (ret != CY_AS_ERROR_SUCCESS) {
547 /* Firmware failed the request. Cancel the DMA transfer. */
548 cy_as_dma_cancel(dev_p, 0x04, CY_AS_ERROR_CANCELED);
549 cy_as_device_clear_storage_async_pending(dev_p);
552 cy_as_ll_destroy_response(dev_p, resp);
553 cy_as_ll_destroy_request(dev_p, rqt);
557 async_write_request_callback(cy_as_device *dev_p,
558 cy_as_end_point_number_t ep, void *buf_p, uint32_t size,
559 cy_as_return_status_t err)
561 cy_as_device_handle h;
562 cy_as_function_callback cb;
569 cy_as_log_debug_message(6, "async_write_request_callback called");
571 h = (cy_as_device_handle)dev_p;
576 cy_as_device_clear_storage_async_pending(dev_p);
579 cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0);
584 sync_mtp_callback(cy_as_device *dev_p, cy_as_end_point_number_t ep,
585 void *buf_p, uint32_t size, cy_as_return_status_t err)
591 dev_p->mtp_error = err;
594 static cy_as_return_status_t
595 cy_as_mtp_operation(cy_as_device *dev_p,
596 cy_as_mtp_block_table *blk_table,
598 uint32_t transaction_id,
599 cy_as_function_callback cb,
604 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
605 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
607 cy_as_funct_c_b_type mtp_cb_op = 0;
610 if (dev_p->mtp_count == 0)
611 return CY_AS_ERROR_NOT_RUNNING;
613 if (rqttype == CY_RQT_INIT_SEND_OBJECT) {
614 mtp_cb_op = CY_FUNCT_CB_MTP_INIT_SEND_OBJECT;
615 dev_p->mtp_turbo_active = cy_true;
616 } else if (rqttype == CY_RQT_INIT_GET_OBJECT) {
617 mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT;
618 dev_p->mtp_turbo_active = cy_true;
620 mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE;
622 ret = is_mtp_active(dev_p);
623 if (ret != CY_AS_ERROR_SUCCESS)
626 if (CY_RQT_INIT_GET_OBJECT == rqttype)
629 /* Create the request to send to the West
631 req_p = cy_as_ll_create_request(dev_p, rqttype,
632 CY_RQT_TUR_RQT_CONTEXT, size);
634 ret = CY_AS_ERROR_OUT_OF_MEMORY;
638 /* Reserve space for the reply, the reply data will
639 * not exceed one word */
640 reply_p = cy_as_ll_create_response(dev_p, 1);
642 ret = CY_AS_ERROR_OUT_OF_MEMORY;
646 cy_as_ll_request_response__set_word(req_p, 0,
647 (uint16_t)(num_bytes & 0xFFFF));
648 cy_as_ll_request_response__set_word(req_p, 1,
649 (uint16_t)((num_bytes >> 16) & 0xFFFF));
651 /* If it is GET_OBJECT, send transaction id as well*/
652 if (CY_RQT_INIT_GET_OBJECT == rqttype) {
653 cy_as_ll_request_response__set_word(req_p, 2,
654 (uint16_t)(transaction_id & 0xFFFF));
655 cy_as_ll_request_response__set_word(req_p, 3,
656 (uint16_t)((transaction_id >> 16) & 0xFFFF));
660 /* Queue the DMA request for block table write */
661 ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
662 sizeof(cy_as_mtp_block_table), cy_false,
663 cy_false, sync_mtp_callback);
665 ret = cy_as_ll_send_request_wait_reply(dev_p,
667 if (ret != CY_AS_ERROR_SUCCESS) {
668 cy_as_dma_cancel(dev_p, 4, CY_AS_ERROR_CANCELED);
669 cy_as_device_clear_storage_async_pending(dev_p);
674 ret = cy_as_dma_drain_queue(dev_p, 4, cy_true);
675 if (ret != CY_AS_ERROR_SUCCESS)
678 ret = dev_p->mtp_error;
682 ret = cy_as_misc_send_request(dev_p, cb, client,
683 CY_FUNCT_CB_MTP_INIT_SEND_OBJECT,
684 0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
685 req_p, reply_p, cy_as_mtp_func_callback);
687 if (ret != CY_AS_ERROR_SUCCESS)
691 /* Protection from interrupt driven code */
692 /* since we are using storage EP4 check if any
693 * storage activity is pending */
694 mask = cy_as_hal_disable_interrupts();
695 if ((cy_as_device_is_storage_async_pending(dev_p)) ||
696 (dev_p->storage_wait)) {
697 cy_as_hal_enable_interrupts(mask);
698 return CY_AS_ERROR_ASYNC_PENDING;
700 cy_as_device_set_storage_async_pending(dev_p);
701 cy_as_hal_enable_interrupts(mask);
704 dev_p->mtp_client = client;
705 dev_p->mtp_op = mtp_cb_op;
707 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
708 cy_false, mtp_write_callback);
709 if (ret != CY_AS_ERROR_SUCCESS)
712 ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
713 sizeof(cy_as_mtp_block_table), cy_false, cy_false,
714 async_write_request_callback);
715 if (ret != CY_AS_ERROR_SUCCESS)
718 /* Kick start the queue if it is not running */
719 cy_as_dma_kick_start(dev_p, 4);
721 return CY_AS_ERROR_SUCCESS;
725 cy_as_ll_destroy_request(dev_p, req_p);
726 cy_as_ll_destroy_response(dev_p, reply_p);
731 cy_as_return_status_t
732 cy_as_mtp_init_send_object(cy_as_device_handle handle,
733 cy_as_mtp_block_table *blk_table,
735 cy_as_function_callback cb,
740 dev_p = (cy_as_device *)handle;
741 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
742 return CY_AS_ERROR_INVALID_HANDLE;
744 return cy_as_mtp_operation(dev_p, blk_table, num_bytes, 0, cb,
745 client, CY_RQT_INIT_SEND_OBJECT);
748 EXPORT_SYMBOL(cy_as_mtp_init_send_object);
750 cy_as_return_status_t
751 cy_as_mtp_init_get_object(cy_as_device_handle handle,
752 cy_as_mtp_block_table *blk_table,
754 uint32_t transaction_id,
755 cy_as_function_callback cb,
760 dev_p = (cy_as_device *)handle;
761 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
762 return CY_AS_ERROR_INVALID_HANDLE;
764 return cy_as_mtp_operation(dev_p, blk_table, num_bytes,
765 transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT);
768 EXPORT_SYMBOL(cy_as_mtp_init_get_object);
770 static cy_as_return_status_t
771 my_handle_response_cancel_send_object(cy_as_device *dev_p,
772 cy_as_ll_request_response *req_p,
773 cy_as_ll_request_response *reply_p,
774 cy_as_return_status_t ret)
776 if (ret != CY_AS_ERROR_SUCCESS)
779 if (cy_as_ll_request_response__get_code(reply_p) !=
780 CY_RESP_SUCCESS_FAILURE) {
781 ret = CY_AS_ERROR_INVALID_RESPONSE;
785 ret = cy_as_ll_request_response__get_word(reply_p, 0);
786 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);
797 cy_as_return_status_t
798 cy_as_mtp_cancel_send_object(cy_as_device_handle handle,
799 cy_as_function_callback cb,
803 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
804 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
807 dev_p = (cy_as_device *)handle;
808 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
809 return CY_AS_ERROR_INVALID_HANDLE;
811 if (dev_p->mtp_count == 0)
812 return CY_AS_ERROR_NOT_RUNNING;
814 /* Create the request to send to the West Bridge device */
815 req_p = cy_as_ll_create_request(dev_p,
816 CY_RQT_CANCEL_SEND_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0);
818 ret = CY_AS_ERROR_OUT_OF_MEMORY;
822 /* Reserve space for the reply, the reply data will
823 * not exceed one word */
824 reply_p = cy_as_ll_create_response(dev_p, 1);
826 ret = CY_AS_ERROR_OUT_OF_MEMORY;
831 ret = cy_as_ll_send_request_wait_reply(dev_p,
833 if (ret != CY_AS_ERROR_SUCCESS)
836 return my_handle_response_cancel_send_object(dev_p,
837 req_p, reply_p, ret);
839 ret = cy_as_misc_send_request(dev_p, cb, client,
840 CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT, 0,
841 dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
842 req_p, reply_p, cy_as_mtp_func_callback);
844 if (ret != CY_AS_ERROR_SUCCESS)
851 cy_as_ll_destroy_request(dev_p, req_p);
852 cy_as_ll_destroy_response(dev_p, reply_p);
856 EXPORT_SYMBOL(cy_as_mtp_cancel_send_object);
858 static cy_as_return_status_t
859 my_handle_response_cancel_get_object(cy_as_device *dev_p,
860 cy_as_ll_request_response *req_p,
861 cy_as_ll_request_response *reply_p,
862 cy_as_return_status_t ret)
864 if (ret != CY_AS_ERROR_SUCCESS)
867 if (cy_as_ll_request_response__get_code(reply_p) !=
868 CY_RESP_SUCCESS_FAILURE) {
869 ret = CY_AS_ERROR_INVALID_RESPONSE;
873 ret = cy_as_ll_request_response__get_word(reply_p, 0);
874 if (ret != CY_AS_ERROR_SUCCESS)
879 cy_as_ll_destroy_request(dev_p, req_p);
880 cy_as_ll_destroy_response(dev_p, reply_p);
885 cy_as_return_status_t
886 cy_as_mtp_cancel_get_object(cy_as_device_handle handle,
887 cy_as_function_callback cb,
891 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
892 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
895 dev_p = (cy_as_device *)handle;
896 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
897 return CY_AS_ERROR_INVALID_HANDLE;
899 if (dev_p->mtp_count == 0)
900 return CY_AS_ERROR_NOT_RUNNING;
902 /* Create the request to send to the West Bridge device */
903 req_p = cy_as_ll_create_request(dev_p, CY_RQT_CANCEL_GET_OBJECT,
904 CY_RQT_TUR_RQT_CONTEXT, 0);
906 ret = CY_AS_ERROR_OUT_OF_MEMORY;
910 /* Reserve space for the reply, the reply data will
911 * not exceed one word */
912 reply_p = cy_as_ll_create_response(dev_p, 1);
914 ret = CY_AS_ERROR_OUT_OF_MEMORY;
919 ret = cy_as_ll_send_request_wait_reply(dev_p,
921 if (ret != CY_AS_ERROR_SUCCESS)
924 return my_handle_response_cancel_get_object(dev_p,
925 req_p, reply_p, ret);
927 ret = cy_as_misc_send_request(dev_p, cb, client,
928 CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT, 0,
929 dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
930 req_p, reply_p, cy_as_mtp_func_callback);
932 if (ret != CY_AS_ERROR_SUCCESS)
939 cy_as_ll_destroy_request(dev_p, req_p);
940 cy_as_ll_destroy_response(dev_p, reply_p);
944 EXPORT_SYMBOL(cy_as_mtp_cancel_get_object);
946 cy_as_return_status_t
947 cy_as_mtp_send_block_table(cy_as_device_handle handle,
948 cy_as_mtp_block_table *blk_table,
949 cy_as_function_callback cb,
953 dev_p = (cy_as_device *)handle;
954 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
955 return CY_AS_ERROR_INVALID_HANDLE;
957 return cy_as_mtp_operation(dev_p, blk_table, 0, 0, cb,
958 client, CY_RQT_SEND_BLOCK_TABLE);
962 cy_as_mtp_func_callback(cy_as_device *dev_p,
964 cy_as_ll_request_response *rqt,
965 cy_as_ll_request_response *resp,
966 cy_as_return_status_t stat)
968 cy_as_func_c_b_node* node = (cy_as_func_c_b_node *)
969 dev_p->func_cbs_mtp->head_p;
970 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
972 cy_bool delay_callback = cy_false;
974 cy_as_hal_assert(dev_p->func_cbs_mtp->count != 0);
975 cy_as_hal_assert(dev_p->func_cbs_mtp->type == CYAS_FUNC_CB);
979 /* The Handlers are responsible for Deleting the
980 * rqt and resp when they are finished
982 code = cy_as_ll_request_response__get_code(rqt);
984 case CY_RQT_START_MTP:
985 ret = my_handle_response_mtp_start(dev_p, rqt,
988 case CY_RQT_STOP_MTP:
989 ret = my_handle_response_mtp_stop(dev_p, rqt,
993 case CY_RQT_INIT_SEND_OBJECT:
994 ret = my_handle_response_init_send_object(dev_p,
995 rqt, resp, stat, cy_true);
996 delay_callback = cy_true;
999 case CY_RQT_CANCEL_SEND_OBJECT:
1000 ret = my_handle_response_cancel_send_object(dev_p,
1004 case CY_RQT_INIT_GET_OBJECT:
1005 ret = my_handle_response_init_get_object(dev_p,
1006 rqt, resp, stat, cy_true);
1007 delay_callback = cy_true;
1010 case CY_RQT_CANCEL_GET_OBJECT:
1011 ret = my_handle_response_cancel_get_object(dev_p,
1015 case CY_RQT_SEND_BLOCK_TABLE:
1016 ret = my_handle_response_send_block_table(dev_p, rqt,
1017 resp, stat, cy_true);
1018 delay_callback = cy_true;
1021 case CY_RQT_ENABLE_USB_PATH:
1022 ret = my_handle_response_no_data(dev_p, rqt, resp);
1023 if (ret == CY_AS_ERROR_SUCCESS)
1024 dev_p->is_storage_only_mode = cy_false;
1027 ret = CY_AS_ERROR_INVALID_RESPONSE;
1028 cy_as_hal_assert(cy_false);
1033 * if the low level layer returns a direct error, use the
1034 * corresponding error code. if not, use the error code
1035 * based on the response from firmware.
1037 if (stat == CY_AS_ERROR_SUCCESS)
1040 if (!delay_callback) {
1041 node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
1042 node->data_type, node->data);
1043 cy_as_remove_c_b_node(dev_p->func_cbs_mtp);
1047 cy_as_return_status_t
1048 cy_as_mtp_storage_only_start(cy_as_device_handle handle)
1050 cy_as_device *dev_p = (cy_as_device *)handle;
1051 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1052 return CY_AS_ERROR_INVALID_HANDLE;
1054 if (!cy_as_device_is_configured(dev_p))
1055 return CY_AS_ERROR_NOT_CONFIGURED;
1057 if (!cy_as_device_is_firmware_loaded(dev_p))
1058 return CY_AS_ERROR_NO_FIRMWARE;
1060 if (dev_p->storage_count == 0)
1061 return CY_AS_ERROR_NOT_RUNNING;
1063 dev_p->is_storage_only_mode = cy_true;
1064 return CY_AS_ERROR_SUCCESS;
1066 EXPORT_SYMBOL(cy_as_mtp_storage_only_start);
1068 cy_as_return_status_t
1069 cy_as_mtp_storage_only_stop(cy_as_device_handle handle,
1070 cy_as_function_callback cb,
1073 cy_as_device *dev_p = (cy_as_device *)handle;
1074 cy_as_ll_request_response *req_p, *reply_p;
1075 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1077 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1078 return CY_AS_ERROR_INVALID_HANDLE;
1080 if (!cy_as_device_is_configured(dev_p))
1081 return CY_AS_ERROR_NOT_CONFIGURED;
1083 if (!cy_as_device_is_firmware_loaded(dev_p))
1084 return CY_AS_ERROR_NO_FIRMWARE;
1086 if (dev_p->storage_count == 0)
1087 return CY_AS_ERROR_NOT_RUNNING;
1089 if (dev_p->is_storage_only_mode == cy_false)
1090 return CY_AS_ERROR_SUCCESS;
1092 if (cy_as_device_is_in_callback(dev_p))
1093 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1095 req_p = cy_as_ll_create_request(dev_p,
1096 CY_RQT_ENABLE_USB_PATH, CY_RQT_TUR_RQT_CONTEXT, 1);
1098 return CY_AS_ERROR_OUT_OF_MEMORY;
1100 reply_p = cy_as_ll_create_response(dev_p, 1);
1102 cy_as_ll_destroy_request(dev_p, req_p);
1103 return CY_AS_ERROR_OUT_OF_MEMORY;
1107 ret = cy_as_ll_send_request_wait_reply(dev_p,
1109 if (ret != CY_AS_ERROR_SUCCESS)
1112 ret = my_handle_response_no_data(dev_p, req_p,
1114 if (ret == CY_AS_ERROR_SUCCESS)
1115 dev_p->is_storage_only_mode = cy_false;
1118 ret = cy_as_misc_send_request(dev_p, cb, client,
1119 CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY, 0,
1120 dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
1121 req_p, reply_p, cy_as_mtp_func_callback);
1123 if (ret != CY_AS_ERROR_SUCCESS)
1130 cy_as_ll_destroy_request(dev_p, req_p);
1131 cy_as_ll_destroy_response(dev_p, reply_p);
1135 EXPORT_SYMBOL(cy_as_mtp_storage_only_stop);