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