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