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 static gboolean __check_internal_storage (gpointer user_data)
92 _handle_lock_status_notification(NULL, NULL);
97 void _mtp_init(add_rem_store_t sel)
99 mtp_char *device_name = NULL;
100 mtp_char *sync_partner = NULL;
104 DBG("Initialization start!");
108 if (g_conf.mmap_threshold) {
109 if (!mallopt(M_MMAP_THRESHOLD, g_conf.mmap_threshold))
110 ERR("mallopt(M_MMAP_THRESHOLD) Fail");
112 if (!mallopt(M_TRIM_THRESHOLD, g_conf.mmap_threshold * 2))
113 ERR("mallopt(M_TRIM_THRESHOLD) Fail");
118 _transport_init_status_info();
119 _transport_set_mtp_operation_state(MTP_STATE_INITIALIZING);
121 device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
122 if (device_name != NULL) {
123 _device_set_device_name(device_name);
126 _device_set_device_name(MTP_DEV_PROPERTY_FRIENDLYNAME);
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);
134 _device_set_sync_partner(MTP_DEV_PROPERTY_SYNCPARTNER);
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");
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");
153 /* Internal Storage */
154 if (MTP_PHONE_LOCK_OFF == _util_get_local_lock_status()) {
156 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
158 ret = media_content_connect();
159 if (MEDIA_CONTENT_ERROR_NONE != ret) {
160 ERR("media_content_connect() Fail(%d)", ret);
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",
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",
186 /* Set mtpdeviceinfo */
189 _features_supported_info();
191 /* Install storage */
192 _device_install_storage(sel);
194 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
195 _inoti_init_filesystem_evnts();
196 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
198 vconf_ret = vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE_READ_ONLY,
199 _handle_lock_status_notification, NULL);
201 ERR("vconf_notify_key_changed(%s) Fail", VCONFKEY_IDLE_LOCK_STATE_READ_ONLY);
205 g_timeout_add(1000, __check_internal_storage, NULL);
207 vconf_ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
208 _handle_mmc_notification, NULL);
210 ERR("vconf_notify_key_changed(%s) Fail", VCONFKEY_SYSMAN_MMC_STATUS);
217 /* Set MTP state to stopped */
218 _transport_set_mtp_operation_state(MTP_STATE_STOPPED);
224 void _mtp_deinit(void)
226 _cmd_hdlr_reset_cmd(&g_mgr->hdlr);
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;
234 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
235 _inoti_deinit_filesystem_events();
236 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
238 vconf_ignore_key_changed(VCONFKEY_IDLE_LOCK_STATE_READ_ONLY,
239 _handle_lock_status_notification);
241 vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
242 _handle_mmc_notification);
247 static void __print_mtp_conf(void)
249 if (g_conf.is_init == false) {
250 ERR("g_conf is not initialized");
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);
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);
272 static void __read_mtp_conf(void)
277 char *saveptr = NULL;
279 g_conf.mmap_threshold = MTP_MMAP_THRESHOLD;
281 g_conf.read_usb_size = MTP_READ_USB_SIZE;
282 g_conf.write_usb_size = MTP_WRITE_USB_SIZE;
284 g_conf.read_file_size = MTP_READ_FILE_SIZE;
285 g_conf.write_file_size = MTP_WRITE_FILE_SIZE;
287 g_conf.init_rx_ipc_size = MTP_INIT_RX_IPC_SIZE;
288 g_conf.init_tx_ipc_size = MTP_INIT_TX_IPC_SIZE;
290 g_conf.max_rx_ipc_size = MTP_MAX_RX_IPC_SIZE;
291 g_conf.max_tx_ipc_size = MTP_MAX_TX_IPC_SIZE;
293 g_conf.max_io_buf_size = MTP_MAX_IO_BUF_SIZE;
294 g_conf.read_file_delay = MTP_READ_FILE_DELAY;
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;
304 fp = fopen(MTP_CONFIG_FILE_PATH, "r");
306 DBG("Default configuration is used");
307 g_conf.is_init = true;
313 while (fgets(buf, sizeof(buf), fp)) {
314 if (buf[0] == '#' || buf[0] == '\n')
317 token = strrchr(buf, '\n');
319 ERR("g_conf is too long");
324 token = strtok_r(buf, "=", &saveptr);
329 if (strcasecmp(token, "mmap_threshold") == 0) {
330 token = strtok_r(NULL, "=", &saveptr);
331 g_conf.mmap_threshold = atoi(token);
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);
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);
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);
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);
349 } else if (strcasecmp(token, "read_usb_size") == 0) {
350 token = strtok_r(NULL, "=", &saveptr);
351 g_conf.read_usb_size = atoi(token);
353 } else if (strcasecmp(token, "write_usb_size") == 0) {
354 token = strtok_r(NULL, "=", &saveptr);
355 g_conf.write_usb_size = atoi(token);
357 } else if (strcasecmp(token, "read_file_size") == 0) {
358 token = strtok_r(NULL, "=", &saveptr);
359 g_conf.read_file_size = atoi(token);
361 } else if (strcasecmp(token, "write_file_size") == 0) {
362 token = strtok_r(NULL, "=", &saveptr);
363 g_conf.write_file_size = atoi(token);
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);
369 } else if (strcasecmp(token, "read_file_delay") == 0) {
370 token = strtok_r(NULL, "=", &saveptr);
371 g_conf.read_file_delay = atoi(token);
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;
377 } else if (strcasecmp(token, "inheritsched") == 0) {
378 token = strtok_r(NULL, "=", &saveptr);
379 g_conf.inheritsched = *token;
381 } else if (strcasecmp(token, "schedpolicy") == 0) {
382 token = strtok_r(NULL, "=", &saveptr);
383 g_conf.schedpolicy = *token;
385 } else if (strcasecmp(token, "file_schedparam") == 0) {
386 token = strtok_r(NULL, "=", &saveptr);
387 g_conf.file_schedparam = atoi(token);
389 } else if (strcasecmp(token, "usb_schedparam") == 0) {
390 token = strtok_r(NULL, "=", &saveptr);
391 g_conf.usb_schedparam = atoi(token);
394 ERR("Unknown option : %s\n", buf);
398 g_conf.is_init = true;
404 void __init_mtp_info(void)
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));
414 void _features_supported_info(void)
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);
422 DBG("***********************************************************");
423 DBG("### Extension ###");
424 if (_get_oma_drm_status() == TRUE) {
425 DBG("### 2. OMADRM : [ON]");
427 DBG("### 2. OMADRM : [OFF]");
430 DBG("***********************************************************");
431 DBG("### Feature ###");
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 */
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("***********************************************************");
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.
454 void mtp_end_event(void)
459 static inline int _main_init()
461 pthread_mutexattr_t mutex_attr;
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");
468 pthread_mutexattr_destroy(&mutex_attr);
469 return MTP_ERROR_GENERAL;
471 pthread_mutexattr_destroy(&mutex_attr);
473 if (_eh_handle_usb_events(USB_INSERTED) == FALSE) {
474 ERR("_eh_handle_usb_events() Fail");
475 return MTP_ERROR_GENERAL;
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;
484 return MTP_ERROR_NONE;
487 int main(int argc, char *argv[])
491 if (_eh_register_notification_callbacks() == FALSE) {
492 ERR("_eh_register_notification_callbacks() Fail");
493 return MTP_ERROR_GENERAL;
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;
503 DBG("MTP UID = [%u] and GID = [%u]\n", getuid(), getgid());
505 g_main_loop_run(g_mainloop);
507 _eh_deregister_notification_callbacks();
508 media_content_disconnect();
510 return MTP_ERROR_NONE;