1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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"
27
28static void
29cy_as_mtp_func_callback(cy_as_device *dev_p,
30 uint8_t context,
31 cy_as_ll_request_response *rqt,
32 cy_as_ll_request_response *resp,
33 cy_as_return_status_t stat);
34
35static cy_as_return_status_t
36is_mtp_active(cy_as_device *dev_p)
37{
38 if (!cy_as_device_is_configured(dev_p))
39 return CY_AS_ERROR_NOT_CONFIGURED;
40
41 if (!cy_as_device_is_firmware_loaded(dev_p))
42 return CY_AS_ERROR_NO_FIRMWARE;
43
44 if (dev_p->mtp_count == 0)
45 return CY_AS_ERROR_NOT_RUNNING;
46
47 if (cy_as_device_is_in_suspend_mode(dev_p))
48 return CY_AS_ERROR_IN_SUSPEND;
49
50 return CY_AS_ERROR_SUCCESS;
51}
52
53static void
54my_mtp_request_callback(cy_as_device *dev_p,
55 uint8_t context,
56 cy_as_ll_request_response *req_p,
57 cy_as_ll_request_response *resp_p,
58 cy_as_return_status_t ret)
59{
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;
66
67 uint8_t code = cy_as_ll_request_response__get_code(req_p);
68
69 (void)resp_p;
70 (void)context;
71 (void)ret;
72
73 switch (code) {
74 case CY_RQT_MTP_EVENT:
75 val = cy_as_ll_request_response__get_word(req_p, 0);
76
77 status = (val >> 8) & 0xFF;
78
79 ev = val & 0xFF;
80 switch (ev) {
81 case 0:
82 {
83 bytecount_l =
84 cy_as_ll_request_response__get_word
85 (req_p, 1);
86 bytecount_h =
87 cy_as_ll_request_response__get_word
88 (req_p, 2);
89 send_obj_data.byte_count =
90 (bytecount_h << 16) | bytecount_l;
91
92 send_obj_data.status = status;
93
94
95 bytecount_l =
96 cy_as_ll_request_response__get_word
97 (req_p, 3);
98 bytecount_h =
99 cy_as_ll_request_response__get_word
100 (req_p, 4);
101 send_obj_data.transaction_id =
102 (bytecount_h << 16) | bytecount_l;
103
104 dev_p->mtp_turbo_active = cy_false;
105
106 if (dev_p->mtp_event_cb)
107 dev_p->mtp_event_cb(
108 (cy_as_device_handle) dev_p,
109 cy_as_mtp_send_object_complete,
110 &send_obj_data);
111 }
112 break;
113
114 case 1:
115 {
116 bytecount_l =
117 cy_as_ll_request_response__get_word
118 (req_p, 1);
119 bytecount_h =
120 cy_as_ll_request_response__get_word
121 (req_p, 2);
122
123 get_obj_data.byte_count =
124 (bytecount_h << 16) | bytecount_l;
125
126 get_obj_data.status = status;
127
128 dev_p->mtp_turbo_active = cy_false;
129
130 if (dev_p->mtp_event_cb)
131 dev_p->mtp_event_cb(
132 (cy_as_device_handle) dev_p,
133 cy_as_mtp_get_object_complete,
134 &get_obj_data);
135 }
136 break;
137
138 case 2:
139 {
140 if (dev_p->mtp_event_cb)
141 dev_p->mtp_event_cb(
142 (cy_as_device_handle) dev_p,
143 cy_as_mtp_block_table_needed, 0);
144 }
145 break;
146 default:
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,
151 sizeof(ev), &ev);
152 break;
153 }
154 break;
155
156 case CY_RQT_TURBO_CMD_FROM_HOST:
157 {
158 mtp_datalen =
159 cy_as_ll_request_response__get_word(req_p, 1);
160
161
162
163 ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_READ_ENDPOINT);
164
165
166
167 cy_as_hal_assert(ep_p->queue_p != 0);
168
169
170
171 cy_as_hal_assert(ep_p->queue_p->size >= mtp_datalen);
172
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);
177 } else {
178 ep_p->maxhwdata = mtp_datalen;
179
180
181
182
183
184
185
186
187
188
189
190 cy_as_dma_end_point_set_stopped(ep_p);
191
192
193 cy_as_dma_kick_start(dev_p,
194 CY_AS_MTP_READ_ENDPOINT);
195 }
196 }
197 break;
198
199 case CY_RQT_TURBO_START_WRITE_DMA:
200 {
201
202
203
204
205
206
207
208 cy_as_ll_send_status_response(dev_p,
209 CY_RQT_TUR_RQT_CONTEXT,
210 CY_AS_ERROR_SUCCESS, 0);
211
212 ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
213 cy_as_hal_assert(ep_p->queue_p != 0);
214
215 cy_as_dma_end_point_set_stopped(ep_p);
216 cy_as_dma_kick_start(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
217 }
218 break;
219
220 default:
221 cy_as_hal_print_message("invalid request received "
222 "on TUR context\n");
223 val = req_p->box0;
224 cy_as_ll_send_data_response(dev_p, CY_RQT_TUR_RQT_CONTEXT,
225 CY_RESP_INVALID_REQUEST, sizeof(val), &val);
226 break;
227 }
228}
229
230static cy_as_return_status_t
231my_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)
234{
235 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
236
237 if (cy_as_ll_request_response__get_code(reply_p) !=
238 CY_RESP_SUCCESS_FAILURE) {
239 ret = CY_AS_ERROR_INVALID_RESPONSE;
240 goto destroy;
241 }
242
243 ret = cy_as_ll_request_response__get_word(reply_p, 0);
244
245destroy:
246 cy_as_ll_destroy_request(dev_p, req_p);
247 cy_as_ll_destroy_response(dev_p, reply_p);
248
249 return ret;
250}
251
252static cy_as_return_status_t
253my_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)
257{
258 if (ret != CY_AS_ERROR_SUCCESS)
259 goto destroy;
260
261 if (cy_as_ll_request_response__get_code(reply_p) !=
262 CY_RESP_SUCCESS_FAILURE) {
263 ret = CY_AS_ERROR_INVALID_RESPONSE;
264 goto destroy;
265 }
266
267 ret = cy_as_ll_request_response__get_word(reply_p, 0);
268 if (ret != CY_AS_ERROR_SUCCESS)
269 goto destroy;
270
271 dev_p->mtp_count++;
272
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;
278
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;
284
285
286 cy_as_dma_set_max_dma_size(dev_p, 0x02, 0x0200);
287
288 cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
289
290destroy:
291 cy_as_ll_destroy_request(dev_p, req_p);
292 cy_as_ll_destroy_response(dev_p, reply_p);
293
294 if (ret != CY_AS_ERROR_SUCCESS)
295 cy_as_ll_register_request_callback(dev_p,
296 CY_RQT_TUR_RQT_CONTEXT, 0);
297
298 cy_as_device_clear_m_s_s_pending(dev_p);
299
300 return ret;
301}
302
303
304cy_as_return_status_t
305cy_as_mtp_start(cy_as_device_handle handle,
306 cy_as_mtp_event_callback event_c_b,
307 cy_as_function_callback cb,
308 uint32_t client
309 )
310{
311 cy_as_ll_request_response *req_p, *reply_p;
312 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
313 cy_as_device *dev_p;
314
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;
318
319 if (!cy_as_device_is_configured(dev_p))
320 return CY_AS_ERROR_NOT_CONFIGURED;
321
322 if (!cy_as_device_is_firmware_loaded(dev_p))
323 return CY_AS_ERROR_NO_FIRMWARE;
324
325 if (cy_as_device_is_in_suspend_mode(dev_p))
326 return CY_AS_ERROR_IN_SUSPEND;
327
328 if (cy_as_device_is_in_callback(dev_p))
329 return CY_AS_ERROR_INVALID_IN_CALLBACK;
330
331 if (cy_as_device_is_m_s_s_pending(dev_p))
332 return CY_AS_ERROR_STARTSTOP_PENDING;
333
334 if (dev_p->storage_count == 0)
335 return CY_AS_ERROR_NOT_RUNNING;
336
337 if (dev_p->usb_count == 0)
338 return CY_AS_ERROR_NOT_RUNNING;
339
340 if (dev_p->is_mtp_firmware == 0)
341 return CY_AS_ERROR_NOT_SUPPORTED;
342
343 cy_as_device_set_m_s_s_pending(dev_p);
344
345 if (dev_p->mtp_count == 0) {
346
347 dev_p->mtp_event_cb = event_c_b;
348
349
350
351
352 cy_as_ll_register_request_callback(dev_p,
353 CY_RQT_TUR_RQT_CONTEXT, my_mtp_request_callback);
354
355
356 req_p = cy_as_ll_create_request(dev_p,
357 CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0);
358 if (req_p == 0) {
359 cy_as_device_clear_m_s_s_pending(dev_p);
360 return CY_AS_ERROR_OUT_OF_MEMORY;
361 }
362
363
364
365 reply_p = cy_as_ll_create_response(dev_p, 1);
366 if (reply_p == 0) {
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;
370 }
371
372 if (cb == 0) {
373 ret = cy_as_ll_send_request_wait_reply(dev_p,
374 req_p, reply_p);
375 if (ret != CY_AS_ERROR_SUCCESS)
376 goto destroy;
377
378 return my_handle_response_mtp_start(dev_p, req_p,
379 reply_p, ret);
380 } else {
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);
385
386 if (ret != CY_AS_ERROR_SUCCESS)
387 goto destroy;
388
389 return ret;
390 }
391
392destroy:
393 cy_as_ll_destroy_request(dev_p, req_p);
394 cy_as_ll_destroy_response(dev_p, reply_p);
395 } else {
396 dev_p->mtp_count++;
397 if (cb)
398 cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0);
399 }
400
401 cy_as_device_clear_m_s_s_pending(dev_p);
402
403 return ret;
404}
405
406static cy_as_return_status_t
407my_handle_response_mtp_stop(cy_as_device *dev_p,
408 cy_as_ll_request_response *req_p,
409 cy_as_ll_request_response *reply_p,
410 cy_as_return_status_t ret)
411{
412 if (ret != CY_AS_ERROR_SUCCESS)
413 goto destroy;
414
415 if (cy_as_ll_request_response__get_code(reply_p) !=
416 CY_RESP_SUCCESS_FAILURE) {
417 ret = CY_AS_ERROR_INVALID_RESPONSE;
418 goto destroy;
419 }
420
421 ret = cy_as_ll_request_response__get_word(reply_p, 0);
422 if (ret != CY_AS_ERROR_SUCCESS)
423 goto destroy;
424
425
426
427
428
429 dev_p->mtp_count--;
430
431destroy:
432 cy_as_ll_destroy_request(dev_p, req_p);
433 cy_as_ll_destroy_response(dev_p, reply_p);
434
435 if (ret != CY_AS_ERROR_SUCCESS)
436 cy_as_ll_register_request_callback(dev_p,
437 CY_RQT_TUR_RQT_CONTEXT, 0);
438
439 cy_as_device_clear_m_s_s_pending(dev_p);
440
441 return ret;
442}
443
444cy_as_return_status_t
445cy_as_mtp_stop(cy_as_device_handle handle,
446 cy_as_function_callback cb,
447 uint32_t client
448 )
449{
450 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
451 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
452
453 cy_as_device *dev_p;
454
455 cy_as_log_debug_message(6, "cy_as_mtp_stop called");
456
457 dev_p = (cy_as_device *)handle;
458 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
459 return CY_AS_ERROR_INVALID_HANDLE;
460
461 ret = is_mtp_active(dev_p);
462 if (ret != CY_AS_ERROR_SUCCESS)
463 return ret;
464
465 if (cy_as_device_is_in_callback(dev_p))
466 return CY_AS_ERROR_INVALID_IN_CALLBACK;
467
468 if (cy_as_device_is_m_s_s_pending(dev_p))
469 return CY_AS_ERROR_STARTSTOP_PENDING;
470
471 cy_as_device_set_m_s_s_pending(dev_p);
472
473 if (dev_p->mtp_count == 1) {
474
475
476 req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_MTP,
477 CY_RQT_TUR_RQT_CONTEXT, 0);
478 if (req_p == 0) {
479 ret = CY_AS_ERROR_OUT_OF_MEMORY;
480 goto destroy;
481 }
482
483
484
485 reply_p = cy_as_ll_create_response(dev_p, 1);
486 if (reply_p == 0) {
487 ret = CY_AS_ERROR_OUT_OF_MEMORY;
488 goto destroy;
489 }
490
491 if (cb == 0) {
492 ret = cy_as_ll_send_request_wait_reply(dev_p,
493 req_p, reply_p);
494 if (ret != CY_AS_ERROR_SUCCESS)
495 goto destroy;
496
497 return my_handle_response_mtp_stop(dev_p, req_p,
498 reply_p, ret);
499 } else {
500 ret = cy_as_misc_send_request(dev_p, cb, client,
501 CY_FUNCT_CB_MTP_STOP, 0, dev_p->func_cbs_mtp,
502 CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
503 cy_as_mtp_func_callback);
504
505 if (ret != CY_AS_ERROR_SUCCESS)
506 goto destroy;
507
508 return ret;
509 }
510
511destroy:
512 cy_as_ll_destroy_request(dev_p, req_p);
513 cy_as_ll_destroy_response(dev_p, reply_p);
514 } else if (dev_p->mtp_count > 1) {
515
516 dev_p->mtp_count--;
517
518 if (cb)
519 cb(handle, ret, client, CY_FUNCT_CB_MTP_STOP, 0);
520 }
521
522 cy_as_device_clear_m_s_s_pending(dev_p);
523
524 return ret;
525}
526
527static void
528mtp_write_callback(
529 cy_as_device *dev_p,
530 uint8_t context,
531 cy_as_ll_request_response *rqt,
532 cy_as_ll_request_response *resp,
533 cy_as_return_status_t ret)
534{
535 cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
536
537 if (ret == CY_AS_ERROR_SUCCESS) {
538 if (cy_as_ll_request_response__get_code(resp) !=
539 CY_RESP_SUCCESS_FAILURE)
540 ret = CY_AS_ERROR_INVALID_RESPONSE;
541 else
542 ret = cy_as_ll_request_response__get_word(resp, 0);
543 }
544
545 if (ret != CY_AS_ERROR_SUCCESS) {
546
547 cy_as_dma_cancel(dev_p, 0x04, CY_AS_ERROR_CANCELED);
548 cy_as_device_clear_storage_async_pending(dev_p);
549 }
550
551 cy_as_ll_destroy_response(dev_p, resp);
552 cy_as_ll_destroy_request(dev_p, rqt);
553}
554
555static void
556async_write_request_callback(cy_as_device *dev_p,
557 cy_as_end_point_number_t ep, void *buf_p, uint32_t size,
558 cy_as_return_status_t err)
559{
560 cy_as_device_handle h;
561 cy_as_function_callback cb;
562
563 (void)size;
564 (void)buf_p;
565 (void)ep;
566
567
568 cy_as_log_debug_message(6, "async_write_request_callback called");
569
570 h = (cy_as_device_handle)dev_p;
571
572 cb = dev_p->mtp_cb;
573 dev_p->mtp_cb = 0;
574
575 cy_as_device_clear_storage_async_pending(dev_p);
576
577 if (cb)
578 cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0);
579
580}
581
582static void
583sync_mtp_callback(cy_as_device *dev_p, cy_as_end_point_number_t ep,
584 void *buf_p, uint32_t size, cy_as_return_status_t err)
585{
586 (void)ep;
587 (void)buf_p;
588 (void)size;
589
590 dev_p->mtp_error = err;
591}
592
593static cy_as_return_status_t
594cy_as_mtp_operation(cy_as_device *dev_p,
595 cy_as_mtp_block_table *blk_table,
596 uint32_t num_bytes,
597 uint32_t transaction_id,
598 cy_as_function_callback cb,
599 uint32_t client,
600 uint8_t rqttype
601 )
602{
603 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
604 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
605 uint32_t mask = 0;
606 cy_as_funct_c_b_type mtp_cb_op = 0;
607 uint16_t size = 2;
608
609 if (dev_p->mtp_count == 0)
610 return CY_AS_ERROR_NOT_RUNNING;
611
612 if (rqttype == CY_RQT_INIT_SEND_OBJECT) {
613 mtp_cb_op = CY_FUNCT_CB_MTP_INIT_SEND_OBJECT;
614 dev_p->mtp_turbo_active = cy_true;
615 } else if (rqttype == CY_RQT_INIT_GET_OBJECT) {
616 mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT;
617 dev_p->mtp_turbo_active = cy_true;
618 } else
619 mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE;
620
621 ret = is_mtp_active(dev_p);
622 if (ret != CY_AS_ERROR_SUCCESS)
623 return ret;
624
625 if (CY_RQT_INIT_GET_OBJECT == rqttype)
626 size = 4;
627
628
629
630 req_p = cy_as_ll_create_request(dev_p, rqttype,
631 CY_RQT_TUR_RQT_CONTEXT, size);
632 if (req_p == 0) {
633 ret = CY_AS_ERROR_OUT_OF_MEMORY;
634 goto destroy;
635 }
636
637
638
639 reply_p = cy_as_ll_create_response(dev_p, 1);
640 if (reply_p == 0) {
641 ret = CY_AS_ERROR_OUT_OF_MEMORY;
642 goto destroy;
643 }
644
645 cy_as_ll_request_response__set_word(req_p, 0,
646 (uint16_t)(num_bytes & 0xFFFF));
647 cy_as_ll_request_response__set_word(req_p, 1,
648 (uint16_t)((num_bytes >> 16) & 0xFFFF));
649
650
651 if (CY_RQT_INIT_GET_OBJECT == rqttype) {
652 cy_as_ll_request_response__set_word(req_p, 2,
653 (uint16_t)(transaction_id & 0xFFFF));
654 cy_as_ll_request_response__set_word(req_p, 3,
655 (uint16_t)((transaction_id >> 16) & 0xFFFF));
656 }
657
658 if (cb == 0) {
659
660 ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
661 sizeof(cy_as_mtp_block_table), cy_false,
662 cy_false, sync_mtp_callback);
663
664 ret = cy_as_ll_send_request_wait_reply(dev_p,
665 req_p, reply_p);
666 if (ret != CY_AS_ERROR_SUCCESS) {
667 cy_as_dma_cancel(dev_p, 4, CY_AS_ERROR_CANCELED);
668 cy_as_device_clear_storage_async_pending(dev_p);
669
670 goto destroy;
671 }
672
673 ret = cy_as_dma_drain_queue(dev_p, 4, cy_true);
674 if (ret != CY_AS_ERROR_SUCCESS)
675 goto destroy;
676
677 ret = dev_p->mtp_error;
678 goto destroy;
679 } else {
680#if 0
681 ret = cy_as_misc_send_request(dev_p, cb, client,
682 CY_FUNCT_CB_MTP_INIT_SEND_OBJECT,
683 0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
684 req_p, reply_p, cy_as_mtp_func_callback);
685
686 if (ret != CY_AS_ERROR_SUCCESS)
687 goto destroy;
688#endif
689
690
691
692
693 mask = cy_as_hal_disable_interrupts();
694 if ((cy_as_device_is_storage_async_pending(dev_p)) ||
695 (dev_p->storage_wait)) {
696 cy_as_hal_enable_interrupts(mask);
697 return CY_AS_ERROR_ASYNC_PENDING;
698 }
699 cy_as_device_set_storage_async_pending(dev_p);
700 cy_as_hal_enable_interrupts(mask);
701
702 dev_p->mtp_cb = cb;
703 dev_p->mtp_client = client;
704 dev_p->mtp_op = mtp_cb_op;
705
706 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
707 cy_false, mtp_write_callback);
708 if (ret != CY_AS_ERROR_SUCCESS)
709 goto destroy;
710
711 ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
712 sizeof(cy_as_mtp_block_table), cy_false, cy_false,
713 async_write_request_callback);
714 if (ret != CY_AS_ERROR_SUCCESS)
715 return ret;
716
717
718 cy_as_dma_kick_start(dev_p, 4);
719
720 return CY_AS_ERROR_SUCCESS;
721 }
722
723destroy:
724 cy_as_ll_destroy_request(dev_p, req_p);
725 cy_as_ll_destroy_response(dev_p, reply_p);
726
727 return ret;
728}
729
730cy_as_return_status_t
731cy_as_mtp_init_send_object(cy_as_device_handle handle,
732 cy_as_mtp_block_table *blk_table,
733 uint32_t num_bytes,
734 cy_as_function_callback cb,
735 uint32_t client
736 )
737{
738 cy_as_device *dev_p;
739 dev_p = (cy_as_device *)handle;
740 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
741 return CY_AS_ERROR_INVALID_HANDLE;
742
743 return cy_as_mtp_operation(dev_p, blk_table, num_bytes, 0, cb,
744 client, CY_RQT_INIT_SEND_OBJECT);
745
746}
747
748cy_as_return_status_t
749cy_as_mtp_init_get_object(cy_as_device_handle handle,
750 cy_as_mtp_block_table *blk_table,
751 uint32_t num_bytes,
752 uint32_t transaction_id,
753 cy_as_function_callback cb,
754 uint32_t client
755 )
756{
757 cy_as_device *dev_p;
758 dev_p = (cy_as_device *)handle;
759 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
760 return CY_AS_ERROR_INVALID_HANDLE;
761
762 return cy_as_mtp_operation(dev_p, blk_table, num_bytes,
763 transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT);
764
765}
766
767static cy_as_return_status_t
768my_handle_response_cancel_send_object(cy_as_device *dev_p,
769 cy_as_ll_request_response *req_p,
770 cy_as_ll_request_response *reply_p,
771 cy_as_return_status_t ret)
772{
773 if (ret != CY_AS_ERROR_SUCCESS)
774 goto destroy;
775
776 if (cy_as_ll_request_response__get_code(reply_p) !=
777 CY_RESP_SUCCESS_FAILURE) {
778 ret = CY_AS_ERROR_INVALID_RESPONSE;
779 goto destroy;
780 }
781
782 ret = cy_as_ll_request_response__get_word(reply_p, 0);
783 if (ret != CY_AS_ERROR_SUCCESS)
784 goto destroy;
785
786
787destroy:
788 cy_as_ll_destroy_request(dev_p, req_p);
789 cy_as_ll_destroy_response(dev_p, reply_p);
790
791 return ret;
792}
793
794cy_as_return_status_t
795cy_as_mtp_cancel_send_object(cy_as_device_handle handle,
796 cy_as_function_callback cb,
797 uint32_t client
798 )
799{
800 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
801 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
802 cy_as_device *dev_p;
803
804 dev_p = (cy_as_device *)handle;
805 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
806 return CY_AS_ERROR_INVALID_HANDLE;
807
808 if (dev_p->mtp_count == 0)
809 return CY_AS_ERROR_NOT_RUNNING;
810
811
812 req_p = cy_as_ll_create_request(dev_p,
813 CY_RQT_CANCEL_SEND_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0);
814 if (req_p == 0) {
815 ret = CY_AS_ERROR_OUT_OF_MEMORY;
816 goto destroy;
817 }
818
819
820
821 reply_p = cy_as_ll_create_response(dev_p, 1);
822 if (reply_p == 0) {
823 ret = CY_AS_ERROR_OUT_OF_MEMORY;
824 goto destroy;
825 }
826
827 if (cb == 0) {
828 ret = cy_as_ll_send_request_wait_reply(dev_p,
829 req_p, reply_p);
830 if (ret != CY_AS_ERROR_SUCCESS)
831 goto destroy;
832
833 return my_handle_response_cancel_send_object(dev_p,
834 req_p, reply_p, ret);
835 } else {
836 ret = cy_as_misc_send_request(dev_p, cb, client,
837 CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT, 0,
838 dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
839 req_p, reply_p, cy_as_mtp_func_callback);
840
841 if (ret != CY_AS_ERROR_SUCCESS)
842 goto destroy;
843
844 return ret;
845 }
846
847destroy:
848 cy_as_ll_destroy_request(dev_p, req_p);
849 cy_as_ll_destroy_response(dev_p, reply_p);
850
851 return ret;
852}
853
854static cy_as_return_status_t
855my_handle_response_cancel_get_object(cy_as_device *dev_p,
856 cy_as_ll_request_response *req_p,
857 cy_as_ll_request_response *reply_p,
858 cy_as_return_status_t ret)
859{
860 if (ret != CY_AS_ERROR_SUCCESS)
861 goto destroy;
862
863 if (cy_as_ll_request_response__get_code(reply_p) !=
864 CY_RESP_SUCCESS_FAILURE) {
865 ret = CY_AS_ERROR_INVALID_RESPONSE;
866 goto destroy;
867 }
868
869 ret = cy_as_ll_request_response__get_word(reply_p, 0);
870 if (ret != CY_AS_ERROR_SUCCESS)
871 goto destroy;
872
873
874destroy:
875 cy_as_ll_destroy_request(dev_p, req_p);
876 cy_as_ll_destroy_response(dev_p, reply_p);
877
878 return ret;
879}
880
881cy_as_return_status_t
882cy_as_mtp_cancel_get_object(cy_as_device_handle handle,
883 cy_as_function_callback cb,
884 uint32_t client
885 )
886{
887 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
888 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
889 cy_as_device *dev_p;
890
891 dev_p = (cy_as_device *)handle;
892 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
893 return CY_AS_ERROR_INVALID_HANDLE;
894
895 if (dev_p->mtp_count == 0)
896 return CY_AS_ERROR_NOT_RUNNING;
897
898
899 req_p = cy_as_ll_create_request(dev_p, CY_RQT_CANCEL_GET_OBJECT,
900 CY_RQT_TUR_RQT_CONTEXT, 0);
901 if (req_p == 0) {
902 ret = CY_AS_ERROR_OUT_OF_MEMORY;
903 goto destroy;
904 }
905
906
907
908 reply_p = cy_as_ll_create_response(dev_p, 1);
909 if (reply_p == 0) {
910 ret = CY_AS_ERROR_OUT_OF_MEMORY;
911 goto destroy;
912 }
913
914 if (cb == 0) {
915 ret = cy_as_ll_send_request_wait_reply(dev_p,
916 req_p, reply_p);
917 if (ret != CY_AS_ERROR_SUCCESS)
918 goto destroy;
919
920 return my_handle_response_cancel_get_object(dev_p,
921 req_p, reply_p, ret);
922 } else {
923 ret = cy_as_misc_send_request(dev_p, cb, client,
924 CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT, 0,
925 dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
926 req_p, reply_p, cy_as_mtp_func_callback);
927
928 if (ret != CY_AS_ERROR_SUCCESS)
929 goto destroy;
930
931 return ret;
932 }
933
934destroy:
935 cy_as_ll_destroy_request(dev_p, req_p);
936 cy_as_ll_destroy_response(dev_p, reply_p);
937
938 return ret;
939}
940
941cy_as_return_status_t
942cy_as_mtp_send_block_table(cy_as_device_handle handle,
943 cy_as_mtp_block_table *blk_table,
944 cy_as_function_callback cb,
945 uint32_t client)
946{
947 cy_as_device *dev_p;
948 dev_p = (cy_as_device *)handle;
949 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
950 return CY_AS_ERROR_INVALID_HANDLE;
951
952 return cy_as_mtp_operation(dev_p, blk_table, 0, 0, cb,
953 client, CY_RQT_SEND_BLOCK_TABLE);
954}
955
956static void
957cy_as_mtp_func_callback(cy_as_device *dev_p,
958 uint8_t context,
959 cy_as_ll_request_response *rqt,
960 cy_as_ll_request_response *resp,
961 cy_as_return_status_t stat)
962{
963 cy_as_func_c_b_node* node = (cy_as_func_c_b_node *)
964 dev_p->func_cbs_mtp->head_p;
965 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
966 uint8_t code;
967 cy_bool delay_callback = cy_false;
968
969 cy_as_hal_assert(dev_p->func_cbs_mtp->count != 0);
970 cy_as_hal_assert(dev_p->func_cbs_mtp->type == CYAS_FUNC_CB);
971
972 (void)context;
973
974
975
976
977 code = cy_as_ll_request_response__get_code(rqt);
978 switch (code) {
979 case CY_RQT_START_MTP:
980 ret = my_handle_response_mtp_start(dev_p, rqt,
981 resp, stat);
982 break;
983 case CY_RQT_STOP_MTP:
984 ret = my_handle_response_mtp_stop(dev_p, rqt,
985 resp, stat);
986 break;
987#if 0
988 case CY_RQT_INIT_SEND_OBJECT:
989 ret = my_handle_response_init_send_object(dev_p,
990 rqt, resp, stat, cy_true);
991 delay_callback = cy_true;
992 break;
993#endif
994 case CY_RQT_CANCEL_SEND_OBJECT:
995 ret = my_handle_response_cancel_send_object(dev_p,
996 rqt, resp, stat);
997 break;
998#if 0
999 case CY_RQT_INIT_GET_OBJECT:
1000 ret = my_handle_response_init_get_object(dev_p,
1001 rqt, resp, stat, cy_true);
1002 delay_callback = cy_true;
1003 break;
1004#endif
1005 case CY_RQT_CANCEL_GET_OBJECT:
1006 ret = my_handle_response_cancel_get_object(dev_p,
1007 rqt, resp, stat);
1008 break;
1009#if 0
1010 case CY_RQT_SEND_BLOCK_TABLE:
1011 ret = my_handle_response_send_block_table(dev_p, rqt,
1012 resp, stat, cy_true);
1013 delay_callback = cy_true;
1014 break;
1015#endif
1016 case CY_RQT_ENABLE_USB_PATH:
1017 ret = my_handle_response_no_data(dev_p, rqt, resp);
1018 if (ret == CY_AS_ERROR_SUCCESS)
1019 dev_p->is_storage_only_mode = cy_false;
1020 break;
1021 default:
1022 ret = CY_AS_ERROR_INVALID_RESPONSE;
1023 cy_as_hal_assert(cy_false);
1024 break;
1025 }
1026
1027
1028
1029
1030
1031
1032 if (stat == CY_AS_ERROR_SUCCESS)
1033 stat = ret;
1034
1035 if (!delay_callback) {
1036 node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
1037 node->data_type, node->data);
1038 cy_as_remove_c_b_node(dev_p->func_cbs_mtp);
1039 }
1040}
1041
1042cy_as_return_status_t
1043cy_as_mtp_storage_only_start(cy_as_device_handle handle)
1044{
1045 cy_as_device *dev_p = (cy_as_device *)handle;
1046 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1047 return CY_AS_ERROR_INVALID_HANDLE;
1048
1049 if (!cy_as_device_is_configured(dev_p))
1050 return CY_AS_ERROR_NOT_CONFIGURED;
1051
1052 if (!cy_as_device_is_firmware_loaded(dev_p))
1053 return CY_AS_ERROR_NO_FIRMWARE;
1054
1055 if (dev_p->storage_count == 0)
1056 return CY_AS_ERROR_NOT_RUNNING;
1057
1058 dev_p->is_storage_only_mode = cy_true;
1059 return CY_AS_ERROR_SUCCESS;
1060}
1061
1062cy_as_return_status_t
1063cy_as_mtp_storage_only_stop(cy_as_device_handle handle,
1064 cy_as_function_callback cb,
1065 uint32_t client)
1066{
1067 cy_as_device *dev_p = (cy_as_device *)handle;
1068 cy_as_ll_request_response *req_p, *reply_p;
1069 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1070
1071 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1072 return CY_AS_ERROR_INVALID_HANDLE;
1073
1074 if (!cy_as_device_is_configured(dev_p))
1075 return CY_AS_ERROR_NOT_CONFIGURED;
1076
1077 if (!cy_as_device_is_firmware_loaded(dev_p))
1078 return CY_AS_ERROR_NO_FIRMWARE;
1079
1080 if (dev_p->storage_count == 0)
1081 return CY_AS_ERROR_NOT_RUNNING;
1082
1083 if (dev_p->is_storage_only_mode == cy_false)
1084 return CY_AS_ERROR_SUCCESS;
1085
1086 if (cy_as_device_is_in_callback(dev_p))
1087 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1088
1089 req_p = cy_as_ll_create_request(dev_p,
1090 CY_RQT_ENABLE_USB_PATH, CY_RQT_TUR_RQT_CONTEXT, 1);
1091 if (req_p == 0)
1092 return CY_AS_ERROR_OUT_OF_MEMORY;
1093
1094 reply_p = cy_as_ll_create_response(dev_p, 1);
1095 if (reply_p == 0) {
1096 cy_as_ll_destroy_request(dev_p, req_p);
1097 return CY_AS_ERROR_OUT_OF_MEMORY;
1098 }
1099
1100 if (cb == 0) {
1101 ret = cy_as_ll_send_request_wait_reply(dev_p,
1102 req_p, reply_p);
1103 if (ret != CY_AS_ERROR_SUCCESS)
1104 goto destroy;
1105
1106 ret = my_handle_response_no_data(dev_p, req_p,
1107 reply_p);
1108 if (ret == CY_AS_ERROR_SUCCESS)
1109 dev_p->is_storage_only_mode = cy_false;
1110 return ret;
1111 } else {
1112 ret = cy_as_misc_send_request(dev_p, cb, client,
1113 CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY, 0,
1114 dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
1115 req_p, reply_p, cy_as_mtp_func_callback);
1116
1117 if (ret != CY_AS_ERROR_SUCCESS)
1118 goto destroy;
1119
1120 return ret;
1121 }
1122
1123destroy:
1124 cy_as_ll_destroy_request(dev_p, req_p);
1125 cy_as_ll_destroy_response(dev_p, reply_p);
1126
1127 return ret;
1128}
1129