a19de3d666f1b1e05e667463ffdaeddefc0ba5ac
[platform/core/connectivity/mtp-responder.git] / src / transport / mtp_usb_driver_slp.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <sys/ioctl.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <signal.h>
21 #include <glib.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"
27 #include "mtp_msgq.h"
28 #include "mtp_thread.h"
29 #include "mtp_transport.h"
30 #include "mtp_event_handler.h"
31 #include <sys/prctl.h>
32
33 /*
34  * GLOBAL AND EXTERN VARIABLES
35  */
36 extern mtp_config_t g_conf;
37
38 /*
39  * STATIC VARIABLES AND FUNCTIONS
40  */
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;
45
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);
51
52 /*
53  * FUNCTIONS
54  */
55 /* LCOV_EXCL_START */
56 static mtp_bool slp_transport_init_usb_device(void)
57 {
58         mtp_int32 status = 0;
59         struct sigaction sig;
60         pid_t mtp_pid = 0;
61         int msg_size;
62
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);
68
69         if (g_usb_fd > 0) {
70                 DBG("Device Already open\n");
71                 return TRUE;
72         }
73
74         g_usb_fd = open(MTP_DRIVER_PATH, O_RDWR);
75         if (g_usb_fd < 0) {
76                 ERR("Device node [%s] open failed,errno [%d]\n", MTP_DRIVER_PATH, errno);
77                 return FALSE;
78         }
79
80         mtp_pid = getpid();
81         status = ioctl(g_usb_fd, MTP_SET_USER_PID, &mtp_pid);
82         if (status < 0) {
83                 ERR("IOCTL MTP_SET_USER_PID failed = [%d]\n", status);
84                 _transport_deinit_usb_device();
85                 return FALSE;
86         }
87
88         pkt_size.rx = g_conf.read_usb_size;
89         pkt_size.tx = g_conf.write_usb_size;
90
91         DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx);
92
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;
96
97         DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz);
98
99         return TRUE;
100 }
101
102 static void slp_transport_deinit_usb_device(void)
103 {
104         if (g_usb_fd >= 0)
105                 close(g_usb_fd);
106         g_usb_fd = -1;
107
108         return;
109 }
110
111 static mtp_uint32 slp_get_tx_pkt_size(void)
112 {
113         return pkt_size.tx;
114 }
115
116 static mtp_uint32 slp_get_rx_pkt_size(void)
117 {
118         return pkt_size.rx;
119 }
120
121 /*
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.
128  */
129 static mtp_int32 slp_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
130 {
131         if (_util_msgq_init(rx_mqid, 0) == FALSE) {
132                 ERR("RX MQ init Fail [%d]\n", errno);
133                 return FALSE;
134         }
135
136         if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE)
137                 ERR("RX MQ setting size Fail [%d]\n", errno);
138
139         if (_util_msgq_init(tx_mqid, 0) == FALSE) {
140                 ERR("TX MQ init Fail [%d]\n", errno);
141                 _util_msgq_deinit(rx_mqid);
142                 *rx_mqid = -1;
143                 return FALSE;
144         }
145
146         if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE)
147                 ERR("TX MQ setting size Fail [%d]\n", errno);
148
149         return TRUE;
150 }
151
152 static void *slp_transport_thread_usb_write(void *arg)
153 {
154         mtp_int32 status = 0;
155         mtp_uint32 len = 0;
156         unsigned char *mtp_buf = NULL;
157         msg_type_t mtype = MTP_UNDEFINED_PACKET;
158         msgq_id_t *mqid = (msgq_id_t *)arg;
159
160         pthread_cleanup_push(__clean_up_msg_queue, mqid);
161
162         do {
163                 /* original LinuxThreads cancelation didn't work right
164                  * so test for it explicitly.
165                  */
166                 pthread_testcancel();
167
168                 _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype);
169
170                 if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) {
171                         status = write(g_usb_fd, mtp_buf, len);
172                         if (status < 0) {
173                                 ERR("USB write fail : %d\n", errno);
174                                 if (errno == ENOMEM || errno == ECANCELED) {
175                                         status = 0;
176                                         __clean_up_msg_queue(mqid);
177                                 }
178                         }
179                         g_free(mtp_buf);
180                         mtp_buf = NULL;
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);
185                         g_free(mtp_buf);
186                         mtp_buf = NULL;
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);
190                 } else {
191                         DBG("mtype = %d is not valid\n", mtype);
192                         status = -1;
193                 }
194
195                 if (status < 0) {
196                         ERR("write data to the device node Fail:\
197                                         status = %d\n", status);
198                         break;
199                 }
200         } while (status >= 0);
201
202         DBG("exited Source thread with status %d\n", status);
203         pthread_cleanup_pop(1);
204         g_free(mtp_buf);
205
206         return NULL;
207 }
208
209 static void *slp_transport_thread_usb_read(void *arg)
210 {
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();
215
216         pthread_cleanup_push(__clean_up_msg_queue, mqid);
217
218         do {
219                 pthread_testcancel();
220
221                 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
222                 if (NULL == pkt.buffer) {
223                         ERR("Sink thread: memalloc Fail.");
224                         break;
225                 }
226
227                 status = read(g_usb_fd, pkt.buffer, rx_size);
228                 if (status <= 0) {
229                         status = __handle_usb_read_err(status, pkt.buffer, rx_size);
230                         if (status <= 0) {
231                                 ERR("__handle_usb_read_err Fail");
232                                 g_free(pkt.buffer);
233                                 break;
234                         }
235                 }
236
237                 pkt.length = status;
238                 if (FALSE == _util_msgq_send(*mqid, (void *)&pkt,
239                                              sizeof(msgq_ptr_t) - sizeof(long), 0)) {
240                         ERR("msgsnd Fail");
241                         g_free(pkt.buffer);
242                 }
243         } while (status > 0);
244
245         DBG("status[%d] errno[%d]\n", status, errno);
246         pthread_cleanup_pop(1);
247
248         return NULL;
249 }
250
251 static mtp_int32 __handle_usb_read_err(mtp_int32 err,
252                 mtp_uchar *buf, mtp_int32 buf_len)
253 {
254         mtp_int32 retry = 0;
255         mtp_bool ret;
256
257         while (retry++ < MTP_USB_ERROR_MAX_RETRY) {
258                 if (err == 0) {
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) {
263                         DBG("EIO");
264
265                         if (MTP_PHONE_USB_CONNECTED !=
266                             _util_get_local_usb_status()) {
267                                 ERR("USB is disconnected");
268                                 break;
269                         }
270
271                         _transport_deinit_usb_device();
272                         ret = _transport_init_usb_device();
273                         if (ret == FALSE) {
274                                 ERR("_transport_init_usb_device Fail");
275                                 continue;
276                         }
277                 } else {
278                         ERR("Unknown error : %d, errno [%d] \n", err, errno);
279                         break;
280                 }
281
282                 err = read(g_usb_fd, buf, buf_len);
283                 if (err > 0)
284                         break;
285         }
286
287         if (err <= 0)
288                 ERR("USB error handling Fail");
289
290         return err;
291 }
292
293 static void __clean_up_msg_queue(void *mq_id)
294 {
295         mtp_int32 len = 0;
296         msgq_ptr_t pkt = { 0 };
297         msgq_id_t l_mqid = *(msgq_id_t *)mq_id;
298
299         ret_if(mq_id == NULL);
300
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)) {
304                 g_free(pkt.buffer);
305                 memset(&pkt, 0, sizeof(msgq_ptr_t));
306         }
307
308         return;
309 }
310
311 static void __handle_control_request(mtp_int32 request)
312 {
313         static mtp_bool kernel_reset = FALSE;
314         static mtp_bool host_cancel = FALSE;
315         mtp_int32 status = 0;
316
317         switch (request) {
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 };
322
323                 host_cancel = TRUE;
324                 _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION);
325                 status = ioctl(g_usb_fd, MTP_GET_SETUP_DATA, buffer);
326                 if (status < 0) {
327                         ERR("IOCTL GET_SETUP_DATA Fail [%d]\n", status);
328                         return;
329                 }
330
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);
335                 break;
336
337         case USB_PTPREQUEST_RESET:
338
339                 DBG("USB_PTPREQUEST_RESET");
340                 _reset_mtp_device();
341                 if (kernel_reset == FALSE)
342                         kernel_reset = TRUE;
343
344                 status = ioctl(g_usb_fd, MTP_SEND_RESET_ACK, NULL);
345                 if (status < 0) {
346                         ERR("IOCTL MTP_SEND_RESET_ACK Fail [%d]\n",
347                             status);
348                 }
349                 break;
350
351         case USB_PTPREQUEST_GETSTATUS:
352
353                 DBG("USB_PTPREQUEST_GETSTATUS");
354
355                 /* Send busy status response just once. This flag is also for
356                  * the case that mtp misses the cancel request packet.
357                  */
358                 static mtp_bool sent_busy = FALSE;
359                 usb_status_req_t statusreq_data = { 0 };
360                 mtp_dword num_param = 0;
361
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;
368                         host_cancel = FALSE;
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;
379
380                         if (kernel_reset == TRUE)
381                                 kernel_reset = FALSE;
382                 } else {
383                         DBG("PTP_RESPONSE_GEN_ERROR");
384                         statusreq_data.len = 0x08;
385                         statusreq_data.code = PTP_RESPONSE_GEN_ERROR;
386                 }
387
388                 if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY)
389                         sent_busy = TRUE;
390                 else
391                         sent_busy = FALSE;
392
393                 status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data);
394                 if (status < 0) {
395                         DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n",
396                             status);
397                         return;
398                 }
399                 break;
400
401         case USB_PTPREQUEST_GETEVENT:
402                 DBG("USB_PTPREQUEST_GETEVENT");
403                 break;
404
405         default:
406                 DBG("Invalid class specific setup request");
407                 break;
408         }
409         return;
410 }
411
412 static void __receive_signal(mtp_int32 n, siginfo_t *info, void *arg)
413 {
414         mtp_int32 request = info->si_int;
415
416         DBG("Received SIgnal From Kernel\n");
417         __handle_control_request(request);
418         return;
419 }
420
421 /*
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.
426  */
427 static mtp_bool slp_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid)
428 {
429         mtp_int32 res = TRUE;
430
431         if (*rx_mqid) {
432                 res = _util_msgq_deinit(rx_mqid);
433                 if (res == FALSE)
434                         ERR("rx_mqid deinit Fail [%d]\n", errno);
435                 else
436                         *rx_mqid = 0;
437         }
438
439         if (*tx_mqid) {
440                 res = _util_msgq_deinit(tx_mqid);
441                 if (res == FALSE) {
442                         ERR("tx_mqid deinit fail [%d]\n", errno);
443                 } else {
444                         *tx_mqid = 0;
445                 }
446         }
447
448         return res;
449 }
450
451 static mtp_uint32 slp_transport_get_usb_packet_len(void)
452 {
453         mtp_int32 status = 0;
454         static mtp_int32 usb_speed = 0;
455
456         if (usb_speed == 0) {
457
458                 status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed);
459                 if (status < 0) {
460                         ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status);
461                         return MTP_MAX_PACKET_SIZE_SEND_FS;
462                 }
463         }
464
465         if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS)
466                 return MTP_MAX_PACKET_SIZE_SEND_FS;
467
468         return MTP_MAX_PACKET_SIZE_SEND_HS;
469 }
470 /* LCOV_EXCL_STOP */
471
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,
483 };