1 /* -*- mode: C; c-file-style: "linux" -*-
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
6 * PROPRIETARY/CONFIDENTIAL
8 * This software is the confidential and proprietary information of
9 * SAMSUNG ELECTRONICS ("Confidential Information"). You agree and acknowledge
10 * that this software is owned by Samsung and you shall not disclose
11 * such Confidential Information and shall use it only in accordance with
12 * the terms of the license agreement you entered into with SAMSUNG ELECTRONICS.
13 * SAMSUNG make no representations or warranties about the suitability of
14 * the software, either express or implied, including but not limited to
15 * the implied warranties of merchantability, fitness for a particular purpose,
16 * or non-infringement. SAMSUNG shall not be liable for any damages suffered by
17 * licensee arising out of or related to this software.
21 #include <sys/ioctl.h>
26 #include "mtp_usb_driver.h"
27 #include "mtp_device.h"
28 #include "ptp_datacodes.h"
29 #include "mtp_support.h"
30 #include "ptp_container.h"
32 #include "mtp_thread.h"
33 #include "mtp_transport.h"
34 #include "mtp_event_handler.h"
35 #include <sys/prctl.h>
36 #include <linux/usb/ch9.h>
37 #include <linux/usb/functionfs.h>
40 * GLOBAL AND EXTERN VARIABLES
42 extern mtp_config_t g_conf;
45 * STATIC VARIABLES AND FUNCTIONS
47 #ifndef FUNCTIONFS_DESCRIPTORS_MAGIC_V2
48 #define FUNCTIONFS_DESCRIPTORS_MAGIC_V2 3
49 enum functionfs_flags {
50 FUNCTIONFS_HAS_FS_DESC = 1,
51 FUNCTIONFS_HAS_HS_DESC = 2,
52 FUNCTIONFS_HAS_SS_DESC = 4,
53 FUNCTIONFS_HAS_MS_OS_DESC = 8,
57 /*PIMA15740-2000 spec*/
58 #define USB_PTPREQUEST_CANCELIO 0x64 /* Cancel request */
59 #define USB_PTPREQUEST_GETEVENT 0x65 /* Get extened event data */
60 #define USB_PTPREQUEST_RESET 0x66 /* Reset Device */
61 #define USB_PTPREQUEST_GETSTATUS 0x67 /* Get Device Status */
62 #define USB_PTPREQUEST_CANCELIO_SIZE 6
63 #define USB_PTPREQUEST_GETSTATUS_SIZE 12
65 #define cpu_to_le16(x) htole16(x)
66 #define cpu_to_le32(x) htole32(x)
67 #define le32_to_cpu(x) le32toh(x)
68 #define le16_to_cpu(x) le16toh(x)
80 struct usb_interface_descriptor intf;
81 struct usb_endpoint_descriptor_no_audio bulk_in;
82 struct usb_endpoint_descriptor_no_audio bulk_out;
83 struct usb_endpoint_descriptor_no_audio int_in;
84 } __attribute__((packed)) fs_descs, hs_descs;
85 // struct {} __attribute__((packed)) os_descs;
86 } __attribute__((packed)) descriptors = {
88 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
89 .length = cpu_to_le32(sizeof(descriptors)),
90 .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC, // | FUNCTIONFS_HAS_MS_OS_DESC,
96 // drivers/usb/gadget/f_mtp_slp.c:207
98 .bLength = sizeof(descriptors.fs_descs.intf),
99 .bDescriptorType = USB_DT_INTERFACE,
101 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
102 .bInterfaceSubClass = 1,
103 .bInterfaceProtocol = 1,
107 .bLength = USB_DT_ENDPOINT_SIZE,
108 .bDescriptorType = USB_DT_ENDPOINT,
109 .bEndpointAddress = 1 | USB_DIR_IN,
110 .bmAttributes = USB_ENDPOINT_XFER_BULK,
111 .wMaxPacketSize = __constant_cpu_to_le16(64),
114 .bLength = USB_DT_ENDPOINT_SIZE,
115 .bDescriptorType = USB_DT_ENDPOINT,
116 .bEndpointAddress = 2 | USB_DIR_OUT,
117 .bmAttributes = USB_ENDPOINT_XFER_BULK,
118 .wMaxPacketSize = __constant_cpu_to_le16(64),
121 .bLength = USB_DT_ENDPOINT_SIZE,
122 .bDescriptorType = USB_DT_ENDPOINT,
123 .bEndpointAddress = 3 | USB_DIR_IN,
124 .bmAttributes = USB_ENDPOINT_XFER_INT,
125 .wMaxPacketSize = __constant_cpu_to_le16(64),
131 .bLength = sizeof(descriptors.fs_descs.intf),
132 .bDescriptorType = USB_DT_INTERFACE,
134 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
135 .bInterfaceSubClass = 1,
136 .bInterfaceProtocol = 1,
140 .bLength = USB_DT_ENDPOINT_SIZE,
141 .bDescriptorType = USB_DT_ENDPOINT,
142 .bEndpointAddress = 1 | USB_DIR_IN,
143 .bmAttributes = USB_ENDPOINT_XFER_BULK,
144 .wMaxPacketSize = __constant_cpu_to_le16(512),
147 .bLength = USB_DT_ENDPOINT_SIZE,
148 .bDescriptorType = USB_DT_ENDPOINT,
149 .bEndpointAddress = 2 | USB_DIR_OUT,
150 .bmAttributes = USB_ENDPOINT_XFER_BULK,
151 .wMaxPacketSize = __constant_cpu_to_le16(512),
154 .bLength = USB_DT_ENDPOINT_SIZE,
155 .bDescriptorType = USB_DT_ENDPOINT,
156 .bEndpointAddress = 3 | USB_DIR_IN,
157 .bmAttributes = USB_ENDPOINT_XFER_INT,
158 .wMaxPacketSize = __constant_cpu_to_le16(64),
164 #define STR_INTERFACE "Samsung MTP"
166 static const struct {
167 struct usb_functionfs_strings_head header;
170 const char str1[sizeof(STR_INTERFACE)];
171 } __attribute__((packed)) lang0;
172 } __attribute__((packed)) strings = {
174 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
175 .length = cpu_to_le32(sizeof(strings)),
176 .str_count = cpu_to_le32(1),
177 .lang_count = cpu_to_le32(1),
180 cpu_to_le16(0x0409), /* en-us */
185 static mtp_int32 g_usb_ep0 = -1; /* read (g_usb_ep0, ...) */
186 static mtp_int32 g_usb_ep_in = -1; /* write (g_usb_ep_in, ...) */
187 static mtp_int32 g_usb_ep_out = -1; /* read (g_usb_ep_out, ...) */
188 static mtp_int32 g_usb_ep_status = -1; /* write (g_usb_ep_status, ...) */
190 static mtp_max_pkt_size_t pkt_size;
191 static mtp_uint32 rx_mq_sz;
192 static mtp_uint32 tx_mq_sz;
193 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
194 mtp_uchar *buf, mtp_int32 buf_len);
195 static void __clean_up_msg_queue(void *param);
196 static void __handle_control_request(mtp_int32 request);
202 static mtp_bool __io_init()
206 g_usb_ep0 = open(MTP_EP0_PATH, O_RDWR);
210 DBG("Writing USB descriptors");
211 ret = write(g_usb_ep0, &descriptors, sizeof(descriptors));
213 ERR("Error writing descriptors");
217 DBG("Writing USB strings");
218 ret = write(g_usb_ep0, &strings, sizeof(strings));
220 ERR("Error writing strings");
224 g_usb_ep_in = open(MTP_EP_IN_PATH, O_RDWR);
225 if (g_usb_ep_in < 0) {
226 ERR("Error opening bulk-in");
230 g_usb_ep_out = open(MTP_EP_OUT_PATH, O_RDWR);
231 if (g_usb_ep_out < 0) {
232 ERR("Error opening bulk-out");
236 g_usb_ep_status = open(MTP_EP_STATUS_PATH, O_RDWR);
237 if (g_usb_ep_status < 0) {
238 ERR("Error opening status");
254 static mtp_bool ffs_transport_init_usb_device(void)
256 mtp_int32 status = 0;
260 DBG("Device Already open\n");
264 status = __io_init();
267 ERR("Device node [%s] open failed, errno [%s]\n",
268 MTP_EP0_PATH, strerror_r(errno, error, sizeof(error)));
272 pkt_size.rx = g_conf.read_usb_size;
273 pkt_size.tx = g_conf.write_usb_size;
275 DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx);
277 msg_size = sizeof(msgq_ptr_t) - sizeof(long);
278 rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size;
279 tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size;
281 DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz);
286 static void ffs_transport_deinit_usb_device(void)
292 if (g_usb_ep_in >= 0)
296 if (g_usb_ep_out >= 0)
300 if (g_usb_ep_status >= 0)
301 close(g_usb_ep_status);
302 g_usb_ep_status = -1;
307 static mtp_uint32 ffs_get_tx_pkt_size(void)
312 static mtp_uint32 ffs_get_rx_pkt_size(void)
318 * static mtp_int32 ffs_transport_mq_init()
319 * This function create a message queue for MTP,
320 * A created message queue will be used to help data transfer between
321 * MTP module and usb buffer.
322 * @return This function returns TRUE on success or
323 * returns FALSE on failure.
325 static mtp_int32 ffs_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
327 if (_util_msgq_init(rx_mqid, 0) == FALSE) {
328 ERR("RX MQ init Fail [%d]\n", errno);
332 if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE)
333 ERR("RX MQ setting size Fail [%d]\n", errno);
335 if (_util_msgq_init(tx_mqid, 0) == FALSE) {
336 ERR("TX MQ init Fail [%d]\n", errno);
337 _util_msgq_deinit(rx_mqid);
342 if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE)
343 ERR("TX MQ setting size Fail [%d]\n", errno);
348 static void *ffs_transport_thread_usb_write(void *arg)
350 mtp_int32 status = 0;
352 unsigned char *mtp_buf = NULL;
353 msg_type_t mtype = MTP_UNDEFINED_PACKET;
354 msgq_id_t *mqid = (msgq_id_t *)arg;
356 pthread_cleanup_push(__clean_up_msg_queue, mqid);
359 /* original LinuxThreads cancelation didn't work right
360 * so test for it explicitly.
362 pthread_testcancel();
364 _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype);
366 if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) {
367 status = write(g_usb_ep_in, mtp_buf, len);
369 ERR("USB write fail : %d\n", errno);
370 if (errno == ENOMEM || errno == ECANCELED) {
372 __clean_up_msg_queue(mqid);
377 } else if (MTP_EVENT_PACKET == mtype) {
378 /* Handling the MTP Asynchronous Events */
379 DBG("Send Interrupt data to kernel via g_usb_ep_status\n");
380 status = write(g_usb_ep_status, mtp_buf, len);
383 } else if (MTP_ZLP_PACKET == mtype) {
384 DBG("Send ZLP data to kerne via g_usb_ep_in\n");
385 status = write(g_usb_ep_in, (void*)0xFEE1DEAD, 0);
387 DBG("mtype = %d is not valid\n", mtype);
392 ERR("write data to the device node Fail:\
393 status = %d\n", status);
396 } while (status >= 0);
398 DBG("exited Source thread with status %d\n", status);
399 pthread_cleanup_pop(1);
405 static int __setup(int ep0, struct usb_ctrlrequest *ctrl)
407 const char* requests[] = {
408 "CANCELIO", /* 0x64 */
409 "GETEVENT", /* 0x65 */
411 "GETSTATUS", /* 0x67 */
413 __u16 wIndex = le16_to_cpu(ctrl->wIndex);
414 __u16 wValue = le16_to_cpu(ctrl->wValue);
415 __u16 wLength = le16_to_cpu(ctrl->wLength);
416 int rc = -EOPNOTSUPP;
419 if ((ctrl->bRequestType & 0x7f) != (USB_TYPE_CLASS | USB_RECIP_INTERFACE)) {
420 DBG(__FILE__ "(%s):%d: Invalid request type: %d",
421 __func__, __LINE__, ctrl->bRequestType);
425 switch (((ctrl->bRequestType & 0x80) << 8) | ctrl->bRequest) {
426 case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_CANCELIO):
428 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
429 __func__, __LINE__, requests[ctrl->bRequest-0x64]);
430 if (wValue != 0 || wIndex != 0 || wLength != 6) {
431 DBG("Invalid request parameters: wValue:%d wIndex:%d wLength:%d\n");
435 __handle_control_request(ctrl->bRequest);
438 case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETSTATUS):
439 case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_RESET):
441 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
442 __func__, __LINE__, requests[ctrl->bRequest-0x64]);
443 __handle_control_request(ctrl->bRequest);
446 case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETEVENT):
448 /* Optional, may stall */
449 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
450 __func__, __LINE__, requests[ctrl->bRequest-0x64]);
456 DBG(__FILE__ "(%s):%d: Invalid request: %d", __func__,
457 __LINE__, ctrl->bRequest);
464 DBG(__FILE__"(%s):%d:stall %0x2x.%02x\n",
465 __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest);
466 if ((ctrl->bRequestType & 0x80) == USB_DIR_IN)
467 status = read(g_usb_ep0, NULL, 0);
469 status = write(g_usb_ep0, NULL, 0);
471 if (status != -1 || errno != EL2HLT) {
472 ERR(__FILE__"(%s):%d:stall error\n",
473 __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest);
479 static void *ffs_transport_thread_usb_read(void *arg)
481 mtp_int32 status = 0;
482 msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL};
483 msgq_id_t *mqid = (msgq_id_t *)arg;
484 mtp_uint32 rx_size = _get_rx_pkt_size();
486 pthread_cleanup_push(__clean_up_msg_queue, mqid);
489 pthread_testcancel();
491 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
492 if (NULL == pkt.buffer) {
493 ERR("Sink thread: memalloc failed.\n");
497 status = read(g_usb_ep_out, pkt.buffer, rx_size);
499 status = __handle_usb_read_err(status, pkt.buffer, rx_size);
501 ERR("__handle_usb_read_err is failed\n");
508 if (FALSE == _util_msgq_send(*mqid, (void *)&pkt,
509 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
513 } while (status > 0);
515 DBG("status[%d] errno[%d]\n", status, errno);
516 pthread_cleanup_pop(1);
521 static void *ffs_transport_thread_usb_control(void *arg)
523 mtp_int32 status = 0;
524 struct usb_functionfs_event event;
525 msgq_id_t *mqid = (msgq_id_t *)arg;
527 pthread_cleanup_push(__clean_up_msg_queue, mqid);
530 pthread_testcancel();
532 status = read(g_usb_ep0, &event, sizeof(event));
535 ERR("read from ep0 failed: %s",
536 strerror_r(errno, error, sizeof(error)));
539 DBG("FUNCTIONFS event received: %d", event.type);
541 switch (event.type) {
542 case FUNCTIONFS_SETUP:
543 DBG("SETUP: bmRequestType:%d bRequest:%d wValue:%d wIndex:%d wLength:%d\n",
544 event.u.setup.bRequestType,
545 event.u.setup.bRequest,
546 event.u.setup.wValue,
547 event.u.setup.wIndex,
548 event.u.setup.wLength);
549 __setup(g_usb_ep0, &event.u.setup);
552 } while (status > 0);
554 DBG("status[%d] errno[%d]\n", status, errno);
555 pthread_cleanup_pop(1);
560 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
561 mtp_uchar *buf, mtp_int32 buf_len)
566 while (retry++ < MTP_USB_ERROR_MAX_RETRY) {
568 DBG("ZLP(Zero Length Packet). Skip");
569 } else if (err < 0 && errno == EINTR) {
570 DBG("read () is interrupted. Skip");
571 } else if (err < 0 && errno == EIO) {
574 if (MTP_PHONE_USB_CONNECTED !=
575 _util_get_local_usb_status()) {
576 ERR("USB is disconnected");
580 _transport_deinit_usb_device();
581 ret = _transport_init_usb_device();
583 ERR("_transport_init_usb_device Fail");
587 ERR("Unknown error : %d, errno [%d] \n", err, errno);
591 err = read(g_usb_ep_out, buf, buf_len);
597 ERR("USB error handling Fail");
602 static void __clean_up_msg_queue(void *mq_id)
605 msgq_ptr_t pkt = { 0 };
606 msgq_id_t l_mqid = *(msgq_id_t *)mq_id;
608 ret_if(mq_id == NULL);
610 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
611 while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt,
612 sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) {
614 memset(&pkt, 0, sizeof(msgq_ptr_t));
620 static void __handle_control_request(mtp_int32 request)
622 static mtp_bool kernel_reset = FALSE;
623 static mtp_bool host_cancel = FALSE;
624 mtp_int32 status = 0;
627 case USB_PTPREQUEST_CANCELIO:
628 // XXX: Convert cancel request data from little-endian
629 // before use: le32_to_cpu(x), le16_to_cpu(x).
630 DBG("USB_PTPREQUEST_CANCELIO\n");
631 cancel_req_t cancelreq_data;
634 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
635 status = read(g_usb_ep0, &cancelreq_data, sizeof(cancelreq_data));
638 ERR("Failed to read data for CANCELIO request\n: %s",
639 strerror_r(errno, error, sizeof(error)));
643 case USB_PTPREQUEST_RESET:
645 DBG("USB_PTPREQUEST_RESET\n");
647 if (kernel_reset == FALSE) {
651 status = read(g_usb_ep0, NULL, 0);
653 ERR("IOCTL MTP_SEND_RESET_ACK Failed [%d]\n",
657 case USB_PTPREQUEST_GETSTATUS:
659 DBG("USB_PTPREQUEST_GETSTATUS");
661 /* Send busy status response just once. This flag is also for
662 * the case that mtp misses the cancel request packet.
664 static mtp_bool sent_busy = FALSE;
665 usb_status_req_t statusreq_data = { 0 };
666 mtp_dword num_param = 0;
668 memset(&statusreq_data, 0x00, sizeof(usb_status_req_t));
669 if (host_cancel == TRUE || (sent_busy == FALSE &&
670 kernel_reset == FALSE)) {
671 DBG("Send busy response, set host_cancel to FALSE");
672 statusreq_data.len = 0x08;
673 statusreq_data.code = PTP_RESPONSE_DEVICEBUSY;
675 } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) {
676 statusreq_data.code =
677 PTP_RESPONSE_TRANSACTIONCANCELLED;
678 DBG("PTP_RESPONSE_TRANSACTIONCANCELLED");
679 statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) +
680 (num_param - 2) * sizeof(mtp_dword));
681 } else if (_device_get_status() == DEVICE_STATUSOK) {
682 DBG("PTP_RESPONSE_OK");
683 statusreq_data.len = 0x08;
684 statusreq_data.code = PTP_RESPONSE_OK;
686 if (kernel_reset == TRUE)
687 kernel_reset = FALSE;
689 DBG("PTP_RESPONSE_GEN_ERROR");
690 statusreq_data.len = 0x08;
691 statusreq_data.code = PTP_RESPONSE_GEN_ERROR;
694 if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY) {
700 /* status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data);
702 DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n",
709 case USB_PTPREQUEST_GETEVENT:
710 DBG("USB_PTPREQUEST_GETEVENT");
714 DBG("Invalid class specific setup request");
721 * mtp_bool ffs_transport_mq_deinit()
722 * This function destroy a message queue for MTP,
723 * @return This function returns TRUE on success or
724 * returns FALSE on failure.
726 static mtp_bool ffs_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
728 mtp_int32 res = TRUE;
731 res = _util_msgq_deinit(rx_mqid);
733 ERR("rx_mqid deinit Fail [%d]\n", errno);
740 res = _util_msgq_deinit(tx_mqid);
742 ERR("tx_mqid deinit fail [%d]\n", errno);
751 static mtp_uint32 ffs_transport_get_usb_packet_len(void)
753 mtp_int32 status = -1;
754 static mtp_int32 usb_speed = 0;
756 if (usb_speed == 0) {
758 //status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed);
760 ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status);
761 return MTP_MAX_PACKET_SIZE_SEND_FS;
765 if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS) {
766 return MTP_MAX_PACKET_SIZE_SEND_FS;
769 return MTP_MAX_PACKET_SIZE_SEND_HS;
773 const mtp_usb_driver_t mtp_usb_driver_ffs = {
774 .transport_init_usb_device = ffs_transport_init_usb_device,
775 .transport_deinit_usb_device = ffs_transport_deinit_usb_device,
776 .transport_thread_usb_write = ffs_transport_thread_usb_write,
777 .transport_thread_usb_read = ffs_transport_thread_usb_read,
778 .transport_thread_usb_control = ffs_transport_thread_usb_control,
779 .transport_mq_init = ffs_transport_mq_init,
780 .transport_mq_deinit = ffs_transport_mq_deinit,
781 .transport_get_usb_packet_len = ffs_transport_get_usb_packet_len,
782 .get_tx_pkt_size = ffs_get_tx_pkt_size,
783 .get_rx_pkt_size = ffs_get_rx_pkt_size,