2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <sys/ioctl.h>
22 #include "mtp_usb_driver.h"
23 #include "mtp_device.h"
24 #include "ptp_datacodes.h"
25 #include "mtp_support.h"
26 #include "ptp_container.h"
28 #include "mtp_thread.h"
29 #include "mtp_transport.h"
30 #include "mtp_event_handler.h"
31 #include <sys/prctl.h>
34 * GLOBAL AND EXTERN VARIABLES
36 extern mtp_config_t g_conf;
39 * STATIC VARIABLES AND FUNCTIONS
41 static mtp_int32 g_usb_fd = -1;
42 static mtp_max_pkt_size_t pkt_size;
43 static mtp_uint32 rx_mq_sz;
44 static mtp_uint32 tx_mq_sz;
46 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
47 mtp_uchar *buf, mtp_int32 buf_len);
48 static void __clean_up_msg_queue(void *pmsqid);
49 static void __handle_control_request(mtp_int32 request);
50 static void __receive_signal(mtp_int32 n, siginfo_t *info, void *unused);
55 static mtp_bool slp_transport_init_usb_device(void)
62 /* Kernel will inform to User Space using signal. */
63 memset(&sig, 0, sizeof(sig));
64 sig.sa_sigaction = __receive_signal;
65 sig.sa_flags = SA_SIGINFO;
66 sigaction(SIG_SETUP, &sig, NULL);
69 DBG("Device Already open\n");
73 g_usb_fd = open(MTP_DRIVER_PATH, O_RDWR);
75 ERR("Device node [%s] open failed,errno [%d]\n", MTP_DRIVER_PATH, errno);
80 status = ioctl(g_usb_fd, MTP_SET_USER_PID, &mtp_pid);
82 ERR("IOCTL MTP_SET_USER_PID failed = [%d]\n", status);
83 _transport_deinit_usb_device();
87 pkt_size.rx = g_conf.read_usb_size;
88 pkt_size.tx = g_conf.write_usb_size;
90 DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx);
92 msg_size = sizeof(msgq_ptr_t) - sizeof(long);
93 rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size;
94 tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size;
96 DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz);
101 static void slp_transport_deinit_usb_device(void)
110 static mtp_uint32 slp_get_tx_pkt_size(void)
115 static mtp_uint32 slp_get_rx_pkt_size(void)
121 * static mtp_int32 slp_transport_mq_init()
122 * This function create a message queue for MTP,
123 * A created message queue will be used to help data transfer between
124 * MTP module and usb buffer.
125 * @return This function returns TRUE on success or
126 * returns FALSE on failure.
128 static mtp_int32 slp_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
130 if (_util_msgq_init(rx_mqid, 0) == FALSE) {
131 ERR("RX MQ init Fail [%d]\n", errno);
135 if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE)
136 ERR("RX MQ setting size Fail [%d]\n", errno);
138 if (_util_msgq_init(tx_mqid, 0) == FALSE) {
139 ERR("TX MQ init Fail [%d]\n", errno);
140 _util_msgq_deinit(rx_mqid);
145 if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE)
146 ERR("TX MQ setting size Fail [%d]\n", errno);
151 static void *slp_transport_thread_usb_write(void *arg)
153 mtp_int32 status = 0;
155 unsigned char *mtp_buf = NULL;
156 msg_type_t mtype = MTP_UNDEFINED_PACKET;
157 msgq_id_t *mqid = (msgq_id_t *)arg;
159 pthread_cleanup_push(__clean_up_msg_queue, mqid);
162 /* original LinuxThreads cancelation didn't work right
163 * so test for it explicitly.
165 pthread_testcancel();
167 _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype);
169 if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) {
170 status = write(g_usb_fd, mtp_buf, len);
172 ERR("USB write fail : %d\n", errno);
173 if (errno == ENOMEM || errno == ECANCELED) {
175 __clean_up_msg_queue(mqid);
180 } else if (MTP_EVENT_PACKET == mtype) {
181 /* Handling the MTP Asynchronous Events */
182 DBG("Send Interrupt data to kernel by IOCTL ");
183 status = ioctl(g_usb_fd, MTP_WRITE_INT_DATA, mtp_buf);
186 } else if (MTP_ZLP_PACKET == mtype) {
187 DBG("Send ZLP data to kernel by IOCTL ");
188 status = ioctl(g_usb_fd, MTP_SET_ZLP_DATA, NULL);
190 DBG("mtype = %d is not valid\n", mtype);
195 ERR("write data to the device node Fail:\
196 status = %d\n", status);
199 } while (status >= 0);
201 DBG("exited Source thread with status %d\n", status);
202 pthread_cleanup_pop(1);
208 static void *slp_transport_thread_usb_read(void *arg)
210 mtp_int32 status = 0;
211 msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL};
212 msgq_id_t *mqid = (msgq_id_t *)arg;
213 mtp_uint32 rx_size = _get_rx_pkt_size();
215 pthread_cleanup_push(__clean_up_msg_queue, mqid);
218 pthread_testcancel();
220 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
221 if (NULL == pkt.buffer) {
222 ERR("Sink thread: memalloc Fail.");
226 status = read(g_usb_fd, pkt.buffer, rx_size);
228 status = __handle_usb_read_err(status, pkt.buffer, rx_size);
230 ERR("__handle_usb_read_err Fail");
237 if (FALSE == _util_msgq_send(*mqid, (void *)&pkt,
238 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
242 } while (status > 0);
244 DBG("status[%d] errno[%d]\n", status, errno);
245 pthread_cleanup_pop(1);
250 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
251 mtp_uchar *buf, mtp_int32 buf_len)
256 while (retry++ < MTP_USB_ERROR_MAX_RETRY) {
258 DBG("ZLP(Zero Length Packet). Skip");
259 } else if (err < 0 && errno == EINTR) {
260 DBG("read () is interrupted. Skip");
261 } else if (err < 0 && errno == EIO) {
264 if (MTP_PHONE_USB_CONNECTED !=
265 _util_get_local_usb_status()) {
266 ERR("USB is disconnected");
270 _transport_deinit_usb_device();
271 ret = _transport_init_usb_device();
273 ERR("_transport_init_usb_device Fail");
277 ERR("Unknown error : %d, errno [%d] \n", err, errno);
281 err = read(g_usb_fd, buf, buf_len);
287 ERR("USB error handling Fail");
292 static void __clean_up_msg_queue(void *mq_id)
295 msgq_ptr_t pkt = { 0 };
296 msgq_id_t l_mqid = *(msgq_id_t *)mq_id;
298 ret_if(mq_id == NULL);
300 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
301 while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt,
302 sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) {
304 memset(&pkt, 0, sizeof(msgq_ptr_t));
310 static void __handle_control_request(mtp_int32 request)
312 static mtp_bool kernel_reset = FALSE;
313 static mtp_bool host_cancel = FALSE;
314 mtp_int32 status = 0;
317 case USB_PTPREQUEST_CANCELIO:
318 DBG("USB_PTPREQUEST_CANCELIO");
319 cancel_req_t cancelreq_data;
320 mtp_byte buffer[USB_PTPREQUEST_CANCELIO_SIZE + 1] = { 0 };
323 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
324 status = ioctl(g_usb_fd, MTP_GET_SETUP_DATA, buffer);
326 ERR("IOCTL GET_SETUP_DATA Fail [%d]\n", status);
330 memcpy(&(cancelreq_data.io_code), buffer, sizeof(mtp_word));
331 memcpy(&(cancelreq_data.tid), &buffer[2], sizeof(mtp_dword));
332 DBG("cancel io code [%d], transaction id [%ld]\n",
333 cancelreq_data.io_code, cancelreq_data.tid);
336 case USB_PTPREQUEST_RESET:
338 DBG("USB_PTPREQUEST_RESET");
340 if (kernel_reset == FALSE)
343 status = ioctl(g_usb_fd, MTP_SEND_RESET_ACK, NULL);
345 ERR("IOCTL MTP_SEND_RESET_ACK Fail [%d]\n",
350 case USB_PTPREQUEST_GETSTATUS:
352 DBG("USB_PTPREQUEST_GETSTATUS");
354 /* Send busy status response just once. This flag is also for
355 * the case that mtp misses the cancel request packet.
357 static mtp_bool sent_busy = FALSE;
358 usb_status_req_t statusreq_data = { 0 };
359 mtp_dword num_param = 0;
361 memset(&statusreq_data, 0x00, sizeof(usb_status_req_t));
362 if (host_cancel == TRUE || (sent_busy == FALSE &&
363 kernel_reset == FALSE)) {
364 DBG("Send busy response, set host_cancel to FALSE");
365 statusreq_data.len = 0x08;
366 statusreq_data.code = PTP_RESPONSE_DEVICEBUSY;
368 } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) {
369 statusreq_data.code =
370 PTP_RESPONSE_TRANSACTIONCANCELLED;
371 DBG("PTP_RESPONSE_TRANSACTIONCANCELLED");
372 statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) +
373 (num_param - 2) * sizeof(mtp_dword));
374 } else if (_device_get_status() == DEVICE_STATUSOK) {
375 DBG("PTP_RESPONSE_OK");
376 statusreq_data.len = 0x08;
377 statusreq_data.code = PTP_RESPONSE_OK;
379 if (kernel_reset == TRUE)
380 kernel_reset = FALSE;
382 DBG("PTP_RESPONSE_GEN_ERROR");
383 statusreq_data.len = 0x08;
384 statusreq_data.code = PTP_RESPONSE_GEN_ERROR;
387 if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY)
392 status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data);
394 DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n",
400 case USB_PTPREQUEST_GETEVENT:
401 DBG("USB_PTPREQUEST_GETEVENT");
405 DBG("Invalid class specific setup request");
411 static void __receive_signal(mtp_int32 n, siginfo_t *info, void *arg)
413 mtp_int32 request = info->si_int;
415 DBG("Received SIgnal From Kernel\n");
416 __handle_control_request(request);
421 * mtp_bool slp_transport_mq_deinit()
422 * This function destroy a message queue for MTP,
423 * @return This function returns TRUE on success or
424 * returns FALSE on failure.
426 static mtp_bool slp_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
428 mtp_int32 res = TRUE;
431 res = _util_msgq_deinit(rx_mqid);
433 ERR("rx_mqid deinit Fail [%d]\n", errno);
439 res = _util_msgq_deinit(tx_mqid);
441 ERR("tx_mqid deinit fail [%d]\n", errno);
450 static mtp_uint32 slp_transport_get_usb_packet_len(void)
452 mtp_int32 status = 0;
453 static mtp_int32 usb_speed = 0;
455 if (usb_speed == 0) {
457 status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed);
459 ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status);
460 return MTP_MAX_PACKET_SIZE_SEND_FS;
464 if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS)
465 return MTP_MAX_PACKET_SIZE_SEND_FS;
467 return MTP_MAX_PACKET_SIZE_SEND_HS;
471 const mtp_usb_driver_t mtp_usb_driver_slp = {
472 .transport_init_usb_device = slp_transport_init_usb_device,
473 .transport_deinit_usb_device = slp_transport_deinit_usb_device,
474 .transport_thread_usb_write = slp_transport_thread_usb_write,
475 .transport_thread_usb_read = slp_transport_thread_usb_read,
476 .transport_thread_usb_control = NULL,
477 .transport_mq_init = slp_transport_mq_init,
478 .transport_mq_deinit = slp_transport_mq_deinit,
479 .transport_get_usb_packet_len = slp_transport_get_usb_packet_len,
480 .get_tx_pkt_size = slp_get_tx_pkt_size,
481 .get_rx_pkt_size = slp_get_rx_pkt_size,