From 93185a26f3c47822348bcec9fc6ea3d93e177e72 Mon Sep 17 00:00:00 2001 From: VBS Date: Wed, 29 Mar 2017 18:47:31 +0900 Subject: [PATCH 01/16] Sync with 3.0 : Ver. 0.0.19 to 0.0.22 Signed-off-by: Jihoon Jung Change-Id: I2b6a00e7a2ef25f6737adbef94d0b49d51409e6d --- packaging/mtp-responder.spec | 4 ++-- src/mtp_cmd_handler.c | 18 ++++++++++++++++-- src/mtp_cmd_handler_util.c | 6 ++++++ src/util/mtp_fs.c | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index d292281..bf0299d 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -5,7 +5,7 @@ ExcludeArch: %arm aarch64 Name: mtp-responder Summary: Media Transfer Protocol daemon (responder) -Version: 0.0.19 +Version: 0.0.22 Release: 1 Group: Network & Connectivity/Other License: Apache-2.0 @@ -57,10 +57,10 @@ ln -sf %{_unitdir}/mtp-responder.service %{_sysconfdir}/systemd/default-extra-de %files %manifest mtp-responder.manifest +%license LICENSE.APLv2 %defattr(-,root,root,-) %{_bindir}/mtp-responder %{_unitdir}/mtp-responder.service %{_prefix}/lib/udev/rules.d/99-mtp-responder.rules /opt/var/lib/misc/mtp-responder.conf %{upgrade_script_path}/500.%{name}-upgrade.sh -#%license LICENSE.APLv2 diff --git a/src/mtp_cmd_handler.c b/src/mtp_cmd_handler.c index acaa3e4..4e20d44 100755 --- a/src/mtp_cmd_handler.c +++ b/src/mtp_cmd_handler.c @@ -737,6 +737,7 @@ static void __get_object(mtp_handler_t *hdlr) if (NULL == ptr) { ERR("_hdlr_alloc_buf_data_container() Fail"); _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } @@ -748,9 +749,11 @@ static void __get_object(mtp_handler_t *hdlr) if (EACCES == error) { _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_ACCESSDENIED); + g_free(blk.data); return; } _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } @@ -1252,6 +1255,7 @@ static void __get_device_prop_desc(mtp_handler_t *hdlr) if (ptr == NULL) { resp = PTP_RESPONSE_GEN_ERROR; _cmd_hdlr_send_response_code(hdlr, resp); + g_free(blk.data); return; } @@ -1299,6 +1303,7 @@ static void __get_device_prop_value(mtp_handler_t *hdlr) if (ptr == NULL) { _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } memcpy(ptr, &batt, no_bytes); @@ -1329,6 +1334,7 @@ static void __get_device_prop_value(mtp_handler_t *hdlr) if (ptr == NULL) { _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } @@ -1361,6 +1367,7 @@ static void __get_device_prop_value(mtp_handler_t *hdlr) if (ptr == NULL) { _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } @@ -1429,6 +1436,7 @@ static void __get_device_prop_value(mtp_handler_t *hdlr) if (ptr == NULL) { _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); g_free(data); _util_file_close(h_file); _prop_deinit_ptparray(&val_arr); @@ -1487,6 +1495,7 @@ static void __set_device_prop_value(mtp_handler_t *hdlr) if (FALSE == _hdlr_rcv_data_container(&blk, max_bytes)) { ERR("_hdlr_rcv_data_container() Fail"); _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } @@ -1724,8 +1733,10 @@ static void __set_object_references(mtp_handler_t *hdlr) } ptr = _hdlr_get_payload_data(&blk); - if (ptr == NULL) + if (ptr == NULL) { + g_free(blk.data); return; + } memcpy(&num_ref, ptr, sizeof(mtp_uint32)); #ifdef __BIG_ENDIAN__ @@ -2682,6 +2693,7 @@ static void __get_interdep_prop_desc(mtp_handler_t *hdlr) num_bytes, fmt)) { ERR("_hutil_get_interdep_prop_config_list_data() Fail"); _cmd_hdlr_send_response_code(hdlr, PTP_RESPONSE_GEN_ERROR); + g_free(blk.data); return; } @@ -2791,8 +2803,10 @@ static void __send_object_prop_list(mtp_handler_t *hdlr) } data = _hdlr_get_payload_data(&blk); - if (data == NULL) + if (data == NULL) { + g_free(blk.data); return; + } ret = _hutil_construct_object_entry_prop_list(store_id, h_parent, fmt, f_size, ((hdlr->data4_send_obj.is_valid == TRUE) ? diff --git a/src/mtp_cmd_handler_util.c b/src/mtp_cmd_handler_util.c index 2e265af..8f821dd 100755 --- a/src/mtp_cmd_handler_util.c +++ b/src/mtp_cmd_handler_util.c @@ -1893,12 +1893,18 @@ mtp_err_t _hutil_construct_object_entry_prop_list(mtp_uint32 store_id, g_free(alb_buf); #endif /* MTP_SUPPORT_ALBUM_ART */ *obj_ptr = obj; + if (obj_info != NULL) + _entity_dealloc_obj_info(obj_info); + return MTP_ERROR_NONE; ERROR_EXIT: #ifdef MTP_SUPPORT_ALBUM_ART g_free(alb_buf); #endif /* MTP_SUPPORT_ALBUM_ART */ + if (obj_info != NULL) + _entity_dealloc_obj_info(obj_info); + return resp; } diff --git a/src/util/mtp_fs.c b/src/util/mtp_fs.c index b206f9b..4085c0e 100755 --- a/src/util/mtp_fs.c +++ b/src/util/mtp_fs.c @@ -923,7 +923,7 @@ void _util_fill_guid_array(void *guidarray, mtp_uint32 start_index, */ void FLOGD(const char *fmt, ...) { - static int written_bytes = 0; + static mtp_int64 written_bytes = 0; FILE *fp = NULL; va_list ap; -- 2.7.4 From 6c7181ea696544d60126550ba38db3e7315ed58c Mon Sep 17 00:00:00 2001 From: Hyihong Chae Date: Tue, 11 Apr 2017 16:04:44 +0900 Subject: [PATCH 02/16] [Tizen 4.0 TV] fix svace issue. Change-Id: Iacc22afdb51a1f11839430f3d65b2e23bf16014b Signed-off-by: HyiHong Chae --- packaging/mtp-responder.spec | 2 +- src/entity/mtp_object.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index bf0299d..d333fb0 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -5,7 +5,7 @@ ExcludeArch: %arm aarch64 Name: mtp-responder Summary: Media Transfer Protocol daemon (responder) -Version: 0.0.22 +Version: 0.0.23 Release: 1 Group: Network & Connectivity/Other License: Apache-2.0 diff --git a/src/entity/mtp_object.c b/src/entity/mtp_object.c index 358af3c..d8279e5 100755 --- a/src/entity/mtp_object.c +++ b/src/entity/mtp_object.c @@ -507,6 +507,7 @@ mtp_bool _entity_check_child_obj_path(mtp_obj_t *obj, if (_util_is_file_opened(child_obj->file_path) == TRUE) { ERR_SECURE("File [%s] is already opened\n", child_obj->file_path); + _prop_deinit_ptparray(&child_arr); return FALSE; } -- 2.7.4 From 1fb7cbb7a3b4dec4c02c230817369dc91a9130ed Mon Sep 17 00:00:00 2001 From: Hyihong Chae Date: Mon, 24 Apr 2017 19:02:21 +0900 Subject: [PATCH 03/16] fix security issue(TSAM-13252) Change-Id: I99c089e88868edbad0532510be7e838e4d570f5f Signed-off-by: HyiHong Chae --- include/util/mtp_support.h | 1 + packaging/mtp-responder.spec | 2 +- src/entity/mtp_store.c | 6 ++++-- src/transport/mtp_transport.c | 1 + src/util/mtp_support.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/include/util/mtp_support.h b/include/util/mtp_support.h index b0cc9c4..a67325b 100755 --- a/include/util/mtp_support.h +++ b/include/util/mtp_support.h @@ -54,5 +54,6 @@ void _util_get_parent_path(const mtp_char *fullpath, mtp_char *p_path); void _util_conv_wstr_to_guid(mtp_wchar *wstr, mtp_uint64 *guid); mtp_bool _util_get_unique_dir_path(const mtp_char *exist_path, mtp_char *new_path, mtp_uint32 new_path_buf_len); +mtp_int32 _util_system_cmd_wait(const mtp_char *cmd); #endif /* _MTP_SUPPORT_H_ */ diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index d333fb0..8317525 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -5,7 +5,7 @@ ExcludeArch: %arm aarch64 Name: mtp-responder Summary: Media Transfer Protocol daemon (responder) -Version: 0.0.23 +Version: 0.0.24 Release: 1 Group: Network & Connectivity/Other License: Apache-2.0 diff --git a/src/entity/mtp_store.c b/src/entity/mtp_store.c index 7297d8b..c3ae8ac 100755 --- a/src/entity/mtp_store.c +++ b/src/entity/mtp_store.c @@ -1199,7 +1199,8 @@ void _entity_list_modified_files(mtp_uint32 minutes) inter_path, minutes, MTP_FILES_MODIFIED_FILES); DBG("find query is [%s]\n", command); - ret = system(command); + ret = _util_system_cmd_wait(command); + if (WIFSIGNALED(ret) && (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT)) { @@ -1215,7 +1216,8 @@ void _entity_list_modified_files(mtp_uint32 minutes) ext_path, minutes, MTP_FILES_MODIFIED_FILES); DBG("find query is [%s]\n", command); - ret = system(command); + ret = _util_system_cmd_wait(command); + if (WIFSIGNALED(ret) && (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT)) { diff --git a/src/transport/mtp_transport.c b/src/transport/mtp_transport.c index 3eee08b..7c73bbd 100755 --- a/src/transport/mtp_transport.c +++ b/src/transport/mtp_transport.c @@ -419,6 +419,7 @@ void _transport_usb_finalize(void) sizeof(msgq_ptr_t) - sizeof(long), 0)) { ERR("_util_msgq_send() Fail"); } + g_free(pkt.buffer); res = _util_thread_join(g_data_rcv, &th_result); if (res == FALSE) diff --git a/src/util/mtp_support.c b/src/util/mtp_support.c index 83108d6..8517146 100755 --- a/src/util/mtp_support.c +++ b/src/util/mtp_support.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "mtp_support.h" #include "ptp_datacodes.h" #include "mtp_util.h" @@ -643,3 +644,38 @@ SUCCESS: DBG_SECURE("Unique dir name[%s]\n", new_path); return TRUE; } + +mtp_int32 _util_system_cmd_wait(const mtp_char *cmd) +{ + + int pid = 0; + int status = 0; + + if (cmd == NULL) + return -1; + + pid = fork(); + + if (pid == -1) + return -1; + + if (pid == 0) { + char *argv[4]; + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = (char*)cmd; + argv[3] = 0; + execv("/bin/sh", argv); + exit(127); + } + + do { + if (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) + return -1; + } else { + return status; + } + } while (1); +} + -- 2.7.4 From ecf1e402b9c9f316fa6952265d8932e7f20fad49 Mon Sep 17 00:00:00 2001 From: Hyihong Chae Date: Tue, 30 May 2017 20:19:38 +0900 Subject: [PATCH 04/16] fix SENSYS issue. (TNEXT-744) Change-Id: Ia1fb37801da4e72306c9b1522156dda2547bdeec Signed-off-by: HyiHong Chae --- packaging/mtp-responder.spec | 2 +- src/util/mtp_thread.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index 8317525..4d27366 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -5,7 +5,7 @@ ExcludeArch: %arm aarch64 Name: mtp-responder Summary: Media Transfer Protocol daemon (responder) -Version: 0.0.24 +Version: 0.0.25 Release: 1 Group: Network & Connectivity/Other License: Apache-2.0 diff --git a/src/util/mtp_thread.c b/src/util/mtp_thread.c index e96d111..e4ba76e 100755 --- a/src/util/mtp_thread.c +++ b/src/util/mtp_thread.c @@ -76,9 +76,14 @@ mtp_bool _util_thread_cancel(pthread_t tid) { mtp_int32 res; + if (tid == 0) { + ERR("tid is NULL\n"); + return FALSE; + } + res = pthread_cancel(tid); if (res != 0) { - ERR("pthread_cancel Fail [%d] errno [%d]\n", tid, errno); + ERR("pthread_cancel Fail [%d] errno [%d]\n", tid, errno); return FALSE; } -- 2.7.4 From e37eb57d8c6adbf23cb646fadd62aa539d506937 Mon Sep 17 00:00:00 2001 From: "jh8801.jung" Date: Tue, 18 Jul 2017 20:02:24 +0900 Subject: [PATCH 05/16] Change daemon user owner to network_fw Signed-off-by: jh8801.jung Change-Id: I6306fc3b24cb4824251248c7f09b806a894a6faf --- CMakeLists.txt | 2 +- include/mtp_config.h | 4 +- include/util/mtp_util.h | 5 +++ mtp-responder.service | 5 +-- packaging/mtp-responder.spec | 1 + src/mtp_cmd_handler_util.c | 2 - src/mtp_event_handler.c | 4 +- src/mtp_init.c | 8 ++-- src/util/mtp_util.c | 100 +++++++++++++++++++++++++++++++++---------- 9 files changed, 95 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dc968a..4e39cfd 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src/util SRCS) INCLUDE(FindPkgConfig) pkg_check_modules(pkgs REQUIRED glib-2.0 capi-content-media-content - capi-media-metadata-extractor vconf dlog tapi capi-system-info storage) + capi-media-metadata-extractor vconf dlog tapi capi-system-info storage libsystemd-daemon) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") diff --git a/include/mtp_config.h b/include/mtp_config.h index d7052a9..eac1d2e 100755 --- a/include/mtp_config.h +++ b/include/mtp_config.h @@ -77,7 +77,7 @@ * Transport related configuration */ /* Internal Storage */ -#define MTP_STORE_PATH_CHAR "/opt/home/owner/content" +#define MTP_INTERNAL_PATH_CHAR "/opt/usr/home/" /* External Storage */ #define MTP_EXTERNAL_PATH_CHAR "/opt/media/SDCardA1" @@ -87,7 +87,7 @@ #define MTP_FILES_MODIFIED_FILES "/tmp/mtp_mod_files.log" /* Base MTP USER Directory */ -#define MTP_USER_DIRECTORY "/opt/usr/media/user" +#define MTP_USER_DIRECTORY "/opt/usr/home/owner/media" /* Hidden Root directory */ #define MTP_HIDDEN_PHONE ".HiddenPhone" diff --git a/include/util/mtp_util.h b/include/util/mtp_util.h index b0c7bb2..c5d56fd 100755 --- a/include/util/mtp_util.h +++ b/include/util/mtp_util.h @@ -25,6 +25,7 @@ #define LOG_TAG "MTP-RESPONDER" #endif /* LOG_TAG */ #include +#include #define FIND_CMD_LEN 300 #define FIND_CMD "/usr/bin/find %s \\( -iname '*.jpg' -o -iname '*.gif' " \ @@ -148,4 +149,8 @@ phone_status_t _util_get_local_lock_status(void); void _util_set_local_lock_status(const phone_status_t val); void _util_get_external_path(char *external_path); void _util_get_internal_path(char *internal_path); +mtp_bool _util_media_content_connect(); +void _util_media_content_disconnect(); + + #endif /* _MTP_UTIL_H_ */ diff --git a/mtp-responder.service b/mtp-responder.service index 8941a90..2019999 100755 --- a/mtp-responder.service +++ b/mtp-responder.service @@ -2,9 +2,8 @@ Description=MTP responder [Service] -User=owner -Group=users -SmackProcessLabel=System +User=network_fw +Group=network_fw SupplementaryGroups=priv_mediastorage priv_externalstorage Type=simple ExecStart=/usr/bin/mtp-responder diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index 4d27366..5edf60a 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -21,6 +21,7 @@ BuildRequires: pkgconfig(capi-content-media-content) BuildRequires: pkgconfig(capi-media-metadata-extractor) BuildRequires: pkgconfig(capi-system-info) Buildrequires: pkgconfig(storage) +BuildRequires: pkgconfig(libsystemd-daemon) Requires(post): /usr/bin/vconftool %define upgrade_script_path /usr/share/upgrade/scripts diff --git a/src/mtp_cmd_handler_util.c b/src/mtp_cmd_handler_util.c index 8f821dd..2b4d495 100755 --- a/src/mtp_cmd_handler_util.c +++ b/src/mtp_cmd_handler_util.c @@ -1893,8 +1893,6 @@ mtp_err_t _hutil_construct_object_entry_prop_list(mtp_uint32 store_id, g_free(alb_buf); #endif /* MTP_SUPPORT_ALBUM_ART */ *obj_ptr = obj; - if (obj_info != NULL) - _entity_dealloc_obj_info(obj_info); return MTP_ERROR_NONE; diff --git a/src/mtp_event_handler.c b/src/mtp_event_handler.c index fa549c8..0dbf921 100755 --- a/src/mtp_event_handler.c +++ b/src/mtp_event_handler.c @@ -390,14 +390,14 @@ void _handle_lock_status_notification(keynode_t *key, void *data) __send_events_from_device_to_pc(MTP_INTERNAL_STORE_ID, PTP_EVENTCODE_STOREADDED, 0, 0); - media_content_connect(); + _util_media_content_connect(); } else if (MTP_PHONE_LOCK_ON == current_val) { _device_uninstall_storage(MTP_ADDREM_INTERNAL); __send_events_from_device_to_pc(MTP_INTERNAL_STORE_ID, PTP_EVENTCODE_STOREREMOVED, 0, 0); - media_content_disconnect(); + _util_media_content_disconnect(); } return; diff --git a/src/mtp_init.c b/src/mtp_init.c index 1d79d17..2f749a1 100755 --- a/src/mtp_init.c +++ b/src/mtp_init.c @@ -155,9 +155,9 @@ void _mtp_init(add_rem_store_t sel) mtp_int32 ret; char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 }; - ret = media_content_connect(); - if (MEDIA_CONTENT_ERROR_NONE != ret) { - ERR("media_content_connect() Fail(%d)", ret); + ret = _util_media_content_connect(); + if (FALSE == ret) { + ERR("media_content_connect() Fail"); goto MTP_INIT_FAIL; } @@ -495,7 +495,7 @@ int main(int argc, char *argv[]) if (MTP_ERROR_NONE != ret) { ERR("_main_init() Fail(%d)", ret); _eh_deregister_notification_callbacks(); - media_content_disconnect(); + _util_media_content_disconnect(); return MTP_ERROR_GENERAL; } DBG("MTP UID = [%u] and GID = [%u]\n", getuid(), getgid()); diff --git a/src/util/mtp_util.c b/src/util/mtp_util.c index a039945..273fd13 100755 --- a/src/util/mtp_util.c +++ b/src/util/mtp_util.c @@ -30,6 +30,11 @@ #include "mtp_fs.h" #include #include +#include +#include +//#include +#include +#include static phone_state_t g_ph_status = { 0 }; @@ -346,43 +351,94 @@ static bool _util_device_external_supported_cb(int storage_id, storage_type_e ty void _util_get_external_path(char *external_path) { int error = STORAGE_ERROR_NONE; + error = storage_foreach_device_supported(_util_device_external_supported_cb, external_path); if (error != STORAGE_ERROR_NONE) { ERR("get external storage path Fail"); - strncpy(external_path, MTP_EXTERNAL_PATH_CHAR, strlen(MTP_EXTERNAL_PATH_CHAR)); + if (external_path != NULL) + strncpy(external_path, MTP_EXTERNAL_PATH_CHAR, strlen(MTP_EXTERNAL_PATH_CHAR) + 1); } } - -static bool _util_device_internal_supported_cb(int storage_id, storage_type_e type, - storage_state_e state, const char *path, void *user_data) +uid_t _util_get_active_user() { - char *storage_path = (char *)user_data; + uid_t *active_user_list = NULL; + uid_t active_user = 0; + int user_cnt = 0; - //DBG("storage id: %d, path: %s", storage_id, path); + user_cnt = sd_get_active_uids(&active_user_list); - if (type == STORAGE_TYPE_INTERNAL && path != NULL) { - strncpy(storage_path, path, strlen(path)); - //DBG("internal storage path : %s", storage_path); - - if (storage_get_root_directory(storage_id, &storage_path) != STORAGE_ERROR_NONE) { - ERR("get internal storage path Fail"); - return FALSE; - } else { - //DBG("get internal storage path : %s", storage_path); - } + if (user_cnt <= 0) { + ERR("Active user not exists : %d", user_cnt); + + if (active_user_list != NULL) + free(active_user_list); + + return -1; } - return TRUE; + if (active_user_list == NULL) { + ERR("active_user_list is NULL"); + return -1; + } + + active_user = active_user_list[0]; + + DBG("Active UID : %d", active_user); + + free(active_user_list); + + if (active_user <= 0) { + ERR("UID is not proper value : %d", active_user); + return -1; + } + + return active_user; } void _util_get_internal_path(char *internal_path) { - int error = STORAGE_ERROR_NONE; - error = storage_foreach_device_supported(_util_device_internal_supported_cb, internal_path); + struct passwd *pwd; + uid_t active_user = 0; + char *active_name = NULL; - if (error != STORAGE_ERROR_NONE) { - ERR("get internal storage path Fail"); - strncpy(internal_path, MTP_STORE_PATH_CHAR, strlen(MTP_STORE_PATH_CHAR)); + active_user = _util_get_active_user(); + pwd = getpwuid(active_user); + active_name = pwd->pw_name; + + if (active_name == NULL) { + ERR("active_name is NULL"); + strncpy(internal_path, MTP_USER_DIRECTORY, strlen(MTP_USER_DIRECTORY) + 1); + return; } + + if (internal_path != NULL) { + strncpy(internal_path, MTP_INTERNAL_PATH_CHAR, strlen(MTP_INTERNAL_PATH_CHAR) + 1); + strncat(internal_path, active_name, strlen(active_name) + 1); + strncat(internal_path, "/media", 7); + } + + ERR("internal path is %s", internal_path); } + +mtp_bool _util_media_content_connect() +{ + mtp_int32 ret = 0; + uid_t active_user = 0; + + active_user = _util_get_active_user(); + + ret = media_content_connect_with_uid(active_user); + if (ret != MEDIA_CONTENT_ERROR_NONE) { + ERR("media_content_connect() failed : %d", ret); + return FALSE; + } + + return TRUE; +} + +void _util_media_content_disconnect() +{ + media_content_disconnect(); +} + -- 2.7.4 From 45af7e931e9d1b1115ebb2d6816240c17725111d Mon Sep 17 00:00:00 2001 From: "jh8801.jung" Date: Tue, 8 Aug 2017 21:40:55 +0900 Subject: [PATCH 06/16] Add SmackLabel in service file Signed-off-by: jh8801.jung Change-Id: Ia8a841275806ffa5029fe46a9ee716cfa8db5e4b --- mtp-responder.service | 1 + 1 file changed, 1 insertion(+) diff --git a/mtp-responder.service b/mtp-responder.service index 2019999..24acdfe 100755 --- a/mtp-responder.service +++ b/mtp-responder.service @@ -8,3 +8,4 @@ SupplementaryGroups=priv_mediastorage priv_externalstorage Type=simple ExecStart=/usr/bin/mtp-responder KillMode=process +SmackProcessLabel=System -- 2.7.4 From afb8592010c7910d298baf2b4d7a670f5a9e9eeb Mon Sep 17 00:00:00 2001 From: "jh8801.jung" Date: Wed, 13 Sep 2017 11:13:23 +0900 Subject: [PATCH 07/16] Fix for svace issue (29398) Signed-off-by: jh8801.jung Change-Id: Ia07ec5c4d18238a614df39adbab464e0c34cff30 --- include/mtp_cmd_handler.h | 2 +- src/mtp_cmd_handler.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mtp_cmd_handler.h b/include/mtp_cmd_handler.h index 90559cf..9e809fe 100755 --- a/include/mtp_cmd_handler.h +++ b/include/mtp_cmd_handler.h @@ -73,7 +73,7 @@ typedef struct { */ typedef struct { mtp_char cmd_buf[MTP_MAX_CMD_BLOCK_SIZE]; - mtp_char header_buf[MTP_USB_HEADER_LENGTH]; + mtp_char header_buf[MTP_USB_HEADER_LENGTH + 1]; mtp_uint32 cmd_size; mtp_uint32 data_size; mtp_uint32 data_count; diff --git a/src/mtp_cmd_handler.c b/src/mtp_cmd_handler.c index 4e20d44..cce170e 100755 --- a/src/mtp_cmd_handler.c +++ b/src/mtp_cmd_handler.c @@ -2131,7 +2131,7 @@ static void __set_object_prop_list(mtp_handler_t *hdlr) mtp_uint32 max_bytes = 0; mtp_uint32 h_obj = 0; mtp_uint32 prop_id = 0; - mtp_uint32 data_type = 0; + mtp_uint16 data_type = 0; mtp_uchar *temp = NULL; mtp_int32 bytes_left = 0; mtp_uint32 prop_val_sz = 0; @@ -2217,7 +2217,7 @@ static void __set_object_prop_list(mtp_handler_t *hdlr) /* Update property*/ ret = _hutil_update_object_property(h_obj, prop_id, - (mtp_uint16 *)&data_type, temp, bytes_left, + &data_type, temp, bytes_left, &prop_val_sz); switch (ret) { -- 2.7.4 From ab087ad7a34dfb99a1d02ac215e5270f6a4e09c7 Mon Sep 17 00:00:00 2001 From: Taesoo Jun Date: Thu, 14 Sep 2017 18:54:36 +0900 Subject: [PATCH 08/16] [Fix] potential memory leak Change-Id: I59abc1f0a7342a0fd9e5304742953641cd2907c6 --- src/entity/mtp_store.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/entity/mtp_store.c b/src/entity/mtp_store.c index c3ae8ac..7105fa3 100755 --- a/src/entity/mtp_store.c +++ b/src/entity/mtp_store.c @@ -738,6 +738,7 @@ mtp_bool _entity_remove_object_mtp_store(mtp_store_t *store, mtp_obj_t *obj, format operation is cancelled."); *response = PTP_RESPONSE_PARTIAL_DELETION; + _prop_deinit_ptparray(&child_arr); return FALSE; } @@ -764,13 +765,12 @@ mtp_bool _entity_remove_object_mtp_store(mtp_store_t *store, mtp_obj_t *obj, operation is cancelled."); *response = PTP_RESPONSE_PARTIAL_DELETION; + _prop_deinit_ptparray(&child_arr); return FALSE; } } } - _prop_deinit_ptparray(&child_arr); - } else { /* Non-Enumerated Folder */ mtp_uint32 num_of_deleted_file = 0; @@ -786,6 +786,7 @@ mtp_bool _entity_remove_object_mtp_store(mtp_store_t *store, mtp_obj_t *obj, if (MTP_ERROR_ACCESS_DENIED == ret) *response = PTP_RESPONSE_ACCESSDENIED; + _prop_deinit_ptparray(&child_arr); return FALSE; } if (num_of_file == 0) @@ -803,6 +804,8 @@ mtp_bool _entity_remove_object_mtp_store(mtp_store_t *store, mtp_obj_t *obj, all_del = FALSE; } } + _prop_deinit_ptparray(&child_arr); + _util_scan_folder_contents_in_db(obj->file_path); if (all_del) { g_snprintf(g_last_deleted, -- 2.7.4 From 54f96c0332104118b2a7e70be316aaa421b60268 Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Tue, 26 Sep 2017 13:54:34 +0900 Subject: [PATCH 09/16] Fix build waring problem due to readdir_r Change-Id: I63e0fdb15366c88d04a85eb85544270647e3ef28 Signed-off-by: saerome.kim --- packaging/mtp-responder.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index 5edf60a..b1f1861 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -36,6 +36,8 @@ cp %{SOURCE1001} . %build +export CFLAGS="$CFLAGS -Wno-deprecated-declarations" + %cmake . make %{?jobs:-j%jobs} -- 2.7.4 From 2bede2d1b6c1e84d6215b7e6e1c4da4b3b1b4935 Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Wed, 6 Dec 2017 21:14:59 +0900 Subject: [PATCH 10/16] Fix WGID 264373 Change-Id: I161c9e52b4cbef70da98c4a3dedfae35f8e133d0 Signed-off-by: saerome.kim --- src/util/mtp_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 src/util/mtp_thread.c diff --git a/src/util/mtp_thread.c b/src/util/mtp_thread.c old mode 100755 new mode 100644 index e4ba76e..2ea7380 --- a/src/util/mtp_thread.c +++ b/src/util/mtp_thread.c @@ -46,7 +46,7 @@ mtp_bool _util_thread_create(pthread_t *tid, const mtp_char *tname, error = pthread_create(tid, &attr, thread_func, arg); if (error != 0) { - ERR("[%s] Thread creation Fail errno [%d]\n", tname, errno); + ERR("Thread creation Fail [%d], errno [%d]\n", error, errno); pthread_attr_destroy(&attr); return FALSE; } -- 2.7.4 From 1376148afbbb98e3ccad6c5002bf07a2fe958700 Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Thu, 15 Mar 2018 14:19:11 +0900 Subject: [PATCH 11/16] fix WGID 110834 - Resource leak problem Change-Id: Ie2985204bc1d44261040d1074521f7eaf0718f90 Signed-off-by: saerome.kim --- src/entity/mtp_store.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/entity/mtp_store.c b/src/entity/mtp_store.c index 7105fa3..882fac5 100755 --- a/src/entity/mtp_store.c +++ b/src/entity/mtp_store.c @@ -472,8 +472,13 @@ mtp_uint32 _entity_get_objects_from_store_till_depth(mtp_store_t *store, mtp_uint32 ii = 0; child_arr = _prop_alloc_ptparray(UINT32_TYPE); - if (child_arr == NULL || child_arr->array_entry == NULL) + if (child_arr == NULL) { return 0; + } + if (child_arr->array_entry == NULL) { + _prop_destroy_ptparray(child_arr); + return 0; + } depth--; -- 2.7.4 From 1aec6bfd5856cc9f13b0818ae983703044d3ed17 Mon Sep 17 00:00:00 2001 From: Taesoo Jun Date: Fri, 30 Mar 2018 09:15:22 +0900 Subject: [PATCH 12/16] Add return value checking for media_info_clone Change-Id: I09dc1c5c96b2f49c52e6baa99971d86f7d77fcbe --- src/util/mtp_media_info.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/util/mtp_media_info.c b/src/util/mtp_media_info.c index 6e7b34f..e1b3bea 100755 --- a/src/util/mtp_media_info.c +++ b/src/util/mtp_media_info.c @@ -28,11 +28,14 @@ static bool __fill_media_id_cb(media_info_h media, void *user_data) { + mtp_int32 ret = MEDIA_CONTENT_ERROR_NONE; media_info_h *media_id = (media_info_h *)user_data; DBG("INTO MEdia id retrieval callback"); - media_info_clone(media_id, media); - - return FALSE; + ret = media_info_clone(media_id, media); + if (ret != MEDIA_CONTENT_ERROR_NONE) { + return FALSE; + } + return TRUE; } static void __scan_folder_cb(media_content_error_e err, void *user_data) -- 2.7.4 From 43cc6de937afdc383b6279c949950995627510fe Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Tue, 3 Apr 2018 19:12:08 +0900 Subject: [PATCH 13/16] Apply partial relro security hardening Change-Id: Ic768751ec01780ae5029be23f76997076f8cbe30 Signed-off-by: saerome.kim --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e39cfd..f2ce402 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -Werror-implicit-function-declaration") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fexceptions -fvisibility=hidden") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") -SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -pie -Wl,--hash-style=both") +SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -pie -Wl,--hash-style=both,-z,relro") ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} pthread rt gcrypt) -- 2.7.4 From 6263c60a6d11c64a07668e181a414b13f4e1a7d0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Stelmach?= Date: Tue, 6 Feb 2018 19:04:18 +0100 Subject: [PATCH 14/16] Implement FunctionFS transport MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit FunctionFS is a generic interface between the kernel and userland processes that allows implementation of USB functions as userspace processes. There may be many instances of FunctionFS mounted each one for a different USB functions. Authored-by: Łukasz Stelmach [Backported from other repository] Signed-off-by: Krzysztof Opasiak [Rebased] Signed-off-by: Paweł Szewczyk Change-Id: Idba4fd657006d445bf1399218784f1c40e3cf626 --- include/transport/mtp_usb_driver.h | 38 ++ src/transport/mtp_transport.c | 31 ++ src/transport/mtp_usb_driver.c | 412 ++----------------- src/transport/mtp_usb_driver_ffs.c | 784 +++++++++++++++++++++++++++++++++++++ src/transport/mtp_usb_driver_slp.c | 482 +++++++++++++++++++++++ 5 files changed, 1361 insertions(+), 386 deletions(-) mode change 100755 => 100644 src/transport/mtp_usb_driver.c create mode 100755 src/transport/mtp_usb_driver_ffs.c create mode 100644 src/transport/mtp_usb_driver_slp.c diff --git a/include/transport/mtp_usb_driver.h b/include/transport/mtp_usb_driver.h index cc63874..6320983 100755 --- a/include/transport/mtp_usb_driver.h +++ b/include/transport/mtp_usb_driver.h @@ -17,12 +17,22 @@ #ifndef _MTP_USB_DRIVER_H_ #define _MTP_USB_DRIVER_H_ +#include "mtp_config.h" #include "mtp_datatype.h" #include "mtp_msgq.h" /* Start of driver related defines */ #define MTP_DRIVER_PATH "/dev/usb_mtp_gadget" +/* FunctionFS endpoint paths */ +#ifndef MTP_FFS_PATH +#define MTP_FFS_PATH "/dev/usb-funcs/mtp" +#endif +#define MTP_EP0_PATH MTP_FFS_PATH "/ep0" +#define MTP_EP_IN_PATH MTP_FFS_PATH "/ep1" +#define MTP_EP_OUT_PATH MTP_FFS_PATH "/ep2" +#define MTP_EP_STATUS_PATH MTP_FFS_PATH "/ep3" + /* These values come from f_mtp_slp.h of kernel source */ #define MTP_IOCTL_LETTER 'Z' #define MTP_GET_HIGH_FULL_SPEED _IOR(MTP_IOCTL_LETTER, 1, int) @@ -44,6 +54,32 @@ typedef struct mtp_max_pkt_size { mtp_uint32 rx; } mtp_max_pkt_size_t; +/* Transport driver interface */ +typedef struct mtp_usb_driver { + mtp_bool (*transport_init_usb_device)(void); + void *(*transport_thread_fake_usb_read)(void *arg); + void *(*transport_thread_fake_usb_write)(void *arg); + void (*transport_deinit_usb_device)(void); + void *(*transport_thread_usb_write)(void *arg); + void *(*transport_thread_usb_read)(void *arg); + void *(*transport_thread_usb_control)(void *arg); + mtp_int32 (*transport_mq_init)(msgq_id_t *rx_ipc, msgq_id_t *tx_ipc); + mtp_bool (*transport_mq_deinit)(msgq_id_t *rx_ipc, msgq_id_t *tx_ipc); + mtp_uint32 (*transport_get_usb_packet_len)(void); + mtp_uint32 (*get_tx_pkt_size)(void); + mtp_uint32 (*get_rx_pkt_size)(void); +} mtp_usb_driver_t; + +extern const mtp_usb_driver_t mtp_usb_driver_slp; +extern const mtp_usb_driver_t mtp_usb_driver_ffs; + +typedef enum { + MTP_TRANSPORT_SLP = 0, + MTP_TRANSPORT_FFS, + MTP_TRANSPORT_NUMBER, /* number of supported transports */ + MTP_TRANSPORT_UNKNOWN, +} mtp_transport_type_t; + /* Maximum repeat count for USB error recovery */ #define MTP_USB_ERROR_MAX_RETRY 5 @@ -51,10 +87,12 @@ mtp_bool _transport_init_usb_device(void); void _transport_deinit_usb_device(void); void *_transport_thread_usb_write(void *arg); void *_transport_thread_usb_read(void *arg); +void *_transport_thread_usb_control(void *arg); mtp_int32 _transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid); mtp_bool _transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid); mtp_uint32 _transport_get_usb_packet_len(void); mtp_uint32 _get_tx_pkt_size(void); mtp_uint32 _get_rx_pkt_size(void); +mtp_transport_type_t _transport_get_type(void); #endif /* _MTP_USB_DRIVER_H_ */ diff --git a/src/transport/mtp_transport.c b/src/transport/mtp_transport.c index 7c73bbd..c178c51 100755 --- a/src/transport/mtp_transport.c +++ b/src/transport/mtp_transport.c @@ -40,6 +40,7 @@ static mtp_mgr_t *g_mgr = &g_mtp_mgr; static mtp_bool g_usb_threads_created = FALSE; static pthread_t g_tx_thrd = 0; static pthread_t g_rx_thrd = 0; +static pthread_t g_ctrl_thrd = 0; static pthread_t g_data_rcv = 0; static msgq_id_t mtp_to_usb_mqid; static msgq_id_t g_usb_to_mtp_mqid; @@ -290,6 +291,7 @@ static mtp_err_t __transport_init_io() mtp_int32 res = 0; thread_func_t usb_write_thread = _transport_thread_usb_write; thread_func_t usb_read_thread = _transport_thread_usb_read; + thread_func_t usb_control_thread = _transport_thread_usb_control; res = _util_thread_create(&g_tx_thrd, "usb write thread", PTHREAD_CREATE_JOINABLE, usb_write_thread, @@ -307,6 +309,17 @@ static mtp_err_t __transport_init_io() goto cleanup; } + if (_transport_get_type() == MTP_TRANSPORT_FFS) { + res = _util_thread_create(&g_ctrl_thrd, "usb control thread", + PTHREAD_CREATE_JOINABLE, + usb_control_thread, + NULL); + if (FALSE == res) { + ERR("CTRL thread creation failed\n"); + goto cleanup; + } + } + g_usb_threads_created = TRUE; return MTP_ERROR_NONE; @@ -314,6 +327,11 @@ static mtp_err_t __transport_init_io() cleanup: _util_print_error(); + if (g_ctrl_thrd) { + res = _util_thread_cancel(g_ctrl_thrd); + DBG("pthread_cancel [%d]\n", res); + g_ctrl_thrd = 0; + } if (g_rx_thrd) { res = _util_thread_cancel(g_rx_thrd); DBG("pthread_cancel [%d]\n", res); @@ -337,6 +355,19 @@ static void __transport_deinit_io() } errno = 0; + if (_transport_get_type() == MTP_TRANSPORT_FFS) { + if (FALSE == _util_thread_cancel(g_ctrl_thrd)) { + ERR("Fail to cancel pthread of g_ctrl_thrd\n"); + } else { + DBG("Succeed to cancel pthread of g_ctrl_thrd\n"); + } + + if (_util_thread_join(g_ctrl_thrd, 0) == FALSE) + ERR("pthread_join of g_ctrl_thrd failed\n"); + + g_ctrl_thrd = 0; + } + if (FALSE == _util_thread_cancel(g_rx_thrd)) ERR("_util_thread_cancel(rx) Fail"); diff --git a/src/transport/mtp_usb_driver.c b/src/transport/mtp_usb_driver.c old mode 100755 new mode 100644 index e392bb9..5576c55 --- a/src/transport/mtp_usb_driver.c +++ b/src/transport/mtp_usb_driver.c @@ -14,107 +14,41 @@ * limitations under the License. */ -#include -#include #include -#include -#include #include "mtp_usb_driver.h" -#include "mtp_device.h" -#include "ptp_datacodes.h" -#include "mtp_support.h" -#include "ptp_container.h" -#include "mtp_msgq.h" -#include "mtp_util.h" -#include "mtp_thread.h" -#include "mtp_transport.h" -#include "mtp_event_handler.h" -/* - * GLOBAL AND EXTERN VARIABLES - */ -extern mtp_config_t g_conf; - -/* - * STATIC VARIABLES AND FUNCTIONS - */ -static mtp_int32 g_usb_fd = -1; -static mtp_max_pkt_size_t pkt_size; -static mtp_uint32 rx_mq_sz; -static mtp_uint32 tx_mq_sz; - -static mtp_int32 __handle_usb_read_err(mtp_int32 err, - mtp_uchar *buf, mtp_int32 buf_len); -static void __clean_up_msg_queue(void *pmsqid); -static void __handle_control_request(mtp_int32 request); -static void __receive_signal(mtp_int32 n, siginfo_t *info, void *unused); +static const mtp_usb_driver_t *usb_driver; /* * FUNCTIONS */ mtp_bool _transport_init_usb_device(void) { - mtp_int32 status = 0; - struct sigaction sig; - pid_t mtp_pid = 0; - int msg_size; - - /* Kernel will inform to User Space using signal. */ - memset(&sig, 0, sizeof(sig)); - sig.sa_sigaction = __receive_signal; - sig.sa_flags = SA_SIGINFO; - sigaction(SIG_SETUP, &sig, NULL); - - if (g_usb_fd > 0) { - DBG("Device Already open"); - return TRUE; - } - - g_usb_fd = open(MTP_DRIVER_PATH, O_RDWR); - if (g_usb_fd < 0) { - ERR("Device node [%s] open Fail,errno [%d]\n", MTP_DRIVER_PATH, errno); - return FALSE; - } - - mtp_pid = getpid(); - status = ioctl(g_usb_fd, MTP_SET_USER_PID, &mtp_pid); - if (status < 0) { - ERR("IOCTL MTP_SET_USER_PID Fail = [%d]\n", status); - _transport_deinit_usb_device(); + if (access(MTP_DRIVER_PATH, F_OK) == 0) { + usb_driver = &mtp_usb_driver_slp; + } else if (access(MTP_EP0_PATH, F_OK) == 0) { + usb_driver = &mtp_usb_driver_ffs; + } else { + ERR("No suport for USB gadgets in kernel"); return FALSE; } - pkt_size.rx = g_conf.read_usb_size; - pkt_size.tx = g_conf.write_usb_size; - - DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx); - - msg_size = sizeof(msgq_ptr_t) - sizeof(long); - rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size; - tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size; - - DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz); - - return TRUE; + return usb_driver->transport_init_usb_device(); } void _transport_deinit_usb_device(void) { - if (g_usb_fd >= 0) - close(g_usb_fd); - g_usb_fd = -1; - - return; + usb_driver->transport_deinit_usb_device(); } mtp_uint32 _get_tx_pkt_size(void) { - return pkt_size.tx; + return usb_driver->get_rx_pkt_size(); } mtp_uint32 _get_rx_pkt_size(void) { - return pkt_size.rx; + return usb_driver->get_rx_pkt_size(); } /* @@ -127,294 +61,22 @@ mtp_uint32 _get_rx_pkt_size(void) */ mtp_int32 _transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid) { - if (_util_msgq_init(rx_mqid, 0) == FALSE) { - ERR("RX MQ init Fail [%d]\n", errno); - return FALSE; - } - - if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE) - ERR("RX MQ setting size Fail [%d]\n", errno); - - if (_util_msgq_init(tx_mqid, 0) == FALSE) { - ERR("TX MQ init Fail [%d]\n", errno); - _util_msgq_deinit(rx_mqid); - *rx_mqid = -1; - return FALSE; - } - - if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE) - ERR("TX MQ setting size Fail [%d]\n", errno); - - return TRUE; + return usb_driver->transport_mq_init(rx_mqid, tx_mqid); } void *_transport_thread_usb_write(void *arg) { - mtp_int32 status = 0; - mtp_uint32 len = 0; - unsigned char *mtp_buf = NULL; - msg_type_t mtype = MTP_UNDEFINED_PACKET; - msgq_id_t *mqid = (msgq_id_t *)arg; - - pthread_cleanup_push(__clean_up_msg_queue, mqid); - - do { - /* original LinuxThreads cancelation didn't work right - * so test for it explicitly. - */ - pthread_testcancel(); - - _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype); - - if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) { - status = write(g_usb_fd, mtp_buf, len); - if (status < 0) { - ERR("USB write fail : %d\n", errno); - if (errno == ENOMEM || errno == ECANCELED) { - status = 0; - __clean_up_msg_queue(mqid); - } - } - g_free(mtp_buf); - mtp_buf = NULL; - } else if (MTP_EVENT_PACKET == mtype) { - /* Handling the MTP Asynchronous Events */ - DBG("Send Interrupt data to kernel by IOCTL "); - status = ioctl(g_usb_fd, MTP_WRITE_INT_DATA, mtp_buf); - g_free(mtp_buf); - mtp_buf = NULL; - } else if (MTP_ZLP_PACKET == mtype) { - DBG("Send ZLP data to kernel by IOCTL "); - status = ioctl(g_usb_fd, MTP_SET_ZLP_DATA, NULL); - } else { - DBG("mtype = %d is not valid\n", mtype); - status = -1; - } - - if (status < 0) { - ERR("write data to the device node Fail:\ - status = %d\n", status); - break; - } - } while (status >= 0); - - DBG("exited Source thread with status %d\n", status); - pthread_cleanup_pop(1); - g_free(mtp_buf); - - return NULL; + return usb_driver->transport_thread_usb_write(arg); } void *_transport_thread_usb_read(void *arg) { - mtp_int32 status = 0; - msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL}; - msgq_id_t *mqid = (msgq_id_t *)arg; - mtp_uint32 rx_size = _get_rx_pkt_size(); - - pthread_cleanup_push(__clean_up_msg_queue, mqid); - - do { - pthread_testcancel(); - - pkt.buffer = (mtp_uchar *)g_malloc(rx_size); - if (NULL == pkt.buffer) { - ERR("Sink thread: memalloc Fail."); - break; - } - - status = read(g_usb_fd, pkt.buffer, rx_size); - if (status <= 0) { - status = __handle_usb_read_err(status, pkt.buffer, rx_size); - if (status <= 0) { - ERR("__handle_usb_read_err Fail"); - g_free(pkt.buffer); - break; - } - } - - pkt.length = status; - if (FALSE == _util_msgq_send(*mqid, (void *)&pkt, - sizeof(msgq_ptr_t) - sizeof(long), 0)) { - ERR("msgsnd Fail"); - g_free(pkt.buffer); - } - } while (status > 0); - - DBG("status[%d] errno[%d]\n", status, errno); - pthread_cleanup_pop(1); - - return NULL; -} - -static mtp_int32 __handle_usb_read_err(mtp_int32 err, - mtp_uchar *buf, mtp_int32 buf_len) -{ - mtp_int32 retry = 0; - mtp_bool ret; - - while (retry++ < MTP_USB_ERROR_MAX_RETRY) { - if (err == 0) { - DBG("ZLP(Zero Length Packet). Skip"); - } else if (err < 0 && errno == EINTR) { - DBG("read () is interrupted. Skip"); - } else if (err < 0 && errno == EIO) { - DBG("EIO"); - - if (MTP_PHONE_USB_CONNECTED != - _util_get_local_usb_status()) { - ERR("USB is disconnected"); - break; - } - - _transport_deinit_usb_device(); - ret = _transport_init_usb_device(); - if (ret == FALSE) { - ERR("_transport_init_usb_device Fail"); - continue; - } - } else { - ERR("Unknown error : %d, errno [%d] \n", err, errno); - break; - } - - err = read(g_usb_fd, buf, buf_len); - if (err > 0) - break; - } - - if (err <= 0) - ERR("USB error handling Fail"); - - return err; + return usb_driver->transport_thread_usb_read(arg); } -static void __clean_up_msg_queue(void *mq_id) +void *_transport_thread_usb_control(void *arg) { - mtp_int32 len = 0; - msgq_ptr_t pkt = { 0 }; - msgq_id_t l_mqid = *(msgq_id_t *)mq_id; - - ret_if(mq_id == NULL); - - _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION); - while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt, - sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) { - g_free(pkt.buffer); - memset(&pkt, 0, sizeof(msgq_ptr_t)); - } - - return; -} - -static void __handle_control_request(mtp_int32 request) -{ - static mtp_bool kernel_reset = FALSE; - static mtp_bool host_cancel = FALSE; - mtp_int32 status = 0; - - switch (request) { - case USB_PTPREQUEST_CANCELIO: - DBG("USB_PTPREQUEST_CANCELIO"); - cancel_req_t cancelreq_data; - mtp_byte buffer[USB_PTPREQUEST_CANCELIO_SIZE + 1] = { 0 }; - - host_cancel = TRUE; - _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION); - status = ioctl(g_usb_fd, MTP_GET_SETUP_DATA, buffer); - if (status < 0) { - ERR("IOCTL GET_SETUP_DATA Fail [%d]\n", status); - return; - } - - memcpy(&(cancelreq_data.io_code), buffer, sizeof(mtp_word)); - memcpy(&(cancelreq_data.tid), &buffer[2], sizeof(mtp_dword)); - DBG("cancel io code [%d], transaction id [%ld]\n", - cancelreq_data.io_code, cancelreq_data.tid); - break; - - case USB_PTPREQUEST_RESET: - - DBG("USB_PTPREQUEST_RESET"); - _reset_mtp_device(); - if (kernel_reset == FALSE) - kernel_reset = TRUE; - - status = ioctl(g_usb_fd, MTP_SEND_RESET_ACK, NULL); - if (status < 0) { - ERR("IOCTL MTP_SEND_RESET_ACK Fail [%d]\n", - status); - } - break; - - case USB_PTPREQUEST_GETSTATUS: - - DBG("USB_PTPREQUEST_GETSTATUS"); - - /* Send busy status response just once. This flag is also for - * the case that mtp misses the cancel request packet. - */ - static mtp_bool sent_busy = FALSE; - usb_status_req_t statusreq_data = { 0 }; - mtp_dword num_param = 0; - - memset(&statusreq_data, 0x00, sizeof(usb_status_req_t)); - if (host_cancel == TRUE || (sent_busy == FALSE && - kernel_reset == FALSE)) { - DBG("Send busy response, set host_cancel to FALSE"); - statusreq_data.len = 0x08; - statusreq_data.code = PTP_RESPONSE_DEVICEBUSY; - host_cancel = FALSE; - } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) { - statusreq_data.code = - PTP_RESPONSE_TRANSACTIONCANCELLED; - DBG("PTP_RESPONSE_TRANSACTIONCANCELLED"); - statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) + - (num_param - 2) * sizeof(mtp_dword)); - } else if (_device_get_status() == DEVICE_STATUSOK) { - DBG("PTP_RESPONSE_OK"); - statusreq_data.len = 0x08; - statusreq_data.code = PTP_RESPONSE_OK; - - if (kernel_reset == TRUE) - kernel_reset = FALSE; - } else { - DBG("PTP_RESPONSE_GEN_ERROR"); - statusreq_data.len = 0x08; - statusreq_data.code = PTP_RESPONSE_GEN_ERROR; - } - - if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY) - sent_busy = TRUE; - else - sent_busy = FALSE; - - status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data); - if (status < 0) { - DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n", - status); - return; - } - break; - - case USB_PTPREQUEST_GETEVENT: - DBG("USB_PTPREQUEST_GETEVENT"); - break; - - default: - DBG("Invalid class specific setup request"); - break; - } - return; -} - -static void __receive_signal(mtp_int32 n, siginfo_t *info, void *arg) -{ - mtp_int32 request = info->si_int; - - DBG("Received SIgnal From Kernel"); - __handle_control_request(request); - return; + return usb_driver->transport_thread_usb_control(arg); } /* @@ -425,43 +87,21 @@ static void __receive_signal(mtp_int32 n, siginfo_t *info, void *arg) */ mtp_bool _transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid) { - mtp_int32 res = TRUE; - - if (*rx_mqid) { - res = _util_msgq_deinit(rx_mqid); - if (res == FALSE) - ERR("rx_mqid deinit Fail [%d]\n", errno); - else - *rx_mqid = 0; - } - - if (*tx_mqid) { - res = _util_msgq_deinit(tx_mqid); - if (res == FALSE) - ERR("tx_mqid deinit fail [%d]\n", errno); - else - *tx_mqid = 0; - } - - return res; + return usb_driver->transport_mq_deinit(rx_mqid, tx_mqid); } mtp_uint32 _transport_get_usb_packet_len(void) { - mtp_int32 status = 0; - static mtp_int32 usb_speed = 0; - - if (usb_speed == 0) { + return usb_driver->transport_get_usb_packet_len(); +} - status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed); - if (status < 0) { - ERR("MTP_GET_HIGH_FULL_SPEED Fail [%d]\n", status); - return MTP_MAX_PACKET_SIZE_SEND_FS; - } - } +mtp_transport_type_t _transport_get_type(void) +{ + if (usb_driver == &mtp_usb_driver_slp) + return MTP_TRANSPORT_SLP; - if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS) - return MTP_MAX_PACKET_SIZE_SEND_FS; + if (usb_driver == &mtp_usb_driver_ffs) + return MTP_TRANSPORT_FFS; - return MTP_MAX_PACKET_SIZE_SEND_HS; + return MTP_TRANSPORT_UNKNOWN; } diff --git a/src/transport/mtp_usb_driver_ffs.c b/src/transport/mtp_usb_driver_ffs.c new file mode 100755 index 0000000..e972756 --- /dev/null +++ b/src/transport/mtp_usb_driver_ffs.c @@ -0,0 +1,784 @@ +/* -*- mode: C; c-file-style: "linux" -*- + * + * mtp-responder + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of + * SAMSUNG ELECTRONICS ("Confidential Information"). You agree and acknowledge + * that this software is owned by Samsung and you shall not disclose + * such Confidential Information and shall use it only in accordance with + * the terms of the license agreement you entered into with SAMSUNG ELECTRONICS. + * SAMSUNG make no representations or warranties about the suitability of + * the software, either express or implied, including but not limited to + * the implied warranties of merchantability, fitness for a particular purpose, + * or non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "mtp_usb_driver.h" +#include "mtp_device.h" +#include "ptp_datacodes.h" +#include "mtp_support.h" +#include "ptp_container.h" +#include "mtp_msgq.h" +#include "mtp_thread.h" +#include "mtp_transport.h" +#include "mtp_event_handler.h" +#include +#include +#include + +/* + * GLOBAL AND EXTERN VARIABLES + */ +extern mtp_config_t g_conf; + +/* + * STATIC VARIABLES AND FUNCTIONS + */ +#ifndef FUNCTIONFS_DESCRIPTORS_MAGIC_V2 +#define FUNCTIONFS_DESCRIPTORS_MAGIC_V2 3 +enum functionfs_flags { + FUNCTIONFS_HAS_FS_DESC = 1, + FUNCTIONFS_HAS_HS_DESC = 2, + FUNCTIONFS_HAS_SS_DESC = 4, + FUNCTIONFS_HAS_MS_OS_DESC = 8, +}; +#endif + +/*PIMA15740-2000 spec*/ +#define USB_PTPREQUEST_CANCELIO 0x64 /* Cancel request */ +#define USB_PTPREQUEST_GETEVENT 0x65 /* Get extened event data */ +#define USB_PTPREQUEST_RESET 0x66 /* Reset Device */ +#define USB_PTPREQUEST_GETSTATUS 0x67 /* Get Device Status */ +#define USB_PTPREQUEST_CANCELIO_SIZE 6 +#define USB_PTPREQUEST_GETSTATUS_SIZE 12 + +#define cpu_to_le16(x) htole16(x) +#define cpu_to_le32(x) htole32(x) +#define le32_to_cpu(x) le32toh(x) +#define le16_to_cpu(x) le16toh(x) + +static const struct { + struct { + __le32 magic; + __le32 length; + __le32 flags; + __le32 fs_count; + __le32 hs_count; + // __le32 os_count; + } header; + struct { + struct usb_interface_descriptor intf; + struct usb_endpoint_descriptor_no_audio bulk_in; + struct usb_endpoint_descriptor_no_audio bulk_out; + struct usb_endpoint_descriptor_no_audio int_in; + } __attribute__((packed)) fs_descs, hs_descs; + // struct {} __attribute__((packed)) os_descs; +} __attribute__((packed)) descriptors = { + .header = { + .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), + .length = cpu_to_le32(sizeof(descriptors)), + .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC, // | FUNCTIONFS_HAS_MS_OS_DESC, + .fs_count = 4, + .hs_count = 4, + // .os_count = 0; + }, + .fs_descs = { + // drivers/usb/gadget/f_mtp_slp.c:207 + .intf = { + .bLength = sizeof(descriptors.fs_descs.intf), + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 1, + }, + .bulk_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(64), + }, + .bulk_out = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(64), + }, + .int_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 3 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(64), + .bInterval = 6, + }, + }, + .hs_descs = { + .intf = { + .bLength = sizeof(descriptors.fs_descs.intf), + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 1, + }, + .bulk_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), + }, + .bulk_out = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), + }, + .int_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 3 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(64), + .bInterval = 6, + }, + }, +}; + +#define STR_INTERFACE "Samsung MTP" + +static const struct { + struct usb_functionfs_strings_head header; + struct { + __le16 code; + const char str1[sizeof(STR_INTERFACE)]; + } __attribute__((packed)) lang0; +} __attribute__((packed)) strings = { + .header = { + .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), + .length = cpu_to_le32(sizeof(strings)), + .str_count = cpu_to_le32(1), + .lang_count = cpu_to_le32(1), + }, + .lang0 = { + cpu_to_le16(0x0409), /* en-us */ + STR_INTERFACE, + }, +}; + +static mtp_int32 g_usb_ep0 = -1; /* read (g_usb_ep0, ...) */ +static mtp_int32 g_usb_ep_in = -1; /* write (g_usb_ep_in, ...) */ +static mtp_int32 g_usb_ep_out = -1; /* read (g_usb_ep_out, ...) */ +static mtp_int32 g_usb_ep_status = -1; /* write (g_usb_ep_status, ...) */ + +static mtp_max_pkt_size_t pkt_size; +static mtp_uint32 rx_mq_sz; +static mtp_uint32 tx_mq_sz; +static mtp_int32 __handle_usb_read_err(mtp_int32 err, + mtp_uchar *buf, mtp_int32 buf_len); +static void __clean_up_msg_queue(void *param); +static void __handle_control_request(mtp_int32 request); + +/* + * FUNCTIONS + */ + +static mtp_bool __io_init() +{ + int ret; + + g_usb_ep0 = open(MTP_EP0_PATH, O_RDWR); + if (g_usb_ep0 < 0) + goto out; + + DBG("Writing USB descriptors"); + ret = write(g_usb_ep0, &descriptors, sizeof(descriptors)); + if (ret < 0) { + ERR("Error writing descriptors"); + goto cleanup; + } + + DBG("Writing USB strings"); + ret = write(g_usb_ep0, &strings, sizeof(strings)); + if (ret < 0) { + ERR("Error writing strings"); + goto cleanup; + } + + g_usb_ep_in = open(MTP_EP_IN_PATH, O_RDWR); + if (g_usb_ep_in < 0) { + ERR("Error opening bulk-in"); + goto cleanup; + } + + g_usb_ep_out = open(MTP_EP_OUT_PATH, O_RDWR); + if (g_usb_ep_out < 0) { + ERR("Error opening bulk-out"); + goto cleanup_in; + } + + g_usb_ep_status = open(MTP_EP_STATUS_PATH, O_RDWR); + if (g_usb_ep_status < 0) { + ERR("Error opening status"); + goto cleanup_out; + } + + return TRUE; + +cleanup_out: + close(g_usb_ep_out); +cleanup_in: + close(g_usb_ep_in); +cleanup: + close(g_usb_ep0); +out: + return FALSE; +} + +static mtp_bool ffs_transport_init_usb_device(void) +{ + mtp_int32 status = 0; + int msg_size; + + if (g_usb_ep0 > 0) { + DBG("Device Already open\n"); + return TRUE; + } + + status = __io_init(); + if (!status) { + char error[256]; + ERR("Device node [%s] open failed, errno [%s]\n", + MTP_EP0_PATH, strerror_r(errno, error, sizeof(error))); + return FALSE; + } + + pkt_size.rx = g_conf.read_usb_size; + pkt_size.tx = g_conf.write_usb_size; + + DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx); + + msg_size = sizeof(msgq_ptr_t) - sizeof(long); + rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size; + tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size; + + DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz); + + return TRUE; +} + +static void ffs_transport_deinit_usb_device(void) +{ + if (g_usb_ep0 >= 0) + close(g_usb_ep0); + g_usb_ep0 = -1; + + if (g_usb_ep_in >= 0) + close(g_usb_ep_in); + g_usb_ep_in = -1; + + if (g_usb_ep_out >= 0) + close(g_usb_ep_out); + g_usb_ep_out = -1; + + if (g_usb_ep_status >= 0) + close(g_usb_ep_status); + g_usb_ep_status = -1; + + return; +} + +static mtp_uint32 ffs_get_tx_pkt_size(void) +{ + return pkt_size.tx; +} + +static mtp_uint32 ffs_get_rx_pkt_size(void) +{ + return pkt_size.rx; +} + +/* + * static mtp_int32 ffs_transport_mq_init() + * This function create a message queue for MTP, + * A created message queue will be used to help data transfer between + * MTP module and usb buffer. + * @return This function returns TRUE on success or + * returns FALSE on failure. + */ +static mtp_int32 ffs_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid) +{ + if (_util_msgq_init(rx_mqid, 0) == FALSE) { + ERR("RX MQ init Fail [%d]\n", errno); + return FALSE; + } + + if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE) + ERR("RX MQ setting size Fail [%d]\n", errno); + + if (_util_msgq_init(tx_mqid, 0) == FALSE) { + ERR("TX MQ init Fail [%d]\n", errno); + _util_msgq_deinit(rx_mqid); + *rx_mqid = -1; + return FALSE; + } + + if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE) + ERR("TX MQ setting size Fail [%d]\n", errno); + + return TRUE; +} + +static void *ffs_transport_thread_usb_write(void *arg) +{ + mtp_int32 status = 0; + mtp_uint32 len = 0; + unsigned char *mtp_buf = NULL; + msg_type_t mtype = MTP_UNDEFINED_PACKET; + msgq_id_t *mqid = (msgq_id_t *)arg; + + pthread_cleanup_push(__clean_up_msg_queue, mqid); + + do { + /* original LinuxThreads cancelation didn't work right + * so test for it explicitly. + */ + pthread_testcancel(); + + _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype); + + if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) { + status = write(g_usb_ep_in, mtp_buf, len); + if (status < 0) { + ERR("USB write fail : %d\n", errno); + if (errno == ENOMEM || errno == ECANCELED) { + status = 0; + __clean_up_msg_queue(mqid); + } + } + g_free(mtp_buf); + mtp_buf = NULL; + } else if (MTP_EVENT_PACKET == mtype) { + /* Handling the MTP Asynchronous Events */ + DBG("Send Interrupt data to kernel via g_usb_ep_status\n"); + status = write(g_usb_ep_status, mtp_buf, len); + g_free(mtp_buf); + mtp_buf = NULL; + } else if (MTP_ZLP_PACKET == mtype) { + DBG("Send ZLP data to kerne via g_usb_ep_in\n"); + status = write(g_usb_ep_in, (void*)0xFEE1DEAD, 0); + } else { + DBG("mtype = %d is not valid\n", mtype); + status = -1; + } + + if (status < 0) { + ERR("write data to the device node Fail:\ + status = %d\n", status); + break; + } + } while (status >= 0); + + DBG("exited Source thread with status %d\n", status); + pthread_cleanup_pop(1); + g_free(mtp_buf); + + return NULL; +} + +static int __setup(int ep0, struct usb_ctrlrequest *ctrl) +{ + const char* requests[] = { + "CANCELIO", /* 0x64 */ + "GETEVENT", /* 0x65 */ + "RESET", /* 0x66 */ + "GETSTATUS", /* 0x67 */ + }; + __u16 wIndex = le16_to_cpu(ctrl->wIndex); + __u16 wValue = le16_to_cpu(ctrl->wValue); + __u16 wLength = le16_to_cpu(ctrl->wLength); + int rc = -EOPNOTSUPP; + int status = 0; + + if ((ctrl->bRequestType & 0x7f) != (USB_TYPE_CLASS | USB_RECIP_INTERFACE)) { + DBG(__FILE__ "(%s):%d: Invalid request type: %d", + __func__, __LINE__, ctrl->bRequestType); + goto stall; + } + + switch (((ctrl->bRequestType & 0x80) << 8) | ctrl->bRequest) { + case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_CANCELIO): + + DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s", + __func__, __LINE__, requests[ctrl->bRequest-0x64]); + if (wValue != 0 || wIndex != 0 || wLength != 6) { + DBG("Invalid request parameters: wValue:%d wIndex:%d wLength:%d\n"); + rc = -EINVAL; + goto stall; + } + __handle_control_request(ctrl->bRequest); + break; + + case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETSTATUS): + case ((USB_DIR_OUT << 8) | USB_PTPREQUEST_RESET): + + DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s", + __func__, __LINE__, requests[ctrl->bRequest-0x64]); + __handle_control_request(ctrl->bRequest); + break; + + case ((USB_DIR_IN << 8) | USB_PTPREQUEST_GETEVENT): + + /* Optional, may stall */ + DBG(__FILE__ "(%s):%d: USB_PTPREQUEST_%s", + __func__, __LINE__, requests[ctrl->bRequest-0x64]); + rc = -EOPNOTSUPP; + goto stall; + break; + + default: + DBG(__FILE__ "(%s):%d: Invalid request: %d", __func__, + __LINE__, ctrl->bRequest); + goto stall; + } + return 0; + +stall: + + DBG(__FILE__"(%s):%d:stall %0x2x.%02x\n", + __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest); + if ((ctrl->bRequestType & 0x80) == USB_DIR_IN) + status = read(g_usb_ep0, NULL, 0); + else + status = write(g_usb_ep0, NULL, 0); + + if (status != -1 || errno != EL2HLT) { + ERR(__FILE__"(%s):%d:stall error\n", + __func__, __LINE__, ctrl->bRequestType, ctrl->bRequest); + rc = errno; + } + return rc; +} + +static void *ffs_transport_thread_usb_read(void *arg) +{ + mtp_int32 status = 0; + msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL}; + msgq_id_t *mqid = (msgq_id_t *)arg; + mtp_uint32 rx_size = _get_rx_pkt_size(); + + pthread_cleanup_push(__clean_up_msg_queue, mqid); + + do { + pthread_testcancel(); + + pkt.buffer = (mtp_uchar *)g_malloc(rx_size); + if (NULL == pkt.buffer) { + ERR("Sink thread: memalloc failed.\n"); + break; + } + + status = read(g_usb_ep_out, pkt.buffer, rx_size); + if (status <= 0) { + status = __handle_usb_read_err(status, pkt.buffer, rx_size); + if (status <= 0) { + ERR("__handle_usb_read_err is failed\n"); + g_free(pkt.buffer); + break; + } + } + + pkt.length = status; + if (FALSE == _util_msgq_send(*mqid, (void *)&pkt, + sizeof(msgq_ptr_t) - sizeof(long), 0)) { + ERR("msgsnd Fail"); + g_free(pkt.buffer); + } + } while (status > 0); + + DBG("status[%d] errno[%d]\n", status, errno); + pthread_cleanup_pop(1); + + return NULL; +} + +static void *ffs_transport_thread_usb_control(void *arg) +{ + mtp_int32 status = 0; + struct usb_functionfs_event event; + msgq_id_t *mqid = (msgq_id_t *)arg; + + pthread_cleanup_push(__clean_up_msg_queue, mqid); + + do { + pthread_testcancel(); + + status = read(g_usb_ep0, &event, sizeof(event)); + if (status < 0) { + char error[256]; + ERR("read from ep0 failed: %s", + strerror_r(errno, error, sizeof(error))); + continue; + } + DBG("FUNCTIONFS event received: %d", event.type); + + switch (event.type) { + case FUNCTIONFS_SETUP: + DBG("SETUP: bmRequestType:%d bRequest:%d wValue:%d wIndex:%d wLength:%d\n", + event.u.setup.bRequestType, + event.u.setup.bRequest, + event.u.setup.wValue, + event.u.setup.wIndex, + event.u.setup.wLength); + __setup(g_usb_ep0, &event.u.setup); + break; + } + } while (status > 0); + + DBG("status[%d] errno[%d]\n", status, errno); + pthread_cleanup_pop(1); + + return NULL; +} + +static mtp_int32 __handle_usb_read_err(mtp_int32 err, + mtp_uchar *buf, mtp_int32 buf_len) +{ + mtp_int32 retry = 0; + mtp_bool ret; + + while (retry++ < MTP_USB_ERROR_MAX_RETRY) { + if (err == 0) { + DBG("ZLP(Zero Length Packet). Skip"); + } else if (err < 0 && errno == EINTR) { + DBG("read () is interrupted. Skip"); + } else if (err < 0 && errno == EIO) { + DBG("EIO"); + + if (MTP_PHONE_USB_CONNECTED != + _util_get_local_usb_status()) { + ERR("USB is disconnected"); + break; + } + + _transport_deinit_usb_device(); + ret = _transport_init_usb_device(); + if (ret == FALSE) { + ERR("_transport_init_usb_device Fail"); + continue; + } + } else { + ERR("Unknown error : %d, errno [%d] \n", err, errno); + break; + } + + err = read(g_usb_ep_out, buf, buf_len); + if (err > 0) + break; + } + + if (err <= 0) + ERR("USB error handling Fail"); + + return err; +} + +static void __clean_up_msg_queue(void *mq_id) +{ + mtp_int32 len = 0; + msgq_ptr_t pkt = { 0 }; + msgq_id_t l_mqid = *(msgq_id_t *)mq_id; + + ret_if(mq_id == NULL); + + _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION); + while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt, + sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) { + g_free(pkt.buffer); + memset(&pkt, 0, sizeof(msgq_ptr_t)); + } + + return; +} + +static void __handle_control_request(mtp_int32 request) +{ + static mtp_bool kernel_reset = FALSE; + static mtp_bool host_cancel = FALSE; + mtp_int32 status = 0; + + switch (request) { + case USB_PTPREQUEST_CANCELIO: + // XXX: Convert cancel request data from little-endian + // before use: le32_to_cpu(x), le16_to_cpu(x). + DBG("USB_PTPREQUEST_CANCELIO\n"); + cancel_req_t cancelreq_data; + + host_cancel = TRUE; + _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION); + status = read(g_usb_ep0, &cancelreq_data, sizeof(cancelreq_data)); + if (status < 0) { + char error[256]; + ERR("Failed to read data for CANCELIO request\n: %s", + strerror_r(errno, error, sizeof(error))); + } + break; + + case USB_PTPREQUEST_RESET: + + DBG("USB_PTPREQUEST_RESET\n"); + _reset_mtp_device(); + if (kernel_reset == FALSE) { + kernel_reset = TRUE; + } + + status = read(g_usb_ep0, NULL, 0); + if (status < 0) { + ERR("IOCTL MTP_SEND_RESET_ACK Failed [%d]\n", + status); + } + break; + case USB_PTPREQUEST_GETSTATUS: + + DBG("USB_PTPREQUEST_GETSTATUS"); + + /* Send busy status response just once. This flag is also for + * the case that mtp misses the cancel request packet. + */ + static mtp_bool sent_busy = FALSE; + usb_status_req_t statusreq_data = { 0 }; + mtp_dword num_param = 0; + + memset(&statusreq_data, 0x00, sizeof(usb_status_req_t)); + if (host_cancel == TRUE || (sent_busy == FALSE && + kernel_reset == FALSE)) { + DBG("Send busy response, set host_cancel to FALSE"); + statusreq_data.len = 0x08; + statusreq_data.code = PTP_RESPONSE_DEVICEBUSY; + host_cancel = FALSE; + } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) { + statusreq_data.code = + PTP_RESPONSE_TRANSACTIONCANCELLED; + DBG("PTP_RESPONSE_TRANSACTIONCANCELLED"); + statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) + + (num_param - 2) * sizeof(mtp_dword)); + } else if (_device_get_status() == DEVICE_STATUSOK) { + DBG("PTP_RESPONSE_OK"); + statusreq_data.len = 0x08; + statusreq_data.code = PTP_RESPONSE_OK; + + if (kernel_reset == TRUE) + kernel_reset = FALSE; + } else { + DBG("PTP_RESPONSE_GEN_ERROR"); + statusreq_data.len = 0x08; + statusreq_data.code = PTP_RESPONSE_GEN_ERROR; + } + + if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY) { + sent_busy = TRUE; + } else { + sent_busy = FALSE; + } + + /* status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data); + if (status < 0) { + DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n", + status); + return; + } */ + + break; + + case USB_PTPREQUEST_GETEVENT: + DBG("USB_PTPREQUEST_GETEVENT"); + break; + + default: + DBG("Invalid class specific setup request"); + break; + } + return; +} + +/* + * mtp_bool ffs_transport_mq_deinit() + * This function destroy a message queue for MTP, + * @return This function returns TRUE on success or + * returns FALSE on failure. + */ +static mtp_bool ffs_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid) +{ + mtp_int32 res = TRUE; + + if (*rx_mqid) { + res = _util_msgq_deinit(rx_mqid); + if (res == FALSE) { + ERR("rx_mqid deinit Fail [%d]\n", errno); + } else { + *rx_mqid = 0; + } + } + + if (*tx_mqid) { + res = _util_msgq_deinit(tx_mqid); + if (res == FALSE) { + ERR("tx_mqid deinit fail [%d]\n", errno); + } else { + *tx_mqid = 0; + } + } + + return res; +} + +static mtp_uint32 ffs_transport_get_usb_packet_len(void) +{ + mtp_int32 status = -1; + static mtp_int32 usb_speed = 0; + + if (usb_speed == 0) { + + //status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed); + if (status < 0) { + ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status); + return MTP_MAX_PACKET_SIZE_SEND_FS; + } + } + + if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS) { + return MTP_MAX_PACKET_SIZE_SEND_FS; + } + + return MTP_MAX_PACKET_SIZE_SEND_HS; +} + + +const mtp_usb_driver_t mtp_usb_driver_ffs = { + .transport_init_usb_device = ffs_transport_init_usb_device, + .transport_deinit_usb_device = ffs_transport_deinit_usb_device, + .transport_thread_usb_write = ffs_transport_thread_usb_write, + .transport_thread_usb_read = ffs_transport_thread_usb_read, + .transport_thread_usb_control = ffs_transport_thread_usb_control, + .transport_mq_init = ffs_transport_mq_init, + .transport_mq_deinit = ffs_transport_mq_deinit, + .transport_get_usb_packet_len = ffs_transport_get_usb_packet_len, + .get_tx_pkt_size = ffs_get_tx_pkt_size, + .get_rx_pkt_size = ffs_get_rx_pkt_size, +}; diff --git a/src/transport/mtp_usb_driver_slp.c b/src/transport/mtp_usb_driver_slp.c new file mode 100644 index 0000000..79f07b0 --- /dev/null +++ b/src/transport/mtp_usb_driver_slp.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "mtp_usb_driver.h" +#include "mtp_device.h" +#include "ptp_datacodes.h" +#include "mtp_support.h" +#include "ptp_container.h" +#include "mtp_msgq.h" +#include "mtp_thread.h" +#include "mtp_transport.h" +#include "mtp_event_handler.h" +#include + +/* + * GLOBAL AND EXTERN VARIABLES + */ +extern mtp_config_t g_conf; + +/* + * STATIC VARIABLES AND FUNCTIONS + */ +static mtp_int32 g_usb_fd = -1; +static mtp_max_pkt_size_t pkt_size; +static mtp_uint32 rx_mq_sz; +static mtp_uint32 tx_mq_sz; + +static mtp_int32 __handle_usb_read_err(mtp_int32 err, + mtp_uchar *buf, mtp_int32 buf_len); +static void __clean_up_msg_queue(void *pmsqid); +static void __handle_control_request(mtp_int32 request); +static void __receive_signal(mtp_int32 n, siginfo_t *info, void *unused); + +/* + * FUNCTIONS + */ +static mtp_bool slp_transport_init_usb_device(void) +{ + mtp_int32 status = 0; + struct sigaction sig; + pid_t mtp_pid = 0; + int msg_size; + + /* Kernel will inform to User Space using signal. */ + memset(&sig, 0, sizeof(sig)); + sig.sa_sigaction = __receive_signal; + sig.sa_flags = SA_SIGINFO; + sigaction(SIG_SETUP, &sig, NULL); + + if (g_usb_fd > 0) { + DBG("Device Already open\n"); + return TRUE; + } + + g_usb_fd = open(MTP_DRIVER_PATH, O_RDWR); + if (g_usb_fd < 0) { + ERR("Device node [%s] open failed,errno [%d]\n", MTP_DRIVER_PATH, errno); + return FALSE; + } + + mtp_pid = getpid(); + status = ioctl(g_usb_fd, MTP_SET_USER_PID, &mtp_pid); + if (status < 0) { + ERR("IOCTL MTP_SET_USER_PID failed = [%d]\n", status); + _transport_deinit_usb_device(); + return FALSE; + } + + pkt_size.rx = g_conf.read_usb_size; + pkt_size.tx = g_conf.write_usb_size; + + DBG("Final : Tx pkt size:[%u], Rx pkt size:[%u]\n", pkt_size.tx, pkt_size.rx); + + msg_size = sizeof(msgq_ptr_t) - sizeof(long); + rx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_rx_ipc_size) * msg_size; + tx_mq_sz = (g_conf.max_io_buf_size / g_conf.max_tx_ipc_size) * msg_size; + + DBG("RX MQ size :[%u], TX MQ size:[%u]\n", rx_mq_sz, tx_mq_sz); + + return TRUE; +} + +static void slp_transport_deinit_usb_device(void) +{ + if (g_usb_fd >= 0) + close(g_usb_fd); + g_usb_fd = -1; + + return; +} + +static mtp_uint32 slp_get_tx_pkt_size(void) +{ + return pkt_size.tx; +} + +static mtp_uint32 slp_get_rx_pkt_size(void) +{ + return pkt_size.rx; +} + +/* + * static mtp_int32 slp_transport_mq_init() + * This function create a message queue for MTP, + * A created message queue will be used to help data transfer between + * MTP module and usb buffer. + * @return This function returns TRUE on success or + * returns FALSE on failure. + */ +static mtp_int32 slp_transport_mq_init(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid) +{ + if (_util_msgq_init(rx_mqid, 0) == FALSE) { + ERR("RX MQ init Fail [%d]\n", errno); + return FALSE; + } + + if (_util_msgq_set_size(*rx_mqid, rx_mq_sz) == FALSE) + ERR("RX MQ setting size Fail [%d]\n", errno); + + if (_util_msgq_init(tx_mqid, 0) == FALSE) { + ERR("TX MQ init Fail [%d]\n", errno); + _util_msgq_deinit(rx_mqid); + *rx_mqid = -1; + return FALSE; + } + + if (_util_msgq_set_size(*tx_mqid, tx_mq_sz) == FALSE) + ERR("TX MQ setting size Fail [%d]\n", errno); + + return TRUE; +} + +static void *slp_transport_thread_usb_write(void *arg) +{ + mtp_int32 status = 0; + mtp_uint32 len = 0; + unsigned char *mtp_buf = NULL; + msg_type_t mtype = MTP_UNDEFINED_PACKET; + msgq_id_t *mqid = (msgq_id_t *)arg; + + pthread_cleanup_push(__clean_up_msg_queue, mqid); + + do { + /* original LinuxThreads cancelation didn't work right + * so test for it explicitly. + */ + pthread_testcancel(); + + _util_rcv_msg_from_mq(*mqid, &mtp_buf, &len, &mtype); + + if (mtype == MTP_BULK_PACKET || mtype == MTP_DATA_PACKET) { + status = write(g_usb_fd, mtp_buf, len); + if (status < 0) { + ERR("USB write fail : %d\n", errno); + if (errno == ENOMEM || errno == ECANCELED) { + status = 0; + __clean_up_msg_queue(mqid); + } + } + g_free(mtp_buf); + mtp_buf = NULL; + } else if (MTP_EVENT_PACKET == mtype) { + /* Handling the MTP Asynchronous Events */ + DBG("Send Interrupt data to kernel by IOCTL "); + status = ioctl(g_usb_fd, MTP_WRITE_INT_DATA, mtp_buf); + g_free(mtp_buf); + mtp_buf = NULL; + } else if (MTP_ZLP_PACKET == mtype) { + DBG("Send ZLP data to kernel by IOCTL "); + status = ioctl(g_usb_fd, MTP_SET_ZLP_DATA, NULL); + } else { + DBG("mtype = %d is not valid\n", mtype); + status = -1; + } + + if (status < 0) { + ERR("write data to the device node Fail:\ + status = %d\n", status); + break; + } + } while (status >= 0); + + DBG("exited Source thread with status %d\n", status); + pthread_cleanup_pop(1); + g_free(mtp_buf); + + return NULL; +} + +static void *slp_transport_thread_usb_read(void *arg) +{ + mtp_int32 status = 0; + msgq_ptr_t pkt = {MTP_DATA_PACKET, 0, 0, NULL}; + msgq_id_t *mqid = (msgq_id_t *)arg; + mtp_uint32 rx_size = _get_rx_pkt_size(); + + pthread_cleanup_push(__clean_up_msg_queue, mqid); + + do { + pthread_testcancel(); + + pkt.buffer = (mtp_uchar *)g_malloc(rx_size); + if (NULL == pkt.buffer) { + ERR("Sink thread: memalloc Fail."); + break; + } + + status = read(g_usb_fd, pkt.buffer, rx_size); + if (status <= 0) { + status = __handle_usb_read_err(status, pkt.buffer, rx_size); + if (status <= 0) { + ERR("__handle_usb_read_err Fail"); + g_free(pkt.buffer); + break; + } + } + + pkt.length = status; + if (FALSE == _util_msgq_send(*mqid, (void *)&pkt, + sizeof(msgq_ptr_t) - sizeof(long), 0)) { + ERR("msgsnd Fail"); + g_free(pkt.buffer); + } + } while (status > 0); + + DBG("status[%d] errno[%d]\n", status, errno); + pthread_cleanup_pop(1); + + return NULL; +} + +static mtp_int32 __handle_usb_read_err(mtp_int32 err, + mtp_uchar *buf, mtp_int32 buf_len) +{ + mtp_int32 retry = 0; + mtp_bool ret; + + while (retry++ < MTP_USB_ERROR_MAX_RETRY) { + if (err == 0) { + DBG("ZLP(Zero Length Packet). Skip"); + } else if (err < 0 && errno == EINTR) { + DBG("read () is interrupted. Skip"); + } else if (err < 0 && errno == EIO) { + DBG("EIO"); + + if (MTP_PHONE_USB_CONNECTED != + _util_get_local_usb_status()) { + ERR("USB is disconnected"); + break; + } + + _transport_deinit_usb_device(); + ret = _transport_init_usb_device(); + if (ret == FALSE) { + ERR("_transport_init_usb_device Fail"); + continue; + } + } else { + ERR("Unknown error : %d, errno [%d] \n", err, errno); + break; + } + + err = read(g_usb_fd, buf, buf_len); + if (err > 0) + break; + } + + if (err <= 0) + ERR("USB error handling Fail"); + + return err; +} + +static void __clean_up_msg_queue(void *mq_id) +{ + mtp_int32 len = 0; + msgq_ptr_t pkt = { 0 }; + msgq_id_t l_mqid = *(msgq_id_t *)mq_id; + + ret_if(mq_id == NULL); + + _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION); + while (TRUE == _util_msgq_receive(l_mqid, (void *)&pkt, + sizeof(msgq_ptr_t) - sizeof(long), 1, &len)) { + g_free(pkt.buffer); + memset(&pkt, 0, sizeof(msgq_ptr_t)); + } + + return; +} + +static void __handle_control_request(mtp_int32 request) +{ + static mtp_bool kernel_reset = FALSE; + static mtp_bool host_cancel = FALSE; + mtp_int32 status = 0; + + switch (request) { + case USB_PTPREQUEST_CANCELIO: + DBG("USB_PTPREQUEST_CANCELIO"); + cancel_req_t cancelreq_data; + mtp_byte buffer[USB_PTPREQUEST_CANCELIO_SIZE + 1] = { 0 }; + + host_cancel = TRUE; + _transport_set_control_event(PTP_EVENTCODE_CANCELTRANSACTION); + status = ioctl(g_usb_fd, MTP_GET_SETUP_DATA, buffer); + if (status < 0) { + ERR("IOCTL GET_SETUP_DATA Fail [%d]\n", status); + return; + } + + memcpy(&(cancelreq_data.io_code), buffer, sizeof(mtp_word)); + memcpy(&(cancelreq_data.tid), &buffer[2], sizeof(mtp_dword)); + DBG("cancel io code [%d], transaction id [%ld]\n", + cancelreq_data.io_code, cancelreq_data.tid); + break; + + case USB_PTPREQUEST_RESET: + + DBG("USB_PTPREQUEST_RESET"); + _reset_mtp_device(); + if (kernel_reset == FALSE) + kernel_reset = TRUE; + + status = ioctl(g_usb_fd, MTP_SEND_RESET_ACK, NULL); + if (status < 0) { + ERR("IOCTL MTP_SEND_RESET_ACK Fail [%d]\n", + status); + } + break; + + case USB_PTPREQUEST_GETSTATUS: + + DBG("USB_PTPREQUEST_GETSTATUS"); + + /* Send busy status response just once. This flag is also for + * the case that mtp misses the cancel request packet. + */ + static mtp_bool sent_busy = FALSE; + usb_status_req_t statusreq_data = { 0 }; + mtp_dword num_param = 0; + + memset(&statusreq_data, 0x00, sizeof(usb_status_req_t)); + if (host_cancel == TRUE || (sent_busy == FALSE && + kernel_reset == FALSE)) { + DBG("Send busy response, set host_cancel to FALSE"); + statusreq_data.len = 0x08; + statusreq_data.code = PTP_RESPONSE_DEVICEBUSY; + host_cancel = FALSE; + } else if (_device_get_phase() == DEVICE_PHASE_NOTREADY) { + statusreq_data.code = + PTP_RESPONSE_TRANSACTIONCANCELLED; + DBG("PTP_RESPONSE_TRANSACTIONCANCELLED"); + statusreq_data.len = (mtp_word)(sizeof(usb_status_req_t) + + (num_param - 2) * sizeof(mtp_dword)); + } else if (_device_get_status() == DEVICE_STATUSOK) { + DBG("PTP_RESPONSE_OK"); + statusreq_data.len = 0x08; + statusreq_data.code = PTP_RESPONSE_OK; + + if (kernel_reset == TRUE) + kernel_reset = FALSE; + } else { + DBG("PTP_RESPONSE_GEN_ERROR"); + statusreq_data.len = 0x08; + statusreq_data.code = PTP_RESPONSE_GEN_ERROR; + } + + if (statusreq_data.code == PTP_RESPONSE_DEVICEBUSY) + sent_busy = TRUE; + else + sent_busy = FALSE; + + status = ioctl(g_usb_fd, MTP_SET_SETUP_DATA, &statusreq_data); + if (status < 0) { + DBG("IOCTL MTP_SET_SETUP_DATA Fail [%d]\n", + status); + return; + } + break; + + case USB_PTPREQUEST_GETEVENT: + DBG("USB_PTPREQUEST_GETEVENT"); + break; + + default: + DBG("Invalid class specific setup request"); + break; + } + return; +} + +static void __receive_signal(mtp_int32 n, siginfo_t *info, void *arg) +{ + mtp_int32 request = info->si_int; + + DBG("Received SIgnal From Kernel\n"); + __handle_control_request(request); + return; +} + +/* + * mtp_bool slp_transport_mq_deinit() + * This function destroy a message queue for MTP, + * @return This function returns TRUE on success or + * returns FALSE on failure. + */ +static mtp_bool slp_transport_mq_deinit(msgq_id_t *rx_mqid, msgq_id_t *tx_mqid) +{ + mtp_int32 res = TRUE; + + if (*rx_mqid) { + res = _util_msgq_deinit(rx_mqid); + if (res == FALSE) + ERR("rx_mqid deinit Fail [%d]\n", errno); + else + *rx_mqid = 0; + } + + if (*tx_mqid) { + res = _util_msgq_deinit(tx_mqid); + if (res == FALSE) { + ERR("tx_mqid deinit fail [%d]\n", errno); + } else { + *tx_mqid = 0; + } + } + + return res; +} + +static mtp_uint32 slp_transport_get_usb_packet_len(void) +{ + mtp_int32 status = 0; + static mtp_int32 usb_speed = 0; + + if (usb_speed == 0) { + + status = ioctl(g_usb_fd, MTP_GET_HIGH_FULL_SPEED, &usb_speed); + if (status < 0) { + ERR("MTP_GET_HIGH_FULL_SPEED Failed [%d]\n", status); + return MTP_MAX_PACKET_SIZE_SEND_FS; + } + } + + if (usb_speed % MTP_MAX_PACKET_SIZE_SEND_HS) + return MTP_MAX_PACKET_SIZE_SEND_FS; + + return MTP_MAX_PACKET_SIZE_SEND_HS; +} + + +const mtp_usb_driver_t mtp_usb_driver_slp = { + .transport_init_usb_device = slp_transport_init_usb_device, + .transport_deinit_usb_device = slp_transport_deinit_usb_device, + .transport_thread_usb_write = slp_transport_thread_usb_write, + .transport_thread_usb_read = slp_transport_thread_usb_read, + .transport_thread_usb_control = NULL, + .transport_mq_init = slp_transport_mq_init, + .transport_mq_deinit = slp_transport_mq_deinit, + .transport_get_usb_packet_len = slp_transport_get_usb_packet_len, + .get_tx_pkt_size = slp_get_tx_pkt_size, + .get_rx_pkt_size = slp_get_rx_pkt_size, +}; -- 2.7.4 From d0a595500968bd7d1b0b7e3a7a271646d8effc89 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Szewczyk?= Date: Thu, 8 Feb 2018 14:33:19 +0100 Subject: [PATCH 15/16] Use systemd functionfs socket activation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This includes creating binary files with descriptors and strings at compile time and systemd configuration of ffs socket. Change-Id: Ib38dc151e5e5d047ddb873661505ca13ddfc3306 Signed-off-by: Paweł Szewczyk --- CMakeLists.txt | 12 ++- include/transport/mtp_descs_strings.h | 62 +++++++++++++ mtp-responder.service | 2 + mtp-responder.socket | 6 ++ packaging/mtp-responder.spec | 5 + src/extract_descs/mtp_extract_descs_strs.c | 55 +++++++++++ src/transport/mtp_descs_strings.c | 108 ++++++++++++++++++++++ src/transport/mtp_usb_driver.c | 3 +- src/transport/mtp_usb_driver_ffs.c | 142 +++-------------------------- 9 files changed, 262 insertions(+), 133 deletions(-) create mode 100644 include/transport/mtp_descs_strings.h create mode 100755 mtp-responder.socket create mode 100644 src/extract_descs/mtp_extract_descs_strs.c create mode 100644 src/transport/mtp_descs_strings.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f2ce402..2b384e2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src/util SRCS) INCLUDE(FindPkgConfig) pkg_check_modules(pkgs REQUIRED glib-2.0 capi-content-media-content - capi-media-metadata-extractor vconf dlog tapi capi-system-info storage libsystemd-daemon) + capi-media-metadata-extractor vconf dlog tapi capi-system-info storage libsystemd-daemon libsystemd) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -30,3 +30,13 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} pthread rt gcrypt) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) INSTALL(FILES mtp-responder.conf DESTINATION /opt/var/lib/misc) + +ADD_EXECUTABLE(extract_descs_strs ${CMAKE_SOURCE_DIR}/src/extract_descs/mtp_extract_descs_strs.c + ${CMAKE_SOURCE_DIR}/src/transport/mtp_descs_strings.c) +ADD_CUSTOM_COMMAND(OUTPUT descs strs + COMMAND ./extract_descs_strs + DEPENDS extract_descs_strs) +ADD_CUSTOM_TARGET(descs_strs ALL DEPENDS descs strs) + +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/descs DESTINATION /etc/mtp-responder) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/strs DESTINATION /etc/mtp-responder) diff --git a/include/transport/mtp_descs_strings.h b/include/transport/mtp_descs_strings.h new file mode 100644 index 0000000..37747ba --- /dev/null +++ b/include/transport/mtp_descs_strings.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012, 2013, 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifndef FUNCTIONFS_DESCRIPTORS_MAGIC_V2 +#define FUNCTIONFS_DESCRIPTORS_MAGIC_V2 3 +enum functionfs_flags { + FUNCTIONFS_HAS_FS_DESC = 1, + FUNCTIONFS_HAS_HS_DESC = 2, + FUNCTIONFS_HAS_SS_DESC = 4, + FUNCTIONFS_HAS_MS_OS_DESC = 8, +}; +#endif + +#define cpu_to_le16(x) htole16(x) +#define cpu_to_le32(x) htole32(x) +#define le32_to_cpu(x) le32toh(x) +#define le16_to_cpu(x) le16toh(x) + +extern struct mtp_usb_descs{ + struct { + __le32 magic; + __le32 length; + __le32 flags; + __le32 fs_count; + __le32 hs_count; + // __le32 os_count; + } header; + struct { + struct usb_interface_descriptor intf; + struct usb_endpoint_descriptor_no_audio bulk_in; + struct usb_endpoint_descriptor_no_audio bulk_out; + struct usb_endpoint_descriptor_no_audio int_in; + } __attribute__((packed)) fs_descs, hs_descs; + // struct {} __attribute__((packed)) os_descs; +} __attribute__((packed)) descriptors; + +#define STR_INTERFACE "Samsung MTP" + +extern struct mtp_usb_strs { + struct usb_functionfs_strings_head header; + struct { + __le16 code; + const char str1[sizeof(STR_INTERFACE)]; + } __attribute__((packed)) lang0; +} __attribute__((packed)) strings; diff --git a/mtp-responder.service b/mtp-responder.service index 24acdfe..69433c4 100755 --- a/mtp-responder.service +++ b/mtp-responder.service @@ -9,3 +9,5 @@ Type=simple ExecStart=/usr/bin/mtp-responder KillMode=process SmackProcessLabel=System +USBFunctionDescriptors=/etc/mtp-responder/descs +USBFunctionStrings=/etc/mtp-responder/strs diff --git a/mtp-responder.socket b/mtp-responder.socket new file mode 100755 index 0000000..0abae50 --- /dev/null +++ b/mtp-responder.socket @@ -0,0 +1,6 @@ +[Unit] +Description=MTP responder functionfs socket + +[Socket] +ListenUSBFunction=/dev/usb-funcs/mtp +Service=mtp-responder.service diff --git a/packaging/mtp-responder.spec b/packaging/mtp-responder.spec index b1f1861..93187ae 100755 --- a/packaging/mtp-responder.spec +++ b/packaging/mtp-responder.spec @@ -22,6 +22,7 @@ BuildRequires: pkgconfig(capi-media-metadata-extractor) BuildRequires: pkgconfig(capi-system-info) Buildrequires: pkgconfig(storage) BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(libsystemd) Requires(post): /usr/bin/vconftool %define upgrade_script_path /usr/share/upgrade/scripts @@ -53,6 +54,7 @@ mkdir -p %{buildroot}%{upgrade_script_path} cp -f scripts/500.%{name}-upgrade.sh %{buildroot}%{upgrade_script_path} install -D -m 0644 mtp-responder.service %{buildroot}/%{_unitdir}/mtp-responder.service +install -D -m 0644 mtp-responder.socket %{buildroot}/%{_unitdir}/mtp-responder.socket %post mkdir -p %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/ @@ -64,6 +66,9 @@ ln -sf %{_unitdir}/mtp-responder.service %{_sysconfdir}/systemd/default-extra-de %defattr(-,root,root,-) %{_bindir}/mtp-responder %{_unitdir}/mtp-responder.service +%{_unitdir}/mtp-responder.socket %{_prefix}/lib/udev/rules.d/99-mtp-responder.rules /opt/var/lib/misc/mtp-responder.conf %{upgrade_script_path}/500.%{name}-upgrade.sh +/etc/mtp-responder/descs +/etc/mtp-responder/strs diff --git a/src/extract_descs/mtp_extract_descs_strs.c b/src/extract_descs/mtp_extract_descs_strs.c new file mode 100644 index 0000000..947c4e2 --- /dev/null +++ b/src/extract_descs/mtp_extract_descs_strs.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, 2013, 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "mtp_descs_strings.h" + +static int write_blob(const char *filename, const void *blob, size_t size) +{ + int ret; + FILE *fp; + + fp = fopen(filename, "w"); + if (!fp) { + fprintf(stderr, "Could not open %s: %m\n", filename); + return -errno; + } + + ret = fwrite(blob, size, 1, fp); + if (ret < 0) { + fprintf(stderr, "Could not write to %s\n"); + goto out; + } + + ret = 0; + +out: + fclose(fp); + return ret; +} + +int main() +{ + int ret; + + ret = write_blob("descs", &descriptors, sizeof(descriptors)); + if (ret < 0) + return ret; + + ret = write_blob("strs", &strings, sizeof(strings)); + return ret; +} diff --git a/src/transport/mtp_descs_strings.c b/src/transport/mtp_descs_strings.c new file mode 100644 index 0000000..f5d90e2 --- /dev/null +++ b/src/transport/mtp_descs_strings.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2012, 2013, 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mtp_descs_strings.h" + +struct mtp_usb_descs descriptors = { + .header = { + .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), + .length = cpu_to_le32(sizeof(descriptors)), + .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC, // | FUNCTIONFS_HAS_MS_OS_DESC, + .fs_count = 4, + .hs_count = 4, + // .os_count = 0; + }, + .fs_descs = { + // drivers/usb/gadget/f_mtp_slp.c:207 + .intf = { + .bLength = sizeof(descriptors.fs_descs.intf), + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 1, + }, + .bulk_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(64), + }, + .bulk_out = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(64), + }, + .int_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 3 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(64), + .bInterval = 6, + }, + }, + .hs_descs = { + .intf = { + .bLength = sizeof(descriptors.fs_descs.intf), + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 1, + }, + .bulk_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), + }, + .bulk_out = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = __constant_cpu_to_le16(512), + }, + .int_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 3 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(64), + .bInterval = 6, + }, + }, +}; + +struct mtp_usb_strs strings = { + .header = { + .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), + .length = cpu_to_le32(sizeof(strings)), + .str_count = cpu_to_le32(1), + .lang_count = cpu_to_le32(1), + }, + .lang0 = { + cpu_to_le16(0x0409), /* en-us */ + STR_INTERFACE, + }, +}; diff --git a/src/transport/mtp_usb_driver.c b/src/transport/mtp_usb_driver.c index 5576c55..6fde025 100644 --- a/src/transport/mtp_usb_driver.c +++ b/src/transport/mtp_usb_driver.c @@ -15,6 +15,7 @@ */ #include +#include #include "mtp_usb_driver.h" static const mtp_usb_driver_t *usb_driver; @@ -26,7 +27,7 @@ mtp_bool _transport_init_usb_device(void) { if (access(MTP_DRIVER_PATH, F_OK) == 0) { usb_driver = &mtp_usb_driver_slp; - } else if (access(MTP_EP0_PATH, F_OK) == 0) { + } else if (access(MTP_EP0_PATH, F_OK) == 0 || sd_listen_fds(0) >= 4) { usb_driver = &mtp_usb_driver_ffs; } else { ERR("No suport for USB gadgets in kernel"); diff --git a/src/transport/mtp_usb_driver_ffs.c b/src/transport/mtp_usb_driver_ffs.c index e972756..091daa8 100755 --- a/src/transport/mtp_usb_driver_ffs.c +++ b/src/transport/mtp_usb_driver_ffs.c @@ -25,6 +25,7 @@ #include #include "mtp_usb_driver.h" #include "mtp_device.h" +#include "mtp_descs_strings.h" #include "ptp_datacodes.h" #include "mtp_support.h" #include "ptp_container.h" @@ -33,8 +34,7 @@ #include "mtp_transport.h" #include "mtp_event_handler.h" #include -#include -#include +#include /* * GLOBAL AND EXTERN VARIABLES @@ -44,15 +44,6 @@ extern mtp_config_t g_conf; /* * STATIC VARIABLES AND FUNCTIONS */ -#ifndef FUNCTIONFS_DESCRIPTORS_MAGIC_V2 -#define FUNCTIONFS_DESCRIPTORS_MAGIC_V2 3 -enum functionfs_flags { - FUNCTIONFS_HAS_FS_DESC = 1, - FUNCTIONFS_HAS_HS_DESC = 2, - FUNCTIONFS_HAS_SS_DESC = 4, - FUNCTIONFS_HAS_MS_OS_DESC = 8, -}; -#endif /*PIMA15740-2000 spec*/ #define USB_PTPREQUEST_CANCELIO 0x64 /* Cancel request */ @@ -62,126 +53,6 @@ enum functionfs_flags { #define USB_PTPREQUEST_CANCELIO_SIZE 6 #define USB_PTPREQUEST_GETSTATUS_SIZE 12 -#define cpu_to_le16(x) htole16(x) -#define cpu_to_le32(x) htole32(x) -#define le32_to_cpu(x) le32toh(x) -#define le16_to_cpu(x) le16toh(x) - -static const struct { - struct { - __le32 magic; - __le32 length; - __le32 flags; - __le32 fs_count; - __le32 hs_count; - // __le32 os_count; - } header; - struct { - struct usb_interface_descriptor intf; - struct usb_endpoint_descriptor_no_audio bulk_in; - struct usb_endpoint_descriptor_no_audio bulk_out; - struct usb_endpoint_descriptor_no_audio int_in; - } __attribute__((packed)) fs_descs, hs_descs; - // struct {} __attribute__((packed)) os_descs; -} __attribute__((packed)) descriptors = { - .header = { - .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), - .length = cpu_to_le32(sizeof(descriptors)), - .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC, // | FUNCTIONFS_HAS_MS_OS_DESC, - .fs_count = 4, - .hs_count = 4, - // .os_count = 0; - }, - .fs_descs = { - // drivers/usb/gadget/f_mtp_slp.c:207 - .intf = { - .bLength = sizeof(descriptors.fs_descs.intf), - .bDescriptorType = USB_DT_INTERFACE, - .bNumEndpoints = 3, - .bInterfaceClass = USB_CLASS_STILL_IMAGE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - .iInterface = 1, - }, - .bulk_in = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(64), - }, - .bulk_out = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(64), - }, - .int_in = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 3 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(64), - .bInterval = 6, - }, - }, - .hs_descs = { - .intf = { - .bLength = sizeof(descriptors.fs_descs.intf), - .bDescriptorType = USB_DT_INTERFACE, - .bNumEndpoints = 3, - .bInterfaceClass = USB_CLASS_STILL_IMAGE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - .iInterface = 1, - }, - .bulk_in = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), - }, - .bulk_out = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), - }, - .int_in = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 3 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(64), - .bInterval = 6, - }, - }, -}; - -#define STR_INTERFACE "Samsung MTP" - -static const struct { - struct usb_functionfs_strings_head header; - struct { - __le16 code; - const char str1[sizeof(STR_INTERFACE)]; - } __attribute__((packed)) lang0; -} __attribute__((packed)) strings = { - .header = { - .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), - .length = cpu_to_le32(sizeof(strings)), - .str_count = cpu_to_le32(1), - .lang_count = cpu_to_le32(1), - }, - .lang0 = { - cpu_to_le16(0x0409), /* en-us */ - STR_INTERFACE, - }, -}; - static mtp_int32 g_usb_ep0 = -1; /* read (g_usb_ep0, ...) */ static mtp_int32 g_usb_ep_in = -1; /* write (g_usb_ep_in, ...) */ static mtp_int32 g_usb_ep_out = -1; /* read (g_usb_ep_out, ...) */ @@ -203,6 +74,15 @@ static mtp_bool __io_init() { int ret; + if (sd_listen_fds(0) >= 4) { + g_usb_ep0 = SD_LISTEN_FDS_START; + g_usb_ep_in = SD_LISTEN_FDS_START + 1; + g_usb_ep_out = SD_LISTEN_FDS_START + 2; + g_usb_ep_status = SD_LISTEN_FDS_START + 3; + + return TRUE; + } + g_usb_ep0 = open(MTP_EP0_PATH, O_RDWR); if (g_usb_ep0 < 0) goto out; -- 2.7.4 From f3e40f271ca8c93b1027fb8dec237a3cae831857 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Wed, 7 Mar 2018 20:07:31 +0100 Subject: [PATCH 16/16] Change default ffs path to match system convention Change-Id: I40c88c5704e7a50f6981fc4f575e2b45ee0cccfd Signed-off-by: Krzysztof Opasiak --- include/transport/mtp_usb_driver.h | 2 +- mtp-responder.socket | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/transport/mtp_usb_driver.h b/include/transport/mtp_usb_driver.h index 6320983..968616a 100755 --- a/include/transport/mtp_usb_driver.h +++ b/include/transport/mtp_usb_driver.h @@ -26,7 +26,7 @@ /* FunctionFS endpoint paths */ #ifndef MTP_FFS_PATH -#define MTP_FFS_PATH "/dev/usb-funcs/mtp" +#define MTP_FFS_PATH "/dev/usb-funcs/mtp/default" #endif #define MTP_EP0_PATH MTP_FFS_PATH "/ep0" #define MTP_EP_IN_PATH MTP_FFS_PATH "/ep1" diff --git a/mtp-responder.socket b/mtp-responder.socket index 0abae50..e430830 100755 --- a/mtp-responder.socket +++ b/mtp-responder.socket @@ -2,5 +2,5 @@ Description=MTP responder functionfs socket [Socket] -ListenUSBFunction=/dev/usb-funcs/mtp +ListenUSBFunction=/dev/usb-funcs/mtp/default Service=mtp-responder.service -- 2.7.4