]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/staging/westbridge/astoria/api/src/cyasmtp.c
Fix common misspellings
[mirror_ubuntu-eoan-kernel.git] / drivers / staging / westbridge / astoria / api / src / cyasmtp.c
CommitLineData
81eb669b
DC
1/* Cypress West Bridge API header file (cyasmtp.h)
2## ===========================
3## Copyright (C) 2010 Cypress Semiconductor
4##
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.
9##
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.
14##
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## ===========================
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,
0769c38d 33 cy_as_return_status_t stat);
81eb669b
DC
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))
0769c38d 39 return CY_AS_ERROR_NOT_CONFIGURED;
81eb669b
DC
40
41 if (!cy_as_device_is_firmware_loaded(dev_p))
0769c38d 42 return CY_AS_ERROR_NO_FIRMWARE;
81eb669b
DC
43
44 if (dev_p->mtp_count == 0)
0769c38d 45 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
46
47 if (cy_as_device_is_in_suspend_mode(dev_p))
0769c38d 48 return CY_AS_ERROR_IN_SUSPEND;
81eb669b 49
0769c38d 50 return CY_AS_ERROR_SUCCESS;
81eb669b
DC
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{
0769c38d
DC
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;
81eb669b 66
0769c38d 67 uint8_t code = cy_as_ll_request_response__get_code(req_p);
81eb669b 68
0769c38d
DC
69 (void)resp_p;
70 (void)context;
71 (void)ret;
81eb669b
DC
72
73 switch (code) {
74 case CY_RQT_MTP_EVENT:
0769c38d 75 val = cy_as_ll_request_response__get_word(req_p, 0);
81eb669b 76 /* MSB indicates status of read/write */
0769c38d 77 status = (val >> 8) & 0xFF;
81eb669b 78 /* event type */
0769c38d 79 ev = val & 0xFF;
81eb669b
DC
80 switch (ev) {
81 case 0: /* SendObject Complete */
82 {
83 bytecount_l =
84 cy_as_ll_request_response__get_word
0769c38d 85 (req_p, 1);
81eb669b
DC
86 bytecount_h =
87 cy_as_ll_request_response__get_word
0769c38d 88 (req_p, 2);
81eb669b 89 send_obj_data.byte_count =
0769c38d 90 (bytecount_h << 16) | bytecount_l;
81eb669b 91
0769c38d 92 send_obj_data.status = status;
81eb669b
DC
93
94 /* use the byte count again */
95 bytecount_l =
96 cy_as_ll_request_response__get_word
0769c38d 97 (req_p, 3);
81eb669b
DC
98 bytecount_h =
99 cy_as_ll_request_response__get_word
0769c38d 100 (req_p, 4);
81eb669b 101 send_obj_data.transaction_id =
0769c38d 102 (bytecount_h << 16) | bytecount_l;
81eb669b 103
0769c38d 104 dev_p->mtp_turbo_active = cy_false;
81eb669b
DC
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,
0769c38d 110 &send_obj_data);
81eb669b 111 }
0769c38d 112 break;
81eb669b
DC
113
114 case 1: /* GetObject Complete */
115 {
116 bytecount_l =
117 cy_as_ll_request_response__get_word
0769c38d 118 (req_p, 1);
81eb669b
DC
119 bytecount_h =
120 cy_as_ll_request_response__get_word
0769c38d 121 (req_p, 2);
81eb669b
DC
122
123 get_obj_data.byte_count =
0769c38d 124 (bytecount_h << 16) | bytecount_l;
81eb669b 125
0769c38d 126 get_obj_data.status = status;
81eb669b 127
0769c38d 128 dev_p->mtp_turbo_active = cy_false;
81eb669b
DC
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 }
0769c38d 136 break;
81eb669b
DC
137
138 case 2: /* BlockTable Needed */
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 }
0769c38d 145 break;
81eb669b 146 default:
0769c38d 147 cy_as_hal_print_message("invalid event type\n");
81eb669b
DC
148 cy_as_ll_send_data_response(dev_p,
149 CY_RQT_TUR_RQT_CONTEXT,
150 CY_RESP_MTP_INVALID_EVENT,
0769c38d
DC
151 sizeof(ev), &ev);
152 break;
81eb669b 153 }
0769c38d 154 break;
81eb669b
DC
155
156 case CY_RQT_TURBO_CMD_FROM_HOST:
157 {
158 mtp_datalen =
0769c38d 159 cy_as_ll_request_response__get_word(req_p, 1);
81eb669b
DC
160
161 /* Get the endpoint pointer based on
162 * the endpoint number */
0769c38d 163 ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_READ_ENDPOINT);
81eb669b
DC
164
165 /* The event should arrive only after the DMA operation
166 * has been queued. */
0769c38d 167 cy_as_hal_assert(ep_p->queue_p != 0);
81eb669b
DC
168
169 /* Put the len in ep data information in
170 * dmaqueue and kick start the queue */
0769c38d 171 cy_as_hal_assert(ep_p->queue_p->size >= mtp_datalen);
81eb669b
DC
172
173 if (mtp_datalen == 0) {
174 cy_as_dma_completed_callback(dev_p->tag,
175 CY_AS_MTP_READ_ENDPOINT, 0,
0769c38d 176 CY_AS_ERROR_SUCCESS);
81eb669b 177 } else {
0769c38d 178 ep_p->maxhwdata = mtp_datalen;
81eb669b
DC
179
180 /*
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
188 * transfer.
189 */
0769c38d 190 cy_as_dma_end_point_set_stopped(ep_p);
81eb669b
DC
191
192 /* Kick start the queue if it is not running */
193 cy_as_dma_kick_start(dev_p,
194 CY_AS_MTP_READ_ENDPOINT);
195 }
196 }
0769c38d 197 break;
81eb669b
DC
198
199 case CY_RQT_TURBO_START_WRITE_DMA:
200 {
201 /*
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
206 * write endpoint.
207 */
208 cy_as_ll_send_status_response(dev_p,
209 CY_RQT_TUR_RQT_CONTEXT,
0769c38d 210 CY_AS_ERROR_SUCCESS, 0);
81eb669b 211
0769c38d
DC
212 ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
213 cy_as_hal_assert(ep_p->queue_p != 0);
81eb669b 214
0769c38d
DC
215 cy_as_dma_end_point_set_stopped(ep_p);
216 cy_as_dma_kick_start(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
81eb669b 217 }
0769c38d 218 break;
81eb669b
DC
219
220 default:
221 cy_as_hal_print_message("invalid request received "
0769c38d
DC
222 "on TUR context\n");
223 val = req_p->box0;
81eb669b 224 cy_as_ll_send_data_response(dev_p, CY_RQT_TUR_RQT_CONTEXT,
0769c38d
DC
225 CY_RESP_INVALID_REQUEST, sizeof(val), &val);
226 break;
81eb669b
DC
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{
0769c38d 235 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
81eb669b
DC
236
237 if (cy_as_ll_request_response__get_code(reply_p) !=
238 CY_RESP_SUCCESS_FAILURE) {
0769c38d
DC
239 ret = CY_AS_ERROR_INVALID_RESPONSE;
240 goto destroy;
81eb669b
DC
241 }
242
0769c38d 243 ret = cy_as_ll_request_response__get_word(reply_p, 0);
81eb669b
DC
244
245destroy:
0769c38d
DC
246 cy_as_ll_destroy_request(dev_p, req_p);
247 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 248
0769c38d 249 return ret;
81eb669b
DC
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)
0769c38d 259 goto destroy;
81eb669b
DC
260
261 if (cy_as_ll_request_response__get_code(reply_p) !=
262 CY_RESP_SUCCESS_FAILURE) {
0769c38d
DC
263 ret = CY_AS_ERROR_INVALID_RESPONSE;
264 goto destroy;
81eb669b
DC
265 }
266
0769c38d 267 ret = cy_as_ll_request_response__get_word(reply_p, 0);
81eb669b 268 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 269 goto destroy;
81eb669b 270
0769c38d 271 dev_p->mtp_count++;
81eb669b
DC
272
273 cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_READ_ENDPOINT,
0769c38d
DC
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;
81eb669b
DC
278
279 cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_WRITE_ENDPOINT,
0769c38d
DC
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;
81eb669b
DC
284
285 /* Packet size is 512 bytes */
0769c38d 286 cy_as_dma_set_max_dma_size(dev_p, 0x02, 0x0200);
81eb669b 287 /* Packet size is 64 bytes until a switch to high speed happens.*/
0769c38d 288 cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
81eb669b
DC
289
290destroy:
0769c38d
DC
291 cy_as_ll_destroy_request(dev_p, req_p);
292 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b
DC
293
294 if (ret != CY_AS_ERROR_SUCCESS)
295 cy_as_ll_register_request_callback(dev_p,
0769c38d 296 CY_RQT_TUR_RQT_CONTEXT, 0);
81eb669b 297
0769c38d 298 cy_as_device_clear_m_s_s_pending(dev_p);
81eb669b 299
0769c38d 300 return ret;
81eb669b
DC
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{
0769c38d
DC
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;
81eb669b 314
0769c38d 315 dev_p = (cy_as_device *)handle;
81eb669b 316 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 317 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
318
319 if (!cy_as_device_is_configured(dev_p))
0769c38d 320 return CY_AS_ERROR_NOT_CONFIGURED;
81eb669b
DC
321
322 if (!cy_as_device_is_firmware_loaded(dev_p))
0769c38d 323 return CY_AS_ERROR_NO_FIRMWARE;
81eb669b
DC
324
325 if (cy_as_device_is_in_suspend_mode(dev_p))
0769c38d 326 return CY_AS_ERROR_IN_SUSPEND;
81eb669b
DC
327
328 if (cy_as_device_is_in_callback(dev_p))
0769c38d 329 return CY_AS_ERROR_INVALID_IN_CALLBACK;
81eb669b
DC
330
331 if (cy_as_device_is_m_s_s_pending(dev_p))
0769c38d 332 return CY_AS_ERROR_STARTSTOP_PENDING;
81eb669b
DC
333
334 if (dev_p->storage_count == 0)
0769c38d 335 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
336
337 if (dev_p->usb_count == 0)
0769c38d 338 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
339
340 if (dev_p->is_mtp_firmware == 0)
0769c38d 341 return CY_AS_ERROR_NOT_SUPPORTED;
81eb669b 342
0769c38d 343 cy_as_device_set_m_s_s_pending(dev_p);
81eb669b
DC
344
345 if (dev_p->mtp_count == 0) {
346
0769c38d 347 dev_p->mtp_event_cb = event_c_b;
81eb669b 348 /*
25985edc 349 * we register here because the start request may cause
81eb669b
DC
350 * events to occur before the response to the start request.
351 */
352 cy_as_ll_register_request_callback(dev_p,
0769c38d 353 CY_RQT_TUR_RQT_CONTEXT, my_mtp_request_callback);
81eb669b
DC
354
355 /* Create the request to send to the West Bridge device */
356 req_p = cy_as_ll_create_request(dev_p,
0769c38d 357 CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0);
81eb669b 358 if (req_p == 0) {
0769c38d
DC
359 cy_as_device_clear_m_s_s_pending(dev_p);
360 return CY_AS_ERROR_OUT_OF_MEMORY;
81eb669b
DC
361 }
362
363 /* Reserve space for the reply, the reply data will
364 * not exceed one word */
0769c38d 365 reply_p = cy_as_ll_create_response(dev_p, 1);
81eb669b 366 if (reply_p == 0) {
0769c38d
DC
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;
81eb669b
DC
370 }
371
372 if (cb == 0) {
373 ret = cy_as_ll_send_request_wait_reply(dev_p,
0769c38d 374 req_p, reply_p);
81eb669b 375 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 376 goto destroy;
81eb669b
DC
377
378 return my_handle_response_mtp_start(dev_p, req_p,
0769c38d 379 reply_p, ret);
81eb669b
DC
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,
0769c38d 384 cy_as_mtp_func_callback);
81eb669b
DC
385
386 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 387 goto destroy;
81eb669b 388
0769c38d 389 return ret;
81eb669b
DC
390 }
391
392destroy:
0769c38d
DC
393 cy_as_ll_destroy_request(dev_p, req_p);
394 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 395 } else {
0769c38d 396 dev_p->mtp_count++;
81eb669b 397 if (cb)
0769c38d 398 cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0);
81eb669b
DC
399 }
400
0769c38d 401 cy_as_device_clear_m_s_s_pending(dev_p);
81eb669b 402
0769c38d 403 return ret;
81eb669b 404}
af109f2e 405EXPORT_SYMBOL(cy_as_mtp_start);
81eb669b
DC
406
407static cy_as_return_status_t
408my_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)
412{
413 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 414 goto destroy;
81eb669b
DC
415
416 if (cy_as_ll_request_response__get_code(reply_p) !=
417 CY_RESP_SUCCESS_FAILURE) {
0769c38d
DC
418 ret = CY_AS_ERROR_INVALID_RESPONSE;
419 goto destroy;
81eb669b
DC
420 }
421
0769c38d 422 ret = cy_as_ll_request_response__get_word(reply_p, 0);
81eb669b 423 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 424 goto destroy;
81eb669b
DC
425
426 /*
25985edc 427 * we successfully shutdown the stack, so decrement
81eb669b
DC
428 * to make the count zero.
429 */
0769c38d 430 dev_p->mtp_count--;
81eb669b
DC
431
432destroy:
0769c38d
DC
433 cy_as_ll_destroy_request(dev_p, req_p);
434 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b
DC
435
436 if (ret != CY_AS_ERROR_SUCCESS)
437 cy_as_ll_register_request_callback(dev_p,
0769c38d 438 CY_RQT_TUR_RQT_CONTEXT, 0);
81eb669b 439
0769c38d 440 cy_as_device_clear_m_s_s_pending(dev_p);
81eb669b 441
0769c38d 442 return ret;
81eb669b
DC
443}
444
445cy_as_return_status_t
446cy_as_mtp_stop(cy_as_device_handle handle,
447 cy_as_function_callback cb,
448 uint32_t client
449 )
450{
0769c38d
DC
451 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
452 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
81eb669b 453
0769c38d 454 cy_as_device *dev_p;
81eb669b 455
0769c38d 456 cy_as_log_debug_message(6, "cy_as_mtp_stop called");
81eb669b 457
0769c38d 458 dev_p = (cy_as_device *)handle;
81eb669b 459 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 460 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b 461
0769c38d 462 ret = is_mtp_active(dev_p);
81eb669b 463 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 464 return ret;
81eb669b
DC
465
466 if (cy_as_device_is_in_callback(dev_p))
0769c38d 467 return CY_AS_ERROR_INVALID_IN_CALLBACK;
81eb669b
DC
468
469 if (cy_as_device_is_m_s_s_pending(dev_p))
0769c38d 470 return CY_AS_ERROR_STARTSTOP_PENDING;
81eb669b 471
0769c38d 472 cy_as_device_set_m_s_s_pending(dev_p);
81eb669b
DC
473
474 if (dev_p->mtp_count == 1) {
475 /* Create the request to send to the West
476 * Bridge device */
477 req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_MTP,
0769c38d 478 CY_RQT_TUR_RQT_CONTEXT, 0);
81eb669b 479 if (req_p == 0) {
0769c38d
DC
480 ret = CY_AS_ERROR_OUT_OF_MEMORY;
481 goto destroy;
81eb669b
DC
482 }
483
484 /* Reserve space for the reply, the reply data will
485 * not exceed one word */
0769c38d 486 reply_p = cy_as_ll_create_response(dev_p, 1);
81eb669b 487 if (reply_p == 0) {
0769c38d
DC
488 ret = CY_AS_ERROR_OUT_OF_MEMORY;
489 goto destroy;
81eb669b
DC
490 }
491
492 if (cb == 0) {
493 ret = cy_as_ll_send_request_wait_reply(dev_p,
0769c38d 494 req_p, reply_p);
81eb669b 495 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 496 goto destroy;
81eb669b
DC
497
498 return my_handle_response_mtp_stop(dev_p, req_p,
0769c38d 499 reply_p, ret);
81eb669b
DC
500 } else {
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,
0769c38d 504 cy_as_mtp_func_callback);
81eb669b
DC
505
506 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 507 goto destroy;
81eb669b 508
0769c38d 509 return ret;
81eb669b
DC
510 }
511
512destroy:
0769c38d
DC
513 cy_as_ll_destroy_request(dev_p, req_p);
514 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b
DC
515 } else if (dev_p->mtp_count > 1) {
516
0769c38d 517 dev_p->mtp_count--;
81eb669b
DC
518
519 if (cb)
0769c38d 520 cb(handle, ret, client, CY_FUNCT_CB_MTP_STOP, 0);
81eb669b
DC
521 }
522
0769c38d 523 cy_as_device_clear_m_s_s_pending(dev_p);
81eb669b 524
0769c38d 525 return ret;
81eb669b
DC
526}
527
528static void
529mtp_write_callback(
530 cy_as_device *dev_p,
531 uint8_t context,
532 cy_as_ll_request_response *rqt,
533 cy_as_ll_request_response *resp,
534 cy_as_return_status_t ret)
535{
0769c38d 536 cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
81eb669b
DC
537
538 if (ret == CY_AS_ERROR_SUCCESS) {
539 if (cy_as_ll_request_response__get_code(resp) !=
540 CY_RESP_SUCCESS_FAILURE)
0769c38d 541 ret = CY_AS_ERROR_INVALID_RESPONSE;
81eb669b 542 else
0769c38d 543 ret = cy_as_ll_request_response__get_word(resp, 0);
81eb669b
DC
544 }
545
546 if (ret != CY_AS_ERROR_SUCCESS) {
547 /* Firmware failed the request. Cancel the DMA transfer. */
0769c38d
DC
548 cy_as_dma_cancel(dev_p, 0x04, CY_AS_ERROR_CANCELED);
549 cy_as_device_clear_storage_async_pending(dev_p);
81eb669b
DC
550 }
551
0769c38d
DC
552 cy_as_ll_destroy_response(dev_p, resp);
553 cy_as_ll_destroy_request(dev_p, rqt);
81eb669b
DC
554}
555
556static void
557async_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)
560{
0769c38d
DC
561 cy_as_device_handle h;
562 cy_as_function_callback cb;
81eb669b 563
0769c38d
DC
564 (void)size;
565 (void)buf_p;
566 (void)ep;
81eb669b
DC
567
568
0769c38d 569 cy_as_log_debug_message(6, "async_write_request_callback called");
81eb669b 570
0769c38d 571 h = (cy_as_device_handle)dev_p;
81eb669b 572
0769c38d
DC
573 cb = dev_p->mtp_cb;
574 dev_p->mtp_cb = 0;
81eb669b 575
0769c38d 576 cy_as_device_clear_storage_async_pending(dev_p);
81eb669b
DC
577
578 if (cb)
0769c38d 579 cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0);
81eb669b
DC
580
581}
582
583static void
584sync_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)
586{
0769c38d
DC
587 (void)ep;
588 (void)buf_p;
589 (void)size;
81eb669b 590
0769c38d 591 dev_p->mtp_error = err;
81eb669b
DC
592}
593
594static cy_as_return_status_t
595cy_as_mtp_operation(cy_as_device *dev_p,
596 cy_as_mtp_block_table *blk_table,
597 uint32_t num_bytes,
598 uint32_t transaction_id,
599 cy_as_function_callback cb,
600 uint32_t client,
601 uint8_t rqttype
602 )
603{
0769c38d
DC
604 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
605 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
606 uint32_t mask = 0;
607 cy_as_funct_c_b_type mtp_cb_op = 0;
608 uint16_t size = 2;
81eb669b
DC
609
610 if (dev_p->mtp_count == 0)
0769c38d 611 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
612
613 if (rqttype == CY_RQT_INIT_SEND_OBJECT) {
0769c38d
DC
614 mtp_cb_op = CY_FUNCT_CB_MTP_INIT_SEND_OBJECT;
615 dev_p->mtp_turbo_active = cy_true;
81eb669b 616 } else if (rqttype == CY_RQT_INIT_GET_OBJECT) {
0769c38d
DC
617 mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT;
618 dev_p->mtp_turbo_active = cy_true;
81eb669b 619 } else
0769c38d 620 mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE;
81eb669b 621
0769c38d 622 ret = is_mtp_active(dev_p);
81eb669b 623 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 624 return ret;
81eb669b
DC
625
626 if (CY_RQT_INIT_GET_OBJECT == rqttype)
0769c38d 627 size = 4;
81eb669b
DC
628
629 /* Create the request to send to the West
630 * Bridge device */
631 req_p = cy_as_ll_create_request(dev_p, rqttype,
0769c38d 632 CY_RQT_TUR_RQT_CONTEXT, size);
81eb669b 633 if (req_p == 0) {
0769c38d
DC
634 ret = CY_AS_ERROR_OUT_OF_MEMORY;
635 goto destroy;
81eb669b
DC
636 }
637
638 /* Reserve space for the reply, the reply data will
639 * not exceed one word */
0769c38d 640 reply_p = cy_as_ll_create_response(dev_p, 1);
81eb669b 641 if (reply_p == 0) {
0769c38d
DC
642 ret = CY_AS_ERROR_OUT_OF_MEMORY;
643 goto destroy;
81eb669b
DC
644 }
645
646 cy_as_ll_request_response__set_word(req_p, 0,
0769c38d 647 (uint16_t)(num_bytes & 0xFFFF));
81eb669b 648 cy_as_ll_request_response__set_word(req_p, 1,
0769c38d 649 (uint16_t)((num_bytes >> 16) & 0xFFFF));
81eb669b
DC
650
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,
0769c38d 654 (uint16_t)(transaction_id & 0xFFFF));
81eb669b 655 cy_as_ll_request_response__set_word(req_p, 3,
0769c38d 656 (uint16_t)((transaction_id >> 16) & 0xFFFF));
81eb669b
DC
657 }
658
659 if (cb == 0) {
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,
0769c38d 663 cy_false, sync_mtp_callback);
81eb669b
DC
664
665 ret = cy_as_ll_send_request_wait_reply(dev_p,
0769c38d 666 req_p, reply_p);
81eb669b 667 if (ret != CY_AS_ERROR_SUCCESS) {
0769c38d
DC
668 cy_as_dma_cancel(dev_p, 4, CY_AS_ERROR_CANCELED);
669 cy_as_device_clear_storage_async_pending(dev_p);
81eb669b 670
0769c38d 671 goto destroy;
81eb669b
DC
672 }
673
0769c38d 674 ret = cy_as_dma_drain_queue(dev_p, 4, cy_true);
81eb669b 675 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 676 goto destroy;
81eb669b 677
0769c38d
DC
678 ret = dev_p->mtp_error;
679 goto destroy;
81eb669b
DC
680 } else {
681#if 0
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,
0769c38d 685 req_p, reply_p, cy_as_mtp_func_callback);
81eb669b
DC
686
687 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 688 goto destroy;
81eb669b
DC
689#endif
690
691 /* Protection from interrupt driven code */
692 /* since we are using storage EP4 check if any
693 * storage activity is pending */
0769c38d 694 mask = cy_as_hal_disable_interrupts();
81eb669b
DC
695 if ((cy_as_device_is_storage_async_pending(dev_p)) ||
696 (dev_p->storage_wait)) {
0769c38d
DC
697 cy_as_hal_enable_interrupts(mask);
698 return CY_AS_ERROR_ASYNC_PENDING;
81eb669b 699 }
0769c38d
DC
700 cy_as_device_set_storage_async_pending(dev_p);
701 cy_as_hal_enable_interrupts(mask);
81eb669b 702
0769c38d
DC
703 dev_p->mtp_cb = cb;
704 dev_p->mtp_client = client;
705 dev_p->mtp_op = mtp_cb_op;
81eb669b
DC
706
707 ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
0769c38d 708 cy_false, mtp_write_callback);
81eb669b 709 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 710 goto destroy;
81eb669b
DC
711
712 ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
713 sizeof(cy_as_mtp_block_table), cy_false, cy_false,
0769c38d 714 async_write_request_callback);
81eb669b 715 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 716 return ret;
81eb669b
DC
717
718 /* Kick start the queue if it is not running */
0769c38d 719 cy_as_dma_kick_start(dev_p, 4);
81eb669b 720
0769c38d 721 return CY_AS_ERROR_SUCCESS;
81eb669b
DC
722 }
723
724destroy:
0769c38d
DC
725 cy_as_ll_destroy_request(dev_p, req_p);
726 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 727
0769c38d 728 return ret;
81eb669b
DC
729}
730
731cy_as_return_status_t
732cy_as_mtp_init_send_object(cy_as_device_handle handle,
733 cy_as_mtp_block_table *blk_table,
734 uint32_t num_bytes,
735 cy_as_function_callback cb,
736 uint32_t client
737 )
738{
0769c38d
DC
739 cy_as_device *dev_p;
740 dev_p = (cy_as_device *)handle;
81eb669b 741 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 742 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
743
744 return cy_as_mtp_operation(dev_p, blk_table, num_bytes, 0, cb,
0769c38d 745 client, CY_RQT_INIT_SEND_OBJECT);
81eb669b
DC
746
747}
af109f2e 748EXPORT_SYMBOL(cy_as_mtp_init_send_object);
81eb669b
DC
749
750cy_as_return_status_t
751cy_as_mtp_init_get_object(cy_as_device_handle handle,
752 cy_as_mtp_block_table *blk_table,
753 uint32_t num_bytes,
754 uint32_t transaction_id,
755 cy_as_function_callback cb,
756 uint32_t client
757 )
758{
0769c38d
DC
759 cy_as_device *dev_p;
760 dev_p = (cy_as_device *)handle;
81eb669b 761 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 762 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
763
764 return cy_as_mtp_operation(dev_p, blk_table, num_bytes,
0769c38d 765 transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT);
81eb669b
DC
766
767}
af109f2e 768EXPORT_SYMBOL(cy_as_mtp_init_get_object);
81eb669b
DC
769
770static cy_as_return_status_t
771my_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)
775{
776 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 777 goto destroy;
81eb669b
DC
778
779 if (cy_as_ll_request_response__get_code(reply_p) !=
780 CY_RESP_SUCCESS_FAILURE) {
0769c38d
DC
781 ret = CY_AS_ERROR_INVALID_RESPONSE;
782 goto destroy;
81eb669b
DC
783 }
784
0769c38d 785 ret = cy_as_ll_request_response__get_word(reply_p, 0);
81eb669b 786 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 787 goto destroy;
81eb669b
DC
788
789
790destroy:
0769c38d
DC
791 cy_as_ll_destroy_request(dev_p, req_p);
792 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 793
0769c38d 794 return ret;
81eb669b
DC
795}
796
797cy_as_return_status_t
798cy_as_mtp_cancel_send_object(cy_as_device_handle handle,
799 cy_as_function_callback cb,
800 uint32_t client
801 )
802{
0769c38d
DC
803 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
804 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
805 cy_as_device *dev_p;
81eb669b 806
0769c38d 807 dev_p = (cy_as_device *)handle;
81eb669b 808 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 809 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
810
811 if (dev_p->mtp_count == 0)
0769c38d 812 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
813
814 /* Create the request to send to the West Bridge device */
815 req_p = cy_as_ll_create_request(dev_p,
0769c38d 816 CY_RQT_CANCEL_SEND_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0);
81eb669b 817 if (req_p == 0) {
0769c38d
DC
818 ret = CY_AS_ERROR_OUT_OF_MEMORY;
819 goto destroy;
81eb669b
DC
820 }
821
822 /* Reserve space for the reply, the reply data will
823 * not exceed one word */
0769c38d 824 reply_p = cy_as_ll_create_response(dev_p, 1);
81eb669b 825 if (reply_p == 0) {
0769c38d
DC
826 ret = CY_AS_ERROR_OUT_OF_MEMORY;
827 goto destroy;
81eb669b
DC
828 }
829
830 if (cb == 0) {
831 ret = cy_as_ll_send_request_wait_reply(dev_p,
0769c38d 832 req_p, reply_p);
81eb669b 833 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 834 goto destroy;
81eb669b
DC
835
836 return my_handle_response_cancel_send_object(dev_p,
0769c38d 837 req_p, reply_p, ret);
81eb669b
DC
838 } else {
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,
0769c38d 842 req_p, reply_p, cy_as_mtp_func_callback);
81eb669b
DC
843
844 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 845 goto destroy;
81eb669b 846
0769c38d 847 return ret;
81eb669b
DC
848 }
849
850destroy:
0769c38d
DC
851 cy_as_ll_destroy_request(dev_p, req_p);
852 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 853
0769c38d 854 return ret;
81eb669b 855}
af109f2e 856EXPORT_SYMBOL(cy_as_mtp_cancel_send_object);
81eb669b
DC
857
858static cy_as_return_status_t
859my_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)
863{
864 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 865 goto destroy;
81eb669b
DC
866
867 if (cy_as_ll_request_response__get_code(reply_p) !=
868 CY_RESP_SUCCESS_FAILURE) {
0769c38d
DC
869 ret = CY_AS_ERROR_INVALID_RESPONSE;
870 goto destroy;
81eb669b
DC
871 }
872
0769c38d 873 ret = cy_as_ll_request_response__get_word(reply_p, 0);
81eb669b 874 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 875 goto destroy;
81eb669b
DC
876
877
878destroy:
0769c38d
DC
879 cy_as_ll_destroy_request(dev_p, req_p);
880 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 881
0769c38d 882 return ret;
81eb669b
DC
883}
884
885cy_as_return_status_t
886cy_as_mtp_cancel_get_object(cy_as_device_handle handle,
887 cy_as_function_callback cb,
888 uint32_t client
889 )
890{
0769c38d
DC
891 cy_as_ll_request_response *req_p = 0, *reply_p = 0;
892 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
893 cy_as_device *dev_p;
81eb669b 894
0769c38d 895 dev_p = (cy_as_device *)handle;
81eb669b 896 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 897 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
898
899 if (dev_p->mtp_count == 0)
0769c38d 900 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
901
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,
0769c38d 904 CY_RQT_TUR_RQT_CONTEXT, 0);
81eb669b 905 if (req_p == 0) {
0769c38d
DC
906 ret = CY_AS_ERROR_OUT_OF_MEMORY;
907 goto destroy;
81eb669b
DC
908 }
909
910 /* Reserve space for the reply, the reply data will
911 * not exceed one word */
0769c38d 912 reply_p = cy_as_ll_create_response(dev_p, 1);
81eb669b 913 if (reply_p == 0) {
0769c38d
DC
914 ret = CY_AS_ERROR_OUT_OF_MEMORY;
915 goto destroy;
81eb669b
DC
916 }
917
918 if (cb == 0) {
919 ret = cy_as_ll_send_request_wait_reply(dev_p,
0769c38d 920 req_p, reply_p);
81eb669b 921 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 922 goto destroy;
81eb669b
DC
923
924 return my_handle_response_cancel_get_object(dev_p,
0769c38d 925 req_p, reply_p, ret);
81eb669b
DC
926 } else {
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,
0769c38d 930 req_p, reply_p, cy_as_mtp_func_callback);
81eb669b
DC
931
932 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 933 goto destroy;
81eb669b 934
0769c38d 935 return ret;
81eb669b
DC
936 }
937
938destroy:
0769c38d
DC
939 cy_as_ll_destroy_request(dev_p, req_p);
940 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 941
0769c38d 942 return ret;
81eb669b 943}
af109f2e 944EXPORT_SYMBOL(cy_as_mtp_cancel_get_object);
81eb669b
DC
945
946cy_as_return_status_t
947cy_as_mtp_send_block_table(cy_as_device_handle handle,
948 cy_as_mtp_block_table *blk_table,
949 cy_as_function_callback cb,
950 uint32_t client)
951{
0769c38d
DC
952 cy_as_device *dev_p;
953 dev_p = (cy_as_device *)handle;
81eb669b 954 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 955 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
956
957 return cy_as_mtp_operation(dev_p, blk_table, 0, 0, cb,
0769c38d 958 client, CY_RQT_SEND_BLOCK_TABLE);
81eb669b
DC
959}
960
961static void
962cy_as_mtp_func_callback(cy_as_device *dev_p,
963 uint8_t context,
964 cy_as_ll_request_response *rqt,
965 cy_as_ll_request_response *resp,
966 cy_as_return_status_t stat)
967{
968 cy_as_func_c_b_node* node = (cy_as_func_c_b_node *)
0769c38d
DC
969 dev_p->func_cbs_mtp->head_p;
970 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
971 uint8_t code;
972 cy_bool delay_callback = cy_false;
81eb669b 973
0769c38d
DC
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);
81eb669b 976
0769c38d 977 (void)context;
81eb669b
DC
978
979 /* The Handlers are responsible for Deleting the
980 * rqt and resp when they are finished
981 */
0769c38d 982 code = cy_as_ll_request_response__get_code(rqt);
81eb669b
DC
983 switch (code) {
984 case CY_RQT_START_MTP:
985 ret = my_handle_response_mtp_start(dev_p, rqt,
0769c38d
DC
986 resp, stat);
987 break;
81eb669b
DC
988 case CY_RQT_STOP_MTP:
989 ret = my_handle_response_mtp_stop(dev_p, rqt,
0769c38d
DC
990 resp, stat);
991 break;
81eb669b
DC
992#if 0
993 case CY_RQT_INIT_SEND_OBJECT:
994 ret = my_handle_response_init_send_object(dev_p,
0769c38d
DC
995 rqt, resp, stat, cy_true);
996 delay_callback = cy_true;
997 break;
81eb669b
DC
998#endif
999 case CY_RQT_CANCEL_SEND_OBJECT:
1000 ret = my_handle_response_cancel_send_object(dev_p,
0769c38d
DC
1001 rqt, resp, stat);
1002 break;
81eb669b
DC
1003#if 0
1004 case CY_RQT_INIT_GET_OBJECT:
1005 ret = my_handle_response_init_get_object(dev_p,
0769c38d
DC
1006 rqt, resp, stat, cy_true);
1007 delay_callback = cy_true;
1008 break;
81eb669b
DC
1009#endif
1010 case CY_RQT_CANCEL_GET_OBJECT:
1011 ret = my_handle_response_cancel_get_object(dev_p,
0769c38d
DC
1012 rqt, resp, stat);
1013 break;
81eb669b
DC
1014#if 0
1015 case CY_RQT_SEND_BLOCK_TABLE:
1016 ret = my_handle_response_send_block_table(dev_p, rqt,
0769c38d
DC
1017 resp, stat, cy_true);
1018 delay_callback = cy_true;
1019 break;
81eb669b
DC
1020#endif
1021 case CY_RQT_ENABLE_USB_PATH:
0769c38d 1022 ret = my_handle_response_no_data(dev_p, rqt, resp);
81eb669b 1023 if (ret == CY_AS_ERROR_SUCCESS)
0769c38d
DC
1024 dev_p->is_storage_only_mode = cy_false;
1025 break;
81eb669b 1026 default:
0769c38d
DC
1027 ret = CY_AS_ERROR_INVALID_RESPONSE;
1028 cy_as_hal_assert(cy_false);
1029 break;
81eb669b
DC
1030 }
1031
1032 /*
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.
1036 */
1037 if (stat == CY_AS_ERROR_SUCCESS)
0769c38d 1038 stat = ret;
81eb669b
DC
1039
1040 if (!delay_callback) {
1041 node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
0769c38d
DC
1042 node->data_type, node->data);
1043 cy_as_remove_c_b_node(dev_p->func_cbs_mtp);
81eb669b
DC
1044 }
1045}
1046
1047cy_as_return_status_t
1048cy_as_mtp_storage_only_start(cy_as_device_handle handle)
1049{
0769c38d 1050 cy_as_device *dev_p = (cy_as_device *)handle;
81eb669b 1051 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 1052 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
1053
1054 if (!cy_as_device_is_configured(dev_p))
0769c38d 1055 return CY_AS_ERROR_NOT_CONFIGURED;
81eb669b
DC
1056
1057 if (!cy_as_device_is_firmware_loaded(dev_p))
0769c38d 1058 return CY_AS_ERROR_NO_FIRMWARE;
81eb669b
DC
1059
1060 if (dev_p->storage_count == 0)
0769c38d 1061 return CY_AS_ERROR_NOT_RUNNING;
81eb669b 1062
0769c38d
DC
1063 dev_p->is_storage_only_mode = cy_true;
1064 return CY_AS_ERROR_SUCCESS;
81eb669b 1065}
af109f2e 1066EXPORT_SYMBOL(cy_as_mtp_storage_only_start);
81eb669b
DC
1067
1068cy_as_return_status_t
1069cy_as_mtp_storage_only_stop(cy_as_device_handle handle,
1070 cy_as_function_callback cb,
1071 uint32_t client)
1072{
0769c38d
DC
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;
81eb669b
DC
1076
1077 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
0769c38d 1078 return CY_AS_ERROR_INVALID_HANDLE;
81eb669b
DC
1079
1080 if (!cy_as_device_is_configured(dev_p))
0769c38d 1081 return CY_AS_ERROR_NOT_CONFIGURED;
81eb669b
DC
1082
1083 if (!cy_as_device_is_firmware_loaded(dev_p))
0769c38d 1084 return CY_AS_ERROR_NO_FIRMWARE;
81eb669b
DC
1085
1086 if (dev_p->storage_count == 0)
0769c38d 1087 return CY_AS_ERROR_NOT_RUNNING;
81eb669b
DC
1088
1089 if (dev_p->is_storage_only_mode == cy_false)
0769c38d 1090 return CY_AS_ERROR_SUCCESS;
81eb669b
DC
1091
1092 if (cy_as_device_is_in_callback(dev_p))
0769c38d 1093 return CY_AS_ERROR_INVALID_IN_CALLBACK;
81eb669b
DC
1094
1095 req_p = cy_as_ll_create_request(dev_p,
0769c38d 1096 CY_RQT_ENABLE_USB_PATH, CY_RQT_TUR_RQT_CONTEXT, 1);
81eb669b 1097 if (req_p == 0)
0769c38d 1098 return CY_AS_ERROR_OUT_OF_MEMORY;
81eb669b 1099
0769c38d 1100 reply_p = cy_as_ll_create_response(dev_p, 1);
81eb669b 1101 if (reply_p == 0) {
0769c38d
DC
1102 cy_as_ll_destroy_request(dev_p, req_p);
1103 return CY_AS_ERROR_OUT_OF_MEMORY;
81eb669b
DC
1104 }
1105
1106 if (cb == 0) {
1107 ret = cy_as_ll_send_request_wait_reply(dev_p,
0769c38d 1108 req_p, reply_p);
81eb669b 1109 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 1110 goto destroy;
81eb669b
DC
1111
1112 ret = my_handle_response_no_data(dev_p, req_p,
0769c38d 1113 reply_p);
81eb669b 1114 if (ret == CY_AS_ERROR_SUCCESS)
0769c38d
DC
1115 dev_p->is_storage_only_mode = cy_false;
1116 return ret;
81eb669b
DC
1117 } else {
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,
0769c38d 1121 req_p, reply_p, cy_as_mtp_func_callback);
81eb669b
DC
1122
1123 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 1124 goto destroy;
81eb669b 1125
0769c38d 1126 return ret;
81eb669b
DC
1127 }
1128
1129destroy:
0769c38d
DC
1130 cy_as_ll_destroy_request(dev_p, req_p);
1131 cy_as_ll_destroy_response(dev_p, reply_p);
81eb669b 1132
0769c38d 1133 return ret;
81eb669b 1134}
af109f2e
SR
1135EXPORT_SYMBOL(cy_as_mtp_storage_only_stop);
1136