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 "mtp_descs_strings.h"
29 #include "ptp_datacodes.h"
30 #include "mtp_support.h"
31 #include "ptp_container.h"
33 #include "mtp_thread.h"
34 #include "mtp_transport.h"
35 #include "mtp_event_handler.h"
37 #include <sys/prctl.h>
38 #include <systemd/sd-daemon.h>
41 * GLOBAL AND EXTERN VARIABLES
43 extern mtp_config_t g_conf;
46 * STATIC VARIABLES AND FUNCTIONS
49 /*PIMA15740-2000 spec*/
50 #define USB_PTPREQUEST_CANCELIO 0x64 /* Cancel request */
51 #define USB_PTPREQUEST_GETEVENT 0x65 /* Get extened event data */
52 #define USB_PTPREQUEST_RESET 0x66 /* Reset Device */
53 #define USB_PTPREQUEST_GETSTATUS 0x67 /* Get Device Status */
54 #define USB_PTPREQUEST_CANCELIO_SIZE 6
55 #define USB_PTPREQUEST_GETSTATUS_SIZE 12
57 static mtp_int32 g_usb_ep0 = -1; /* read (g_usb_ep0, ...) */
58 static mtp_int32 g_usb_ep_in = -1; /* write (g_usb_ep_in, ...) */
59 static mtp_int32 g_usb_ep_out = -1; /* read (g_usb_ep_out, ...) */
60 static mtp_int32 g_usb_ep_status = -1; /* write (g_usb_ep_status, ...) */
62 static mtp_max_pkt_size_t pkt_size;
63 static mtp_uint32 rx_mq_sz;
64 static mtp_uint32 tx_mq_sz;
65 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
66 mtp_uchar *buf, mtp_int32 buf_len);
67 static void __clean_up_msg_queue(void *param);
68 static void __handle_control_request(mtp_int32 request);
74 static mtp_bool __io_init()
78 if (sd_listen_fds(0) >= 4) {
79 DBG("socket-activated");
80 g_usb_ep0 = SD_LISTEN_FDS_START;
81 g_usb_ep_in = SD_LISTEN_FDS_START + 1;
82 g_usb_ep_out = SD_LISTEN_FDS_START + 2;
83 g_usb_ep_status = SD_LISTEN_FDS_START + 3;
88 g_usb_ep0 = open(MTP_EP0_PATH, O_RDWR);
92 DBG("Writing USB descriptors");
93 ret = write(g_usb_ep0, &descriptors, sizeof(descriptors));
95 ERR("Error writing descriptors");
99 DBG("Writing USB strings");
100 ret = write(g_usb_ep0, &strings, sizeof(strings));
102 ERR("Error writing strings");
106 g_usb_ep_in = open(MTP_EP_IN_PATH, O_RDWR);
107 if (g_usb_ep_in < 0) {
108 ERR("Error opening bulk-in");
112 g_usb_ep_out = open(MTP_EP_OUT_PATH, O_RDWR);
113 if (g_usb_ep_out < 0) {
114 ERR("Error opening bulk-out");
118 g_usb_ep_status = open(MTP_EP_STATUS_PATH, O_RDWR);
119 if (g_usb_ep_status < 0) {
120 ERR("Error opening status");
136 static mtp_bool ffs_transport_init_usb_device(void)
138 mtp_int32 status = 0;
142 DBG("Device Already open\n");
146 status = __io_init();
149 ERR("Device node [%s] open failed, errno [%s]\n",
150 MTP_EP0_PATH, strerror_r(errno, error, sizeof(error)));
154 pkt_size.rx = g_conf.read_usb_size;
155 pkt_size.tx = g_conf.write_usb_size;
157 DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx);
159 msg_size = sizeof(msgq_ptr_t) - sizeof(long);
160 rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size;
161 tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size;
163 DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz);
168 static void ffs_transport_deinit_usb_device(void)
174 if (g_usb_ep_in >= 0)
178 if (g_usb_ep_out >= 0)
182 if (g_usb_ep_status >= 0)
183 close(g_usb_ep_status);
184 g_usb_ep_status = -1;
189 static mtp_uint32 ffs_get_tx_pkt_size(void)
194 static mtp_uint32 ffs_get_rx_pkt_size(void)
200 * static mtp_int32 ffs_transport_mq_init()
201 * This function create a message queue for MTP,
202 * A created message queue will be used to help data transfer between
203 * MTP module and usb buffer.
204 * @return This function returns TRUE on success or
205 * returns FALSE on failure.
207 static mtp_int32 ffs_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
209 if (_util_msgq_init(rx_mqid, 0) == FALSE) {
210 ERR("RX MQ init Fail [%d]\n", errno);
214 if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE)
215 ERR("RX MQ setting size Fail [%d]\n", errno);
217 if (_util_msgq_init(tx_mqid, 0) == FALSE) {
218 ERR("TX MQ init Fail [%d]\n", errno);
219 _util_msgq_deinit(rx_mqid);
224 if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE)
225 ERR("TX MQ setting size Fail [%d]\n", errno);
230 static void *ffs_transport_thread_usb_write(void *arg)
232 mtp_int32 status = 0;
234 unsigned char *mtp_buf = NULL;
235 msg_type_t mtype = MTP_UNDEFINED_PACKET;
236 msgq_id_t *mqid = (msgq_id_t *)arg;
238 pthread_cleanup_push(__clean_up_msg_queue, mqid);
241 /* original LinuxThreads cancelation didn't work right
242 * so test for it explicitly.
244 pthread_testcancel();
246 _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype);
248 if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) {
249 status = write(g_usb_ep_in, mtp_buf, len);
251 ERR("USB write fail : %d\n", errno);
252 if (errno == ENOMEM || errno == ECANCELED) {
254 __clean_up_msg_queue(mqid);
259 } else if (MTP_EVENT_PACKET == mtype) {
260 /* Handling the MTP Asynchronous Events */
261 DBG("Send Interrupt data to kernel via g_usb_ep_status\n");
262 status = write(g_usb_ep_status, mtp_buf, len);
265 } else if (MTP_ZLP_PACKET == mtype) {
266 DBG("Send ZLP data to kerne via g_usb_ep_in\n");
267 status = write(g_usb_ep_in, (void*)0xFEE1DEAD, 0);
269 DBG("mtype = %d is not valid\n", mtype);
274 ERR("write data to the device node Fail:\
275 status = %d\n", status);
278 } while (status >= 0);
280 DBG("exited Source thread with status %d\n", status);
281 pthread_cleanup_pop(1);
287 static int __setup(int ep0, struct usb_ctrlrequest *ctrl)
289 const char* requests[] = {
290 "CANCELIO", /* 0x64 */
291 "GETEVENT", /* 0x65 */
293 "GETSTATUS", /* 0x67 */
295 __u16 wIndex = le16_to_cpu(ctrl->wIndex);
296 __u16 wValue = le16_to_cpu(ctrl->wValue);
297 __u16 wLength = le16_to_cpu(ctrl->wLength);
298 int rc = -EOPNOTSUPP;
301 if ((ctrl->bRequestType & 0x7f) != (USB_TYPE_CLASS | USB_RECIP_INTERFACE)) {
302 DBG(__FILE__ "(%s):%d: Invalid request type: %d",
303 __func__, __LINE__, ctrl->bRequestType);
307 switch (((ctrl->bRequestType & 0x80) << 8) | ctrl->bRequest) {
308 case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_CANCELIO):
310 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
311 __func__, __LINE__, requests[ctrl->bRequest-0x64]);
312 if (wValue != 0 || wIndex != 0 || wLength != 6) {
313 DBG("Invalid request parameters: wValue:%d wIndex:%d wLength:%d\n");
317 __handle_control_request(ctrl->bRequest);
320 case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETSTATUS):
321 case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_RESET):
323 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
324 __func__, __LINE__, requests[ctrl->bRequest-0x64]);
325 __handle_control_request(ctrl->bRequest);
328 case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETEVENT):
330 /* Optional, may stall */
331 DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s",
332 __func__, __LINE__, requests[ctrl->bRequest-0x64]);
338 DBG(__FILE__ "(%s):%d: Invalid request: %d", __func__,
339 __LINE__, ctrl->bRequest);
346 DBG(__FILE__"(%s):%d:stall %0x2x.%02x\n",
347 __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest);
348 if ((ctrl->bRequestType & 0x80) == USB_DIR_IN)
349 status = read(g_usb_ep0, NULL, 0);
351 status = write(g_usb_ep0, NULL, 0);
353 if (status != -1 || errno != EL2HLT) {
354 ERR(__FILE__"(%s):%d:stall error\n",
355 __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest);
361 static void *ffs_transport_thread_usb_read(void *arg)
363 mtp_int32 status = 0;
364 msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL};
365 msgq_id_t *mqid = (msgq_id_t *)arg;
366 mtp_uint32 rx_size = _get_rx_pkt_size();
368 pthread_cleanup_push(__clean_up_msg_queue, mqid);
371 pthread_testcancel();
373 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
374 if (NULL == pkt.buffer) {
375 ERR("Sink thread: memalloc failed.\n");
379 status = read(g_usb_ep_out, pkt.buffer, rx_size);
381 status = __handle_usb_read_err(status, pkt.buffer, rx_size);
383 ERR("__handle_usb_read_err is failed\n");
390 if (FALSE == _util_msgq_send(*mqid, (void *)&pkt,
391 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
395 } while (status > 0);
397 DBG("status[%d] errno[%d]\n", status, errno);
398 pthread_cleanup_pop(1);
403 static void *ffs_transport_thread_usb_control(void *arg)
405 mtp_int32 status = 0;
406 struct usb_functionfs_event event;
407 msgq_id_t *mqid = (msgq_id_t *)arg;
409 pthread_cleanup_push(__clean_up_msg_queue, mqid);
412 pthread_testcancel();
414 status = read(g_usb_ep0, &event, sizeof(event));
417 ERR("read from ep0 failed: %s",
418 strerror_r(errno, error, sizeof(error)));
421 DBG("FUNCTIONFS event received: %d", event.type);
423 switch (event.type) {
424 case FUNCTIONFS_SETUP:
425 DBG("SETUP: bmRequestType:%d bRequest:%d wValue:%d wIndex:%d wLength:%d\n",
426 event.u.setup.bRequestType,
427 event.u.setup.bRequest,
428 event.u.setup.wValue,
429 event.u.setup.wIndex,
430 event.u.setup.wLength);
431 __setup(g_usb_ep0, &event.u.setup);
433 case FUNCTIONFS_ENABLE:
435 _util_set_local_usb_status(MTP_PHONE_USB_CONNECTED);
437 case FUNCTIONFS_DISABLE:
439 _util_set_local_usb_status(MTP_PHONE_USB_DISCONNECTED);
440 _eh_send_event_req_to_eh_thread(EVENT_USB_REMOVED, 0, 0, NULL);
443 } while (status > 0);
445 DBG("status[%d] errno[%d]\n", status, errno);
446 pthread_cleanup_pop(1);
451 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
452 mtp_uchar *buf, mtp_int32 buf_len)
457 while (retry++ < MTP_USB_ERROR_MAX_RETRY) {
459 DBG("ZLP(Zero Length Packet). Skip");
460 } else if (err < 0 && errno == EINTR) {
461 DBG("read () is interrupted. Skip");
462 } else if (err < 0 && errno == EIO) {
465 if (MTP_PHONE_USB_CONNECTED !=
466 _util_get_local_usb_status()) {
467 ERR("USB is disconnected");
471 _transport_deinit_usb_device();
472 ret = _transport_init_usb_device();
474 ERR("_transport_init_usb_device Fail");
477 } else if (err < 0 && errno == ESHUTDOWN) {
480 ERR("Unknown error : %d, errno [%d] \n", err, errno);
484 err = read(g_usb_ep_out, buf, buf_len);
490 ERR("USB error handling Fail");
495 static void __clean_up_msg_queue(void *mq_id)
498 msgq_ptr_t pkt = { 0 };
501 ret_if(mq_id == NULL);
503 l_mqid = *(msgq_id_t *)mq_id;
504 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
505 while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt,
506 sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) {
508 memset(&pkt, 0, sizeof(msgq_ptr_t));
514 static void __handle_control_request(mtp_int32 request)
516 static mtp_bool kernel_reset = FALSE;
517 static mtp_bool host_cancel = FALSE;
518 mtp_int32 status = 0;
521 case USB_PTPREQUEST_CANCELIO:
522 // XXX: Convert cancel request data from little-endian
523 // before use: le32_to_cpu(x), le16_to_cpu(x).
524 DBG("USB_PTPREQUEST_CANCELIO\n");
525 cancel_req_t cancelreq_data;
528 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
529 status = read(g_usb_ep0, &cancelreq_data, sizeof(cancelreq_data));
532 ERR("Failed to read data for CANCELIO request\n: %s",
533 strerror_r(errno, error, sizeof(error)));
537 case USB_PTPREQUEST_RESET:
539 DBG("USB_PTPREQUEST_RESET\n");
541 if (kernel_reset == FALSE) {
545 status = read(g_usb_ep0, NULL, 0);
547 ERR("IOCTL MTP_SEND_RESET_ACK Failed [%d]\n",
551 case USB_PTPREQUEST_GETSTATUS:
553 DBG("USB_PTPREQUEST_GETSTATUS");
555 /* Send busy status response just once. This flag is also for
556 * the case that mtp misses the cancel request packet.
558 static mtp_bool sent_busy = FALSE;
559 usb_status_req_t statusreq_data = { 0 };
560 mtp_dword num_param = 0;
562 memset(&statusreq_data, 0x00, sizeof(usb_status_req_t));
563 if (host_cancel == TRUE || (sent_busy == FALSE &&
564 kernel_reset == FALSE)) {
565 DBG("Send busy response, set host_cancel to FALSE");
566 statusreq_data.len = 0x08;
567 statusreq_data.code = PTP_RESPONSE_DEVICEBUSY;
569 } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) {
570 statusreq_data.code =
571 PTP_RESPONSE_TRANSACTIONCANCELLED;
572 DBG("PTP_RESPONSE_TRANSACTIONCANCELLED");
573 statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) +
574 (num_param - 2) * sizeof(mtp_dword));
575 } else if (_device_get_status() == DEVICE_STATUSOK) {
576 DBG("PTP_RESPONSE_OK");
577 statusreq_data.len = 0x08;
578 statusreq_data.code = PTP_RESPONSE_OK;
580 if (kernel_reset == TRUE)
581 kernel_reset = FALSE;
583 DBG("PTP_RESPONSE_GEN_ERROR");
584 statusreq_data.len = 0x08;
585 statusreq_data.code = PTP_RESPONSE_GEN_ERROR;
588 if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY) {
594 /* status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data);
596 DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n",
603 case USB_PTPREQUEST_GETEVENT:
604 DBG("USB_PTPREQUEST_GETEVENT");
608 DBG("Invalid class specific setup request");
615 * mtp_bool ffs_transport_mq_deinit()
616 * This function destroy a message queue for MTP,
617 * @return This function returns TRUE on success or
618 * returns FALSE on failure.
620 static mtp_bool ffs_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
622 mtp_int32 res = TRUE;
625 res = _util_msgq_deinit(rx_mqid);
627 ERR("rx_mqid deinit Fail [%d]\n", errno);
634 res = _util_msgq_deinit(tx_mqid);
636 ERR("tx_mqid deinit fail [%d]\n", errno);
645 static mtp_uint32 ffs_transport_get_usb_packet_len(void)
647 mtp_int32 status = -1;
648 static mtp_int32 usb_speed = 0;
650 if (usb_speed == 0) {
652 //status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed);
654 ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status);
655 return MTP_MAX_PACKET_SIZE_SEND_FS;
659 if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS) {
660 return MTP_MAX_PACKET_SIZE_SEND_FS;
663 return MTP_MAX_PACKET_SIZE_SEND_HS;
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,