diff options
author | taeyoung <ty317.kim@samsung.com> | 2016-09-09 20:27:41 +0900 |
---|---|---|
committer | taeyoung <ty317.kim@samsung.com> | 2016-09-27 13:38:47 +0900 |
commit | cee53090535dea2babe82c6c57ef6cc53d90cae7 (patch) | |
tree | c46a161bc1599c3768e1a65451f9e21e8d6f8903 | |
parent | ec4423047f3508f3b0df1b78779492958c7104ac (diff) | |
download | device-manager-plugin-odroid-cee53090535dea2babe82c6c57ef6cc53d90cae7.tar.gz device-manager-plugin-odroid-cee53090535dea2babe82c6c57ef6cc53d90cae7.tar.bz2 device-manager-plugin-odroid-cee53090535dea2babe82c6c57ef6cc53d90cae7.zip |
Add USB gadget HAL implementation
USB gadget HAL is an abstraction layer which translates
set of functions into full USB gadget description specific
for this particular device.
Change-Id: I9920a8e400aa3c16df9a650e7611d9eb920ae623
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
Signed-off-by: taeyoung <ty317.kim@samsung.com>
-rw-r--r-- | CMakeLists.txt | 16 | ||||
-rw-r--r-- | hw/shared.c | 129 | ||||
-rw-r--r-- | hw/shared.h | 43 | ||||
-rw-r--r-- | hw/usb_gadget/CMakeLists.txt | 19 | ||||
-rw-r--r-- | hw/usb_gadget/usb_gadget.c | 392 | ||||
-rw-r--r-- | packaging/device-manager-plugin-odroid.changes | 2 | ||||
-rw-r--r-- | packaging/device-manager-plugin-odroid.manifest (renamed from device-manager-plugin-odroid.manifest) | 0 | ||||
-rw-r--r-- | packaging/device-manager-plugin-odroid.spec | 19 |
8 files changed, 610 insertions, 10 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 264036c..86fbb1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,11 @@ -cmake_minimum_required(VERSION 2.8) -project(slp_devman_plugin) +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(device-manager-odroid C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +ADD_SUBDIRECTORY(hw/usb_gadget) + +SET(PROJ_NAME slp_devman_plugin) set(SRCS src/device_manager_plugin_odroid.c @@ -10,6 +16,6 @@ pkg_check_modules(pkgs REQUIRED devman_plugin) include_directories(${pkgs_INCLUDE_DIRS}) -add_library(${PROJECT_NAME} SHARED ${SRCS}) -target_link_libraries(${PROJECT_NAME} ${pkgs_LIBRARIES}) -install(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +add_library(${PROJ_NAME} SHARED ${SRCS}) +target_link_libraries(${PROJ_NAME} ${pkgs_LIBRARIES}) +install(TARGETS ${PROJ_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/hw/shared.c b/hw/shared.c new file mode 100644 index 0000000..b6401c1 --- /dev/null +++ b/hw/shared.c @@ -0,0 +1,129 @@ +/* + * device-node + * + * Copyright (c) 2015 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#define BUF_MAX 255 + +static int sys_read_buf(char *file, char *buf, int len) +{ + int fd, r; + + if (!file || !buf || len < 0) + return -EINVAL; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -ENOENT; + + r = read(fd, buf, len); + close(fd); + if ((r >= 0) && (r < len)) + buf[r] = '\0'; + else + return -EIO; + + return 0; +} + +static int sys_write_buf(char *file, char *buf) +{ + int fd, r; + + if (!file || !buf) + return -EINVAL; + + fd = open(file, O_WRONLY); + if (fd == -1) + return -EPERM; + + r = write(fd, buf, strlen(buf)); + close(fd); + if (r < 0) + return -EIO; + + return 0; +} + +int sys_get_int(char *fname, int *val) +{ + char buf[BUF_MAX]; + int r; + + if (!fname || !val) + return -EINVAL; + + r = sys_read_buf(fname, buf, sizeof(buf)); + if (r < 0) + return r; + + *val = atoi(buf); + return 0; +} + +int sys_get_str(char *fname, char *str, int len) +{ + int r; + + if (!fname || !str || len < 0) + return -EINVAL; + + r = sys_read_buf(fname, str, len); + if (r < 0) + return r; + + return 0; +} + +int sys_set_int(char *fname, int val) +{ + char buf[BUF_MAX]; + int r; + + if (!fname) + return -EINVAL; + + snprintf(buf, sizeof(buf), "%d", val); + r = sys_write_buf(fname, buf); + if (r < 0) + return r; + + return 0; +} + +int sys_set_str(char *fname, char *val) +{ + int r; + + if (!fname || !val) + return -EINVAL; + + r = sys_write_buf(fname, val); + if (r < 0) + return r; + + return 0; +} diff --git a/hw/shared.h b/hw/shared.h new file mode 100644 index 0000000..da51ca4 --- /dev/null +++ b/hw/shared.h @@ -0,0 +1,43 @@ +/* + * libdevice-node + * + * Copyright (c) 2015 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. + */ + + +#ifndef __HW_DEFAULT_SHARED_H__ +#define __HW_DEFAULT_SHARED_H__ + +#define FEATURE_HARDWARE_DLOG +#ifdef FEATURE_HARDWARE_DLOG +#define LOG_TAG "HARDWARE" +#include <dlog.h> +#define _I(fmt, args...) SLOGI(fmt, ##args) +#define _D(fmt, args...) SLOGD(fmt, ##args) +#define _E(fmt, args...) SLOGE(fmt, ##args) +#else +#define _I(x, ...) do { } while (0) +#define _D(x, ...) do { } while (0) +#define _E(x, ...) do { } while (0) +#endif + +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) + +int sys_get_int(char *fname, int *val); +int sys_get_str(char *fname, char *str, int len); +int sys_set_int(char *fname, int val); +int sys_set_str(char *fname, char *val); + +#endif diff --git a/hw/usb_gadget/CMakeLists.txt b/hw/usb_gadget/CMakeLists.txt new file mode 100644 index 0000000..2e28b15 --- /dev/null +++ b/hw/usb_gadget/CMakeLists.txt @@ -0,0 +1,19 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(usb_gadget C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +INCLUDE(FindPkgConfig) +pkg_check_modules(usb_gadget_pkgs REQUIRED hwcommon) + +FOREACH(flag ${usb_gadget_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +ADD_LIBRARY(${PROJECT_NAME} MODULE usb_gadget.c ../shared.c) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${usb_gadget_pkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "") +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR}/hw COMPONENT RuntimeLibraries) diff --git a/hw/usb_gadget/usb_gadget.c b/hw/usb_gadget/usb_gadget.c new file mode 100644 index 0000000..0bcb10b --- /dev/null +++ b/hw/usb_gadget/usb_gadget.c @@ -0,0 +1,392 @@ +/* + * libdevice-node + * + * Copyright (c) 2016 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. + */ + +#ifndef __HW_USB_GADGET_SIMPLE_TRANSLATOR_H__ + +#include <hw/usb_gadget.h> + +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define zalloc(amount) calloc(1, amount) + +/* Based on slp-gadget and initial version of USB HAL by Taeyoung Kim */ +#define DEFAULT_VID 0x04e8 +#define DEFAULT_PID 0x6860 +#define DEFAULT_BCD_DEVICE 0xffff + +#define DEFAULT_LANG 0x409 /* US_en */ +#define DEFAULT_MANUFACTURER "Samsung" +#define DEFAULT_PRODUCT "TIZEN" +#define DEFAULT_SERIAL "01234TEST" + +#define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6)) +#define DEFAULT_MAX_POWER 500 + +static void simple_cleanup_config(struct usb_configuration *config) +{ + int i; + + if (!config) + return; + + if (config->strs) { + for (i = 0; config->strs[i].lang_code; ++i) + free(config->strs[i].config_str); + + free(config->strs); + } + + /* + * Each function will be free later, + * for now we cleanup only pointers. + */ + if (config->funcs) + free(config->funcs); + + free(config); +} + +static void simple_cleanup_gadget(struct usb_gadget *gadget) +{ + int i; + + if (!gadget) + return; + + if (gadget->strs) { + for (i = 0; gadget->strs[i].lang_code; ++i) { + free(gadget->strs[i].manufacturer); + free(gadget->strs[i].product); + free(gadget->strs[i].serial); + } + free(gadget->strs); + } + + if (gadget->configs) { + for (i = 0; gadget->configs[i]; ++i) + simple_cleanup_config(gadget->configs[i]); + + free(gadget->configs); + } + + if (gadget->funcs) { + for (i = 0; gadget->funcs[i]; ++i) + gadget->funcs[i]->free_func(gadget->funcs[i]); + + free(gadget->funcs); + } + + free(gadget); +} + +static int alloc_default_config(struct usb_configuration **_config) +{ + struct usb_configuration *config; + + config = zalloc(sizeof(*config)); + if (!config) + goto out; + + config->strs = calloc(1, sizeof(*config->strs)); + if (!config->strs) + goto free_config; + + config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES; + config->attrs.MaxPower = DEFAULT_MAX_POWER; + + *_config = config; + + return 0; + +free_config: + free(config); +out: + return -ENOMEM; +} + +static int alloc_default_gadget(struct usb_gadget **_gadget) +{ + struct usb_gadget *gadget; + struct usb_gadget_strings *strs; + struct usb_configuration **configs; + + gadget = zalloc(sizeof(*gadget)); + if (!gadget) + goto out; + + gadget->attrs.idVendor = DEFAULT_VID; + gadget->attrs.idProduct = DEFAULT_PID; + gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE; + + strs = calloc(2, sizeof(*strs)); + if (!strs) + goto free_gadget; + + strs[0].lang_code = 0x409; + strs[0].manufacturer = strdup(DEFAULT_MANUFACTURER); + strs[0].product = strdup(DEFAULT_PRODUCT); + strs[0].serial = strdup(DEFAULT_SERIAL); + + if (!strs[0].manufacturer || !strs[0].product || !strs[0].serial) + goto free_strs; + + gadget->strs = strs; + + /* slp-gadget use max 2 confiuration and NULL termination */ + configs = calloc(3, sizeof(*configs)); + if (!configs) + goto free_strs; + + gadget->configs = configs; + *_gadget = gadget; + + return 0; + +free_strs: + free(strs[0].manufacturer); + free(strs[0].product); + free(strs[0].serial); + free(strs); +free_gadget: + free(gadget); +out: + return -ENOMEM; +} + +static inline struct usb_function *find_func(struct usb_gadget *gadget, + int func_id) +{ + int i; + + for (i = 0; gadget->funcs[i] && gadget->funcs[i]->id != func_id; ++i); + + return gadget->funcs[i]; +} + +static int simple_id_to_gadget(struct usb_gadget_id *gadget_id, + struct usb_gadget **_gadget) +{ + struct usb_gadget *gadget; + int n_configs; + /* zero terminates */ + int functions[2][sizeof(gadget_id->function_mask)*8]; + int n_functions; + struct usb_function **funcs; + int idx, i, j; + int ret; + + if (!gadget_id || !_gadget) + return -EINVAL; + + ret = alloc_default_gadget(&gadget); + if (ret) + goto out; + + /* + * Currently all gadgets use inly single configuration but + * slp-gadget is capable to handle two of them + * + * Order of interfaces in configuration is significant + * so in this switch we sort our functions in a correct order + */ + switch (gadget_id->function_mask) { + case USB_FUNCTION_SDB: + n_configs = 1; + functions[0][0] = USB_FUNCTION_SDB; + functions[0][1] = 0; + gadget->attrs.idProduct = 0x685d; + break; + case USB_FUNCTION_MTP: + n_configs = 1; + functions[0][0] = USB_FUNCTION_MTP; + functions[0][1] = 0; + gadget->attrs.idProduct = 0x6860; + break; + case USB_FUNCTION_RNDIS: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = 0; + gadget->attrs.idProduct = 0x6863; + break; + case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB: + n_configs = 1; + functions[0][0] = USB_FUNCTION_MTP; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = USB_FUNCTION_SDB; + functions[0][3] = 0; + gadget->attrs.idProduct = 0x6860; + break; + case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB + | USB_FUNCTION_DIAG: + n_configs = 1; + functions[0][0] = USB_FUNCTION_MTP; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = USB_FUNCTION_SDB; + functions[0][3] = USB_FUNCTION_DIAG; + functions[0][4] = 0; + gadget->attrs.idProduct = 0x6860; + break; + case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = USB_FUNCTION_SDB; + functions[0][2] = 0; + gadget->attrs.idProduct = 0x6864; + break; + case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB | USB_FUNCTION_ACM | USB_FUNCTION_DIAG: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = USB_FUNCTION_SDB; + functions[0][2] = USB_FUNCTION_ACM; + functions[0][3] = USB_FUNCTION_DIAG; + functions[0][4] = 0; + gadget->attrs.idProduct = 0x6864; + break; + case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = USB_FUNCTION_DIAG; + functions[0][2] = 0; + gadget->attrs.idProduct = 0x6864; + break; + case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM: + n_configs = 1; + functions[0][0] = USB_FUNCTION_ACM; + functions[0][1] = USB_FUNCTION_SDB; + functions[0][2] = USB_FUNCTION_DM; + functions[0][3] = 0; + gadget->attrs.idProduct = 0x6860; + break; + case USB_FUNCTION_DIAG | USB_FUNCTION_ACM | USB_FUNCTION_RMNET: + n_configs = 1; + functions[0][0] = USB_FUNCTION_DIAG; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = USB_FUNCTION_RMNET; + functions[0][3] = 0; + gadget->attrs.idProduct = 0x685d; + break; + }; + + if (n_configs > 2) { + ret = -EINVAL; + goto free_gadget; + } + + n_functions = __builtin_popcount(gadget_id->function_mask); + + funcs = calloc(n_functions + 1, sizeof(*funcs)); + if (!funcs) { + ret = -ENOMEM; + goto free_gadget; + } + + gadget->funcs = funcs; + + idx = 0; + for (i = 0; i < ARRAY_SIZE(_available_funcs); ++i) { + int func_id = 1 << i; + + if (!(gadget_id->function_mask & func_id)) + continue; + + ret = _available_funcs[i]->clone(_available_funcs[i], + gadget->funcs + idx); + if (ret) + goto free_functions; + ++idx; + } + + for (j = 0; j < n_configs; ++j) { + struct usb_configuration *config; + int n_funcs_in_config; + + for (i = 0; functions[j][i]; ++i); + n_funcs_in_config = i; + + ret = alloc_default_config(&config); + if (ret) + goto free_configs; + + gadget->configs[j] = config; + config->funcs = calloc(n_funcs_in_config + 1, + sizeof(void *)); + if (!config->funcs) + goto free_configs; + + for (i = 0; functions[j][i]; ++i) + config->funcs[i] = find_func(gadget, functions[j][i]); + } + + *_gadget = gadget; + return 0; +free_configs: +free_functions: +free_gadget: + simple_cleanup_gadget(gadget); +out: + return ret; +} + +static int simple_translator_open(struct hw_info *info, + const char *id, struct hw_common **common) +{ + struct usb_gadget_translator *simple_translator; + + if (!info || !common) + return -EINVAL; + + simple_translator = zalloc(sizeof(*simple_translator)); + if (!simple_translator) + return -ENOMEM; + + simple_translator->common.info = info; + simple_translator->id_to_gadget = simple_id_to_gadget; + simple_translator->cleanup_gadget = simple_cleanup_gadget; + + *common = &simple_translator->common; + return 0; +} + +static int simple_translator_close(struct hw_common *common) +{ + struct usb_gadget_translator *simple_translator; + + if (!common) + return -EINVAL; + + simple_translator = container_of(common, struct usb_gadget_translator, + common); + + free(simple_translator); + return 0; +} + +HARDWARE_MODULE_STRUCTURE = { + .magic = HARDWARE_INFO_TAG, + .hal_version = HARDWARE_INFO_VERSION, + .device_version = USB_GADGET_DEVICE_VERSION, + .id = USB_GADGET_DEVICE_ID, + .name = "simple_translator", + .open = simple_translator_open, + .close = simple_translator_close, +}; + +#endif diff --git a/packaging/device-manager-plugin-odroid.changes b/packaging/device-manager-plugin-odroid.changes deleted file mode 100644 index 2223d47..0000000 --- a/packaging/device-manager-plugin-odroid.changes +++ /dev/null @@ -1,2 +0,0 @@ -* Fri Jun 27 2014 Ćukasz Stelmach <l.stelmach@samsung.com> 6373e7e1 -- Initial release diff --git a/device-manager-plugin-odroid.manifest b/packaging/device-manager-plugin-odroid.manifest index a76fdba..a76fdba 100644 --- a/device-manager-plugin-odroid.manifest +++ b/packaging/device-manager-plugin-odroid.manifest diff --git a/packaging/device-manager-plugin-odroid.spec b/packaging/device-manager-plugin-odroid.spec index b824f1e..7a220c7 100644 --- a/packaging/device-manager-plugin-odroid.spec +++ b/packaging/device-manager-plugin-odroid.spec @@ -5,23 +5,36 @@ Release: 0 Group: System/Hardware Adaptation License: Apache-2.0 Source0: %{name}-%{version}.tar.gz +Source1: %{name}.manifest +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig BuildRequires: cmake BuildRequires: pkgconfig(devman_plugin) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(hwcommon) +BuildRequires: pkgconfig(glib-2.0) %description -Tizen OEM Adaptation Layer library for ODROID development board. +Device manager plugin for ODROID development board. %prep %setup -q +cp %{SOURCE1} . %build -%cmake . +%cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} + make %{?jobs:-j%jobs} %install %make_install +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + %files +%{_libdir}/hw/*.so +%manifest %{name}.manifest %license LICENSE -%manifest device-manager-plugin-odroid.manifest %{_libdir}/libslp_devman_plugin.so |