Fix double free
[platform/core/connectivity/mtp-responder.git] / src / transport / mtp_usb_driver_ffs.c
1 /* -*- mode: C; c-file-style: "linux" -*-
2  *
3  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #define _GNU_SOURCE
19 #include <sys/ioctl.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <signal.h>
23 #include <glib.h>
24 #include "mtp_usb_driver.h"
25 #include "mtp_device.h"
26 #include "mtp_descs_strings.h"
27 #include "ptp_datacodes.h"
28 #include "mtp_support.h"
29 #include "ptp_container.h"
30 #include "mtp_msgq.h"
31 #include "mtp_thread.h"
32 #include "mtp_transport.h"
33 #include "mtp_event_handler.h"
34 #include "mtp_init.h"
35 #include <sys/prctl.h>
36 #include <systemd/sd-daemon.h>
37
38 /*
39  * GLOBAL AND EXTERN VARIABLES
40  */
41 extern mtp_config_t g_conf;
42
43 /*
44  * STATIC VARIABLES AND FUNCTIONS
45  */
46
47 /*PIMA15740-2000 spec*/
48 #define USB_PTPREQUEST_CANCELIO   0x64    /* Cancel request */
49 #define USB_PTPREQUEST_GETEVENT   0x65    /* Get extened event data */
50 #define USB_PTPREQUEST_RESET      0x66    /* Reset Device */
51 #define USB_PTPREQUEST_GETSTATUS  0x67    /* Get Device Status */
52 #define USB_PTPREQUEST_CANCELIO_SIZE 6
53 #define USB_PTPREQUEST_GETSTATUS_SIZE 12
54
55 static mtp_int32 g_usb_ep0 = -1;       /* read (g_usb_ep0, ...) */
56 static mtp_int32 g_usb_ep_in = -1;     /* write (g_usb_ep_in, ...) */
57 static mtp_int32 g_usb_ep_out = -1;    /* read (g_usb_ep_out, ...) */
58 static mtp_int32 g_usb_ep_status = -1; /* write (g_usb_ep_status, ...) */
59
60 static mtp_max_pkt_size_t pkt_size;
61 static mtp_uint32 rx_mq_sz;
62 static mtp_uint32 tx_mq_sz;
63 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
64                 mtp_uchar *buf, mtp_int32 buf_len);
65 static void __clean_up_msg_queue(void *param);
66 static void __handle_control_request(mtp_int32 request);
67
68 /*
69  * FUNCTIONS
70  */
71
72 /* LCOV_EXCL_START */
73 static mtp_bool __io_init()
74 {
75         int ret;
76
77         if (sd_listen_fds(0) >= 4) {
78                 DBG("socket-activated");
79                 g_usb_ep0 = SD_LISTEN_FDS_START;
80                 g_usb_ep_in = SD_LISTEN_FDS_START + 1;
81                 g_usb_ep_out = SD_LISTEN_FDS_START + 2;
82                 g_usb_ep_status = SD_LISTEN_FDS_START + 3;
83
84                 return TRUE;
85         }
86
87         g_usb_ep0 = open(MTP_EP0_PATH, O_RDWR);
88         if (g_usb_ep0 < 0)
89                 goto out;
90
91         DBG("Writing USB descriptors");
92         ret = write(g_usb_ep0, &descriptors, sizeof(descriptors));
93         if (ret < 0) {
94                 ERR("Error writing descriptors");
95                 goto cleanup;
96         }
97
98         DBG("Writing USB strings");
99         ret = write(g_usb_ep0, &strings, sizeof(strings));
100         if (ret < 0) {
101                 ERR("Error writing strings");
102                 goto cleanup;
103         }
104
105         g_usb_ep_in = open(MTP_EP_IN_PATH, O_RDWR);
106         if (g_usb_ep_in < 0) {
107                 ERR("Error opening bulk-in");
108                 goto cleanup;
109         }
110
111         g_usb_ep_out = open(MTP_EP_OUT_PATH, O_RDWR);
112         if (g_usb_ep_out < 0) {
113                 ERR("Error opening bulk-out");
114                 goto cleanup_in;
115         }
116
117         g_usb_ep_status = open(MTP_EP_STATUS_PATH, O_RDWR);
118         if (g_usb_ep_status < 0) {
119                 ERR("Error opening status");
120                 goto cleanup_out;
121         }
122
123         return TRUE;
124
125 cleanup_out:
126         close(g_usb_ep_out);
127 cleanup_in:
128         close(g_usb_ep_in);
129 cleanup:
130         close(g_usb_ep0);
131 out:
132         return FALSE;
133 }
134
135 static mtp_bool ffs_transport_init_usb_device(void)
136 {
137         mtp_int32 status = 0;
138         int msg_size;
139
140         if (g_usb_ep0 > 0) {
141                 DBG("Device Already open\n");
142                 return TRUE;
143         }
144
145         status = __io_init();
146         if (!status) {
147                 char error[256];
148                 ERR("Device node [%s] open failed, errno [%s]\n",
149                     MTP_EP0_PATH, strerror_r(errno, error, sizeof(error)));
150                 return FALSE;
151         }
152
153         pkt_size.rx = g_conf.read_usb_size;
154         pkt_size.tx = g_conf.write_usb_size;
155
156         DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx);
157
158         msg_size = sizeof(msgq_ptr_t) - sizeof(long);
159         rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size;
160         tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size;
161
162         DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz);
163
164         return TRUE;
165 }
166
167 static void ffs_transport_deinit_usb_device(void)
168 {
169         if (g_usb_ep0 >= 0)
170                 close(g_usb_ep0);
171         g_usb_ep0 = -1;
172
173         if (g_usb_ep_in >= 0)
174                 close(g_usb_ep_in);
175         g_usb_ep_in = -1;
176
177         if (g_usb_ep_out >= 0)
178                 close(g_usb_ep_out);
179         g_usb_ep_out = -1;
180
181         if (g_usb_ep_status >= 0)
182                 close(g_usb_ep_status);
183         g_usb_ep_status = -1;
184
185         return;
186 }
187
188 static mtp_uint32 ffs_get_tx_pkt_size(void)
189 {
190         return pkt_size.tx;
191 }
192
193 static mtp_uint32 ffs_get_rx_pkt_size(void)
194 {
195         return pkt_size.rx;
196 }
197
198 /*
199  * static mtp_int32 ffs_transport_mq_init()
200  * This function create a message queue for MTP,
201  * A created message queue will be used to help data transfer between
202  * MTP module and usb buffer.
203  * @return      This function returns TRUE on success or
204  *              returns FALSE on failure.
205  */
206 static mtp_int32 ffs_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
207 {
208         if (_util_msgq_init(rx_mqid, 0) == FALSE) {
209                 ERR("RX MQ init Fail [%d]\n", errno);
210                 return FALSE;
211         }
212
213         if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE)
214                 ERR("RX MQ setting size Fail [%d]\n", errno);
215
216         if (_util_msgq_init(tx_mqid, 0) == FALSE) {
217                 ERR("TX MQ init Fail [%d]\n", errno);
218                 _util_msgq_deinit(rx_mqid);
219                 *rx_mqid = -1;
220                 return FALSE;
221         }
222
223         if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE)
224                 ERR("TX MQ setting size Fail [%d]\n", errno);
225
226         return TRUE;
227 }
228
229 static void *ffs_transport_thread_usb_write(void *arg)
230 {
231         mtp_int32 status = 0;
232         mtp_uint32 len = 0;
233         unsigned char *mtp_buf = NULL;
234         msg_type_t mtype = MTP_UNDEFINED_PACKET;
235         msgq_id_t *mqid = (msgq_id_t *)arg;
236
237         pthread_cleanup_push(__clean_up_msg_queue, mqid);
238
239         do {
240                 /* original LinuxThreads cancelation didn't work right
241                  * so test for it explicitly.
242                  */
243                 pthread_testcancel();
244
245                 _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype);
246
247                 if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) {
248                         status = write(g_usb_ep_in, mtp_buf, len);
249                         if (status < 0) {
250                                 ERR("USB write fail : %d\n", errno);
251                                 if (errno == ENOMEM || errno == ECANCELED) {
252                                         status = 0;
253                                         __clean_up_msg_queue(mqid);
254                                 }
255                         }
256                         g_free(mtp_buf);
257                         mtp_buf = NULL;
258                 } else if (MTP_EVENT_PACKET == mtype) {
259                         /* Handling the MTP Asynchronous Events */
260                         DBG("Send Interrupt data to kernel via g_usb_ep_status\n");
261                         status = write(g_usb_ep_status, mtp_buf, len);
262                         g_free(mtp_buf);
263                         mtp_buf = NULL;
264                 } else if (MTP_ZLP_PACKET == mtype) {
265                         DBG("Send ZLP data to kerne via g_usb_ep_in\n");
266                         status = write(g_usb_ep_in, (void*)0xFEE1DEAD, 0);
267                 } else {
268                         DBG("mtype = %d is not valid\n", mtype);
269                         status = -1;
270                 }
271
272                 if (status < 0) {
273                         ERR("write data to the device node Fail:\
274                                         status = %d\n", status);
275                         break;
276                 }
277         } while (status >= 0);
278
279         DBG("exited Source thread with status %d\n", status);
280         pthread_cleanup_pop(1);
281         g_free(mtp_buf);
282
283         return NULL;
284 }
285
286 static int __setup(int ep0, struct usb_ctrlrequest *ctrl)
287 {
288         const char* requests[] = {
289                 "CANCELIO",     /* 0x64 */
290                 "GETEVENT",     /* 0x65 */
291                 "RESET",        /* 0x66 */
292                 "GETSTATUS",    /* 0x67 */
293         };
294         __u16 wIndex = le16_to_cpu(ctrl->wIndex);
295         __u16 wValue = le16_to_cpu(ctrl->wValue);
296         __u16 wLength = le16_to_cpu(ctrl->wLength);
297         int rc = -EOPNOTSUPP;
298         int status = 0;
299
300         if ((ctrl->bRequestType & 0x7f) != (USB_TYPE_CLASS | USB_RECIP_INTERFACE)) {
301                 DBG(__FILE__ "(%s):%d: Invalid request type: %d",
302                     __func__, __LINE__, ctrl->bRequestType);
303                 goto stall;
304         }
305
306         switch (((ctrl->bRequestType & 0x80) << 8) | ctrl->bRequest) {
307         case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_CANCELIO):
308
309                 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
310                     __func__, __LINE__, requests[ctrl->bRequest-0x64]);
311                 if (wValue != 0 || wIndex != 0 || wLength != 6) {
312                         DBG("Invalid request parameters: wValue:%hu wIndex:%hu wLength:%hu\n", wIndex, wValue, wLength);
313                         rc = -EINVAL;
314                         goto stall;
315                 }
316                 __handle_control_request(ctrl->bRequest);
317                 break;
318
319         case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETSTATUS):
320         case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_RESET):
321
322                 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
323                     __func__, __LINE__, requests[ctrl->bRequest-0x64]);
324                 __handle_control_request(ctrl->bRequest);
325                 break;
326
327         case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETEVENT):
328
329                 /* Optional, may stall */
330                 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
331                     __func__, __LINE__, requests[ctrl->bRequest-0x64]);
332                 rc = -EOPNOTSUPP;
333                 goto stall;
334                 break;
335
336         default:
337                 DBG(__FILE__ "(%s):%d: Invalid request: %d", __func__,
338                     __LINE__, ctrl->bRequest);
339                 goto stall;
340         }
341         return 0;
342
343 stall:
344
345         DBG(__FILE__"(%s):%d:stall %0x2x.%02x\n",
346             __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest);
347         if ((ctrl->bRequestType & 0x80) == USB_DIR_IN)
348                 status = read(g_usb_ep0, NULL, 0);
349         else
350                 status = write(g_usb_ep0, NULL, 0);
351
352         if (status != -1 || errno != EL2HLT) {
353                 ERR(__FILE__"(%s):%d:stall error\n",
354                     __func__, __LINE__);
355                 rc = errno;
356         }
357         return rc;
358 }
359
360 static void *ffs_transport_thread_usb_read(void *arg)
361 {
362         mtp_int32 status = 0;
363         msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL};
364         msgq_id_t *mqid = (msgq_id_t *)arg;
365         mtp_uint32 rx_size = _get_rx_pkt_size();
366
367         pthread_cleanup_push(__clean_up_msg_queue, mqid);
368
369         do {
370                 pthread_testcancel();
371
372                 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
373                 if (NULL == pkt.buffer) {
374                         ERR("Sink thread: memalloc failed.\n");
375                         break;
376                 }
377
378                 status = read(g_usb_ep_out, pkt.buffer, rx_size);
379                 if (status <= 0) {
380                         status = __handle_usb_read_err(status, pkt.buffer, rx_size);
381                         if (status <= 0) {
382                                 ERR("__handle_usb_read_err is failed\n");
383                                 g_free(pkt.buffer);
384                                 break;
385                         }
386                 }
387
388                 pkt.length = status;
389                 if (FALSE == _util_msgq_send(*mqid, (void *)&pkt,
390                                              sizeof(msgq_ptr_t) - sizeof(long), 0)) {
391                         ERR("msgsnd Fail");
392                         g_free(pkt.buffer);
393                 }
394         } while (status > 0);
395
396         DBG("status[%d] errno[%d]\n", status, errno);
397         pthread_cleanup_pop(1);
398
399         return NULL;
400 }
401
402 static void *ffs_transport_thread_usb_control(void *arg)
403 {
404         mtp_int32 status = 0;
405         struct usb_functionfs_event event;
406         msgq_id_t *mqid = (msgq_id_t *)arg;
407
408         pthread_cleanup_push(__clean_up_msg_queue, mqid);
409
410         do {
411                 pthread_testcancel();
412
413                 status = read(g_usb_ep0, &event, sizeof(event));
414                 if (status < 0) {
415                         char error[256];
416                         ERR("read from ep0 failed: %s",
417                             strerror_r(errno, error, sizeof(error)));
418                         continue;
419                 }
420                 DBG("FUNCTIONFS event received: %d", event.type);
421
422                 switch (event.type) {
423                 case FUNCTIONFS_SETUP:
424                         DBG("SETUP: bmRequestType:%d bRequest:%d wValue:%d wIndex:%d wLength:%d\n",
425                             event.u.setup.bRequestType,
426                             event.u.setup.bRequest,
427                             event.u.setup.wValue,
428                             event.u.setup.wIndex,
429                             event.u.setup.wLength);
430                         __setup(g_usb_ep0, &event.u.setup);
431                         break;
432                 case FUNCTIONFS_ENABLE:
433                         DBG("ENABLE");
434                         _util_set_local_usb_status(MTP_PHONE_USB_CONNECTED);
435                         break;
436                 case FUNCTIONFS_DISABLE:
437                         DBG("DISABLE");
438                         _util_set_local_usb_status(MTP_PHONE_USB_DISCONNECTED);
439                         _eh_send_event_req_to_eh_thread(EVENT_USB_REMOVED, 0, 0, NULL);
440                         break;
441                 }
442         } while (status > 0);
443
444         DBG("status[%d] errno[%d]\n", status, errno);
445         pthread_cleanup_pop(1);
446
447         return NULL;
448 }
449
450 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
451                 mtp_uchar *buf, mtp_int32 buf_len)
452 {
453         mtp_int32 retry = 0;
454         mtp_bool ret;
455
456         while (retry++ < MTP_USB_ERROR_MAX_RETRY) {
457                 if (err == 0) {
458                         DBG("ZLP(Zero Length Packet). Skip");
459                 } else if (err < 0 && errno == EINTR) {
460                         DBG("read () is interrupted. Skip");
461                 } else if (err < 0 && errno == EIO) {
462                         DBG("EIO");
463
464                         if (MTP_PHONE_USB_CONNECTED !=
465                             _util_get_local_usb_status()) {
466                                 ERR("USB is disconnected");
467                                 break;
468                         }
469
470                         _transport_deinit_usb_device();
471                         ret = _transport_init_usb_device();
472                         if (ret == FALSE) {
473                                 ERR("_transport_init_usb_device Fail");
474                                 continue;
475                         }
476                 } else if (err < 0 && errno == ESHUTDOWN) {
477                         DBG("ESHUTDOWN");
478                 } else {
479                         ERR("Unknown error : %d, errno [%d] \n", err, errno);
480                         break;
481                 }
482
483                 err = read(g_usb_ep_out, buf, buf_len);
484                 if (err > 0)
485                         break;
486         }
487
488         if (err <= 0)
489                 ERR("USB error handling Fail");
490
491         return err;
492 }
493
494 static void __clean_up_msg_queue(void *mq_id)
495 {
496         mtp_int32 len = 0;
497         msgq_ptr_t pkt = { 0 };
498         msgq_id_t l_mqid;
499
500         ret_if(mq_id == NULL);
501
502         l_mqid = *(msgq_id_t *)mq_id;
503         _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
504         while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt,
505                                           sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) {
506                 g_free(pkt.buffer);
507                 memset(&pkt, 0, sizeof(msgq_ptr_t));
508         }
509
510         return;
511 }
512
513 static void __handle_control_request(mtp_int32 request)
514 {
515         static mtp_bool kernel_reset = FALSE;
516         static mtp_bool host_cancel = FALSE;
517         mtp_int32 status = 0;
518
519         switch (request) {
520         case USB_PTPREQUEST_CANCELIO:
521                 // XXX: Convert cancel request data from little-endian
522                 // before use:  le32_to_cpu(x), le16_to_cpu(x).
523                 DBG("USB_PTPREQUEST_CANCELIO\n");
524                 cancel_req_t cancelreq_data;
525
526                 host_cancel = TRUE;
527                 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
528                 status = read(g_usb_ep0, &cancelreq_data, sizeof(cancelreq_data));
529                 if (status < 0) {
530                         char error[256];
531                         ERR("Failed to read data for CANCELIO request\n: %s",
532                                         strerror_r(errno, error, sizeof(error)));
533                 }
534                 break;
535
536         case USB_PTPREQUEST_RESET:
537
538                 DBG("USB_PTPREQUEST_RESET\n");
539                 _reset_mtp_device();
540                 if (kernel_reset == FALSE) {
541                         kernel_reset = TRUE;
542                 }
543
544                 status = read(g_usb_ep0, NULL, 0);
545                 if (status < 0) {
546                         ERR("IOCTL MTP_SEND_RESET_ACK Failed [%d]\n",
547                                 status);
548                 }
549                 break;
550         case USB_PTPREQUEST_GETSTATUS:
551
552                 DBG("USB_PTPREQUEST_GETSTATUS");
553
554                 /* Send busy status response just once. This flag is also for
555                  * the case that mtp misses the cancel request packet.
556                  */
557                 static mtp_bool sent_busy = FALSE;
558                 usb_status_req_t statusreq_data = { 0 };
559                 mtp_dword num_param = 0;
560
561                 memset(&statusreq_data, 0x00, sizeof(usb_status_req_t));
562                 if (host_cancel == TRUE || (sent_busy == FALSE &&
563                                             kernel_reset == FALSE)) {
564                         DBG("Send busy response, set host_cancel to FALSE");
565                         statusreq_data.len = 0x08;
566                         statusreq_data.code = PTP_RESPONSE_DEVICEBUSY;
567                         host_cancel = FALSE;
568                 } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) {
569                         statusreq_data.code =
570                                 PTP_RESPONSE_TRANSACTIONCANCELLED;
571                         DBG("PTP_RESPONSE_TRANSACTIONCANCELLED");
572                         statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) +
573                                                         (num_param - 2) * sizeof(mtp_dword));
574                 } else if (_device_get_status() == DEVICE_STATUSOK) {
575                         DBG("PTP_RESPONSE_OK");
576                         statusreq_data.len = 0x08;
577                         statusreq_data.code = PTP_RESPONSE_OK;
578
579                         if (kernel_reset == TRUE)
580                                 kernel_reset = FALSE;
581                 } else {
582                         DBG("PTP_RESPONSE_GEN_ERROR");
583                         statusreq_data.len = 0x08;
584                         statusreq_data.code = PTP_RESPONSE_GEN_ERROR;
585                 }
586
587                 if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY) {
588                         sent_busy = TRUE;
589                 } else {
590                         sent_busy = FALSE;
591                 }
592
593                 /* status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data);
594                 if (status < 0) {
595                         DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n",
596                                         status);
597                         return;
598                 } */
599
600                 break;
601
602         case USB_PTPREQUEST_GETEVENT:
603                 DBG("USB_PTPREQUEST_GETEVENT");
604                 break;
605
606         default:
607                 DBG("Invalid class specific setup request");
608                 break;
609         }
610         return;
611 }
612
613 /*
614  * mtp_bool ffs_transport_mq_deinit()
615  * This function destroy a message queue for MTP,
616  * @return      This function returns TRUE on success or
617  *              returns FALSE on failure.
618  */
619 static mtp_bool ffs_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
620 {
621         mtp_int32 res = TRUE;
622
623         if (*rx_mqid) {
624                 res = _util_msgq_deinit(rx_mqid);
625                 if (res == FALSE) {
626                         ERR("rx_mqid deinit Fail [%d]\n", errno);
627                 } else {
628                         *rx_mqid = 0;
629                 }
630         }
631
632         if (*tx_mqid) {
633                 res = _util_msgq_deinit(tx_mqid);
634                 if (res == FALSE) {
635                         ERR("tx_mqid deinit fail [%d]\n", errno);
636                 } else {
637                         *tx_mqid = 0;
638                 }
639         }
640
641         return res;
642 }
643
644 static mtp_uint32 ffs_transport_get_usb_packet_len(void)
645 {
646         mtp_int32 status = -1;
647         static mtp_int32 usb_speed = 0;
648
649         if (usb_speed == 0) {
650
651                 //status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed);
652                 if (status < 0) {
653                         ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status);
654                         return MTP_MAX_PACKET_SIZE_SEND_FS;
655                 }
656         }
657
658         if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS) {
659                 return MTP_MAX_PACKET_SIZE_SEND_FS;
660         }
661
662         return MTP_MAX_PACKET_SIZE_SEND_HS;
663 }
664 /* LCOV_EXCL_STOP */
665
666
667 const mtp_usb_driver_t mtp_usb_driver_ffs = {
668         .transport_init_usb_device = ffs_transport_init_usb_device,
669         .transport_deinit_usb_device = ffs_transport_deinit_usb_device,
670         .transport_thread_usb_write = ffs_transport_thread_usb_write,
671         .transport_thread_usb_read = ffs_transport_thread_usb_read,
672         .transport_thread_usb_control = ffs_transport_thread_usb_control,
673         .transport_mq_init = ffs_transport_mq_init,
674         .transport_mq_deinit = ffs_transport_mq_deinit,
675         .transport_get_usb_packet_len = ffs_transport_get_usb_packet_len,
676         .get_tx_pkt_size = ffs_get_tx_pkt_size,
677         .get_rx_pkt_size = ffs_get_rx_pkt_size,
678 };