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