2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <sys/types.h>
19 #include <sys/syscall.h>
21 #include <glib-object.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"
34 #include "mtp_media_info.h"
37 * GLOBAL AND EXTERN VARIABLES
39 extern pthread_t g_eh_thrd;
40 extern pthread_mutex_t g_cmd_inoti_mutex;
41 extern mtp_bool g_is_sync_estab;
47 * STATIC VARIABLES AND FUNCTIONS
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);
59 * static void __mtp_exit(void)
60 * This function send MTP stopped state to event handler thread and MTP UI
65 static void __mtp_exit(void)
69 DBG("## Terminate all threads");
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");
78 if (g_is_sync_estab) {
80 vconf_set_int(VCONFKEY_MTP_SYNC_TIME_INT, (int)cur_time);
83 DBG("## Terminate main loop");
85 g_main_loop_quit(g_mainloop);
90 void _mtp_init(add_rem_store_t sel)
92 mtp_char wmpinfopath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
93 mtp_char *device_name = NULL;
94 mtp_char *sync_partner = NULL;
98 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
100 DBG("Initialization start!");
104 if (g_conf.mmap_threshold) {
105 if (!mallopt(M_MMAP_THRESHOLD, g_conf.mmap_threshold))
106 ERR("mallopt(M_MMAP_THRESHOLD) Fail");
108 if (!mallopt(M_TRIM_THRESHOLD, g_conf.mmap_threshold * 2))
109 ERR("mallopt(M_TRIM_THRESHOLD) Fail");
114 _transport_init_status_info();
115 _transport_set_mtp_operation_state(MTP_STATE_INITIALIZING);
117 device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
118 if (device_name != NULL) {
119 _device_set_device_name(device_name);
122 _device_set_device_name(MTP_DEV_PROPERTY_FRIENDLYNAME);
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);
130 _device_set_sync_partner(MTP_DEV_PROPERTY_SYNCPARTNER);
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");
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");
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",
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",
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);
175 ERR("szWMPInfoPath is too long");
178 #endif /*MTP_SUPPORT_HIDE_WMPINFO_XML*/
180 /* Set mtpdeviceinfo */
183 _features_supported_info();
185 /* Install storage */
186 _device_install_storage(sel);
188 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
189 _inoti_init_filesystem_evnts();
190 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
192 vconf_ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
193 _handle_mmc_notification, NULL);
195 ERR("vconf_notify_key_changed(%s) Fail", VCONFKEY_SYSMAN_MMC_STATUS);
202 /* Set MTP state to stopped */
203 _transport_set_mtp_operation_state(MTP_STATE_STOPPED);
209 void _mtp_deinit(void)
211 _cmd_hdlr_reset_cmd(&g_mgr->hdlr);
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;
219 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
220 _inoti_deinit_filesystem_events();
221 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
223 vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
224 _handle_mmc_notification);
229 static void __print_mtp_conf(void)
231 if (g_conf.is_init == false) {
232 ERR("g_conf is not initialized");
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);
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);
254 static void __read_mtp_conf(void)
259 char *saveptr = NULL;
261 g_conf.mmap_threshold = MTP_MMAP_THRESHOLD;
263 g_conf.read_usb_size = MTP_READ_USB_SIZE;
264 g_conf.write_usb_size = MTP_WRITE_USB_SIZE;
266 g_conf.read_file_size = MTP_READ_FILE_SIZE;
267 g_conf.write_file_size = MTP_WRITE_FILE_SIZE;
269 g_conf.init_rx_ipc_size = MTP_INIT_RX_IPC_SIZE;
270 g_conf.init_tx_ipc_size = MTP_INIT_TX_IPC_SIZE;
272 g_conf.max_rx_ipc_size = MTP_MAX_RX_IPC_SIZE;
273 g_conf.max_tx_ipc_size = MTP_MAX_TX_IPC_SIZE;
275 g_conf.max_io_buf_size = MTP_MAX_IO_BUF_SIZE;
276 g_conf.read_file_delay = MTP_READ_FILE_DELAY;
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;
286 fp = fopen(MTP_CONFIG_FILE_PATH, "r");
288 DBG("Default configuration is used");
289 g_conf.is_init = true;
295 while (fgets(buf, sizeof(buf), fp)) {
296 if (buf[0] == '#' || buf[0] == '\n')
299 token = strrchr(buf, '\n');
301 ERR("g_conf is too long");
306 token = strtok_r(buf, "=", &saveptr);
311 if (strcasecmp(token, "mmap_threshold") == 0) {
312 token = strtok_r(NULL, "=", &saveptr);
313 g_conf.mmap_threshold = atoi(token);
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);
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);
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);
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);
331 } else if (strcasecmp(token, "read_usb_size") == 0) {
332 token = strtok_r(NULL, "=", &saveptr);
333 g_conf.read_usb_size = atoi(token);
335 } else if (strcasecmp(token, "write_usb_size") == 0) {
336 token = strtok_r(NULL, "=", &saveptr);
337 g_conf.write_usb_size = atoi(token);
339 } else if (strcasecmp(token, "read_file_size") == 0) {
340 token = strtok_r(NULL, "=", &saveptr);
341 g_conf.read_file_size = atoi(token);
343 } else if (strcasecmp(token, "write_file_size") == 0) {
344 token = strtok_r(NULL, "=", &saveptr);
345 g_conf.write_file_size = atoi(token);
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);
351 } else if (strcasecmp(token, "read_file_delay") == 0) {
352 token = strtok_r(NULL, "=", &saveptr);
353 g_conf.read_file_delay = atoi(token);
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;
359 } else if (strcasecmp(token, "inheritsched") == 0) {
360 token = strtok_r(NULL, "=", &saveptr);
361 g_conf.inheritsched = *token;
363 } else if (strcasecmp(token, "schedpolicy") == 0) {
364 token = strtok_r(NULL, "=", &saveptr);
365 g_conf.schedpolicy = *token;
367 } else if (strcasecmp(token, "file_schedparam") == 0) {
368 token = strtok_r(NULL, "=", &saveptr);
369 g_conf.file_schedparam = atoi(token);
371 } else if (strcasecmp(token, "usb_schedparam") == 0) {
372 token = strtok_r(NULL, "=", &saveptr);
373 g_conf.usb_schedparam = atoi(token);
376 ERR("Unknown option : %s\n", buf);
380 g_conf.is_init = true;
386 void __init_mtp_info(void)
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));
396 void _features_supported_info(void)
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);
404 DBG("***********************************************************");
405 DBG("### Extension ###");
406 if (_get_oma_drm_status() == TRUE) {
407 DBG("### 2. OMADRM : [ON]");
409 DBG("### 2. OMADRM : [OFF]");
412 DBG("***********************************************************");
413 DBG("### Feature ###");
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 */
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("***********************************************************");
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.
436 void mtp_end_event(void)
441 static inline int _main_init()
443 pthread_mutexattr_t mutex_attr;
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");
450 pthread_mutexattr_destroy(&mutex_attr);
451 return MTP_ERROR_GENERAL;
453 pthread_mutexattr_destroy(&mutex_attr);
455 if (_eh_handle_usb_events(USB_INSERTED) == FALSE) {
456 ERR("_eh_handle_usb_events() Fail");
457 return MTP_ERROR_GENERAL;
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;
466 return MTP_ERROR_NONE;
469 int main(int argc, char *argv[])
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;
479 if (_eh_register_notification_callbacks() == FALSE) {
480 ERR("_eh_register_notification_callbacks() Fail");
481 return MTP_ERROR_GENERAL;
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;
491 DBG("MTP UID = [%u] and GID = [%u]\n", getuid(), getgid());
493 g_main_loop_run(g_mainloop);
495 _eh_deregister_notification_callbacks();
496 media_content_disconnect();
498 return MTP_ERROR_NONE;