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;
99 DBG("Initialization start!");
103 if (g_conf.mmap_threshold) {
104 if (!mallopt(M_MMAP_THRESHOLD, g_conf.mmap_threshold))
105 ERR("mallopt(M_MMAP_THRESHOLD) Fail");
107 if (!mallopt(M_TRIM_THRESHOLD, g_conf.mmap_threshold * 2))
108 ERR("mallopt(M_TRIM_THRESHOLD) Fail");
113 _transport_init_status_info();
114 _transport_set_mtp_operation_state(MTP_STATE_INITIALIZING);
116 device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
117 if (device_name != NULL) {
118 _device_set_device_name(device_name);
121 _device_set_device_name(MTP_DEV_PROPERTY_FRIENDLYNAME);
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);
129 _device_set_sync_partner(MTP_DEV_PROPERTY_SYNCPARTNER);
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");
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");
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);
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);
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);
171 ERR("szWMPInfoPath is too long");
174 #endif /*MTP_SUPPORT_HIDE_WMPINFO_XML*/
176 /* Set mtpdeviceinfo */
179 _features_supported_info();
181 /* Install storage */
182 _device_install_storage(sel);
184 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
185 _inoti_init_filesystem_evnts();
186 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
188 vconf_ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
189 _handle_mmc_notification, NULL);
191 ERR("vconf_notify_key_changed(%s) Fail", VCONFKEY_SYSMAN_MMC_STATUS);
198 /* Set MTP state to stopped */
199 _transport_set_mtp_operation_state(MTP_STATE_STOPPED);
205 void _mtp_deinit(void)
207 _cmd_hdlr_reset_cmd(&g_mgr->hdlr);
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;
215 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
216 _inoti_deinit_filesystem_events();
217 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
219 vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
220 _handle_mmc_notification);
225 static void __print_mtp_conf(void)
227 if (g_conf.is_init == false) {
228 ERR("g_conf is not initialized");
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);
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);
250 static void __read_mtp_conf(void)
255 char *saveptr = NULL;
257 g_conf.mmap_threshold = MTP_MMAP_THRESHOLD;
259 g_conf.read_usb_size = MTP_READ_USB_SIZE;
260 g_conf.write_usb_size = MTP_WRITE_USB_SIZE;
262 g_conf.read_file_size = MTP_READ_FILE_SIZE;
263 g_conf.write_file_size = MTP_WRITE_FILE_SIZE;
265 g_conf.init_rx_ipc_size = MTP_INIT_RX_IPC_SIZE;
266 g_conf.init_tx_ipc_size = MTP_INIT_TX_IPC_SIZE;
268 g_conf.max_rx_ipc_size = MTP_MAX_RX_IPC_SIZE;
269 g_conf.max_tx_ipc_size = MTP_MAX_TX_IPC_SIZE;
271 g_conf.max_io_buf_size = MTP_MAX_IO_BUF_SIZE;
272 g_conf.read_file_delay = MTP_READ_FILE_DELAY;
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;
282 fp = fopen(MTP_CONFIG_FILE_PATH, "r");
284 DBG("Default configuration is used");
285 g_conf.is_init = true;
291 while (fgets(buf, sizeof(buf), fp)) {
292 if (buf[0] == '#' || buf[0] == '\n')
295 token = strrchr(buf, '\n');
297 ERR("g_conf is too long");
302 token = strtok_r(buf, "=", &saveptr);
307 if (strcasecmp(token, "mmap_threshold") == 0) {
308 token = strtok_r(NULL, "=", &saveptr);
309 g_conf.mmap_threshold = atoi(token);
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);
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);
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);
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);
327 } else if (strcasecmp(token, "read_usb_size") == 0) {
328 token = strtok_r(NULL, "=", &saveptr);
329 g_conf.read_usb_size = atoi(token);
331 } else if (strcasecmp(token, "write_usb_size") == 0) {
332 token = strtok_r(NULL, "=", &saveptr);
333 g_conf.write_usb_size = atoi(token);
335 } else if (strcasecmp(token, "read_file_size") == 0) {
336 token = strtok_r(NULL, "=", &saveptr);
337 g_conf.read_file_size = atoi(token);
339 } else if (strcasecmp(token, "write_file_size") == 0) {
340 token = strtok_r(NULL, "=", &saveptr);
341 g_conf.write_file_size = atoi(token);
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);
347 } else if (strcasecmp(token, "read_file_delay") == 0) {
348 token = strtok_r(NULL, "=", &saveptr);
349 g_conf.read_file_delay = atoi(token);
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;
355 } else if (strcasecmp(token, "inheritsched") == 0) {
356 token = strtok_r(NULL, "=", &saveptr);
357 g_conf.inheritsched = *token;
359 } else if (strcasecmp(token, "schedpolicy") == 0) {
360 token = strtok_r(NULL, "=", &saveptr);
361 g_conf.schedpolicy = *token;
363 } else if (strcasecmp(token, "file_schedparam") == 0) {
364 token = strtok_r(NULL, "=", &saveptr);
365 g_conf.file_schedparam = atoi(token);
367 } else if (strcasecmp(token, "usb_schedparam") == 0) {
368 token = strtok_r(NULL, "=", &saveptr);
369 g_conf.usb_schedparam = atoi(token);
372 ERR("Unknown option : %s\n", buf);
376 g_conf.is_init = true;
382 void __init_mtp_info(void)
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));
392 void _features_supported_info(void)
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);
400 DBG("***********************************************************");
401 DBG("### Extension ###");
402 if (_get_oma_drm_status() == TRUE) {
403 DBG("### 2. OMADRM : [ON]");
405 DBG("### 2. OMADRM : [OFF]");
408 DBG("***********************************************************");
409 DBG("### Feature ###");
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 */
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("***********************************************************");
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.
432 void mtp_end_event(void)
437 static inline int _main_init()
439 pthread_mutexattr_t mutex_attr;
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");
446 pthread_mutexattr_destroy(&mutex_attr);
447 return MTP_ERROR_GENERAL;
449 pthread_mutexattr_destroy(&mutex_attr);
451 if (_eh_handle_usb_events(USB_INSERTED) == FALSE) {
452 ERR("_eh_handle_usb_events() Fail");
453 return MTP_ERROR_GENERAL;
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;
462 return MTP_ERROR_NONE;
465 int main(int argc, char *argv[])
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;
475 if (_eh_register_notification_callbacks() == FALSE) {
476 ERR("_eh_register_notification_callbacks() Fail");
477 return MTP_ERROR_GENERAL;
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;
487 DBG("MTP UID = [%u] and GID = [%u]\n", getuid(), getgid());
489 g_main_loop_run(g_mainloop);
491 _eh_deregister_notification_callbacks();
492 media_content_disconnect();
494 return MTP_ERROR_NONE;