Sync code with Tizen 3.0 branch
[platform/core/connectivity/mtp-responder.git] / src / mtp_init.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 <sys/types.h>
19 #include <sys/syscall.h>
20 #include <glib.h>
21 #include <glib-object.h>
22 #include <malloc.h>
23 #include <vconf.h>
24 #include "mtp_init.h"
25 #include "mtp_config.h"
26 #include "mtp_thread.h"
27 #include "mtp_support.h"
28 #include "mtp_device.h"
29 #include "mtp_event_handler.h"
30 #include "mtp_cmd_handler.h"
31 #include "mtp_inoti_handler.h"
32 #include "mtp_transport.h"
33 #include "mtp_util.h"
34 #include "mtp_media_info.h"
35
36 /*
37  * GLOBAL AND EXTERN VARIABLES
38  */
39 extern pthread_t g_eh_thrd;
40 extern pthread_mutex_t g_cmd_inoti_mutex;
41 extern mtp_bool g_is_sync_estab;
42
43 mtp_mgr_t g_mtp_mgr;
44 mtp_config_t g_conf;
45
46 /*
47  * STATIC VARIABLES AND FUNCTIONS
48  */
49 static GMainLoop *g_mainloop = NULL;
50 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
51 static void __read_mtp_conf(void);
52 static void __init_mtp_info(void);
53 static void __mtp_exit(void);
54 /*
55  * FUNCTIONS
56  */
57
58 /*
59  * static void __mtp_exit(void)
60  * This function send MTP stopped state to event handler thread and MTP UI
61  * @param[in]           None.
62  * @param[out]          None.
63  * @return              None.
64  */
65 static void __mtp_exit(void)
66 {
67         long cur_time;
68
69         DBG("## Terminate all threads");
70         if (g_eh_thrd) {
71                 _eh_send_event_req_to_eh_thread(EVENT_USB_REMOVED, 0, 0, NULL);
72                 if (_util_thread_join(g_eh_thrd, NULL) == FALSE)
73                         ERR("_util_thread_join() Fail");
74
75                 g_eh_thrd = 0;
76         }
77
78         if (g_is_sync_estab) {
79                 time(&cur_time);
80                 vconf_set_int(VCONFKEY_MTP_SYNC_TIME_INT, (int)cur_time);
81         }
82
83         DBG("## Terminate main loop");
84
85         g_main_loop_quit(g_mainloop);
86
87         return;
88 }
89
90 static gboolean __check_internal_storage(gpointer user_data)
91 {
92         _handle_lock_status_notification(NULL, NULL);
93
94         return true;
95 }
96
97 void _mtp_init(add_rem_store_t sel)
98 {
99         mtp_char *device_name = NULL;
100         mtp_char *sync_partner = NULL;
101         int vconf_ret = 0;
102         mtp_int32 error = 0;
103
104         DBG("Initialization start!");
105
106         __read_mtp_conf();
107
108         if (g_conf.mmap_threshold) {
109                 if (!mallopt(M_MMAP_THRESHOLD, g_conf.mmap_threshold))
110                         ERR("mallopt(M_MMAP_THRESHOLD) Fail");
111
112                 if (!mallopt(M_TRIM_THRESHOLD, g_conf.mmap_threshold * 2))
113                         ERR("mallopt(M_TRIM_THRESHOLD) Fail");
114         }
115
116         __init_mtp_info();
117
118         _transport_init_status_info();
119         _transport_set_mtp_operation_state(MTP_STATE_INITIALIZING);
120
121         device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
122         if (device_name != NULL) {
123                 _device_set_device_name(device_name);
124                 g_free(device_name);
125         } else {
126                 _device_set_device_name(MTP_DEV_PROPERTY_FRIENDLYNAME);
127         }
128
129         sync_partner = vconf_get_str(VCONFKEY_MTP_SYNC_PARTNER_STR);
130         if (sync_partner != NULL && strlen(sync_partner) > 0) {
131                 _device_set_sync_partner(sync_partner);
132                 g_free(sync_partner);
133         } else {
134                 _device_set_sync_partner(MTP_DEV_PROPERTY_SYNCPARTNER);
135         }
136
137
138         g_mgr->ftemp_st.filepath = g_strdup(MTP_TEMP_FILE_DEFAULT);
139         if (g_mgr->ftemp_st.filepath == NULL) {
140                 ERR("g_strdup() Fail");
141                 goto MTP_INIT_FAIL;
142         }
143
144         if (g_mgr->ftemp_st.temp_buff == NULL) {
145                 /* Allocate memory for temporary */
146                 g_mgr->ftemp_st.temp_buff = (mtp_char *)g_malloc(g_conf.write_file_size);
147                 if (g_mgr->ftemp_st.temp_buff == NULL) {
148                         ERR("memory allocation fail");
149                         goto MTP_INIT_FAIL;
150                 }
151         }
152
153         /* Internal Storage */
154         if (MTP_PHONE_LOCK_OFF == _util_get_local_lock_status()) {
155                 mtp_int32 ret;
156                 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
157
158                 ret = media_content_connect();
159                 if (MEDIA_CONTENT_ERROR_NONE != ret) {
160                         ERR("media_content_connect() Fail(%d)", ret);
161                         goto MTP_INIT_FAIL;
162                 }
163
164                 _util_get_internal_path(inter_path);
165                 if (access(inter_path, F_OK) < 0) {
166                         if (FALSE == _util_dir_create((const mtp_char *)inter_path, &error)) {
167                                 ERR("Cannot make directory!! [%s]\n",
168                                                 inter_path);
169                                 goto MTP_INIT_FAIL;
170                         }
171                 }
172         }
173         /* External Storage */
174         if (MTP_PHONE_MMC_INSERTED == _util_get_local_mmc_status()) {
175                 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
176                 _util_get_external_path(ext_path);
177                 if (access(ext_path, F_OK) < 0) {
178                         if (FALSE == _util_dir_create((const mtp_char *)ext_path, &error)) {
179                                 ERR("Cannot make directory!! [%s]\n",
180                                                 ext_path);
181                                 goto MTP_INIT_FAIL;
182                         }
183                 }
184         }
185
186         /* Set mtpdeviceinfo */
187         _init_mtp_device();
188
189         _features_supported_info();
190
191         /* Install storage */
192         _device_install_storage(sel);
193
194 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
195         _inoti_init_filesystem_evnts();
196 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
197
198         vconf_ret = vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE_READ_ONLY,
199                         _handle_lock_status_notification, NULL);
200         if (vconf_ret < 0) {
201                 ERR("vconf_notify_key_changed(%s) Fail", VCONFKEY_IDLE_LOCK_STATE_READ_ONLY);
202                 goto MTP_INIT_FAIL;
203         }
204
205         g_timeout_add(1000, __check_internal_storage, NULL);
206
207         vconf_ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
208                         _handle_mmc_notification, NULL);
209         if (vconf_ret < 0) {
210                 ERR("vconf_notify_key_changed(%s) Fail", VCONFKEY_SYSMAN_MMC_STATUS);
211                 goto MTP_INIT_FAIL;
212         }
213
214         return;
215
216 MTP_INIT_FAIL:
217         /* Set MTP state to stopped */
218         _transport_set_mtp_operation_state(MTP_STATE_STOPPED);
219         mtp_end_event();
220
221         return;
222 }
223
224 void _mtp_deinit(void)
225 {
226         _cmd_hdlr_reset_cmd(&g_mgr->hdlr);
227
228         /* initialize MTP_USE_FILE_BUFFER*/
229         if (g_mgr->ftemp_st.temp_buff != NULL) {
230                 g_free(g_mgr->ftemp_st.temp_buff);
231                 g_mgr->ftemp_st.temp_buff = NULL;
232         }
233
234 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
235         _inoti_deinit_filesystem_events();
236 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
237
238         vconf_ignore_key_changed(VCONFKEY_IDLE_LOCK_STATE_READ_ONLY,
239                         _handle_lock_status_notification);
240
241         vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
242                         _handle_mmc_notification);
243
244         return;
245 }
246
247 static void __print_mtp_conf(void)
248 {
249         if (g_conf.is_init == false) {
250                 ERR("g_conf is not initialized");
251                 return;
252         }
253
254         DBG("MMAP_THRESHOLD : %d\n", g_conf.mmap_threshold);
255         DBG("INIT_RX_IPC_SIZE : %d\n", g_conf.init_rx_ipc_size);
256         DBG("INIT_TX_IPC_SIZE : %d\n", g_conf.init_tx_ipc_size);
257         DBG("MAX_RX_IPC_SIZE : %d\n", g_conf.max_rx_ipc_size);
258         DBG("MAX_TX_IPC_SIZE : %d\n", g_conf.max_tx_ipc_size);
259         DBG("READ_USB_SIZE : %d\n", g_conf.read_usb_size);
260         DBG("WRITE_USB_SIZE : %d\n", g_conf.write_usb_size);
261         DBG("READ_FILE_SIZE : %d\n", g_conf.read_file_size);
262         DBG("WRITE_FILE_SIZE : %d\n", g_conf.write_file_size);
263         DBG("MAX_IO_BUF_SIZE : %d\n\n", g_conf.max_io_buf_size);
264
265         DBG("SUPPORT_PTHEAD_SHCED : %s\n", g_conf.support_pthread_sched ? "Support" : "Not support");
266         DBG("INHERITSCHED : %c\n", g_conf.inheritsched);
267         DBG("SCHEDPOLICY : %c\n", g_conf.schedpolicy);
268         DBG("FILE_SCHEDPARAM: %d\n", g_conf.file_schedparam);
269         DBG("USB_SCHEDPARAM: %d\n\n", g_conf.usb_schedparam);
270 }
271
272 static void __read_mtp_conf(void)
273 {
274         FILE *fp;
275         char buf[256];
276         char *token;
277         char *saveptr = NULL;
278
279         g_conf.mmap_threshold = MTP_MMAP_THRESHOLD;
280
281         g_conf.read_usb_size = MTP_READ_USB_SIZE;
282         g_conf.write_usb_size = MTP_WRITE_USB_SIZE;
283
284         g_conf.read_file_size = MTP_READ_FILE_SIZE;
285         g_conf.write_file_size = MTP_WRITE_FILE_SIZE;
286
287         g_conf.init_rx_ipc_size = MTP_INIT_RX_IPC_SIZE;
288         g_conf.init_tx_ipc_size = MTP_INIT_TX_IPC_SIZE;
289
290         g_conf.max_rx_ipc_size = MTP_MAX_RX_IPC_SIZE;
291         g_conf.max_tx_ipc_size = MTP_MAX_TX_IPC_SIZE;
292
293         g_conf.max_io_buf_size = MTP_MAX_IO_BUF_SIZE;
294         g_conf.read_file_delay = MTP_READ_FILE_DELAY;
295
296         if (MTP_SUPPORT_PTHREAD_SCHED) {
297                 g_conf.support_pthread_sched = MTP_SUPPORT_PTHREAD_SCHED;
298                 g_conf.inheritsched = MTP_INHERITSCHED;
299                 g_conf.schedpolicy = MTP_SCHEDPOLICY;
300                 g_conf.file_schedparam = MTP_FILE_SCHEDPARAM;
301                 g_conf.usb_schedparam = MTP_USB_SCHEDPARAM;
302         }
303
304         fp = fopen(MTP_CONFIG_FILE_PATH, "r");
305         if (fp == NULL) {
306                 DBG("Default configuration is used");
307                 g_conf.is_init = true;
308
309                 __print_mtp_conf();
310                 return;
311         }
312
313         while (fgets(buf, sizeof(buf), fp)) {
314                 if (buf[0] == '#' || buf[0] == '\n')
315                         continue;
316
317                 token = strrchr(buf, '\n');
318                 if (token == NULL) {
319                         ERR("g_conf is too long");
320                         break;
321                 }
322                 *token = '\0';
323
324                 token = strtok_r(buf, "=", &saveptr);
325                 if (token == NULL)
326                         continue;
327
328                 if (strcasecmp(token, "mmap_threshold") == 0) {
329                         token = strtok_r(NULL, "=", &saveptr);
330                         g_conf.mmap_threshold = atoi(token);
331
332                 } else if (strcasecmp(token, "init_rx_ipc_size") == 0) {
333                         token = strtok_r(NULL, "=", &saveptr);
334                         g_conf.init_rx_ipc_size = atoi(token);
335
336                 } else if (strcasecmp(token, "init_tx_ipc_size") == 0) {
337                         token = strtok_r(NULL, "=", &saveptr);
338                         g_conf.init_tx_ipc_size = atoi(token);
339
340                 } else if (strcasecmp(token, "max_rx_ipc_size") == 0) {
341                         token = strtok_r(NULL, "=", &saveptr);
342                         g_conf.max_rx_ipc_size = atoi(token);
343
344                 } else if (strcasecmp(token, "max_tx_ipc_size") == 0) {
345                         token = strtok_r(NULL, "=", &saveptr);
346                         g_conf.max_tx_ipc_size = atoi(token);
347
348                 } else if (strcasecmp(token, "read_usb_size") == 0) {
349                         token = strtok_r(NULL, "=", &saveptr);
350                         g_conf.read_usb_size = atoi(token);
351
352                 } else if (strcasecmp(token, "write_usb_size") == 0) {
353                         token = strtok_r(NULL, "=", &saveptr);
354                         g_conf.write_usb_size = atoi(token);
355
356                 } else if (strcasecmp(token, "read_file_size") == 0) {
357                         token = strtok_r(NULL, "=", &saveptr);
358                         g_conf.read_file_size = atoi(token);
359
360                 } else if (strcasecmp(token, "write_file_size") == 0) {
361                         token = strtok_r(NULL, "=", &saveptr);
362                         g_conf.write_file_size = atoi(token);
363
364                 } else if (strcasecmp(token, "max_io_buf_size") == 0) {
365                         token = strtok_r(NULL, "=", &saveptr);
366                         g_conf.max_io_buf_size = atoi(token);
367
368                 } else if (strcasecmp(token, "read_file_delay") == 0) {
369                         token = strtok_r(NULL, "=", &saveptr);
370                         g_conf.read_file_delay = atoi(token);
371
372                 } else if (strcasecmp(token, "support_pthread_sched") == 0) {
373                         token = strtok_r(NULL, "=", &saveptr);
374                         g_conf.support_pthread_sched = atoi(token) ? true : false;
375
376                 } else if (strcasecmp(token, "inheritsched") == 0) {
377                         token = strtok_r(NULL, "=", &saveptr);
378                         g_conf.inheritsched = *token;
379
380                 } else if (strcasecmp(token, "schedpolicy") == 0) {
381                         token = strtok_r(NULL, "=", &saveptr);
382                         g_conf.schedpolicy = *token;
383
384                 } else if (strcasecmp(token, "file_schedparam") == 0) {
385                         token = strtok_r(NULL, "=", &saveptr);
386                         g_conf.file_schedparam = atoi(token);
387
388                 } else if (strcasecmp(token, "usb_schedparam") == 0) {
389                         token = strtok_r(NULL, "=", &saveptr);
390                         g_conf.usb_schedparam = atoi(token);
391
392                 } else {
393                         ERR("Unknown option : %s\n", buf);
394                 }
395         }
396         fclose(fp);
397         g_conf.is_init = true;
398
399         __print_mtp_conf();
400         return;
401 }
402
403 void __init_mtp_info(void)
404 {
405         /* initialize struct one time*/
406         memset(&g_mgr->ftemp_st, 0, sizeof(g_mgr->ftemp_st));
407         memset(&g_mgr->hdlr, 0, sizeof(g_mgr->hdlr));
408         memset(&g_mgr->meta_info, 0, sizeof(g_mgr->meta_info));
409
410         return ;
411 }
412
413 void _features_supported_info(void)
414 {
415         DBG("***********************************************************");
416         DBG("### MTP Information ###");
417         DBG("### 1. Solution            : SLP");
418         DBG("### 2. MTP Version         : 1.0");
419         DBG("### 3. DB Limitation       : Reference(%d)\n", MTP_MAX_REFDB_ROWCNT);
420
421         DBG("***********************************************************");
422         DBG("### Extension ###");
423         if (_get_oma_drm_status() == TRUE)
424                 DBG("### 2. OMADRM              : [ON]");
425         else
426                 DBG("### 2. OMADRM              : [OFF]");
427
428         DBG("***********************************************************");
429         DBG("### Feature ###");
430
431 #ifdef MTP_SUPPORT_ALBUM_ART
432         DBG("### 2. MTP_SUPPORT_ALBUM_ART       : [ON]");
433 #else /* MTP_SUPPORT_ALBUM_ART */
434         DBG("### 2. MTP_SUPPORT_ALBUM_ART       : [OFF]");
435 #endif /* MTP_SUPPORT_ALBUM_ART */
436
437 #ifdef MTP_SUPPORT_SET_PROTECTION
438         DBG("### 3. MTP_SUPPORT_SET_PROTECTION  : [ON]");
439 #else /* MTP_SUPPORT_SET_PROTECTION */
440         DBG("### 3. MTP_SUPPORT_SET_PROTECTION  : [OFF]");
441 #endif /* MTP_SUPPORT_SET_PROTECTION */
442         DBG("***********************************************************");
443         return;
444 }
445
446 /*
447  * void mtp_end_event(void)
448  * This function terminates mtp.
449  * It must not be called in gthr_mtp_event thread.
450  * It makes dead lock state if it is called in gthr_mtp_event thread.
451  */
452 void mtp_end_event(void)
453 {
454         __mtp_exit();
455 }
456
457 static inline int _main_init()
458 {
459         pthread_mutexattr_t mutex_attr;
460
461         pthread_mutexattr_init(&mutex_attr);
462         pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
463         if (0 != pthread_mutex_init(&g_cmd_inoti_mutex, &mutex_attr)) {
464                 ERR("pthread_mutex_init() Fail");
465                 _util_print_error();
466                 pthread_mutexattr_destroy(&mutex_attr);
467                 return MTP_ERROR_GENERAL;
468         }
469         pthread_mutexattr_destroy(&mutex_attr);
470
471         if (_eh_handle_usb_events(USB_INSERTED) == FALSE) {
472                 ERR("_eh_handle_usb_events() Fail");
473                 return MTP_ERROR_GENERAL;
474         }
475
476         g_mainloop = g_main_loop_new(NULL, FALSE);
477         if (g_mainloop == NULL) {
478                 ERR("g_mainloop is NULL");
479                 return MTP_ERROR_GENERAL;
480         }
481
482         return MTP_ERROR_NONE;
483 }
484
485 int main(int argc, char *argv[])
486 {
487         mtp_int32 ret;
488
489         if (_eh_register_notification_callbacks() == FALSE) {
490                 ERR("_eh_register_notification_callbacks() Fail");
491                 return MTP_ERROR_GENERAL;
492         }
493
494         ret = _main_init();
495         if (MTP_ERROR_NONE != ret) {
496                 ERR("_main_init() Fail(%d)", ret);
497                 _eh_deregister_notification_callbacks();
498                 media_content_disconnect();
499                 return MTP_ERROR_GENERAL;
500         }
501         DBG("MTP UID = [%u] and GID = [%u]\n", getuid(), getgid());
502
503         g_main_loop_run(g_mainloop);
504
505         _eh_deregister_notification_callbacks();
506         media_content_disconnect();
507
508         return MTP_ERROR_NONE;
509 }