981bfe4f5dd912804e75b2538e7ca5385b2af846
[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
329                 if (strcasecmp(token, "mmap_threshold") == 0) {
330                         token = strtok_r(NULL, "=", &saveptr);
331                         g_conf.mmap_threshold = atoi(token);
332
333                 } else if (strcasecmp(token, "init_rx_ipc_size") == 0) {
334                         token = strtok_r(NULL, "=", &saveptr);
335                         g_conf.init_rx_ipc_size = atoi(token);
336
337                 } else if (strcasecmp(token, "init_tx_ipc_size") == 0) {
338                         token = strtok_r(NULL, "=", &saveptr);
339                         g_conf.init_tx_ipc_size = atoi(token);
340
341                 } else if (strcasecmp(token, "max_rx_ipc_size") == 0) {
342                         token = strtok_r(NULL, "=", &saveptr);
343                         g_conf.max_rx_ipc_size = atoi(token);
344
345                 } else if (strcasecmp(token, "max_tx_ipc_size") == 0) {
346                         token = strtok_r(NULL, "=", &saveptr);
347                         g_conf.max_tx_ipc_size = atoi(token);
348
349                 } else if (strcasecmp(token, "read_usb_size") == 0) {
350                         token = strtok_r(NULL, "=", &saveptr);
351                         g_conf.read_usb_size = atoi(token);
352
353                 } else if (strcasecmp(token, "write_usb_size") == 0) {
354                         token = strtok_r(NULL, "=", &saveptr);
355                         g_conf.write_usb_size = atoi(token);
356
357                 } else if (strcasecmp(token, "read_file_size") == 0) {
358                         token = strtok_r(NULL, "=", &saveptr);
359                         g_conf.read_file_size = atoi(token);
360
361                 } else if (strcasecmp(token, "write_file_size") == 0) {
362                         token = strtok_r(NULL, "=", &saveptr);
363                         g_conf.write_file_size = atoi(token);
364
365                 } else if (strcasecmp(token, "max_io_buf_size") == 0) {
366                         token = strtok_r(NULL, "=", &saveptr);
367                         g_conf.max_io_buf_size = atoi(token);
368
369                 } else if (strcasecmp(token, "read_file_delay") == 0) {
370                         token = strtok_r(NULL, "=", &saveptr);
371                         g_conf.read_file_delay = atoi(token);
372
373                 } else if (strcasecmp(token, "support_pthread_sched") == 0) {
374                         token = strtok_r(NULL, "=", &saveptr);
375                         g_conf.support_pthread_sched = atoi(token) ? true : false;
376
377                 } else if (strcasecmp(token, "inheritsched") == 0) {
378                         token = strtok_r(NULL, "=", &saveptr);
379                         g_conf.inheritsched = *token;
380
381                 } else if (strcasecmp(token, "schedpolicy") == 0) {
382                         token = strtok_r(NULL, "=", &saveptr);
383                         g_conf.schedpolicy = *token;
384
385                 } else if (strcasecmp(token, "file_schedparam") == 0) {
386                         token = strtok_r(NULL, "=", &saveptr);
387                         g_conf.file_schedparam = atoi(token);
388
389                 } else if (strcasecmp(token, "usb_schedparam") == 0) {
390                         token = strtok_r(NULL, "=", &saveptr);
391                         g_conf.usb_schedparam = atoi(token);
392
393                 } else {
394                         ERR("Unknown option : %s\n", buf);
395                 }
396         }
397         fclose(fp);
398         g_conf.is_init = true;
399
400         __print_mtp_conf();
401         return;
402 }
403
404 void __init_mtp_info(void)
405 {
406         /* initialize struct one time*/
407         memset(&g_mgr->ftemp_st, 0, sizeof(g_mgr->ftemp_st));
408         memset(&g_mgr->hdlr, 0, sizeof(g_mgr->hdlr));
409         memset(&g_mgr->meta_info, 0, sizeof(g_mgr->meta_info));
410
411         return ;
412 }
413
414 void _features_supported_info(void)
415 {
416         DBG("***********************************************************");
417         DBG("### MTP Information ###");
418         DBG("### 1. Solution            : SLP");
419         DBG("### 2. MTP Version         : 1.0");
420         DBG("### 3. DB Limitation       : Reference(%d)\n", MTP_MAX_REFDB_ROWCNT);
421
422         DBG("***********************************************************");
423         DBG("### Extension ###");
424         if (_get_oma_drm_status() == TRUE) {
425                 DBG("### 2. OMADRM              : [ON]");
426         } else {
427                 DBG("### 2. OMADRM              : [OFF]");
428         }
429
430         DBG("***********************************************************");
431         DBG("### Feature ###");
432
433 #ifdef MTP_SUPPORT_ALBUM_ART
434         DBG("### 2. MTP_SUPPORT_ALBUM_ART       : [ON]");
435 #else /* MTP_SUPPORT_ALBUM_ART */
436         DBG("### 2. MTP_SUPPORT_ALBUM_ART       : [OFF]");
437 #endif /* MTP_SUPPORT_ALBUM_ART */
438
439 #ifdef MTP_SUPPORT_SET_PROTECTION
440         DBG("### 3. MTP_SUPPORT_SET_PROTECTION  : [ON]");
441 #else /* MTP_SUPPORT_SET_PROTECTION */
442         DBG("### 3. MTP_SUPPORT_SET_PROTECTION  : [OFF]");
443 #endif /* MTP_SUPPORT_SET_PROTECTION */
444         DBG("***********************************************************");
445         return;
446 }
447
448 /*
449  * void mtp_end_event(void)
450  * This function terminates mtp.
451  * It must not be called in gthr_mtp_event thread.
452  * It makes dead lock state if it is called in gthr_mtp_event thread.
453  */
454 void mtp_end_event(void)
455 {
456         __mtp_exit();
457 }
458
459 static inline int _main_init()
460 {
461         pthread_mutexattr_t mutex_attr;
462
463         pthread_mutexattr_init(&mutex_attr);
464         pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
465         if (0 != pthread_mutex_init(&g_cmd_inoti_mutex, &mutex_attr)) {
466                 ERR("pthread_mutex_init() Fail");
467                 _util_print_error();
468                 pthread_mutexattr_destroy(&mutex_attr);
469                 return MTP_ERROR_GENERAL;
470         }
471         pthread_mutexattr_destroy(&mutex_attr);
472
473         if (_eh_handle_usb_events(USB_INSERTED) == FALSE) {
474                 ERR("_eh_handle_usb_events() Fail");
475                 return MTP_ERROR_GENERAL;
476         }
477
478         g_mainloop = g_main_loop_new(NULL, FALSE);
479         if (g_mainloop == NULL) {
480                 ERR("g_mainloop is NULL");
481                 return MTP_ERROR_GENERAL;
482         }
483
484         return MTP_ERROR_NONE;
485 }
486
487 int main(int argc, char *argv[])
488 {
489         mtp_int32 ret;
490
491         if (_eh_register_notification_callbacks() == FALSE) {
492                 ERR("_eh_register_notification_callbacks() Fail");
493                 return MTP_ERROR_GENERAL;
494         }
495
496         ret = _main_init();
497         if (MTP_ERROR_NONE != ret) {
498                 ERR("_main_init() Fail(%d)", ret);
499                 _eh_deregister_notification_callbacks();
500                 media_content_disconnect();
501                 return MTP_ERROR_GENERAL;
502         }
503         DBG("MTP UID = [%u] and GID = [%u]\n", getuid(), getgid());
504
505         g_main_loop_run(g_mainloop);
506
507         _eh_deregister_notification_callbacks();
508         media_content_disconnect();
509
510         return MTP_ERROR_NONE;
511 }