Sync code with Tizen 3.0 branch
[platform/core/connectivity/mtp-responder.git] / src / transport / mtp_transport.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 <unistd.h>
18 #include <glib.h>
19 #include "mtp_config.h"
20 #include "mtp_transport.h"
21 #include "mtp_support.h"
22 #include "mtp_util.h"
23 #include "ptp_datacodes.h"
24 #include "mtp_device.h"
25 #include "mtp_msgq.h"
26 #include "mtp_cmd_handler.h"
27 #include "mtp_thread.h"
28 #include "mtp_usb_driver.h"
29
30 /*
31  * GLOBAL AND EXTERN VARIABLES
32  */
33 extern mtp_config_t g_conf;
34 extern mtp_mgr_t g_mtp_mgr;
35
36 /*
37  * STATIC VARIABLES
38  */
39 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
40 static mtp_bool g_usb_threads_created = FALSE;
41 static pthread_t g_tx_thrd = 0;
42 static pthread_t g_rx_thrd = 0;
43 static pthread_t g_data_rcv = 0;
44 static msgq_id_t mtp_to_usb_mqid;
45 static msgq_id_t g_usb_to_mtp_mqid;
46 static status_info_t g_status;
47
48 /*
49  * STATIC FUNCTIONS
50  */
51 static void *__transport_thread_data_rcv(void *func);
52 static mtp_err_t __transport_init_io();
53 static void __transport_deinit_io();
54
55 /*
56  * FUNCTIONS
57  */
58 void _transport_save_cmd_buffer(mtp_char *buffer, mtp_uint32 size)
59 {
60         memcpy(g_mgr->ftemp_st.cmd_buf, buffer, size);
61         g_mgr->ftemp_st.cmd_size = size;
62         g_mgr->ftemp_st.data_count = 0;
63         return;
64 }
65
66 mtp_err_t _transport_rcv_temp_file_data(mtp_byte *buffer, mtp_uint32 size,
67                 mtp_uint32 *count)
68 {
69         FILE* h_file = NULL;
70         mtp_int32 error = 0;
71         mtp_uint32 data_sz;
72
73
74         h_file = _util_file_open(g_mgr->ftemp_st.filepath,
75                         MTP_FILE_READ, &error);
76         if (h_file == NULL) {
77                 DBG_SECURE("_util_file_open(%s) Fail", g_mgr->ftemp_st.filepath);
78                 return MTP_ERROR_NONE;
79         }
80
81         /*copy header */
82         memcpy(buffer, g_mgr->ftemp_st.header_buf,
83                         sizeof(header_container_t));
84
85         /*copy body packet */
86         data_sz = size - sizeof(header_container_t);
87         _util_file_read(h_file, &buffer[sizeof(header_container_t)],
88                         data_sz, count);
89         if (*count <= 0) {
90                 ERR("file read error expected [%u] actual [%u]\n",
91                                 data_sz, *count);
92         }
93
94         *count += sizeof(header_container_t);
95
96         if (_util_file_close(h_file) != 0) {
97                 ERR("_util_file_close Fail");
98                 _util_print_error();
99         }
100
101         /* delete temp file, it have to be called in receive_data fn */
102         if (remove(g_mgr->ftemp_st.filepath) < 0) {
103                 ERR_SECURE("remove(%s) Fail", g_mgr->ftemp_st.filepath);
104                 _util_print_error();
105         }
106
107         g_mgr->ftemp_st.data_size = 0;
108         g_mgr->ftemp_st.data_count = 0;
109
110         return MTP_ERROR_NONE;
111 }
112
113 mtp_err_t _transport_rcv_temp_file_info(mtp_byte *buf, char *filepath,
114                 mtp_uint64 *t_size, mtp_uint32 filepath_len)
115 {
116         file_attr_t atttrs = { 0 };
117         mtp_bool ret = FALSE;
118
119         memcpy(buf, g_mgr->ftemp_st.header_buf,
120                         sizeof(header_container_t));
121
122         ret = _util_get_file_attrs(g_mgr->ftemp_st.filepath, &atttrs);
123         if (FALSE == ret) {
124                 ERR_SECURE("_util_get_file_attrs(%s) Fail", g_mgr->ftemp_st.filepath);
125                 return MTP_ERROR_GENERAL;
126         }
127
128         *t_size = sizeof(header_container_t) + atttrs.fsize;
129         g_strlcpy(filepath, g_mgr->ftemp_st.filepath, filepath_len);
130
131         g_mgr->ftemp_st.data_size = 0;
132         g_mgr->ftemp_st.data_count = 0;
133
134         g_strlcpy(g_mgr->ftemp_st.filepath, MTP_TEMP_FILE_DEFAULT,
135                         MTP_MAX_PATHNAME_SIZE + 1);
136         g_mgr->ftemp_st.fhandle = NULL;
137         g_mgr->ftemp_st.file_size = 0;
138
139         return MTP_ERROR_NONE;
140 }
141
142 mtp_err_t _transport_send_event(mtp_byte *buf, mtp_uint32 size,
143                 mtp_uint32 *count)
144 {
145         mtp_bool resp = FALSE;
146         msgq_ptr_t pkt = { 0 };
147
148         retv_if(buf == NULL, MTP_ERROR_INVALID_PARAM);
149         retvm_if(size > _get_tx_pkt_size(), MTP_ERROR_INVALID_PARAM,
150                         "size = %d, _get_tx_pkt_size() = (%d)", size, _get_tx_pkt_size());
151
152         pkt.mtype = MTP_EVENT_PACKET;
153         pkt.signal = 0x0000;
154         pkt.length = size;
155
156         pkt.buffer = (mtp_uchar *)g_malloc(size);
157         if (NULL == pkt.buffer) {
158                 ERR("g_malloc() Fail");
159                 return MTP_ERROR_GENERAL;
160         }
161         memcpy(pkt.buffer, buf, size);
162         resp = _util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
163                         sizeof(msgq_ptr_t) - sizeof(long), 0);
164         if (resp == FALSE) {
165                 ERR("_util_msgq_send() Fail");
166                 return MTP_ERROR_GENERAL;
167         }
168
169         *count = size;
170         return MTP_ERROR_NONE;
171 }
172
173 /*
174  * This function writes data to Message Queue, which will be read by a thread.
175  * the thread will write message, read from MQ, on USB.
176  * @param       buf             [in] A pointer to data written.
177  * @param       pkt_len         [in] Specifies the number of bytes to write.
178  * @return      This function returns length of written data in bytes
179  */
180 mtp_uint32 _transport_send_pkt_to_tx_mq(const mtp_byte *buf,
181                 mtp_uint32 pkt_len)
182 {
183         mtp_bool ret = 0;
184         mtp_uint32 len = pkt_len;
185         mtp_uint32 sent_len = 0;
186         msgq_ptr_t pkt = { 0 };
187         mtp_uint32 tx_size = _get_tx_pkt_size();
188         const mtp_uchar *temp = (const mtp_uchar *)buf;
189
190         retv_if(buf == NULL, 0);
191         retv_if(pkt_len == 0, 0);
192
193         pkt.mtype = MTP_DATA_PACKET;
194         pkt.signal = 0x0000;
195
196         while (len) {
197                 sent_len = len < tx_size ? len : tx_size;
198
199                 pkt.length = sent_len;
200                 pkt.buffer = (mtp_uchar *)g_malloc(sent_len);
201                 if (NULL == pkt.buffer) {
202                         ERR("g_malloc() Fail");
203                         return 0;
204                 }
205
206                 memcpy(pkt.buffer, temp, sent_len);
207                 ret = _util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
208                                 sizeof(msgq_ptr_t) - sizeof(long), 0);
209                 if (ret == FALSE) {
210                         ERR("_util_msgq_send() Fail");
211                         g_free(pkt.buffer);
212                         return 0;
213                 }
214
215                 len -= sent_len;
216                 temp += sent_len;
217         }
218
219         return pkt_len;
220 }
221
222 mtp_uint32 _transport_send_bulk_pkt_to_tx_mq(const mtp_byte *buf,
223                 mtp_uint32 pkt_len)
224 {
225         mtp_uint32 sent_len = 0;
226         mtp_uint32 tx_size = _get_tx_pkt_size();
227         msgq_ptr_t pkt = {MTP_BULK_PACKET, 0, 0, NULL};
228
229         retv_if(buf == NULL, 0);
230         retv_if(pkt_len == 0, 0);
231
232         pkt.length = tx_size;
233         while (pkt_len > tx_size) {
234                 pkt.buffer = (mtp_uchar *)g_malloc(pkt.length);
235                 if (NULL == pkt.buffer) {
236                         ERR("g_malloc() Fail");
237                         return 0;
238                 }
239                 memcpy(pkt.buffer, &buf[sent_len], pkt.length);
240
241                 if (!_util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
242                                         sizeof(msgq_ptr_t) - sizeof(long), 0)) {
243                         ERR("_util_msgq_send() Fail");
244                         g_free(pkt.buffer);
245                         return 0;
246                 }
247
248                 pkt_len -= pkt.length;
249                 sent_len += pkt.length;
250         }
251
252         pkt.length = pkt_len;
253         pkt.buffer = (mtp_uchar *)g_malloc(pkt.length);
254         if (NULL == pkt.buffer) {
255                 ERR("g_malloc() Fail");
256                 return 0;
257         }
258         memcpy(pkt.buffer, &buf[sent_len], pkt.length);
259
260         if (!_util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
261                                 sizeof(msgq_ptr_t) - sizeof(long), 0)) {
262                 ERR("_util_msgq_send() Fail");
263                 g_free(pkt.buffer);
264                 return 0;
265         }
266         sent_len += pkt.length;
267
268         return sent_len;
269 }
270
271 void _transport_send_zlp(void)
272 {
273         msgq_ptr_t pkt = { 0 };
274         mtp_bool resp = FALSE;
275
276         pkt.mtype = MTP_ZLP_PACKET;
277         pkt.signal = 0x0000;
278         pkt.length = 0;
279         pkt.buffer = NULL;
280
281         resp = _util_msgq_send(mtp_to_usb_mqid, (void *)&pkt,
282                         sizeof(msgq_ptr_t) - sizeof(long), 0);
283         if (resp == FALSE)
284                 ERR("_util_msgq_send() Fail");
285         return;
286 }
287
288 static mtp_err_t __transport_init_io()
289 {
290         mtp_int32 res = 0;
291         thread_func_t usb_write_thread = _transport_thread_usb_write;
292         thread_func_t usb_read_thread = _transport_thread_usb_read;
293
294         res = _util_thread_create(&g_tx_thrd, "usb write thread",
295                         PTHREAD_CREATE_JOINABLE, usb_write_thread,
296                         (void *)&mtp_to_usb_mqid);
297         if (FALSE == res) {
298                 ERR("_util_thread_create(TX) Fail");
299                 goto cleanup;
300         }
301
302         res = _util_thread_create(&g_rx_thrd, "usb read thread",
303                         PTHREAD_CREATE_JOINABLE, usb_read_thread,
304                         (void *)&g_usb_to_mtp_mqid);
305         if (FALSE == res) {
306                 ERR("_util_thread_create(RX) Fail");
307                 goto cleanup;
308         }
309
310         g_usb_threads_created = TRUE;
311
312         return MTP_ERROR_NONE;
313
314 cleanup:
315         _util_print_error();
316
317         if (g_rx_thrd) {
318                 res = _util_thread_cancel(g_rx_thrd);
319                 DBG("pthread_cancel [%d]\n", res);
320                 g_rx_thrd = 0;
321         }
322         if (g_tx_thrd) {
323                 res = _util_thread_cancel(g_tx_thrd);
324                 DBG("pthread_cancel [%d]\n", res);
325                 g_tx_thrd = 0;
326         }
327         g_usb_threads_created = FALSE;
328
329         return MTP_ERROR_GENERAL;
330 }
331
332 static void __transport_deinit_io()
333 {
334         if (g_usb_threads_created == FALSE) {
335                 ERR("io threads are not created.");
336                 return;
337         }
338         errno = 0;
339
340         if (FALSE == _util_thread_cancel(g_rx_thrd))
341                 ERR("_util_thread_cancel(rx) Fail");
342
343         if (_util_thread_join(g_rx_thrd, 0) == FALSE)
344                 ERR("_util_thread_join(rx) Fail");
345
346         g_rx_thrd = 0;
347
348         if (FALSE == _util_thread_cancel(g_tx_thrd))
349                 ERR("_util_thread_cancel(tx) Fail");
350
351         if (_util_thread_join(g_tx_thrd, 0) == FALSE)
352                 ERR("_util_thread_join(tx) Fail");
353
354         g_tx_thrd = 0;
355
356         g_usb_threads_created = FALSE;
357         return;
358 }
359
360 mtp_bool _transport_init_interfaces(_cmd_handler_cb func)
361 {
362         mtp_int32 res = 0;
363         mtp_bool ret = FALSE;
364
365         ret = _transport_init_usb_device();
366         if (ret == FALSE) {
367                 /* mtp driver open failed */
368                 ERR("_transport_init_usb_device() Fail");
369                 return FALSE;
370         }
371
372         if (_transport_mq_init(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid) == FALSE) {
373                 ERR("_transport_mq_init() Fail");
374                 _transport_deinit_usb_device();
375                 return FALSE;
376         }
377
378         if (__transport_init_io() != MTP_ERROR_NONE) {
379                 ERR("__transport_init_io() Fail");
380                 _transport_mq_deinit(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid);
381                 _transport_deinit_usb_device();
382                 return FALSE;
383         }
384
385         res = _util_thread_create(&g_data_rcv, "Data Receive thread",
386                         PTHREAD_CREATE_JOINABLE, __transport_thread_data_rcv,
387                         (void *)func);
388         if (res == FALSE) {
389                 ERR("_util_thread_create(data_rcv) Fail");
390                 __transport_deinit_io();
391                 _transport_mq_deinit(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid);
392                 _transport_deinit_usb_device();
393                 return FALSE;
394         }
395
396         return TRUE;
397 }
398
399 void _transport_usb_finalize(void)
400 {
401         mtp_int32 res = 0;
402         void *th_result = NULL;
403         msgq_ptr_t pkt;
404         mtp_uint32 rx_size = _get_rx_pkt_size();
405
406         __transport_deinit_io();
407
408         if (g_data_rcv != 0) {
409                 pkt.buffer = (mtp_uchar *)g_malloc(rx_size);
410                 if (pkt.buffer == NULL) {
411                         ERR("g_malloc() Fail");
412                         return;
413                 }
414                 pkt.mtype = MTP_DATA_PACKET;
415                 pkt.signal = 0xABCD;
416                 pkt.length = 6;
417                 memset(pkt.buffer, 0, rx_size);
418                 if (FALSE == _util_msgq_send(g_usb_to_mtp_mqid, (void *)&pkt,
419                                         sizeof(msgq_ptr_t) - sizeof(long), 0)) {
420                         ERR("_util_msgq_send() Fail");
421                 }
422
423                 res = _util_thread_join(g_data_rcv, &th_result);
424                 if (res == FALSE)
425                         ERR("_util_thread_join(data_rcv) Fail");
426         }
427
428         if (_transport_mq_deinit(&g_usb_to_mtp_mqid, &mtp_to_usb_mqid) == FALSE)
429                 ERR("_transport_mq_deinit() Fail");
430
431         _transport_deinit_usb_device();
432
433         return;
434 }
435
436 static void *__transport_thread_data_rcv(void *func)
437 {
438         msgq_ptr_t pkt = { 0 };
439         mtp_uchar *pkt_data = NULL;
440         mtp_uint32 pkt_len = 0;
441         mtp_int32 flag = 1;
442         mtp_int32 len = 0;
443         _cmd_handler_cb _cmd_handler_func = (_cmd_handler_cb)func;
444
445         while (flag) {
446                 if (_util_msgq_receive(g_usb_to_mtp_mqid, (void *)&pkt,
447                                         sizeof(pkt) - sizeof(long), 0, &len) == FALSE) {
448                         ERR("_util_msgq_receive() Fail");
449                         flag = 0;
450                         break;
451                 }
452                 if (len == sizeof(msgq_ptr_t) - sizeof(long)) {
453                         len = pkt.length;
454                         if (pkt.length == 6 && pkt.signal == 0xABCD) {
455                                 ERR("Got NULL character in MQ");
456                                 flag = 0;
457                                 break;
458                         }
459                         pkt_data = pkt.buffer;
460                         pkt_len = pkt.length;
461                         _cmd_handler_func((mtp_char *)pkt_data, pkt_len);
462                         g_free(pkt_data);
463                         pkt_data = NULL;
464                         pkt_len = 0;
465                         memset(&pkt, 0, sizeof(pkt));
466                 } else {
467                         g_free(pkt.buffer);
468                         pkt.buffer = NULL;
469                         ERR("Received packet is less than real size");
470                 }
471         }
472
473         ERR("thread_data_rcv[%u] exiting\n", g_data_rcv);
474         _util_thread_exit("__transport_thread_data_rcv is over");
475         return NULL;
476 }
477
478 void _transport_init_status_info(void)
479 {
480         memset((void *)&g_status, 0, sizeof(status_info_t));
481         return;
482 }
483
484 mtp_int32 _transport_get_control_event(void)
485 {
486         mtp_uint32 event_code;
487
488         event_code = g_status.ctrl_event_code;
489
490         /* initialize for next usage */
491         if (event_code != 0)
492                 g_status.ctrl_event_code = 0;
493
494         return event_code;
495 }
496
497 void _transport_set_control_event(mtp_int32 event_code)
498 {
499         g_status.ctrl_event_code = event_code;
500 }
501
502 mtp_state_t _transport_get_mtp_operation_state(void)
503 {
504         return g_status.mtp_op_state;
505 }
506
507 void _transport_set_mtp_operation_state(mtp_state_t state)
508 {
509         g_status.mtp_op_state = state;
510         return;
511 }
512
513 void _transport_set_usb_discon_state(mtp_bool is_usb_discon)
514 {
515         g_status.is_usb_discon = is_usb_discon;
516         return;
517 }
518
519 mtp_bool _transport_get_usb_discon_state(void)
520 {
521         return g_status.is_usb_discon;
522 }
523
524 void _transport_set_cancel_initialization(mtp_bool value)
525 {
526         g_status.cancel_intialization = value;
527 }
528
529 mtp_bool _transport_get_cancel_initialization(void)
530 {
531         return g_status.cancel_intialization;
532 }