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);
56 static mtp_bool slp_transport_init_usb_device(void)
63 /* Kernel will inform to User Space using signal. */
64 memset(&sig, 0, sizeof(sig));
65 sig.sa_sigaction = __receive_signal;
66 sig.sa_flags = SA_SIGINFO;
67 sigaction(SIG_SETUP, &sig, NULL);
70 DBG("Device Already open\n");
74 g_usb_fd = open(MTP_DRIVER_PATH, O_RDWR);
76 ERR("Device node [%s] open failed,errno [%d]\n", MTP_DRIVER_PATH, errno);
81 status = ioctl(g_usb_fd, MTP_SET_USER_PID, &mtp_pid);
83 ERR("IOCTL MTP_SET_USER_PID failed = [%d]\n", status);
84 _transport_deinit_usb_device();
88 pkt_size.rx = g_conf.read_usb_size;
89 pkt_size.tx = g_conf.write_usb_size;
91 DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx);
93 msg_size = sizeof(msgq_ptr_t) - sizeof(long);
94 rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size;
95 tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size;
97 DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz);
102 static void slp_transport_deinit_usb_device(void)
111 static mtp_uint32 slp_get_tx_pkt_size(void)
116 static mtp_uint32 slp_get_rx_pkt_size(void)
122 * static mtp_int32 slp_transport_mq_init()
123 * This function create a message queue for MTP,
124 * A created message queue will be used to help data transfer between
125 * MTP module and usb buffer.
126 * @return This function returns TRUE on success or
127 * returns FALSE on failure.
129 static mtp_int32 slp_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
131 if (_util_msgq_init(rx_mqid, 0) == FALSE) {
132 ERR("RX MQ init Fail [%d]\n", errno);
136 if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE)
137 ERR("RX MQ setting size Fail [%d]\n", errno);
139 if (_util_msgq_init(tx_mqid, 0) == FALSE) {
140 ERR("TX MQ init Fail [%d]\n", errno);
141 _util_msgq_deinit(rx_mqid);
146 if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE)
147 ERR("TX MQ setting size Fail [%d]\n", errno);
152 static void *slp_transport_thread_usb_write(void *arg)
154 mtp_int32 status = 0;
156 unsigned char *mtp_buf = NULL;
157 msg_type_t mtype = MTP_UNDEFINED_PACKET;
158 msgq_id_t *mqid = (msgq_id_t *)arg;
160 pthread_cleanup_push(__clean_up_msg_queue, mqid);
163 /* original LinuxThreads cancelation didn't work right
164 * so test for it explicitly.
166 pthread_testcancel();
168 _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype);
170 if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) {
171 status = write(g_usb_fd, mtp_buf, len);
173 ERR("USB write fail : %d\n", errno);
174 if (errno == ENOMEM || errno == ECANCELED) {
176 __clean_up_msg_queue(mqid);
181 } else if (MTP_EVENT_PACKET == mtype) {
182 /* Handling the MTP Asynchronous Events */
183 DBG("Send Interrupt data to kernel by IOCTL ");
184 status = ioctl(g_usb_fd, MTP_WRITE_INT_DATA, mtp_buf);
187 } else if (MTP_ZLP_PACKET == mtype) {
188 DBG("Send ZLP data to kernel by IOCTL ");
189 status = ioctl(g_usb_fd, MTP_SET_ZLP_DATA, NULL);
191 DBG("mtype = %d is not valid\n", mtype);
196 ERR("write data to the device node Fail:\
197 status = %d\n", status);
200 } while (status >= 0);
202 DBG("exited Source thread with status %d\n", status);
203 pthread_cleanup_pop(1);
209 static void *slp_transport_thread_usb_read(void *arg)
211 mtp_int32 status = 0;
212 msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL};
213 msgq_id_t *mqid = (msgq_id_t *)arg;
214 mtp_uint32 rx_size = _get_rx_pkt_size();
216 pthread_cleanup_push(__clean_up_msg_queue, mqid);
219 pthread_testcancel();
221 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
222 if (NULL == pkt.buffer) {
223 ERR("Sink thread: memalloc Fail.");
227 status = read(g_usb_fd, pkt.buffer, rx_size);
229 status = __handle_usb_read_err(status, pkt.buffer, rx_size);
231 ERR("__handle_usb_read_err Fail");
238 if (FALSE == _util_msgq_send(*mqid, (void *)&pkt,
239 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
243 } while (status > 0);
245 DBG("status[%d] errno[%d]\n", status, errno);
246 pthread_cleanup_pop(1);
251 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
252 mtp_uchar *buf, mtp_int32 buf_len)
257 while (retry++ < MTP_USB_ERROR_MAX_RETRY) {
259 DBG("ZLP(Zero Length Packet). Skip");
260 } else if (err < 0 && errno == EINTR) {
261 DBG("read () is interrupted. Skip");
262 } else if (err < 0 && errno == EIO) {
265 if (MTP_PHONE_USB_CONNECTED !=
266 _util_get_local_usb_status()) {
267 ERR("USB is disconnected");
271 _transport_deinit_usb_device();
272 ret = _transport_init_usb_device();
274 ERR("_transport_init_usb_device Fail");
278 ERR("Unknown error : %d, errno [%d] \n", err, errno);
282 err = read(g_usb_fd, buf, buf_len);
288 ERR("USB error handling Fail");
293 static void __clean_up_msg_queue(void *mq_id)
296 msgq_ptr_t pkt = { 0 };
297 msgq_id_t l_mqid = *(msgq_id_t *)mq_id;
299 ret_if(mq_id == NULL);
301 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
302 while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt,
303 sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) {
305 memset(&pkt, 0, sizeof(msgq_ptr_t));
311 static void __handle_control_request(mtp_int32 request)
313 static mtp_bool kernel_reset = FALSE;
314 static mtp_bool host_cancel = FALSE;
315 mtp_int32 status = 0;
318 case USB_PTPREQUEST_CANCELIO:
319 DBG("USB_PTPREQUEST_CANCELIO");
320 cancel_req_t cancelreq_data;
321 mtp_byte buffer[USB_PTPREQUEST_CANCELIO_SIZE + 1] = { 0 };
324 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
325 status = ioctl(g_usb_fd, MTP_GET_SETUP_DATA, buffer);
327 ERR("IOCTL GET_SETUP_DATA Fail [%d]\n", status);
331 memcpy(&(cancelreq_data.io_code), buffer, sizeof(mtp_uint16));
332 memcpy(&(cancelreq_data.tid), &buffer[2], sizeof(mtp_uint32));
333 DBG("cancel io code [%d], transaction id [%du]\n",
334 cancelreq_data.io_code, cancelreq_data.tid);
337 case USB_PTPREQUEST_RESET:
339 DBG("USB_PTPREQUEST_RESET");
341 if (kernel_reset == FALSE)
344 status = ioctl(g_usb_fd, MTP_SEND_RESET_ACK, NULL);
346 ERR("IOCTL MTP_SEND_RESET_ACK Fail [%d]\n",
351 case USB_PTPREQUEST_GETSTATUS:
353 DBG("USB_PTPREQUEST_GETSTATUS");
355 /* Send busy status response just once. This flag is also for
356 * the case that mtp misses the cancel request packet.
358 static mtp_bool sent_busy = FALSE;
359 usb_status_req_t statusreq_data = { 0 };
360 mtp_dword num_param = 0;
362 memset(&statusreq_data, 0x00, sizeof(usb_status_req_t));
363 if (host_cancel == TRUE || (sent_busy == FALSE &&
364 kernel_reset == FALSE)) {
365 DBG("Send busy response, set host_cancel to FALSE");
366 statusreq_data.len = 0x08;
367 statusreq_data.code = PTP_RESPONSE_DEVICEBUSY;
369 } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) {
370 statusreq_data.code =
371 PTP_RESPONSE_TRANSACTIONCANCELLED;
372 DBG("PTP_RESPONSE_TRANSACTIONCANCELLED");
373 statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) +
374 (num_param - 2) * sizeof(mtp_dword));
375 } else if (_device_get_status() == DEVICE_STATUSOK) {
376 DBG("PTP_RESPONSE_OK");
377 statusreq_data.len = 0x08;
378 statusreq_data.code = PTP_RESPONSE_OK;
380 if (kernel_reset == TRUE)
381 kernel_reset = FALSE;
383 DBG("PTP_RESPONSE_GEN_ERROR");
384 statusreq_data.len = 0x08;
385 statusreq_data.code = PTP_RESPONSE_GEN_ERROR;
388 if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY)
393 status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data);
395 DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n",
401 case USB_PTPREQUEST_GETEVENT:
402 DBG("USB_PTPREQUEST_GETEVENT");
406 DBG("Invalid class specific setup request");
412 static void __receive_signal(mtp_int32 n, siginfo_t *info, void *arg)
414 mtp_int32 request = info->si_int;
416 DBG("Received SIgnal From Kernel\n");
417 __handle_control_request(request);
422 * mtp_bool slp_transport_mq_deinit()
423 * This function destroy a message queue for MTP,
424 * @return This function returns TRUE on success or
425 * returns FALSE on failure.
427 static mtp_bool slp_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
429 mtp_int32 res = TRUE;
432 res = _util_msgq_deinit(rx_mqid);
434 ERR("rx_mqid deinit Fail [%d]\n", errno);
440 res = _util_msgq_deinit(tx_mqid);
442 ERR("tx_mqid deinit fail [%d]\n", errno);
451 static mtp_uint32 slp_transport_get_usb_packet_len(void)
453 mtp_int32 status = 0;
454 static mtp_int32 usb_speed = 0;
456 if (usb_speed == 0) {
458 status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed);
460 ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status);
461 return MTP_MAX_PACKET_SIZE_SEND_FS;
465 if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS)
466 return MTP_MAX_PACKET_SIZE_SEND_FS;
468 return MTP_MAX_PACKET_SIZE_SEND_HS;
472 const mtp_usb_driver_t mtp_usb_driver_slp = {
473 .transport_init_usb_device = slp_transport_init_usb_device,
474 .transport_deinit_usb_device = slp_transport_deinit_usb_device,
475 .transport_thread_usb_write = slp_transport_thread_usb_write,
476 .transport_thread_usb_read = slp_transport_thread_usb_read,
477 .transport_thread_usb_control = NULL,
478 .transport_mq_init = slp_transport_mq_init,
479 .transport_mq_deinit = slp_transport_mq_deinit,
480 .transport_get_usb_packet_len = slp_transport_get_usb_packet_len,
481 .get_tx_pkt_size = slp_get_tx_pkt_size,
482 .get_rx_pkt_size = slp_get_rx_pkt_size,