diff options
33 files changed, 457 insertions, 11053 deletions
diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 7dfeaed..0000000 --- a/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -/examples/* -!/examples/*.* -/examples/.deps -/examples/.libs -/src/.deps -/src/.libs -/tests/* -!/tests/*.* -/tests/.deps -*.o -*.lo -*.la -*.so -*.so.* -Makefile -Makefile.in -/configure -/config.* -/aclocal.m4 -/autom4te.cache -/compile -/depcomp -/libtool -/ltmain.sh -/ar-lib -/missing -/install-sh -/doxygen.cfg -/libusbg.pc @@ -1,3 +1 @@ Matt Porter <mporter@linaro.org> -Krzysztof Opasiak <k.opasiak@samsung.com> - @@ -1,2 +1,5 @@ -Tue, 22 Dec 2015 Krzysztof Opasiak <k.opasiak@samsung.com> 0.0.1 - - Initial fork from libusbg +Mon, 20 Jan 2014 Matt Porter <mporter@linaro.org> 0.1.0 +- Rename from libgadget->libusbg +- Update examples to use standard configfs mount point +Wed, 04 Sep 2013 Matt Porter <mporter@linaro.org> 0.0.1 +- Initial release @@ -1,4 +1,4 @@ -Installing libusbgx: +Installing libusbg: $ autoreconf -i $ ./configure diff --git a/Makefile.am b/Makefile.am index 05e1379..5fc3cd6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,13 +1,8 @@ include $(top_srcdir)/aminclude.am SUBDIRS = src examples - -if BUILD_TESTS -SUBDIRS += tests -endif - ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = doxygen.cfg library_includedir=$(includedir)/usbg library_include_HEADERS = include/usbg/usbg.h pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libusbgx.pc +pkgconfig_DATA = libusbg.pc @@ -1,7 +1,7 @@ -libusbg-neXt (libusbgx) +libusbg ------- -libusbgx is a C library encapsulating the kernel USB gadget-configfs +libusbg is a C library encapsulating the kernel USB gadget-configfs userspace API functionality. It provides routines for creating and parsing USB gadget devices using diff --git a/configure.ac b/configure.ac index a456ba7..878c2ab 100644 --- a/configure.ac +++ b/configure.ac @@ -1,51 +1,10 @@ -AC_INIT([libusbgx], [0.0.1], [k.opasiak@samsung.com]) -AM_INIT_AUTOMAKE([1.12 -Wall -Werror foreign serial-tests]) +AC_INIT([libusbg], [0.1.0], [mporter@linaro.org]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) AC_PROG_CC AM_PROG_AR -AM_PROG_CC_C_O AC_CONFIG_MACRO_DIR([m4]) AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) - -AC_ARG_WITH([libconfig], - AS_HELP_STRING([--without-libconfig], [build without using libconfig]), - [with_libconfig=$withval], [with_libconfig=yes]) - -AC_ARG_ENABLE([gadget-schemes], - AS_HELP_STRING([--disable-gadget-schemes], [build without gadget-schemes support]), - [enable_gadget_schemes=$enableval], [enable_gadget_schemes=yes]) - -AC_ARG_ENABLE([tests], - AS_HELP_STRING([--enable-tests], [build with tests]), - [enable_tests=$enableval], [enable_tests=no]) - -# if both tests and schemes are disabled, we do not need libconfig -AS_IF([test "x$enable_gadget_schemes" = xno && test "x$enable_tests" = xno], [with_libconfig=no]) - -AS_IF([test "x$with_libconfig" = xyes], [ - PKG_CHECK_MODULES([LIBCONFIG], [libconfig >= 1.4], - [ AC_DEFINE(HAS_LIBCONFIG, 1, [detected libconfig]) - PKG_CHECK_MODULES([NEW_LIBCONFIG], [libconfig >= 1.5], - AC_DEFINE(HAVE_LIBCONFIG_15, 1, [detected libconfig equal to or greater than 1.5]), - AC_DEFINE(HAVE_LIBCONFIG_15, 0, [])) - ]) - CFLAGS="$CFLAGS $LIBCONFIG_CFLAGS" - LIBS="$LIBS $LIBCONFIG_LIBS" -], [ - enable_gadget_schemes=no -]) - -AS_IF([test "x$enable_tests" = xyes], [ - PKG_CHECK_MODULES([CMOCKA], [cmocka >= 1.0.0], - AC_DEFINE(HAS_CMOCKA, 1, [detected cmocka])) - AC_CONFIG_FILES([tests/Makefile]) -]) -AM_CONDITIONAL(BUILD_TESTS, [test "x$enable_tests" = xyes]) - -AS_IF([test "x$enable_gadget_schemes" = xyes], - [AC_DEFINE(HAS_GADGET_SCHEMES, 1, [gadget schemes are enables])]) -AM_CONDITIONAL(TEST_GADGET_SCHEMES, [test "x$enable_gadget_schemes" != xno]) - LT_INIT -AC_CONFIG_FILES([Makefile src/Makefile examples/Makefile libusbgx.pc doxygen.cfg]) +AC_CONFIG_FILES([Makefile src/Makefile examples/Makefile libusbg.pc]) DX_INIT_DOXYGEN([$PACKAGE_NAME],[doxygen.cfg]) AC_OUTPUT diff --git a/doc/gadget_schemes.txt b/doc/gadget_schemes.txt deleted file mode 100644 index d1d44a5..0000000 --- a/doc/gadget_schemes.txt +++ /dev/null @@ -1,301 +0,0 @@ - - Gadget schemes - - -Index: -1. What are gadget schemes? -2. Why gadget schemes? -3. Gadget scheme syntax - 3.1 Function scheme - 3.2 Configuration scheme - 3.3 Gadget scheme -4. Conclusion - - - 1. What are gadget schemes? - -Gadget schemes are files which contains configuration data of -gadget/function/configuration. Those files can be generated using -usbg_export_*() functions for whole gadget, configuration or single -function. Library provides also set of usbg_import_*() functions which -allows to load configuration data back to configfs. - - - 2. Why gadget schemes? - -New kernel interface - ConfigFS which along with libcomposite allows -to set up custom gadget. This can be achieved using simple, command -line file system operation like mkdir, rmdir, ln -s, read and -write. Yes, it is possible to configure usb gadget using only command -line but each time after reboot user needs to recreate all gadgets -once again. This means that after each reboot user needs to use about -15 commands (depends on number and types of function). This is -definitely not acceptable for those who used legacy gadgets and write -only modprobe g_ether. - -One of first idea to solve this is to create a script and run it -after each reboot. This approach is feasible but has many -disadvantages. First of them is security. ConfigFS is modifiable by -default only by root, so scripts has to be executed with root -rights. Secondly it's really hard to modify such a script because many -calls has hard-coded path where for example echo should be -done. There is a lot of simple, but low level operations which can -cause a lot of confusion for beginner. - -Second approach is to create executable which will create our gadget -using base libusbg API. It is also possible but let's think for a -moment why configfs has been introduced. It has been announced to -separate code from configuration. Code is a piece of C code in kernel -module which realizes usb function and configuration is understood as -composition of those functions into a gadget as a whole. If we would -like to create binary file for each gadget we would waste a lot of -work which kernel contributors put to remove hard-coded gadgets from -linux kernel. This all leads us to solution described in this document -- gadget schemes. Light weight configuration files which describes -composition of functions into gadget. They can be simply loaded using -usbg_import_*() and exported using usbg_export_*(). This makes them -easy to use equivalent of modprobe gadget_module. - - - 3. Gadget scheme syntax - -Gadget schemes implementation uses libconfig for reading and writing -scheme files. This means that all limitations of libconfig are also -present in gadget schemes. More over there are additional constrains -for scheme files. Gadget scheme is only a password and import and -export is not limited to whole gadgets. It is possible to export all 3 -types of gadget entity: function, configuration and gadget. Please -refer to libconfig documentation for details about syntax and rules. - - 3.1 Function scheme - -Function scheme is a file or part of file which represents single -function. - -Example: - -instance = "my_func_instance" -type = "ecm" - -attrs = { - dev_addr = "ef:33:be:9a:90:36" - dev_addr = "ab:63:6e:8b:10:16" - qmult = 5 -} - -For functions, type is the only attribute which is always -mandatory. Instance is mandatory only if function is part of bigger -scheme (gadget for example). By default usbg_export_function() does -not export instance name, because usbg_import_function() takes -instance as one of parameters. This convention allows for simple -function movement between gadgets without names conflict. - -Attrs section is optional. It may not be included, present but empty -or present and filled with function attributes. Attribute names are -similar as those from configfs. Each type of function has own set of -possible attributes. It is worth to mention that some attributes are -read only and they cannot be imported from file. To make it more -user-friendly read-only parameters are just ignored. This allows for -direct use of previously exported function in import. If some -attribute has not been provided default value provided by kernel will -be used. - - 3.2 Configuration scheme - -Configuration scheme is a file or part of file which represents single -configuration with its attributes, strings and bindings. - -Simple example: - -id = 1 -name = "My favorite config" - -attrs = { - bMaxPower = 0x40 - bmAttributes = 0x00 -} - -strings = ( - { - lang = 0x409 - configuration = "My favorite string" - } -) - -functions = ( - "function_label" -) - -This is example of simple configuration with some attributes values, -strings in US English and only one function. For configurations name -is the only field which is always mandatory. Id is mandatory only if -this is a part of bigger structure (gadget scheme). - -Attrs section is optional. It may not be included, present but empty -or present and filled with function attributes. Attribute names are -similar as those from configfs. Currently usb configuration has only -two attributes: bMaxPower and bmAttributes. Their meaning and set of -allowed values can be found in usb standard. - -Strings section presence policy is the same as attrs section. This -section contains a list (that's the meaning of parentheses) of strings -with their language codes. Each group of strings has to declare their -language using lang field. Configuration string is optional. If this -field is not set, empty string provided by kernel will be used for -this language. Max number of languages is defined during kernel -compilation using MAX_USB_STRING_LANGS define. - -Functions section is also optional. This allows for exporting not -fully configured configurations. This section defines bindings between -functions and configurations. The easiest and shortest way to define a -connection between functions and configuration is to provide list of -comma separated functions labels. For details about function labels -please refer to gadget schemes subsection. Bindings of function to -given configuration could be defined in different ways which has been -presented in featured example. - -Featured example: - -id = 1 -name = "My favorite config" - -attrs = { - bMaxPower = 0x40 - bmAttributes = 0x00 -} - -strings = ( - { - lang = 0x409 - configuration = "My favorite string" - } , { - lang = 0x415 - configuration = "Moj ulubiony napis" - } -) - -functions = ( - "function_label" - , { - name = "my_binding_name" - function = "other_function_label" - } , { - name = "my_binding_name" - function = { - type = "ecm" - instance = "my_inline_func_definition" - attrs = { - dev_addr = "ef:33:be:9a:90:36" - } - } - } -) - -First way to add function to configuration has been described along -with simple example. Second way is to provide a group with two -fields. First one is name and it should contain a string with binding -name. This field is optional and can be omitted what makes this more -verbose equivalent of previous method. Second field, named function -is mandatory. This field should contain function label. Third way to -add function to config is to define it inline. This method allows to -define a brand new function instead of providing function label of -existing one. - - 3.3 Gadget scheme - -Gadget scheme is a file which represents whole gadget with -configurations, attributes, strings and functions. - -Example: - -attrs = { - bcdUSB = 0x200 - bDeviceClass = 0x0 - bDeviceSubClass = 0x0 - bDeviceProtocol = 0x0 - bMaxPacketSize0 = 0x40 - idVendor = 0x1D6B - idProduct = 0x104 - bcdDevice = 0x1 -} - -strings = ( - { - lang = 0x409 - manufacturer = "Foo Inc." - product = "Bar Gadget" - serialnumber = "0123456789" - } -) - -functions = { - acm_usb0 = { - instance = "usb0" - type = "acm" - } - - my_awesome_label = { - instance = "inst_name" - @include "my_func_scheme.scheme" - } -} - -configs = ( - { - id = 1 - name = "The only one" - attrs = { - bmAttributes = 0x80 - bMaxPower = 0x2 - } - strings = ( - { - lang = 0x409 - configuration = "Config id 1" - } ) - functions = ( - { - name = "acm.GS0" - function = "acm_usb0" - } - ) - } , { - id = 2 - @include "some_config.scheme" - } -) - -All sections in gadget scheme are optional. If attrs section has not -been defined defaults provided by kernel are used for each attribute. -All possible gadget attributes has been listed in above example. Their -names are similar to those provided by usb standard and configfs. - -Strings section is similar to strings section from configuration -scheme. Allowed strings are listed in example. - -Functions section is used to define functions which are aggregated by -this gadget. Definition of each function begins with unique label. Any -string which fulfills libconfig naming rules can be used as label, -but there is one important thing - function labels are not stored in -configfs. They are transient and are lost while executing -usbg_cleanup(). To allow using this label after next usbg_init() there -is a naming rule: type + "_" + instance. If label follows this -convention it could be regenerated each time when it is -needed. Definition of each function contains a function scheme which -has been described in one of previous sections. It is also possible -to use include directive of libconfig and provide only instance name -in gadget shceme and include previously exported function scheme from -other gadget. - -Configfs section contains list of configurations definitions. Each -configuration is defined using configuration scheme described in -previous section. Each configuration can be fully defined in gadget -scheme file or simply included from other file just like function. - - 4. Conclusion - -Syntax of gadget scheme is based on libconfig and if any doubts appear -don't hesitate to look into documentation of this library. There are -also sample applications which shows how to use usbg_import_*() and -usbg_export_*() functions in examples directory. - diff --git a/doc/tests_guideline.txt b/doc/tests_guideline.txt deleted file mode 100644 index 2f5a2d8..0000000 --- a/doc/tests_guideline.txt +++ /dev/null @@ -1,166 +0,0 @@ -Libusbg testing guideline -------------------------- - -Libusbg tests use cmocka library to simulate fake configfs filesystem, -by wrapping input/output functions. - -## Building and running tests - -# Requirements -Building libusbg tests requires: --CMocka unit testing framework in version >= 0.3 --libconfig in version >= 1.4 - -# Building and running -Before testing make sure that you have successfully built libusbg (see INSTALL for -more details). Tests must be enabled in configuration, do it by adding proper flag -when configuring: - - $ ./configure --enable-tests - -Then, to build and run all provided tests, run following command: - - $ make check - -This should execute testing script and produce report on standart output. -It contains list of all test cases and its status - OK, FAILED and SKIPPED. At the -end of report number of passed/failed tests is written and then all failed test -cases are listed. This report is also avaible in tests/test-suite.log file. - -It's also possible to pass custom configuration file to testing environment. -Currently it's used only for skipping tests. Use --generate-config and ---use-config options of test.sh to generate default config and read config -from file. Run ./test.sh --help for more help with testing environment. - -# Tests skipping -When you want to skip some test cases, use configuration files for test suite. -To generate default config run: - - $ make check GENERATE_CONFIG=[file_name] - -It will generate tests/[file_name] file with configuration for testing. You can -remove test cases from 'tests' list to disable them. With custom configuration file -run: - - $make check USE_CONFIG=[file_name] - -Where file_name is name of previously generated configuration file. Test suite -will skip tests not listed in config. - - -## Writting tests - -Before starting your own tests implementation, become familiar with cmocka -library (cmocka.org). - -test.c file contains tests implementation. Test cases are stored in -UnitTest structures (from cmocka) and run by run_tests macro. - -In cmocka each test case can be composed of three parts: setup, test and -teardown. - -# Setup functions -In setup input data must be initialized and assigned to pointer given as -argument. - -Libusbg requires initialized usbg_state structure for most of it's api -functions. In most cases we define initial state in test_* strutures and -pass it to test function, in order to run usbg_init. Each test_state -can be defined quite simply by listing gadgets, its configs and functions -(using gcc extenstion), e.g.: - - static struct test_state simple_state = { - .path = "config", - .gadgets = simple_gadgets, - .udcs = simple_udcs - }; - -test_state structure (or other structure, if neccessary for test case) -is casted to void * in setup function. Note, that when using test_state -you must sort its content and fill additional fields (i.e. pathes strings). -It can be done by calling prepare_state before test. - -# Test functions -Test functions contain libusbg functions calls, preparations for them and -checking results. - -When calling usbg function which operates on filesystem proper preparation -is needed. Usbg-test framework provides functions which tell cmocka what -operations are expected from corresponding usbg function (push_* and pull_* -functions). - -E.g., in most cases you want correctly initialized usbg_state. It can be done -by preparing filesystem by push_init and running usbg_init after that: - - push_init(in); - usbg_ret = usbg_init(in->path, out); - -init_with_state function does that and checks results. - -When tested usbg function was run, you can check results by cmocka assert -macros. Usbg-test also provides set of assert functions for usbg structures. - -# Teardown functions -When test was run, you can define teardown function, which can do the cleanup. -Argument is passed same way as before, by assigning it to cmocka state pointer -in test function and receiving it in teardown function. - -In most cases you will just want to cleanup after initializing state and running -some usbg functions. To do that teardown_state can be used as teardown function. -You can write custom teardown for other cases. - -Note that in preparation for test some memory is allocated. All allocated -pointers are stored on global stack and should be freed by calling cleanup_stack -after test is finished (in teardown function). - -Remember that teardown is called also when test failed. You should assign -something correct (NULL for example) for your teardown function to test -argument before running functions which may fail. - -# Composing test cases -All test cases are defined in list of UnitTest structures. You can define test -case by macros provided by cmocka or by USBG_TEST or USBG_TEST_TS macro. - -USBG_TEST is similar to unit_test_setup_teardown from cmocka, but always uses -the same teardown (teardown_state) and names test case with custom string. -It combines setup function with test function, so one test function can be -run with many different states. - -# Documenting test cases -For tests documentation few doxygen macros are created. -\usbg_test indicates that current comment block contains test case documentation. -\test_desc{name, description, function} describe test with its name, function -which is tested and short descripttion of what this test does. - -# Adding tests -Simplest way to add more tests is defining test states and new setup functions, -combining them with existing testing functions using USBG_TEST. You can also -write own test function. When you have test and setup prepared, add - - USBG_TEST_TS("test_name", test_function, setup_function), -or - USBG_TEST("test_name", test_function, setup_function, teardown_function), - -at the end of tests[] array. Remember to add documentation to the case -(see Documenting test cases). - -# Removing tests -In order to remove test case just delete corresponding element on tests[] list -(including documentation above it). - -# Modyfing tests -When you want to change data using in test case, change corresponding test_* -structures. Note, that single test state can be used in many test cases and -modyfing it can effect them as well. -You can also change test logic (by modifying test function used in case), as -long as you know what you're doing. - - -## Final notes - -Remember, that in test environment functions operating on files are replaced -and operations on files cannot be performed. However, using standard input/output -is possible. - -All test cases are run in single thread, so some failures on one test case -(e.g. SIGSEGV) can cause crash on whole tests set. diff --git a/doxygen.cfg.in b/doxygen.cfg index d42ff83..4d7a5d8 100644 --- a/doxygen.cfg.in +++ b/doxygen.cfg @@ -650,8 +650,6 @@ WARN_LOGFILE = INPUT = $(SRCDIR)/include/usbg/ $(SRCDIR)/src $(SRCDIR)/examples/ -@BUILD_TESTS_TRUE@INPUT += $(SRCDIR)/tests/ - # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built @@ -1505,7 +1503,7 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = DOXYGEN +PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. @@ -1781,8 +1779,3 @@ GENERATE_LEGEND = YES # the various graphs. DOT_CLEANUP = YES - -ALIASES += tests_start="<table> <tr> <th>Name</th> <th>Description</th> <th>Tested function</th> </tr> \n" -ALIASES += usbg_test="\page usbg_tests" -ALIASES += test_desc{3}="<tr> <td>\1</td> <td>\2</td> <td>\ref \3</td> </tr> \n" -ALIASES += tests_end="</table> " diff --git a/examples/Makefile.am b/examples/Makefile.am index 8c2acb2..f9f9407 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,10 +1,5 @@ -bin_PROGRAMS = show-gadgets gadget-acm-ecm gadget-vid-pid-remove gadget-ffs gadget-export gadget-import show-udcs gadget-ms gadget-midi +bin_PROGRAMS = show-gadgets gadget-acm-ecm gadget_acm_ecm_SOURCES = gadget-acm-ecm.c show_gadgets_SOURCES = show-gadgets.c -gadget_vid_pid_remove_SOURCES = gadget-vid-pid-remove.c -gadget_ffs_SOURCES = gadget-ffs.c -gadget_export_SOURCE = gadget-export.c -gadget_import_SOURCE = gadget-import.c -show_udcs_SOURCE = show-udcs.c -AM_CPPFLAGS=-I$(top_srcdir)/include/ -AM_LDFLAGS=-L../src/ -lusbgx +AM_CPPFLAGS=-I../include/ +AM_LDFLAGS=-L../src/ -lusbg diff --git a/examples/gadget-acm-ecm.c b/examples/gadget-acm-ecm.c index 65407ff..4e8010f 100644 --- a/examples/gadget-acm-ecm.c +++ b/examples/gadget-acm-ecm.c @@ -16,7 +16,6 @@ #include <errno.h> #include <stdio.h> -#include <linux/usb/ch9.h> #include <usbg/usbg.h> /** @@ -38,24 +37,24 @@ int main(void) int usbg_ret; usbg_gadget_attrs g_attrs = { - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_PER_INTERFACE, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = 64, /* Max allowed ep0 packet size */ - .idVendor = VENDOR, - .idProduct = PRODUCT, - .bcdDevice = 0x0001, /* Verson of device */ + 0x0200, /* bcdUSB */ + 0x00, /* Defined at interface level */ + 0x00, /* subclass */ + 0x00, /* device protocol */ + 0x0040, /* Max allowed packet size */ + VENDOR, + PRODUCT, + 0x0001, /* Verson of device */ }; usbg_gadget_strs g_strs = { - .str_ser = "0123456789", /* Serial number */ - .str_mnf = "Foo Inc.", /* Manufacturer */ - .str_prd = "Bar Gadget" /* Product string */ + "0123456789", /* Serial number */ + "Foo Inc.", /* Manufacturer */ + "Bar Gadget" /* Product string */ }; usbg_config_strs c_strs = { - .configuration = "CDC 2xACM+ECM" + "CDC 2xACM+ECM" }; usbg_ret = usbg_init("/sys/kernel/config", &s); diff --git a/examples/gadget-export.c b/examples/gadget-export.c deleted file mode 100644 index 9d51e9e..0000000 --- a/examples/gadget-export.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Krzysztof Opasiak <k.opasiak@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/** - * @file gadget-export.c - * @example gadget-export.c - * This is an example of how to export a gadget to file. - * Common reason of doing this is to share schema of gadget - * between different devices or preserve gadget between reboots. - */ - -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <usbg/usbg.h> - -int main(int argc, char **argv) -{ - usbg_state *s; - usbg_gadget *g; - int ret = -EINVAL; - int usbg_ret; - FILE *output; - - if (argc != 3) { - fprintf(stderr, "Usage: gadget-export gadget_name file_name\n"); - return ret; - } - - /* Prepare output file */ - output = fopen(argv[2], "w"); - if (!output) { - fprintf(stderr, "Error on fopen. Error: %s\n", strerror(errno)); - goto out1; - } - - /* Do gadget exporting */ - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB gadget init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - g = usbg_get_gadget(s, argv[1]); - if (!g) { - fprintf(stderr, "Error on get gadget\n"); - goto out3; - } - - usbg_ret = usbg_export_gadget(g, output); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on export gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out3; - } - - ret = 0; - -out3: - usbg_cleanup(s); -out2: - fclose(output); -out1: - return ret; -} diff --git a/examples/gadget-ffs.c b/examples/gadget-ffs.c deleted file mode 100644 index 6274c15..0000000 --- a/examples/gadget-ffs.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Krzysztof Opasiak <k.opasiak@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/** - * @file gadget-ffs.c - * @example gadget-ffs.c - * This is an example of how to create gadget with FunctionFS based functions - * in two ways. After executing this program gadget will not be enabled - * because ffs instances should be mounted and both descriptors and strings - * should be written to ep0. - * For more details about FunctionFS please refer to FunctionFS documentation - * in linux kernel repository. - */ - -#include <errno.h> -#include <stdio.h> -#include <linux/usb/ch9.h> -#include <usbg/usbg.h> - -#define VENDOR 0x1d6b -#define PRODUCT 0x0104 - -int main(void) -{ - usbg_state *s; - usbg_gadget *g; - usbg_config *c; - usbg_function *f_ffs1, *f_ffs2; - int ret = -EINVAL; - int usbg_ret; - - usbg_gadget_attrs g_attrs = { - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_PER_INTERFACE, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = 64, /* Max allowed ep0 packet size */ - .idVendor = VENDOR, - .idProduct = PRODUCT, - .bcdDevice = 0x0001, /* Verson of device */ - }; - - usbg_gadget_strs g_strs = { - .str_ser = "0123456789", /* Serial number */ - .str_mnf = "Foo Inc.", /* Manufacturer */ - .str_prd = "Bar Gadget" /* Product string */ - }; - - usbg_config_strs c_strs = { - .configuration = "2xFFS" - }; - - usbg_function_attrs f_attrs = { - .attrs.ffs = { - .dev_name = "my_awesome_dev_name", - }, - }; - - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB gadget init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out1; - } - - usbg_ret = usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on create gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_create_function(g, F_FFS, "my_dev_name", NULL, &f_ffs1); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating ffs1 function\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - /* When NULL is passed as instance name, dev_name take from f_attrs - is used as instance name for this function */ - usbg_ret = usbg_create_function(g, F_FFS, NULL, &f_attrs, &f_ffs2); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating ffs2 function\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - /* NULL can be passed to use kernel defaults */ - usbg_ret = usbg_create_config(g, 1, "The only one", NULL, &c_strs, &c); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating config\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_add_config_function(c, "some_name_here", f_ffs1); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error adding ffs1\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_add_config_function(c, "some_name_here_too", f_ffs2); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error adding ffs2\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - fprintf(stdout, "2xFFS gadget has been created.\n" - "Enable it after preparing your functions.\n"); - - /* - * Here we end up with two created ffs instances but they are not - * fully operational. Now we have to do step by step: - * 1) Mount both instances: - * $ mount my_dev_name -t functionfs /path/to/mount/dir1 - * $ mount my_awesome_dev_name -t functionfs /path/to/mount/dir2 - * - * 2) Run ffs daemons for both instances: - * $ my-ffs-daemon /path/to/mount/dir1 - * $ my-ffs-daemon /path/to/mount/dir2 - * - * 3) Enable your gadget: - * $ echo "my_udc_name" > /sys/kernel/config/usb_gadget/g1/UDC - */ - - ret = 0; - -out2: - usbg_cleanup(s); - -out1: - return ret; -} diff --git a/examples/gadget-import.c b/examples/gadget-import.c deleted file mode 100644 index e684fdb..0000000 --- a/examples/gadget-import.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Krzysztof Opasiak <k.opasiak@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/** - * @file gadget-import.c - * @example gadget-import.c - * This is an example of how to import a gadget from file. - * Common reason of doing this is to create gadget base on schema - * from other devices or resurect gadget after reboot. - */ - -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <usbg/usbg.h> - -int main(int argc, char **argv) -{ - usbg_state *s; - int ret = -EINVAL; - int usbg_ret; - FILE *input; - - if (argc != 3) { - fprintf(stderr, "Usage: gadget-import gadget_name file_name\n"); - return ret; - } - - /* Prepare input file */ - input = fopen(argv[2], "r"); - if (!input) { - fprintf(stderr, "Error on fopen. Error: %s\n", strerror(errno)); - goto out1; - } - - /* Do gadget exporting */ - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB gadget init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_import_gadget(s, input, argv[1], NULL); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on import gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - if (usbg_ret == USBG_ERROR_INVALID_FORMAT) - fprintf(stderr, "Line: %d. Error: %s\n", - usbg_get_gadget_import_error_line(s), - usbg_get_gadget_import_error_text(s)); - goto out3; - } - - ret = 0; - -out3: - usbg_cleanup(s); -out2: - fclose(input); -out1: - return ret; -} diff --git a/examples/gadget-midi.c b/examples/gadget-midi.c deleted file mode 100644 index f795de1..0000000 --- a/examples/gadget-midi.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Pawel Szewczyk <p.szewczyk@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <errno.h> -#include <stdio.h> -#include <linux/usb/ch9.h> -#include <usbg/usbg.h> - -#define VENDOR 0x1d6b -#define PRODUCT 0x0104 - -int main() { - usbg_state *s; - usbg_gadget *g; - usbg_config *c; - usbg_function *f_midi; - int ret = -EINVAL; - int usbg_ret; - - usbg_gadget_attrs g_attrs = { - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_PER_INTERFACE, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = 64, /* Max allowed ep0 packet size */ - .idVendor = VENDOR, - .idProduct = PRODUCT, - .bcdDevice = 0x0001, /* Verson of device */ - }; - - usbg_gadget_strs g_strs = { - .str_ser = "0123456789", /* Serial number */ - .str_mnf = "Foo Inc.", /* Manufacturer */ - .str_prd = "Bar Gadget" /* Product string */ - }; - - usbg_config_strs c_strs = { - .configuration = "1xMIDI" - }; - - usbg_function_attrs f_attrs = { - .header.attrs_type = USBG_F_ATTRS_MIDI, - .attrs.midi = { - .index = 0, - .id = "usb0", - .buflen = 128, - .qlen = 16, - .in_ports = 2, - .out_ports = 3, - }, - }; - - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on usbg init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out1; - } - - usbg_ret = usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - usbg_ret = usbg_create_function(g, F_MIDI, "usb0", &f_attrs, &f_midi); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating function\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_create_config(g, 1, "The only one", NULL, &c_strs, &c); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating config\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_add_config_function(c, "some_name", f_midi); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error adding function\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_enable_gadget(g, DEFAULT_UDC); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error enabling gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - ret = 0; -out2: - usbg_cleanup(s); - -out1: - return ret; -} diff --git a/examples/gadget-ms.c b/examples/gadget-ms.c deleted file mode 100644 index d6c4aaf..0000000 --- a/examples/gadget-ms.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Krzysztof Opasiak <k.opasiak@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/** - * @file gadget-ms.c - * @example gadget-ms.c - * This is an example of how to create gadget with mass storage function - * with two luns. - */ - -#include <errno.h> -#include <stdio.h> -#include <linux/usb/ch9.h> -#include <usbg/usbg.h> - -#define VENDOR 0x1d6b -#define PRODUCT 0x0104 - -int main(int argc, char **argv) -{ - usbg_state *s; - usbg_gadget *g; - usbg_config *c; - usbg_function *f_ms; - int ret = -EINVAL; - int usbg_ret; - - usbg_gadget_attrs g_attrs = { - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_PER_INTERFACE, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = 64, /* Max allowed ep0 packet size */ - .idVendor = VENDOR, - .idProduct = PRODUCT, - .bcdDevice = 0x0001, /* Verson of device */ - }; - - usbg_gadget_strs g_strs = { - .str_ser = "0123456789", /* Serial number */ - .str_mnf = "Foo Inc.", /* Manufacturer */ - .str_prd = "Bar Gadget" /* Product string */ - }; - - usbg_f_ms_lun_attrs f_ms_luns_array[] = { - { - .id = -1, /* allows to place in any position */ - .cdrom = 1, - .ro = 0, - .nofua = 0, - .removable = 1, - .filename = "", - }, { - .id = -1, /* allows to place in any position */ - .cdrom = 0, - .ro = 0, - .nofua = 0, - .removable = 1, - .filename = argv[1], - } - }; - - usbg_f_ms_lun_attrs *f_ms_luns[] = { - /* - * When id in lun structure is below 0 we can place it in any - * arbitrary position - */ - &f_ms_luns_array[1], - &f_ms_luns_array[0], - NULL, - }; - - usbg_function_attrs f_attrs = { - .header.attrs_type = USBG_F_ATTRS_MS, - .attrs.ms = { - .stall = 0, - .nluns = 2, - .luns = f_ms_luns, - }, - }; - - usbg_config_strs c_strs = { - "1xMass Storage" - }; - - if (argc < 2) { - fprintf(stderr, "Usage: gadget-ms file\n"); - goto out1; - } - - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB gadget init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out1; - } - - usbg_ret = usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on create gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_create_function(g, F_MASS_STORAGE, "my_reader", - &f_attrs, &f_ms); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating mass storage function\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - /* NULL can be passed to use kernel defaults */ - usbg_ret = usbg_create_config(g, 1, "The only one", NULL, &c_strs, &c); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error creating config\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_add_config_function(c, "some_name_here", f_ms); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error adding ms function\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - usbg_ret = usbg_enable_gadget(g, DEFAULT_UDC); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error enabling gadget\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - ret = 0; - -out2: - usbg_cleanup(s); - -out1: - return ret; -} diff --git a/examples/gadget-vid-pid-remove.c b/examples/gadget-vid-pid-remove.c deleted file mode 100644 index c3f9c9b..0000000 --- a/examples/gadget-vid-pid-remove.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Krzysztof Opasiak <k.opasiak@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/** - * @file gadget-vid-pid-remove.c - * @example gadget-vid-pid-remove.c - * This is an example of how to find and remove an gadget device with given - * Vendor ID and product ID. - */ - -#include <errno.h> -#include <stdio.h> -#include <usbg/usbg.h> - -#define VENDOR 0x1d6b -#define PRODUCT 0x0104 - -int remove_gadget(usbg_gadget *g) -{ - int usbg_ret; - usbg_udc *u; - - /* Check if gadget is enabled */ - u = usbg_get_gadget_udc(g); - - /* If gadget is enable we have to disable it first */ - if (u) { - usbg_ret = usbg_disable_gadget(g); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB disable gadget udc\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out; - } - } - - /* Remove gadget with USBG_RM_RECURSE flag to remove - * also its configurations, functions and strings */ - usbg_ret = usbg_rm_gadget(g, USBG_RM_RECURSE); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB gadget remove\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - } - -out: - return usbg_ret; -} - -int main(void) -{ - int usbg_ret; - int ret = -EINVAL; - usbg_state *s; - usbg_gadget *g; - usbg_gadget_attrs g_attrs; - - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB state init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out1; - } - - g = usbg_get_first_gadget(s); - while (g != NULL) { - /* Get current gadget attrs to be compared */ - usbg_ret = usbg_get_gadget_attrs(g, &g_attrs); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB get gadget attrs\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out2; - } - - /* Compare attrs with given values and remove if suitable */ - if (g_attrs.idVendor == VENDOR && g_attrs.idProduct == PRODUCT) { - usbg_gadget *g_next = usbg_get_next_gadget(g); - - usbg_ret = remove_gadget(g); - if (usbg_ret != USBG_SUCCESS) - goto out2; - - g = g_next; - } else { - g = usbg_get_next_gadget(g); - } - } - -out2: - usbg_cleanup(s); -out1: - return ret; -} diff --git a/examples/show-gadgets.c b/examples/show-gadgets.c index d27cde5..1ae3860 100644 --- a/examples/show-gadgets.c +++ b/examples/show-gadgets.c @@ -29,51 +29,33 @@ void show_gadget(usbg_gadget *g) { - const char *name, *udc; - usbg_udc *u; + char buf[USBG_MAX_STR_LENGTH]; int usbg_ret; usbg_gadget_attrs g_attrs; usbg_gadget_strs g_strs; - name = usbg_get_gadget_name(g); - if (!name) { - fprintf(stderr, "Unable to get gadget name\n"); - return; - } - + usbg_get_gadget_name(g, buf, USBG_MAX_STR_LENGTH); usbg_ret = usbg_get_gadget_attrs(g, &g_attrs); if (usbg_ret != USBG_SUCCESS) { fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); + usbg_strerror(usbg_ret)); return; } fprintf(stdout, "ID %04x:%04x '%s'\n", - g_attrs.idVendor, g_attrs.idProduct, name); + g_attrs.idVendor, g_attrs.idProduct, buf); - u = usbg_get_gadget_udc(g); - if (u) - /* gadget is enabled */ - udc = usbg_get_udc_name(u); - else - /* gadget is disabled */ - udc = "\0"; - - fprintf(stdout, " UDC\t\t\t%s\n", udc); - - fprintf(stdout, " bcdUSB\t\t%x.%02x\n", - g_attrs.bcdUSB >> 8, - g_attrs.bcdUSB & 0x00ff); + usbg_get_gadget_udc(g, buf, USBG_MAX_STR_LENGTH); + fprintf(stdout, " UDC\t\t\t%s\n", buf); fprintf(stdout, " bDeviceClass\t\t0x%02x\n", g_attrs.bDeviceClass); fprintf(stdout, " bDeviceSubClass\t0x%02x\n", g_attrs.bDeviceSubClass); fprintf(stdout, " bDeviceProtocol\t0x%02x\n", g_attrs.bDeviceProtocol); - fprintf(stdout, " bMaxPacketSize0\t%d\n", g_attrs.bMaxPacketSize0); + fprintf(stdout, " bMaxPacketSize0\t0x%02x\n", g_attrs.bMaxPacketSize0); + fprintf(stdout, " bcdDevice\t\t0x%04x\n", g_attrs.bcdDevice); + fprintf(stdout, " bcdUSB\t\t0x%04x\n", g_attrs.bcdUSB); fprintf(stdout, " idVendor\t\t0x%04x\n", g_attrs.idVendor); fprintf(stdout, " idProduct\t\t0x%04x\n", g_attrs.idProduct); - fprintf(stdout, " bcdDevice\t\t%x.%02x\n", - g_attrs.bcdDevice >> 8, - g_attrs.bcdDevice & 0x00ff); usbg_ret = usbg_get_gadget_strs(g, LANG_US_ENG, &g_strs); if (usbg_ret != USBG_SUCCESS) { @@ -81,24 +63,19 @@ void show_gadget(usbg_gadget *g) usbg_strerror(usbg_ret)); return; } + fprintf(stdout, " Serial Number\t\t%s\n", g_strs.str_ser); fprintf(stdout, " Manufacturer\t\t%s\n", g_strs.str_mnf); fprintf(stdout, " Product\t\t%s\n", g_strs.str_prd); - fprintf(stdout, " Serial Number\t\t%s\n", g_strs.str_ser); } void show_function(usbg_function *f) { - const char *instance; + char instance[USBG_MAX_STR_LENGTH]; usbg_function_type type; int usbg_ret; usbg_function_attrs f_attrs; - instance = usbg_get_function_instance(f); - if (!instance) { - fprintf(stderr, "Unable to get function instance name\n"); - return; - } - + usbg_get_function_instance(f, instance, USBG_MAX_STR_LENGTH); type = usbg_get_function_type(f); usbg_ret = usbg_get_function_attrs(f, &f_attrs); if (usbg_ret != USBG_SUCCESS) { @@ -109,90 +86,46 @@ void show_function(usbg_function *f) fprintf(stdout, " Function, type: %s instance: %s\n", usbg_get_function_type_str(type), instance); - - switch (f_attrs.header.attrs_type) { - case USBG_F_ATTRS_SERIAL: + switch (type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: fprintf(stdout, " port_num\t\t%d\n", - f_attrs.attrs.serial.port_num); + f_attrs.serial.port_num); break; - - case USBG_F_ATTRS_NET: - { - usbg_f_net_attrs *f_net_attrs = &f_attrs.attrs.net; - + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: fprintf(stdout, " dev_addr\t\t%s\n", - ether_ntoa(&f_net_attrs->dev_addr)); + ether_ntoa(&f_attrs.net.dev_addr)); fprintf(stdout, " host_addr\t\t%s\n", - ether_ntoa(&f_net_attrs->host_addr)); - fprintf(stdout, " ifname\t\t%s\n", f_net_attrs->ifname); - fprintf(stdout, " qmult\t\t%d\n", f_net_attrs->qmult); + ether_ntoa(&f_attrs.net.host_addr)); + fprintf(stdout, " ifname\t\t%s\n", f_attrs.net.ifname); + fprintf(stdout, " qmult\t\t%d\n", f_attrs.net.qmult); break; - } - - case USBG_F_ATTRS_PHONET: - fprintf(stdout, " ifname\t\t%s\n", f_attrs.attrs.phonet.ifname); + case F_PHONET: + fprintf(stdout, " ifname\t\t%s\n", f_attrs.phonet.ifname); break; - - case USBG_F_ATTRS_FFS: - fprintf(stdout, " dev_name\t\t%s\n", f_attrs.attrs.ffs.dev_name); - break; - - case USBG_F_ATTRS_MS: - { - usbg_f_ms_attrs *attrs = &f_attrs.attrs.ms; - int i; - - fprintf(stdout, " stall\t\t%d\n", attrs->stall); - fprintf(stdout, " nluns\t\t%d\n", attrs->nluns); - for (i = 0; i < attrs->nluns; ++i) { - fprintf(stdout, " lun %d:\n", attrs->luns[i]->id); - fprintf(stdout, " cdrom\t\t%d\n", attrs->luns[i]->cdrom); - fprintf(stdout, " ro\t\t%d\n", attrs->luns[i]->ro); - fprintf(stdout, " nofua\t\t%d\n", attrs->luns[i]->nofua); - fprintf(stdout, " removable\t\t%d\n", attrs->luns[i]->removable); - fprintf(stdout, " file\t\t%s\n", attrs->luns[i]->filename); - } - break; - } - - case USBG_F_ATTRS_MIDI: - { - usbg_f_midi_attrs *attrs = &f_attrs.attrs.midi; - - fprintf(stdout, " index\t\t%d\n", attrs->index); - fprintf(stdout, " id\t\t\t%s\n", attrs->id); - fprintf(stdout, " in_ports\t\t%d\n", attrs->in_ports); - fprintf(stdout, " out_ports\t\t%d\n", attrs->out_ports); - fprintf(stdout, " buflen\t\t%d\n", attrs->buflen); - fprintf(stdout, " qlen\t\t%d\n", attrs->qlen); - break; - } - default: fprintf(stdout, " UNKNOWN\n"); } - - usbg_cleanup_function_attrs(&f_attrs); } void show_config(usbg_config *c) { usbg_binding *b; usbg_function *f; - const char *label, *instance, *bname; + char buf[USBG_MAX_STR_LENGTH], instance[USBG_MAX_STR_LENGTH]; usbg_function_type type; usbg_config_attrs c_attrs; usbg_config_strs c_strs; int usbg_ret, id; - label = usbg_get_config_label(c); - if (!label) { - fprintf(stderr, "Unable to get config label\n"); - return; - } - + usbg_get_config_label(c, buf, USBG_MAX_STR_LENGTH); id = usbg_get_config_id(c); - fprintf(stdout, " Configuration: '%s' ID: %d\n", label, id); + fprintf(stdout, " Configuration: '%s' ID: %d\n", buf, id); usbg_ret = usbg_get_config_attrs(c, &c_attrs); if (usbg_ret != USBG_SUCCESS) { @@ -214,15 +147,11 @@ void show_config(usbg_config *c) fprintf(stdout, " configuration\t%s\n", c_strs.configuration); usbg_for_each_binding(b, c) { - bname = usbg_get_binding_name(b); + usbg_get_binding_name(b, buf, USBG_MAX_STR_LENGTH); f = usbg_get_binding_target(b); - instance = usbg_get_function_instance(f); + usbg_get_function_instance(f, instance, USBG_MAX_STR_LENGTH); type = usbg_get_function_type(f); - if (!bname || !instance) { - fprintf(stderr, "Unable to get binding details\n"); - return; - } - fprintf(stdout, " %s -> %s %s\n", bname, + fprintf(stdout, " %s -> %s %s\n", buf, usbg_get_function_type_str(type), instance); } } diff --git a/examples/show-udcs.c b/examples/show-udcs.c deleted file mode 100644 index 66e950f..0000000 --- a/examples/show-udcs.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2014 Samsung Electronics - * - * Krzysztof Opasiak <k.opasiak@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/** - * @file show-udcs.c - * @example show-udcs.c - * This is an example of how to learn about UDCs available in system - * and find out what gadget are enabled on them. - */ - -#include <errno.h> -#include <stdio.h> -#include <usbg/usbg.h> - -int main(void) -{ - int usbg_ret; - int ret = -EINVAL; - usbg_state *s; - usbg_gadget *g; - usbg_udc *u; - const char *udc_name, *gadget_name; - - usbg_ret = usbg_init("/sys/kernel/config", &s); - if (usbg_ret != USBG_SUCCESS) { - fprintf(stderr, "Error on USB state init\n"); - fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret), - usbg_strerror(usbg_ret)); - goto out; - } - - usbg_for_each_udc(u, s) { - udc_name = usbg_get_udc_name(u); - g = usbg_get_udc_gadget(u); - if (g) - /* some gadget is enabled */ - gadget_name = usbg_get_gadget_name(g); - else - gadget_name = ""; - - fprintf(stdout, "%s <-> %s\n", udc_name, gadget_name); - } - - ret = 0; - usbg_cleanup(s); -out: - return ret; -} diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index bcf221d..1407f10 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -22,20 +22,15 @@ #include <netinet/ether.h> #include <stdint.h> #include <limits.h> -#include <stdbool.h> -#include <stdio.h> /* For FILE * */ - -#ifdef __cplusplus -extern "C" { -#endif /** * @file include/usbg/usbg.h + * @todo Add usbg_remove_[gadget|config|function|binding] APIs * @todo Clean up static buffers in structures */ /** - * @addtogroup libusbgx + * @addtogroup libusbg * Public API for USB gadget-configfs library * @{ */ @@ -44,21 +39,9 @@ extern "C" { #define LANG_US_ENG 0x0409 #define DEFAULT_CONFIG_LABEL "config" -/* This one has to be at least 18 bytes to hold network address */ #define USBG_MAX_STR_LENGTH 256 #define USBG_MAX_PATH_LENGTH PATH_MAX #define USBG_MAX_NAME_LENGTH 40 -/* Dev name for ffs is a part of function name, we subtract 4 char for "ffs." */ -#define USBG_MAX_DEV_LENGTH (USBG_MAX_NAME_LENGTH - 4) -/* ConfigFS just like SysFS uses page size as max size of file content */ -#define USBG_MAX_FILE_SIZE 4096 - -/** - * @brief Additional option for usbg_rm_* functions. - * @details This option allows to remove all content - * of gadget/config/function recursively. - */ -#define USBG_RM_RECURSE 1 /* * Internal structures @@ -68,7 +51,6 @@ struct usbg_gadget; struct usbg_config; struct usbg_function; struct usbg_binding; -struct usbg_udc; /** * @brief State of the gadget devices in the system @@ -96,29 +78,6 @@ typedef struct usbg_function usbg_function; typedef struct usbg_binding usbg_binding; /** - * @brief USB device controller - */ -typedef struct usbg_udc usbg_udc; - -/** - * @typedef usbg_gadget_attr - * @brief Gadget attributes which can be set using - * usbg_set_gadget_attr() function. - */ -typedef enum { - USBG_GADGET_ATTR_MIN = 0, - BCD_USB = USBG_GADGET_ATTR_MIN, - B_DEVICE_CLASS, - B_DEVICE_SUB_CLASS, - B_DEVICE_PROTOCOL, - B_MAX_PACKET_SIZE_0, - ID_VENDOR, - ID_PRODUCT, - BCD_DEVICE, - USBG_GADGET_ATTR_MAX, -} usbg_gadget_attr; - -/** * @typedef usbg_gadget_attrs * @brief USB gadget device attributes */ @@ -134,14 +93,6 @@ typedef struct uint16_t bcdDevice; } usbg_gadget_attrs; -typedef enum { - USBG_GADGET_STR_MIN = 0, - STR_PRODUCT = USBG_GADGET_STR_MIN, - STR_MANUFACTURER, - STR_SERIAL_NUMBER, - USBG_GADGET_STR_MAX, -} usbg_gadget_str; - /** * @typedef usbg_gadget_strs * @brief USB gadget device strings @@ -178,8 +129,7 @@ typedef struct */ typedef enum { - USBG_FUNCTION_TYPE_MIN = 0, - F_SERIAL = USBG_FUNCTION_TYPE_MIN, + F_SERIAL, F_ACM, F_OBEX, F_ECM, @@ -188,11 +138,6 @@ typedef enum F_EEM, F_RNDIS, F_PHONET, - F_FFS, - F_MASS_STORAGE, - F_MIDI, - F_LOOPBACK, - USBG_FUNCTION_TYPE_MAX, } usbg_function_type; /** @@ -210,7 +155,7 @@ typedef struct { typedef struct { struct ether_addr dev_addr; struct ether_addr host_addr; - const char *ifname; + char ifname[USBG_MAX_STR_LENGTH]; int qmult; } usbg_f_net_attrs; @@ -219,66 +164,10 @@ typedef struct { * @brief Attributes for the phonet USB function */ typedef struct { - const char *ifname; + char ifname[USBG_MAX_STR_LENGTH]; } usbg_f_phonet_attrs; /** - * @typedef usbg_f_ffs_attrs - * @brief Attributes for function fs based functions - * @details This is read only and a virtual attribute, it is non present - * on config fs. - */ -typedef struct { - const char *dev_name; -} usbg_f_ffs_attrs; - -/** - * @typedef usbg_f_ms_attrs - * @brief Attributes for mass storage functions - */ -typedef struct usbg_f_ms_lun_attrs { - int id; - bool cdrom; - bool ro; - bool nofua; - bool removable; - const char *filename; -} usbg_f_ms_lun_attrs; - -/** - * @typedef usbg_f_ms_attrs - * @brief Attributes for mass storage functions - */ -typedef struct { - bool stall; - int nluns; - usbg_f_ms_lun_attrs **luns; -} usbg_f_ms_attrs; - -/** - * @typedef usbg_f_midi_attrs - * @brief Attributes for the MIDI function - */ -typedef struct { - int index; - const char *id; - unsigned int in_ports; - unsigned int out_ports; - unsigned int buflen; - unsigned int qlen; -} usbg_f_midi_attrs; - - -/** - * @typedef usbg_f_loopback_attrs - * @brief Attributes for Loopback function - */ -typedef struct { - unsigned int buflen; - unsigned int qlen; -} usbg_f_loopback_attrs; - -/** * @typedef attrs * @brief Attributes for a given function type */ @@ -286,29 +175,6 @@ typedef union { usbg_f_serial_attrs serial; usbg_f_net_attrs net; usbg_f_phonet_attrs phonet; - usbg_f_ffs_attrs ffs; - usbg_f_ms_attrs ms; - usbg_f_midi_attrs midi; - usbg_f_loopback_attrs loopback; -} usbg_f_attrs; - -typedef enum { - USBG_F_ATTRS_SERIAL = 1, - USBG_F_ATTRS_NET, - USBG_F_ATTRS_PHONET, - USBG_F_ATTRS_FFS, - USBG_F_ATTRS_MS, - USBG_F_ATTRS_MIDI, - USBG_F_ATTRS_LOOPBACK, -} usbg_f_attrs_type; - -typedef struct { - int attrs_type; -} usbg_f_attrs_header; - -typedef struct { - usbg_f_attrs_header header; - usbg_f_attrs attrs; } usbg_function_attrs; /* Error codes */ @@ -329,22 +195,17 @@ typedef enum { USBG_ERROR_BUSY = -8, USBG_ERROR_NOT_SUPPORTED = -9, USBG_ERROR_PATH_TOO_LONG = -10, - USBG_ERROR_INVALID_FORMAT = -11, - USBG_ERROR_MISSING_TAG = -12, - USBG_ERROR_INVALID_TYPE = -13, - USBG_ERROR_INVALID_VALUE = -14, - USBG_ERROR_NOT_EMPTY = -15, USBG_ERROR_OTHER_ERROR = -99 } usbg_error; -/** +/* * @brief Get the error name as a constant string * @param e error code * @return Constant string with error name */ extern const char *usbg_error_name(usbg_error e); -/** +/* * @brief Get the short description of error * @param e error code * @return Constant string with error description @@ -354,30 +215,20 @@ extern const char *usbg_strerror(usbg_error e); /* Library init and cleanup */ /** - * @brief Initialize the libusbgx library state + * @brief Initialize the libusbg library state * @param configfs_path Path to the mounted configfs filesystem - * @param state Pointer to be filled with pointer to usbg_state + * @param Pointer to be filled with pointer to usbg_state * @return 0 on success, usbg_error on error */ -extern int usbg_init(const char *configfs_path, usbg_state **state); +extern int usbg_init(char *configfs_path, usbg_state **state); /** - * @brief Clean up the libusbgx library state + * @brief Clean up the libusbg library state * @param s Pointer to state */ extern void usbg_cleanup(usbg_state *s); /** - * @brief Get ConfigFS path - * @param s Pointer to state - * @return Path to configfs or NULL if error occurred - * @warning Returned buffer should not be edited! - * Returned string is valid as long as passed usbg_state is valid. - * For example path is valid until usbg_cleanup() call. - */ -extern const char *usbg_get_configfs_path(usbg_state *s); - -/** * @brief Get ConfigFS path length * @param s Pointer to state * @return Length of path or usbg_error if error occurred. @@ -385,13 +236,13 @@ extern const char *usbg_get_configfs_path(usbg_state *s); extern size_t usbg_get_configfs_path_len(usbg_state *s); /** - * @brief Copy ConfigFS path to buffer + * @brieg Get ConfigFS path * @param s Pointer to state * @param buf Buffer where path should be copied * @param len Length of given buffer * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_cpy_configfs_path(usbg_state *s, char *buf, size_t len); +extern int usbg_get_configfs_path(usbg_state *s, char *buf, size_t len); /* USB gadget queries */ @@ -425,67 +276,6 @@ extern usbg_function *usbg_get_function(usbg_gadget *g, */ extern usbg_config *usbg_get_config(usbg_gadget *g, int id, const char *label); -/** - * @brief Get a udc by name - * @param s Pointer to state - * @param name Name of the udc - * @return Pointer to udc or NULL if a matching udc isn't found - */ -extern usbg_udc *usbg_get_udc(usbg_state *s, const char *name); - -/* USB gadget/config/function/binding removal */ - -/** - * @brief Remove binding between configuration and function - * @details This function frees also the memory allocated for binding - * @param b Binding to be removed - * @return 0 on success, usbg_error if error occurred - */ -extern int usbg_rm_binding(usbg_binding *b); - -/** - * @brief Remove configuration - * @details This function frees also the memory allocated for configuration - * @param c Configuration to be removed - * @param opts Additional options for configuration removal. - * @return 0 on success, usbg_error if error occurred - */ -extern int usbg_rm_config(usbg_config *c, int opts); - -/** - * @brief Remove existing USB function - * @details This function frees also the memory allocated for function - * @param f Function to be removed - * @param opts Additional options for configuration removal. - * @return 0 on success, usbg_error if error occurred - */ -extern int usbg_rm_function(usbg_function *f, int opts); - -/** - * @brief Remove existing USB gadget - * @details This function frees also the memory allocated for gadget - * @param g Gadget to be removed - * @param opts Additional options for configuration removal. - * @return 0 on success, usbg_error if error occurred - */ -extern int usbg_rm_gadget(usbg_gadget *g, int opts); - -/** - * @brief Remove configuration strings for given language - * @param c Pointer to configuration - * @param lang Language of strings which should be deleted - * @return 0 on success, usbg_error if error occurred - */ -extern int usbg_rm_config_strs(usbg_config *c, int lang); - -/** - * @brief Remove gadget strings for given language - * @param g Pointer to gadget - * @param lang Language of strings which should be deleted - * @return 0 on success, usbg_error if error occurred - */ -extern int usbg_rm_gadget_strs(usbg_gadget *g, int lang); - /* USB gadget allocation and configuration */ /** @@ -497,7 +287,7 @@ extern int usbg_rm_gadget_strs(usbg_gadget *g, int lang); * @param g Pointer to be filled with pointer to gadget * @return 0 on success usbg_error if error occurred */ -extern int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, +extern int usbg_create_gadget_vid_pid(usbg_state *s, char *name, uint16_t idVendor, uint16_t idProduct, usbg_gadget **g); /** @@ -511,60 +301,8 @@ extern int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, * @note Given strings are assumed to be in US English * @return 0 on success usbg_error if error occurred */ -extern int usbg_create_gadget(usbg_state *s, const char *name, - const usbg_gadget_attrs *g_attrs, const usbg_gadget_strs *g_strs, - usbg_gadget **g); - -/** - * @brief Get string representing selected gadget attribute - * @param attr code of selected attribute - * @return String suitable for given attribute or NULL if such - * string has not been found - */ -extern const char *usbg_get_gadget_attr_str(usbg_gadget_attr attr); - -/** - * @brief Lookup attr code based on its name - * @param name of attribute - * @return code of suitable attribute or usbg_error - */ -extern int usbg_lookup_gadget_attr(const char *name); - -/** - * @brief Lookup str code based on its name - * @param name of string - * @return code of suitable string or usbg_error - */ -extern int usbg_lookup_gadget_str(const char *name); - -/** - * @brief Get name of selected gadget string - * @param str Gadget string code - * @return Name of string associated with this code - */ -extern const char *usbg_get_gadget_str_name(usbg_gadget_str str); - -/** - * @brief Set selected attribute to value - * @param g Pointer to gadget - * @param attr Code of selected attribute - * @param val value to be set - * @return 0 on success, usbg_error otherwise - * @note val is of type int but value provided to this function should - * be suitable to place it in type dedicated for selected attr (uint16 or uint8) - */ -extern int usbg_set_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr, int val); - -/** - * @brief Get value of selected attribute - * @param g Pointer to gadget - * @param attr Code of selected attribute - * @return Value of selected attribute (always above zero) or - * usbg_error if error occurred. - * @note User should use only lowest one or two bytes as attribute value - * depending on attribute size (see usbg_gadget_attrs for details). - */ -extern int usbg_get_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr); +extern int usbg_create_gadget(usbg_state *s, char *name, + usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, usbg_gadget **g); /** * @brief Set the USB gadget attributes @@ -573,7 +311,7 @@ extern int usbg_get_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr); * @return 0 on success usbg_error if error occurred */ extern int usbg_set_gadget_attrs(usbg_gadget *g, - const usbg_gadget_attrs *g_attrs); + usbg_gadget_attrs *g_attrs); /** * @brief Get the USB gadget strings @@ -584,16 +322,6 @@ extern int usbg_set_gadget_attrs(usbg_gadget *g, extern int usbg_get_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs); /** - * @brief Get gadget name - * @param g Pointer to gadget - * @return Gadget name or NULL if error occurred. - * @warning Returned buffer should not be edited! - * Returned string is valid as long as passed usbg_gadget is valid. - * For example gadget name is valid until someone remove gadget. - */ -extern const char *usbg_get_gadget_name(usbg_gadget *g); - -/** * @brief Get gadget name length * @param g Gadget which name length should be returned * @return Length of name string or usbg_error if error occurred. @@ -601,13 +329,13 @@ extern const char *usbg_get_gadget_name(usbg_gadget *g); extern size_t usbg_get_gadget_name_len(usbg_gadget *g); /** - * @brief Copy gadget name - * @param g Pointer to gadget + * @brieg Get gadget name + * @param b Pointer to gadget * @param buf Buffer where name should be copied * @param len Length of given buffer * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_cpy_gadget_name(usbg_gadget *g, char *buf, size_t len); +extern int usbg_get_gadget_name(usbg_gadget *g, char *buf, size_t len); /** * @brief Set the USB gadget vendor id @@ -682,31 +410,21 @@ extern int usbg_set_gadget_device_bcd_usb(usbg_gadget *g, uint16_t bcdUSB); * @brief Get the USB gadget strings * @param g Pointer to gadget * @param lang Language of strings - * @param g_strs Structure to be filled + * @param g_sttrs Structure to be filled * @return 0 on success usbg_error if error occurred */ extern int usbg_get_gadget_strs(usbg_gadget *g, int lang, usbg_gadget_strs *g_strs); /** - * @brief Set selected string - * @param g Pointer to gadget - * @param str Code of selected string - * @param val value to be set - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_set_gadget_str(usbg_gadget *g, usbg_gadget_str str, int lang, - const char *val); - -/** * @brief Set the USB gadget strings * @param g Pointer to gadget * @param lang USB language ID - * @param g_strs Gadget attributes + * @param g_sttrs Gadget attributes * @return 0 on success usbg_error if error occurred */ extern int usbg_set_gadget_strs(usbg_gadget *g, int lang, - const usbg_gadget_strs *g_strs); + usbg_gadget_strs *g_strs); /** * @brief Set the serial number for a gadget @@ -715,8 +433,7 @@ extern int usbg_set_gadget_strs(usbg_gadget *g, int lang, * @param ser Serial number * @return 0 on success usbg_error if error occurred */ -extern int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, - const char *ser); +extern int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *ser); /** * @brief Set the manufacturer name for a gadget @@ -725,8 +442,7 @@ extern int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, * @param mnf Manufacturer * @return 0 on success usbg_error if error occurred */ -extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, - const char *mnf); +extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, char *mnf); /** * @brief Set the product name for a gadget @@ -735,8 +451,7 @@ extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, * @param prd Product * @return 0 on success usbg_error if error occurred */ -extern int usbg_set_gadget_product(usbg_gadget *g, int lang, - const char *prd); +extern int usbg_set_gadget_product(usbg_gadget *g, int lang, char *prd); /* USB function allocation and configuration */ @@ -751,18 +466,7 @@ extern int usbg_set_gadget_product(usbg_gadget *g, int lang, * @return 0 on success usbg_error if error occurred */ extern int usbg_create_function(usbg_gadget *g, usbg_function_type type, - const char *instance, const usbg_function_attrs *f_attrs, - usbg_function **f); - -/** - * @brief Get function instance name - * @param f Pointer to function - * @return instance name or NULL if error occurred. - * @warning Returned buffer should not be edited! - * Returned string is valid as long as passed usbg_function is valid. - * For example instance name is valid until someone remove this function. - */ -extern const char *usbg_get_function_instance(usbg_function *f); + char *instance, usbg_function_attrs *f_attrs, usbg_function **f); /** * @brief Get function instance name length @@ -772,13 +476,13 @@ extern const char *usbg_get_function_instance(usbg_function *f); extern size_t usbg_get_function_instance_len(usbg_function *f); /** - * @brief Copy function instance name + * @brief Get function instance name * @param f Pointer to function * @param buf Buffer where instance name should be copied * @param len Length of given buffer * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_cpy_function_instance(usbg_function *f, char *buf, size_t len); +extern int usbg_get_function_instance(usbg_function *f, char *buf, size_t len); /** * @brief Get function type as a string @@ -787,30 +491,6 @@ extern int usbg_cpy_function_instance(usbg_function *f, char *buf, size_t len); */ extern const char *usbg_get_function_type_str(usbg_function_type type); -/** - * @brief Lookup function type suitable for given name - * @param name Name of function - * @return Function type enum or negative error code - */ -extern int usbg_lookup_function_type(const char *name); - -/** - * @brief Lookup attrs type for given type of function - * @param f_type type of functions - * @return Attributes type for this type of function - */ -extern int usbg_lookup_function_attrs_type(int f_type); - -/** - * @brief Cleanup content of function attributes - * @param f_attrs function attributes which should be cleaned up. - * @note This function should be called to free - * additional memory allocated by usbg_get_function_attrs(). - * @warning None of attributes in passed structure should be - * accessed after returning from this function. - */ -extern void usbg_cleanup_function_attrs(usbg_function_attrs *f_attrs); - /* USB configurations allocation and configuration */ /** @@ -825,18 +505,7 @@ extern void usbg_cleanup_function_attrs(usbg_function_attrs *f_attrs); * @return 0 on success usbg_error if error occurred */ extern int usbg_create_config(usbg_gadget *g, int id, const char *label, - const usbg_config_attrs *c_attrs, const usbg_config_strs *c_strs, - usbg_config **c); - -/** - * @brief Get config label - * @param c Pointer to config - * @return config label or NULL if error occurred. - * @warning Returned buffer should not be edited! - * Returned string is valid as long as passed usbg_config is valid. - * For example config label is valid until someone remove this function. - */ -extern const char *usbg_get_config_label(usbg_config *c); + usbg_config_attrs *c_attrs, usbg_config_strs *c_strs, usbg_config **c); /** * @brief Get config label length @@ -846,16 +515,16 @@ extern const char *usbg_get_config_label(usbg_config *c); extern size_t usbg_get_config_label_len(usbg_config *c); /** - * @brief Copy config label + * @brieg Get config label * @param c Pointer to config * @param buf Buffer where label should be copied * @param len Length of given buffer * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_cpy_config_label(usbg_config *c, char *buf, size_t len); +extern int usbg_get_config_label(usbg_config *c, char *buf, size_t len); /** - * @brief Get config id + * @brieg Get config id * @param c Pointer to config * @return Configuration id or usbg_error if error occurred. */ @@ -868,7 +537,7 @@ extern int usbg_get_config_id(usbg_config *c); * @return 0 on success or usbg_error if error occurred. */ extern int usbg_set_config_attrs(usbg_config *c, - const usbg_config_attrs *c_attrs); + usbg_config_attrs *c_attrs); /** * @brief Get the USB configuration strings @@ -898,7 +567,7 @@ extern int usbg_set_config_bm_attrs(usbg_config *c, int bmAttributes); * @brief Get the USB configuration strings * @param c Pointer to configuration * @param lang Language of strings - * @param c_strs Structure to be filled + * @param c_sttrs Structure to be filled * @return 0 on success or usbg_error if error occurred. */ extern int usbg_get_config_strs(usbg_config *c, int lang, @@ -908,11 +577,11 @@ extern int usbg_get_config_strs(usbg_config *c, int lang, * @brief Set the USB configuration strings * @param c Pointer to configuration * @param lang USB language ID - * @param c_strs Configuration strings + * @param c_sttrs Configuration strings * @return 0 on success, usbg_error on failure. */ extern int usbg_set_config_strs(usbg_config *c, int lang, - const usbg_config_strs *c_strs); + usbg_config_strs *c_strs); /** * @brief Set the configuration string @@ -921,7 +590,7 @@ extern int usbg_set_config_strs(usbg_config *c, int lang, * @param string Configuration description * @return 0 on success, usbg_error on failure. */ -extern int usbg_set_config_string(usbg_config *c, int lang, const char *string); +extern int usbg_set_config_string(usbg_config *c, int lang, char *string); /** * @brief Add a function to a configuration @@ -930,8 +599,7 @@ extern int usbg_set_config_string(usbg_config *c, int lang, const char *string); * @param f Pointer to function * @return 0 on success, usbg_error on failure. */ -extern int usbg_add_config_function(usbg_config *c, const char *name, - usbg_function *f); +extern int usbg_add_config_function(usbg_config *c, char *name, usbg_function *f); /** * @brief Get target function of given binding @@ -941,16 +609,6 @@ extern int usbg_add_config_function(usbg_config *c, const char *name, extern usbg_function *usbg_get_binding_target(usbg_binding *b); /** - * @brief Get binding name - * @param b Pointer to binding - * @return Binding name or NULL if error occurred. - * @warning Returned buffer should not be edited! - * Returned string is valid as long as passed usbg_binding is valid. - * For example binding name is valid until someone remove this binding. - */ -extern const char *usbg_get_binding_name(usbg_binding *b); - -/** * @brief Get binding name length * @param b Binding which name length should be returned * @return Length of name string or usbg_error if error occurred. @@ -958,24 +616,30 @@ extern const char *usbg_get_binding_name(usbg_binding *b); extern size_t usbg_get_binding_name_len(usbg_binding *b); /** - * @brief Copy binding name + * @brief Get binding name * @param b Pointer to binding * @param buf Buffer where name should be copied * @param len Length of given buffer * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_cpy_binding_name(usbg_binding *b, char *buf, size_t len); +extern int usbg_get_binding_name(usbg_binding *b, char *buf, size_t len); /* USB gadget setup and teardown */ /** + * @brief Get a list of UDC devices on the system + * @param udc_list Pointer to pointer to dirent pointer + * @return Number of UDC devices on success, usbg_error on failure + */ +extern int usbg_get_udcs(struct dirent ***udc_list); + +/** * @brief Enable a USB gadget device * @param g Pointer to gadget - * @param udc where gadget should be assigned. - * If NULL, default one (first) is used. + * @param udc Name of UDC to enable gadget * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_enable_gadget(usbg_gadget *g, usbg_udc *udc); +extern int usbg_enable_gadget(usbg_gadget *g, char *udc); /** * @brief Disable a USB gadget device @@ -985,16 +649,6 @@ extern int usbg_enable_gadget(usbg_gadget *g, usbg_udc *udc); extern int usbg_disable_gadget(usbg_gadget *g); /** - * @brief Get name of udc - * @param u Pointer to udc - * @return UDC name or NULL if error occurred. - * @warning Returned buffer should not be edited! - * Returned string is valid as long as passed usbg_state is valid. - * For example UDC name is valid until usbg_cleanup(). - */ -extern const char *usbg_get_udc_name(usbg_udc *u); - -/** * @brief Get gadget name length * @param g Gadget which name length should be returned * @return Length of name string or usbg_error if error occurred. @@ -1003,27 +657,14 @@ extern const char *usbg_get_udc_name(usbg_udc *u); extern size_t usbg_get_gadget_udc_len(usbg_gadget *g); /** - * @brief Copy name of udc - * @param u Pointer to udc + * @brieg Get name of udc to which gadget is binded + * @param b Pointer to gadget * @param buf Buffer where udc name should be copied * @param len Length of given buffer * @return 0 on success or usbg_error if error occurred. + * @note If gadget isn't enabled on any udc returned string is empty. */ -extern int usbg_cpy_udc_name(usbg_udc *u, char *buf, size_t len); - -/** - * @brief Get udc to which gadget is bound - * @param g Pointer to gadget - * @return Pointer to UDC or NULL if gadget is not enabled - */ -extern usbg_udc *usbg_get_gadget_udc(usbg_gadget *g); - -/** - * @brief Get gadget which is attached to this UDC - * @param u Pointer to udc - * @return Pointer to gadget or NULL if UDC is free - */ -extern usbg_gadget *usbg_get_udc_gadget(usbg_udc *u); +extern int usbg_get_gadget_udc(usbg_gadget *g, char *buf, size_t len); /* * USB function-specific attribute configuration @@ -1052,8 +693,7 @@ extern int usbg_get_function_attrs(usbg_function *f, * @param f_attrs Attributes to be set * @return 0 on success, usbg_error if error occurred */ -extern int usbg_set_function_attrs(usbg_function *f, - const usbg_function_attrs *f_attrs); +extern int usbg_set_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs); /** * @brief Set USB function network device address @@ -1116,15 +756,6 @@ extern int usbg_set_net_qmult(usbg_function *f, int qmult); b = usbg_get_next_binding(b)) /** - * @def usbg_for_each_udc(b, c) - * Iterates over each udc - */ -#define usbg_for_each_udc(u, s) \ - for (u = usbg_get_first_udc(s); \ - u != NULL; \ - u = usbg_get_next_udc(u)) - -/** * @brief Get first gadget in gadget list * @param s State of library * @return Pointer to gadget or NULL if list is empty. @@ -1150,164 +781,41 @@ extern usbg_config *usbg_get_first_config(usbg_gadget *g); /** * @brief Get first binding in binding list - * @param c Pointer to configuration + * @param C Pointer to configuration * @return Pointer to binding or NULL if list is empty. * @note Bindings are sorted in strings (name) order */ extern usbg_binding *usbg_get_first_binding(usbg_config *c); /** - * @brief Get first udc in udc list - * @param s State of library - * @return Pointer to udc or NULL if list is empty. - * @note UDCs are sorted in strings (name) order - */ -extern usbg_udc *usbg_get_first_udc(usbg_state *s); - -/** * @brief Get the next gadget on a list. - * @param g Pointer to current gadget + * @pram g Pointer to current gadget * @return Next gadget or NULL if end of list. */ extern usbg_gadget *usbg_get_next_gadget(usbg_gadget *g); /** * @brief Get the next function on a list. - * @param f Pointer to current function + * @pram g Pointer to current function * @return Next function or NULL if end of list. */ extern usbg_function *usbg_get_next_function(usbg_function *f); /** * @brief Get the next config on a list. - * @param c Pointer to current config + * @pram g Pointer to current config * @return Next config or NULL if end of list. */ extern usbg_config *usbg_get_next_config(usbg_config *c); /** * @brief Get the next binding on a list. - * @param b Pointer to current binding + * @pram g Pointer to current binding * @return Next binding or NULL if end of list. */ extern usbg_binding *usbg_get_next_binding(usbg_binding *b); /** - * @brief Get the next udc on a list. - * @param u Pointer to current udc - * @return Next udc or NULL if end of list. - */ -extern usbg_udc *usbg_get_next_udc(usbg_udc *u); - -/* Import / Export API */ - -/** - * @brief Exports usb function to file - * @param f Pointer to function to be exported - * @param stream where function should be saved - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_export_function(usbg_function *f, FILE *stream); - -/** - * @brief Exports configuration to file - * @param c Pointer to configuration to be exported - * @param stream where configuration should be saved - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_export_config(usbg_config *c, FILE *stream); - -/** - * @brief Exports whole gadget to file - * @param g Pointer to gadget to be exported - * @param stream where gadget should be saved - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_export_gadget(usbg_gadget *g, FILE *stream); - -/** - * @brief Imports usb function from file and adds it to given gadget - * @param g Gadget where function should be placed - * @param stream from which function should be imported - * @param instance name which should be used for new function - * @param f place for pointer to imported function - * if NULL this param will be ignored. - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_import_function(usbg_gadget *g, FILE *stream, - const char *instance, usbg_function **f); - -/** - * @brief Imports usb configuration from file and adds it to given gadget - * @param g Gadget where configuration should be placed - * @param stream from which configuration should be imported - * @param id which should be used for new configuration - * @param c place for pointer to imported configuration - * if NULL this param will be ignored. - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_import_config(usbg_gadget *g, FILE *stream, int id, - usbg_config **c); -/** - * @brief Imports usb gadget from file - * @param s current state of library - * @param stream from which gadget should be imported - * @param name which should be used for new gadget - * @param g place for pointer to imported gadget - * if NULL this param will be ignored. - * @return 0 on success, usbg_error otherwise - */ -extern int usbg_import_gadget(usbg_state *s, FILE *stream, - const char *name, usbg_gadget **g); - -/** - * @brief Get text of error which occurred during last function import - * @param g gadget where function import error occurred - * @return Text of error or NULL if no error data - */ -extern const char *usbg_get_func_import_error_text(usbg_gadget *g); - -/** - * @brief Get line number where function import error occurred - * @param g gadget where function import error occurred - * @return line number or value below 0 if no error data - */ -extern int usbg_get_func_import_error_line(usbg_gadget *g); - -/** - * @brief Get text of error which occurred during last config import - * @param g gadget where config import error occurred - * @return Text of error or NULL if no error data - */ -extern const char *usbg_get_config_import_error_text(usbg_gadget *g); - -/** - * @brief Get line number where config import error occurred - * @param g gadget where config import error occurred - * @return line number or value below 0 if no error data - */ -extern int usbg_get_config_import_error_line(usbg_gadget *g); - -/** - * @brief Get text of error which occurred during last gadget import - * @param s where gadget import error occurred - * @return Text of error or NULL if no error data - */ -extern const char *usbg_get_gadget_import_error_text(usbg_state *s); - -/** - * @brief Get line number where gadget import error occurred - * @param s where gadget import error occurred - * @return line number or value below 0 if no error data - */ -extern int usbg_get_gadget_import_error_line(usbg_state *s); - -/** * @} */ - -#ifdef __cplusplus -} -#endif - #endif /* __USBG_H__ */ diff --git a/include/usbg/usbg_internal.h b/include/usbg/usbg_internal.h deleted file mode 100644 index 30d3fcf..0000000 --- a/include/usbg/usbg_internal.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -#ifndef USBG_INTERNAL_H -#define USBG_INTERNAL_H - -#include <sys/queue.h> -#include <string.h> -#include <usbg/usbg.h> - -#ifdef HAS_LIBCONFIG -#include <libconfig.h> -#else - typedef struct _should_not_be_used config_t; - void config_destroy(config_t *config); -#endif - -/** - * @file include/usbg/usbg_internal.h - */ - -#ifndef offsetof -#define offsetof(type, member) __builtin_offsetof (type, member) -#endif /* offsetof */ - -#ifndef container_of -#define container_of(ptr, type, field) ({ \ - const typeof(((type *)0)->field) *member = (ptr); \ - (type *)( (char *)member - offsetof(type, field) ); \ - }) -#endif /* container_of */ - -struct usbg_state -{ - char *path; - char *configfs_path; - - TAILQ_HEAD(ghead, usbg_gadget) gadgets; - TAILQ_HEAD(uhead, usbg_udc) udcs; - config_t *last_failed_import; -}; - -struct usbg_gadget -{ - char *name; - char *path; - - TAILQ_ENTRY(usbg_gadget) gnode; - TAILQ_HEAD(chead, usbg_config) configs; - TAILQ_HEAD(fhead, usbg_function) functions; - usbg_state *parent; - config_t *last_failed_import; - usbg_udc *udc; -}; - -struct usbg_config -{ - TAILQ_ENTRY(usbg_config) cnode; - TAILQ_HEAD(bhead, usbg_binding) bindings; - usbg_gadget *parent; - - char *name; - char *path; - char *label; - int id; -}; - -typedef int (*usbg_rm_function_callback)(usbg_function *, int); - -struct usbg_function -{ - TAILQ_ENTRY(usbg_function) fnode; - usbg_gadget *parent; - - char *name; - char *path; - char *instance; - /* Only for internal library usage */ - char *label; - usbg_function_type type; - usbg_rm_function_callback rm_callback; -}; - -struct usbg_binding -{ - TAILQ_ENTRY(usbg_binding) bnode; - usbg_config *parent; - usbg_function *target; - - char *name; - char *path; -}; - -struct usbg_udc -{ - TAILQ_ENTRY(usbg_udc) unode; - usbg_state *parent; - usbg_gadget *gadget; - - char *name; -}; - -#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array)) - -#define ARRAY_SIZE_SENTINEL(array, size) \ - static void __attribute__ ((unused)) array##_size_sentinel() \ - { \ - char array##_smaller_than_expected[ \ - (int)(ARRAY_SIZE(array) - size)] \ - __attribute__ ((unused)); \ - \ - char array##_larger_than_expected[ \ - (int)(size - ARRAY_SIZE(array))] \ - __attribute__ ((unused)); \ - } - -#define ERROR(msg, ...) do {\ - fprintf(stderr, "%s() "msg" \n", \ - __func__, ##__VA_ARGS__);\ - fflush(stderr);\ - } while (0) - -#define ERRORNO(msg, ...) do {\ - fprintf(stderr, "%s() %s: "msg" \n", \ - __func__, strerror(errno), ##__VA_ARGS__);\ - fflush(stderr);\ - } while (0) - -/* Insert in string order */ -#define INSERT_TAILQ_STRING_ORDER(HeadPtr, HeadType, NameField, ToInsert, NodeField) \ - do { \ - if (TAILQ_EMPTY((HeadPtr)) || \ - (strcmp((ToInsert)->NameField, TAILQ_FIRST((HeadPtr))->NameField) < 0)) \ - TAILQ_INSERT_HEAD((HeadPtr), (ToInsert), NodeField); \ - else if (strcmp((ToInsert)->NameField, TAILQ_LAST((HeadPtr), HeadType)->NameField) > 0) \ - TAILQ_INSERT_TAIL((HeadPtr), (ToInsert), NodeField); \ - else { \ - typeof(ToInsert) _cur; \ - TAILQ_FOREACH(_cur, (HeadPtr), NodeField) { \ - if (strcmp((ToInsert)->NameField, _cur->NameField) > 0) \ - continue; \ - TAILQ_INSERT_BEFORE(_cur, (ToInsert), NodeField); \ - } \ - } \ - } while (0) - -#define STRINGS_DIR "strings" -#define CONFIGS_DIR "configs" -#define FUNCTIONS_DIR "functions" -#define GADGETS_DIR "usb_gadget" - -static inline int file_select(const struct dirent *dent) -{ - if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0)) - return 0; - else - return 1; -} - -int usbg_translate_error(int error); - -char *usbg_ether_ntoa_r(const struct ether_addr *addr, char *buf); - -#endif /* USBG_INTERNAL_H */ - diff --git a/libusbgx.pc.in b/libusbg.pc.in index 8ea8fb5..46eb245 100644 --- a/libusbgx.pc.in +++ b/libusbg.pc.in @@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: libusbgx +Name: libusbg Description: USB gadget-configfs library -Requires: libconfig +Requires: Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lusbg Cflags: -I${includedir} diff --git a/src/Makefile.am b/src/Makefile.am index b1eb951..d955a4c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,4 @@ -lib_LTLIBRARIES = libusbgx.la -libusbgx_la_SOURCES = usbg.c -if TEST_GADGET_SCHEMES -libusbgx_la_SOURCES += usbg_schemes_libconfig.c -else -libusbgx_la_SOURCES += usbg_schemes_none.c -endif -libusbgx_la_LDFLAGS = $(LIBCONFIG_LIBS) -libusbgx_la_LDFLAGS += -version-info 0:0:0 -libusbgx_la_CFLAGS = $(LIBCONFIG_CFLAGS) -AM_CPPFLAGS=-I$(top_srcdir)/include/ +lib_LTLIBRARIES = libusbg.la +libusbg_la_SOURCES = usbg.c +libusbg_la_LDFLAGS = -version-info 0:1:0 +AM_CPPFLAGS=-I../include/ @@ -16,7 +16,7 @@ #include <dirent.h> #include <errno.h> - +#include <usbg/usbg.h> #include <netinet/ether.h> #include <stdio.h> #include <stdlib.h> @@ -26,13 +26,68 @@ #include <sys/stat.h> #include <unistd.h> #include <ctype.h> -#include <stdbool.h> -#include "usbg/usbg_internal.h" + +#define STRINGS_DIR "strings" +#define CONFIGS_DIR "configs" +#define FUNCTIONS_DIR "functions" /** * @file usbg.c + * @todo Handle buffer overflows */ +struct usbg_state +{ + char *path; + + TAILQ_HEAD(ghead, usbg_gadget) gadgets; +}; + +struct usbg_gadget +{ + char *name; + char *path; + char udc[USBG_MAX_STR_LENGTH]; + + TAILQ_ENTRY(usbg_gadget) gnode; + TAILQ_HEAD(chead, usbg_config) configs; + TAILQ_HEAD(fhead, usbg_function) functions; + usbg_state *parent; +}; + +struct usbg_config +{ + TAILQ_ENTRY(usbg_config) cnode; + TAILQ_HEAD(bhead, usbg_binding) bindings; + usbg_gadget *parent; + + char *name; + char *path; + char *label; + int id; +}; + +struct usbg_function +{ + TAILQ_ENTRY(usbg_function) fnode; + usbg_gadget *parent; + + char *name; + char *path; + char *instance; + + usbg_function_type type; +}; + +struct usbg_binding +{ + TAILQ_ENTRY(usbg_binding) bnode; + usbg_config *parent; + usbg_function *target; + + char *name; + char *path; +}; /** * @var function_names @@ -49,38 +104,39 @@ const char *function_names[] = "eem", "rndis", "phonet", - "ffs", - "mass_storage", - "midi", - "Loopback", -}; - -ARRAY_SIZE_SENTINEL(function_names, USBG_FUNCTION_TYPE_MAX); - -const char *gadget_attr_names[] = -{ - "bcdUSB", - "bDeviceClass", - "bDeviceSubClass", - "bDeviceProtocol", - "bMaxPacketSize0", - "idVendor", - "idProduct", - "bcdDevice" -}; - -ARRAY_SIZE_SENTINEL(gadget_attr_names, USBG_GADGET_ATTR_MAX); - -const char *gadget_str_names[] = -{ - "product", - "manufacturer", - "serialnumber", }; -ARRAY_SIZE_SENTINEL(gadget_str_names, USBG_GADGET_STR_MAX); - -int usbg_translate_error(int error) +#define ERROR(msg, ...) do {\ + fprintf(stderr, "%s() "msg" \n", \ + __func__, ##__VA_ARGS__);\ + fflush(stderr);\ + } while (0) + +#define ERRORNO(msg, ...) do {\ + fprintf(stderr, "%s() %s: "msg" \n", \ + __func__, strerror(errno), ##__VA_ARGS__);\ + fflush(stderr);\ + } while (0) + +/* Insert in string order */ +#define INSERT_TAILQ_STRING_ORDER(HeadPtr, HeadType, NameField, ToInsert, NodeField) \ + do { \ + if (TAILQ_EMPTY((HeadPtr)) || \ + (strcmp((ToInsert)->NameField, TAILQ_FIRST((HeadPtr))->NameField) < 0)) \ + TAILQ_INSERT_HEAD((HeadPtr), (ToInsert), NodeField); \ + else if (strcmp((ToInsert)->NameField, TAILQ_LAST((HeadPtr), HeadType)->NameField) > 0) \ + TAILQ_INSERT_TAIL((HeadPtr), (ToInsert), NodeField); \ + else { \ + typeof(ToInsert) _cur; \ + TAILQ_FOREACH(_cur, (HeadPtr), NodeField) { \ + if (strcmp((ToInsert)->NameField, _cur->NameField) > 0) \ + continue; \ + TAILQ_INSERT_BEFORE(_cur, (ToInsert), NodeField); \ + } \ + } \ + } while (0) + +static int usbg_translate_error(int error) { int ret; @@ -90,14 +146,12 @@ int usbg_translate_error(int error) break; case EACCES: case EROFS: - case EPERM: ret = USBG_ERROR_NO_ACCESS; break; case ENOENT: case ENOTDIR: ret = USBG_ERROR_NOT_FOUND; break; - case ERANGE: case EINVAL: case USBG_ERROR_INVALID_PARAM: ret = USBG_ERROR_INVALID_PARAM; @@ -114,9 +168,6 @@ int usbg_translate_error(int error) case EBUSY: ret = USBG_ERROR_BUSY; break; - case ENOTEMPTY: - ret = USBG_ERROR_NOT_EMPTY; - break; default: ret = USBG_ERROR_OTHER_ERROR; } @@ -162,21 +213,6 @@ const char *usbg_error_name(usbg_error e) case USBG_ERROR_PATH_TOO_LONG: ret = "USBG_ERROR_PATH_TOO_LONG"; break; - case USBG_ERROR_INVALID_FORMAT: - ret = "USBG_ERROR_INVALID_FORMAT"; - break; - case USBG_ERROR_MISSING_TAG: - ret = "USBG_ERROR_MISSING_TAG"; - break; - case USBG_ERROR_INVALID_TYPE: - ret = "USBG_ERROR_INVALID_TYPE"; - break; - case USBG_ERROR_INVALID_VALUE: - ret = "USBG_ERROR_INVALID_VALUE"; - break; - case USBG_ERROR_NOT_EMPTY: - ret = "USBG_ERROR_NOT_EMPTY"; - break; case USBG_ERROR_OTHER_ERROR: ret = "USBG_ERROR_OTHER_ERROR"; break; @@ -223,21 +259,6 @@ const char *usbg_strerror(usbg_error e) case USBG_ERROR_PATH_TOO_LONG: ret = "Created path was too long to process it."; break; - case USBG_ERROR_INVALID_FORMAT: - ret = "Given file has incompatible format."; - break; - case USBG_ERROR_MISSING_TAG: - ret = "One of mandatory tags is missing."; - break; - case USBG_ERROR_INVALID_TYPE: - ret = "One of attributes has incompatible type."; - break; - case USBG_ERROR_INVALID_VALUE: - ret = "Incorrect value provided as attribute."; - break; - case USBG_ERROR_NOT_EMPTY: - ret = "Entity is not empty."; - break; case USBG_ERROR_OTHER_ERROR: ret = "Other error"; break; @@ -246,112 +267,30 @@ const char *usbg_strerror(usbg_error e) return ret; } -int usbg_lookup_function_attrs_type(int f_type) -{ - int ret; - - switch (f_type) { - case F_SERIAL: - case F_ACM: - case F_OBEX: - ret = USBG_F_ATTRS_SERIAL; - break; - case F_ECM: - case F_SUBSET: - case F_NCM: - case F_EEM: - case F_RNDIS: - ret = USBG_F_ATTRS_NET; - break; - case F_PHONET: - ret = USBG_F_ATTRS_PHONET; - break; - case F_FFS: - ret = USBG_F_ATTRS_FFS; - break; - case F_MASS_STORAGE: - ret = USBG_F_ATTRS_MS; - break; - case F_MIDI: - ret = USBG_F_ATTRS_MIDI; - break; - case F_LOOPBACK: - ret = USBG_F_ATTRS_LOOPBACK; - break; - default: - ret = USBG_ERROR_NOT_SUPPORTED; - } - - return ret; -} - -int usbg_lookup_function_type(const char *name) +static int usbg_lookup_function_type(char *name) { - int i = USBG_FUNCTION_TYPE_MIN; + int i = 0; + int max = sizeof(function_names)/sizeof(char *); if (!name) - return USBG_ERROR_INVALID_PARAM; + return -1; do { if (!strcmp(name, function_names[i])) - return i; - i++; - } while (i != USBG_FUNCTION_TYPE_MAX); - - return USBG_ERROR_NOT_FOUND; -} - -const char *usbg_get_function_type_str(usbg_function_type type) -{ - return type >= USBG_FUNCTION_TYPE_MIN && - type < USBG_FUNCTION_TYPE_MAX ? - function_names[type] : NULL; -} - -int usbg_lookup_gadget_attr(const char *name) -{ - int i = USBG_GADGET_ATTR_MIN; - - if (!name) - return USBG_ERROR_INVALID_PARAM; - - do { - if (!strcmp(name, gadget_attr_names[i])) - return i; - i++; - } while (i != USBG_GADGET_ATTR_MAX); - - return USBG_ERROR_NOT_FOUND; -} - -int usbg_lookup_gadget_str(const char *name) -{ - int i = USBG_GADGET_STR_MIN; - - if (!name) - return USBG_ERROR_INVALID_PARAM; - - do { - if (!strcmp(name, gadget_str_names[i])) - return i; + break; i++; - } while (i != USBG_GADGET_STR_MAX); + } while (i != max); - return USBG_ERROR_NOT_FOUND; -} + if (i == max) + i = -1; -const char *usbg_get_gadget_attr_str(usbg_gadget_attr attr) -{ - return attr >= USBG_GADGET_ATTR_MIN && - attr < USBG_GADGET_ATTR_MAX ? - gadget_attr_names[attr] : NULL; + return i; } -const char *usbg_get_gadget_str_name(usbg_gadget_str str) +const const char *usbg_get_function_type_str(usbg_function_type type) { - return str >= USBG_GADGET_STR_MIN && - str < USBG_GADGET_STR_MAX ? - gadget_str_names[str] : NULL; + return type > 0 && type < sizeof(function_names)/sizeof(char *) ? + function_names[type] : NULL; } static usbg_error usbg_split_function_instance_type(const char *full_name, @@ -429,46 +368,45 @@ static int bindings_select(const struct dirent *dent) return 0; } -static int usbg_read_buf(const char *path, const char *name, const char *file, - char *buf) +static int file_select(const struct dirent *dent) +{ + if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0)) + return 0; + else + return 1; +} + +static int usbg_read_buf(char *path, char *name, char *file, char *buf) { char p[USBG_MAX_PATH_LENGTH]; FILE *fp; - char *ret_ptr; int nmb; int ret = USBG_SUCCESS; nmb = snprintf(p, sizeof(p), "%s/%s/%s", path, name, file); - if (nmb >= sizeof(p)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - fp = fopen(p, "r"); - if (!fp) { - /* Set error correctly */ - ret = usbg_translate_error(errno); - goto out; - } + if (nmb < sizeof(p)) { + fp = fopen(p, "r"); + if (fp) { + /* Successfully opened */ + if (!fgets(buf, USBG_MAX_STR_LENGTH, fp)) { + ERROR("read error"); + ret = USBG_ERROR_IO; + } - ret_ptr = fgets(buf, USBG_MAX_STR_LENGTH, fp); - if (!ret_ptr) { - /* File is empty */ - if (feof(fp)) - buf[0] = '\0'; - /* Error occurred */ - else - ret = USBG_ERROR_IO; + fclose(fp); + } else { + /* Set error correctly */ + ret = usbg_translate_error(errno); + } + } else { + ret = USBG_ERROR_PATH_TOO_LONG; } - fclose(fp); - -out: return ret; } -static int usbg_read_int(const char *path, const char *name, const char *file, - int base, int *dest) +static int usbg_read_int(char *path, char *name, char *file, int base, + int *dest) { char buf[USBG_MAX_STR_LENGTH]; char *pos; @@ -487,23 +425,7 @@ static int usbg_read_int(const char *path, const char *name, const char *file, #define usbg_read_dec(p, n, f, d) usbg_read_int(p, n, f, 10, d) #define usbg_read_hex(p, n, f, d) usbg_read_int(p, n, f, 16, d) -static int usbg_read_bool(const char *path, const char *name, const char *file, - bool *dest) -{ - int buf; - int ret; - - ret = usbg_read_dec(path, name, file, &buf); - if (ret != USBG_SUCCESS) - goto out; - - *dest = !!buf; -out: - return ret; -} - -static int usbg_read_string(const char *path, const char *name, - const char *file, char *buf) +static int usbg_read_string(char *path, char *name, char *file, char *buf) { char *p = NULL; int ret; @@ -521,30 +443,7 @@ static int usbg_read_string(const char *path, const char *name, return ret; } -static int usbg_read_string_alloc(const char *path, const char *name, - const char *file, const char **dest) -{ - char buf[USBG_MAX_FILE_SIZE]; - char *new_buf = NULL; - int ret = USBG_SUCCESS; - - ret = usbg_read_string(path, name, file, buf); - if (ret != USBG_SUCCESS) - goto out; - - new_buf = strdup(buf); - if (!new_buf) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - *dest = new_buf; -out: - return ret; -} - -static int usbg_write_buf(const char *path, const char *name, const char *file, - const char *buf) +static int usbg_write_buf(char *path, char *name, char *file, char *buf) { char p[USBG_MAX_PATH_LENGTH]; FILE *fp; @@ -574,8 +473,8 @@ static int usbg_write_buf(const char *path, const char *name, const char *file, return ret; } -static int usbg_write_int(const char *path, const char *name, const char *file, - int value, const char *str) +static int usbg_write_int(char *path, char *name, char *file, int value, + char *str) { char buf[USBG_MAX_STR_LENGTH]; int nmb; @@ -587,13 +486,11 @@ static int usbg_write_int(const char *path, const char *name, const char *file, } #define usbg_write_dec(p, n, f, v) usbg_write_int(p, n, f, v, "%d\n") -#define usbg_write_hex(p, n, f, v) usbg_write_int(p, n, f, v, "0x%x\n") #define usbg_write_hex16(p, n, f, v) usbg_write_int(p, n, f, v, "0x%04x\n") #define usbg_write_hex8(p, n, f, v) usbg_write_int(p, n, f, v, "0x%02x\n") -#define usbg_write_bool(p, n, f, v) usbg_write_dec(p, n, f, !!v) -static inline int usbg_write_string(const char *path, const char *name, - const char *file, const char *buf) +static inline int usbg_write_string(char *path, char *name, char *file, + char *buf) { return usbg_write_buf(path, name, file, buf); } @@ -609,7 +506,6 @@ static inline void usbg_free_function(usbg_function *f) { free(f->path); free(f->name); - free(f->label); free(f); } @@ -631,12 +527,6 @@ static void usbg_free_gadget(usbg_gadget *g) { usbg_config *c; usbg_function *f; - - if (g->last_failed_import) { - config_destroy(g->last_failed_import); - free(g->last_failed_import); - } - while (!TAILQ_EMPTY(&g->configs)) { c = TAILQ_FIRST(&g->configs); TAILQ_REMOVE(&g->configs, c, cnode); @@ -652,41 +542,20 @@ static void usbg_free_gadget(usbg_gadget *g) free(g); } -static void usbg_free_udc(usbg_udc *u) -{ - free(u->name); - free(u); -} - static void usbg_free_state(usbg_state *s) { usbg_gadget *g; - usbg_udc *u; - while (!TAILQ_EMPTY(&s->gadgets)) { g = TAILQ_FIRST(&s->gadgets); TAILQ_REMOVE(&s->gadgets, g, gnode); usbg_free_gadget(g); } - - while (!TAILQ_EMPTY(&s->udcs)) { - u = TAILQ_FIRST(&s->udcs); - TAILQ_REMOVE(&s->udcs, u, unode); - usbg_free_udc(u); - } - - if (s->last_failed_import) { - config_destroy(s->last_failed_import); - free(s->last_failed_import); - } - free(s->path); - free(s->configfs_path); free(s); } -static usbg_gadget *usbg_allocate_gadget(const char *path, const char *name, +static usbg_gadget *usbg_allocate_gadget(char *path, char *name, usbg_state *parent) { usbg_gadget *g; @@ -695,11 +564,9 @@ static usbg_gadget *usbg_allocate_gadget(const char *path, const char *name, if (g) { TAILQ_INIT(&g->functions); TAILQ_INIT(&g->configs); - g->last_failed_import = NULL; g->name = strdup(name); g->path = strdup(path); g->parent = parent; - g->udc = NULL; if (!(g->name) || !(g->path)) { free(g->name); @@ -748,8 +615,6 @@ out: return c; } -static int usbg_rm_ms_function(usbg_function *f, int opts); - static usbg_function *usbg_allocate_function(const char *path, usbg_function_type type, const char *instance, usbg_gadget *parent) { @@ -761,7 +626,6 @@ static usbg_function *usbg_allocate_function(const char *path, if (!f) goto out; - f->label = NULL; type_name = usbg_get_function_type_str(type); if (!type_name) { free(f); @@ -780,16 +644,6 @@ static usbg_function *usbg_allocate_function(const char *path, f->parent = parent; f->type = type; - /* only composed functions (with subdirs) require this callback */ - switch (usbg_lookup_function_attrs_type(type)) { - case USBG_F_ATTRS_MS: - f->rm_callback = usbg_rm_ms_function; - break; - default: - f->rm_callback = NULL; - break; - } - if (!(f->path)) { free(f->name); free(f->path); @@ -801,7 +655,7 @@ out: return f; } -static usbg_binding *usbg_allocate_binding(const char *path, const char *name, +static usbg_binding *usbg_allocate_binding(char *path, char *name, usbg_config *parent) { usbg_binding *b; @@ -823,108 +677,20 @@ static usbg_binding *usbg_allocate_binding(const char *path, const char *name, return b; } -static usbg_udc *usbg_allocate_udc(usbg_state *parent, const char *name) -{ - usbg_udc *u; - - u = malloc(sizeof(*u)); - if (!u) - goto out; - - u->gadget = NULL; - u->parent = parent; - u->name = strdup(name); - if (!u->name) { - free(u); - u = NULL; - } - - out: - return u; -} - -static int ubsg_rm_file(const char *path, const char *name) -{ - int ret = USBG_SUCCESS; - int nmb; - char buf[USBG_MAX_PATH_LENGTH]; - - nmb = snprintf(buf, sizeof(buf), "%s/%s", path, name); - if (nmb < sizeof(buf)) { - nmb = unlink(buf); - if (nmb != 0) - ret = usbg_translate_error(errno); - } else { - ret = USBG_ERROR_PATH_TOO_LONG; - } - - return ret; -} - -static int usbg_rm_dir(const char *path, const char *name) -{ - int ret = USBG_SUCCESS; - int nmb; - char buf[USBG_MAX_PATH_LENGTH]; - - nmb = snprintf(buf, sizeof(buf), "%s/%s", path, name); - if (nmb < sizeof(buf)) { - nmb = rmdir(buf); - if (nmb != 0) - ret = usbg_translate_error(errno); - } else { - ret = USBG_ERROR_PATH_TOO_LONG; - } - - return ret; -} - -static int usbg_rm_all_dirs(const char *path) -{ - int ret = USBG_SUCCESS; - int n, i; - struct dirent **dent; - - n = scandir(path, &dent, file_select, alphasort); - if (n >= 0) { - for (i = 0; i < n; ++i) { - if (ret == USBG_SUCCESS) - ret = usbg_rm_dir(path, dent[i]->d_name); - - free(dent[i]); - } - free(dent); - } else { - ret = usbg_translate_error(errno); - } - - return ret; -} - -char *usbg_ether_ntoa_r(const struct ether_addr *addr, char *buf) -{ - sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - addr->ether_addr_octet[0], addr->ether_addr_octet[1], - addr->ether_addr_octet[2], addr->ether_addr_octet[3], - addr->ether_addr_octet[4], addr->ether_addr_octet[5]); - return buf; -} - static int usbg_parse_function_net_attrs(usbg_function *f, - usbg_f_net_attrs *f_net_attrs) + usbg_function_attrs *f_attrs) { struct ether_addr *addr; - struct ether_addr addr_buf; - char str_addr[USBG_MAX_STR_LENGTH]; + char str_addr[40]; int ret; ret = usbg_read_string(f->path, f->name, "dev_addr", str_addr); if (ret != USBG_SUCCESS) goto out; - addr = ether_aton_r(str_addr, &addr_buf); + addr = ether_aton(str_addr); if (addr) { - f_net_attrs->dev_addr = *addr; + f_attrs->net.dev_addr = *addr; } else { ret = USBG_ERROR_IO; goto out; @@ -934,215 +700,19 @@ static int usbg_parse_function_net_attrs(usbg_function *f, if (ret != USBG_SUCCESS) goto out; - addr = ether_aton_r(str_addr, &addr_buf); + addr = ether_aton(str_addr); if (addr) { - f_net_attrs->host_addr = *addr; + f_attrs->net.host_addr = *addr; } else { ret = USBG_ERROR_IO; goto out; } - ret = usbg_read_dec(f->path, f->name, "qmult", &(f_net_attrs->qmult)); + ret = usbg_read_string(f->path, f->name, "ifname", f_attrs->net.ifname); if (ret != USBG_SUCCESS) goto out; - ret = usbg_read_string_alloc(f->path, f->name, "ifname", - &(f_net_attrs->ifname)); -out: - return ret; -} - -static int usbg_parse_function_ms_lun_attrs(const char *path, const char *lun, - usbg_f_ms_lun_attrs *lun_attrs) -{ - int ret; - - memset(lun_attrs, 0, sizeof(*lun_attrs)); - - ret = sscanf(lun, "lun.%d", &lun_attrs->id); - if (ret != 1) - goto out; - - ret = usbg_read_bool(path, lun, "cdrom", &(lun_attrs->cdrom)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_bool(path, lun, "ro", &(lun_attrs->ro)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_bool(path, lun, "nofua", &(lun_attrs->nofua)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_bool(path, lun, "removable", &(lun_attrs->removable)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_string_alloc(path, lun, "file", - &(lun_attrs->filename)); - -out: - return ret; -} - -static inline int lun_select(const struct dirent *dent) -{ - int ret; - int id; - - ret = file_select(dent); - if (!ret) - goto out; - - ret = sscanf(dent->d_name, "lun.%d", &id); -out: - return ret; -} - -static inline int lun_sort(const struct dirent **d1, const struct dirent **d2) -{ - int ret; - int id1, id2; - - ret = sscanf((*d1)->d_name, "lun.%d", &id1); - if (ret != 1) - goto err; - - ret = sscanf((*d2)->d_name, "lun.%d", &id2); - if (ret != 1) - goto err; - - if (id1 < id2) - ret = 1; - - return id1 < id2 ? -1 : id1 > id2; -err: - /* - * This should not happened because dentries has been - * already checked by lun_select function. This - * error procedure is just in case. - */ - return -1; -} - -static int usbg_parse_function_ms_attrs(usbg_function *f, - usbg_f_ms_attrs *f_ms_attrs) -{ - int ret; - int nmb; - int i = 0; - char fpath[USBG_MAX_PATH_LENGTH]; - usbg_f_ms_lun_attrs *lun_attrs; - usbg_f_ms_lun_attrs **luns; - struct dirent **dent; - - ret = usbg_read_bool(f->path, f->name, "stall", - &(f_ms_attrs->stall)); - if (ret != USBG_SUCCESS) - goto out; - - - nmb = snprintf(fpath, sizeof(fpath), "%s/%s/", - f->path, f->name); - if (nmb >= sizeof(fpath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - nmb = scandir(fpath, &dent, lun_select, lun_sort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - luns = calloc(nmb + 1, sizeof(*luns)); - if (!luns) { - ret = USBG_ERROR_NO_MEM; - goto err; - } - - f_ms_attrs->luns = luns; - f_ms_attrs->nluns = nmb; - - for (i = 0; i < nmb; i++) { - lun_attrs = malloc(sizeof(*lun_attrs)); - if (!lun_attrs) { - ret = USBG_ERROR_NO_MEM; - goto err; - } - - ret = usbg_parse_function_ms_lun_attrs(fpath, dent[i]->d_name, - lun_attrs); - if (ret != USBG_SUCCESS) { - free(lun_attrs); - goto err; - } - - luns[i] = lun_attrs; - free(dent[i]); - } - free(dent); - - return USBG_SUCCESS; - -err: - while (i < nmb) { - free(dent[i]); - ++i; - } - free(dent); - - usbg_cleanup_function_attrs( - container_of((usbg_f_attrs *)f_ms_attrs, - usbg_function_attrs, attrs)); -out: - return ret; -} - -static int usbg_parse_function_midi_attrs(usbg_function *f, - usbg_f_midi_attrs *attrs) -{ - int ret; - - ret = usbg_read_dec(f->path, f->name, "index", &(attrs->index)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_string_alloc(f->path, f->name, "id", &(attrs->id)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "in_ports", (int*)&(attrs->in_ports)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "out_ports", (int*)&(attrs->out_ports)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "buflen", (int*)&(attrs->buflen)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "qlen", (int*)&(attrs->qlen)); - if (ret != USBG_SUCCESS) - goto out; - -out: - return ret; -} - -static int usbg_parse_function_loopback_attrs(usbg_function *f, - usbg_f_loopback_attrs *attrs) -{ - int ret; - - ret = usbg_read_dec(f->path, f->name, "buflen", (int *)&(attrs->buflen)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "qlen", (int *)&(attrs->qlen)); + ret = usbg_read_dec(f->path, f->name, "qmult", &(f_attrs->net.qmult)); out: return ret; @@ -1152,70 +722,34 @@ static int usbg_parse_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) { int ret; - int attrs_type; - - attrs_type = usbg_lookup_function_attrs_type(f->type); - if (attrs_type < 0) { - ret = attrs_type; - goto out; - } - switch (attrs_type) { - case USBG_F_ATTRS_SERIAL: - f_attrs->header.attrs_type = USBG_F_ATTRS_SERIAL; + switch (f->type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: ret = usbg_read_dec(f->path, f->name, "port_num", - &(f_attrs->attrs.serial.port_num)); - break; - - case USBG_F_ATTRS_NET: - f_attrs->header.attrs_type = USBG_F_ATTRS_NET; - ret = usbg_parse_function_net_attrs(f, &(f_attrs->attrs.net)); + &(f_attrs->serial.port_num)); break; - - case USBG_F_ATTRS_PHONET: - f_attrs->header.attrs_type = USBG_F_ATTRS_PHONET; - ret = usbg_read_string_alloc(f->path, f->name, "ifname", - &(f_attrs->attrs.phonet.ifname)); - break; - - case USBG_F_ATTRS_FFS: - { - usbg_f_ffs_attrs *ffs_attrs = &(f_attrs->attrs.ffs); - - f_attrs->header.attrs_type = USBG_F_ATTRS_FFS; - ffs_attrs->dev_name = strdup(f->instance); - if (!ffs_attrs->dev_name) - ret = USBG_ERROR_NO_MEM; - else - ret = USBG_SUCCESS; - break; - } - - case USBG_F_ATTRS_MS: - f_attrs->header.attrs_type = USBG_F_ATTRS_MS; - ret = usbg_parse_function_ms_attrs(f, &(f_attrs->attrs.ms)); - break; - - case USBG_F_ATTRS_MIDI: - f_attrs->header.attrs_type = USBG_F_ATTRS_MIDI; - ret = usbg_parse_function_midi_attrs(f, &(f_attrs->attrs.midi)); + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: + ret = usbg_parse_function_net_attrs(f, f_attrs); break; - - case USBG_F_ATTRS_LOOPBACK: - f_attrs->header.attrs_type = USBG_F_ATTRS_LOOPBACK; - ret = usbg_parse_function_loopback_attrs(f, &(f_attrs->attrs.loopback)); + case F_PHONET: + ret = usbg_read_string(f->path, f->name, "ifname", + f_attrs->phonet.ifname); break; - default: ERROR("Unsupported function type\n"); ret = USBG_ERROR_NOT_SUPPORTED; - break; } -out: + return ret; } -static int usbg_parse_functions(const char *path, usbg_gadget *g) +static int usbg_parse_functions(char *path, usbg_gadget *g) { usbg_function *f; int i, n; @@ -1260,7 +794,7 @@ out: return ret; } -static int usbg_parse_config_attrs(const char *path, const char *name, +static int usbg_parse_config_attrs(char *path, char *name, usbg_config_attrs *c_attrs) { int buf, ret; @@ -1277,7 +811,7 @@ static int usbg_parse_config_attrs(const char *path, const char *name, return ret; } -static int usbg_parse_config_strs(const char *path, const char *name, +static int usbg_parse_config_strs(char *path, char *name, int lang, usbg_config_strs *c_strs) { DIR *dir; @@ -1304,7 +838,8 @@ static int usbg_parse_config_strs(const char *path, const char *name, return ret; } -static int usbg_parse_config_binding(usbg_config *c, char *bpath, int path_size) +static int usbg_parse_config_binding(usbg_config *c, char *bpath, + int path_size) { int nmb; int ret; @@ -1315,7 +850,7 @@ static int usbg_parse_config_binding(usbg_config *c, char *bpath, int path_size) usbg_function *f; usbg_binding *b; - nmb = readlink(bpath, target, sizeof(target) - 1 ); + nmb = readlink(bpath, target, sizeof(target)); if (nmb < 0) { ret = usbg_translate_error(errno); goto out; @@ -1418,7 +953,7 @@ out: return ret; } -static int usbg_parse_configs(const char *path, usbg_gadget *g) +static int usbg_parse_configs(char *path, usbg_gadget *g) { int i, n; int ret = USBG_SUCCESS; @@ -1450,7 +985,7 @@ out: return ret; } -static int usbg_parse_gadget_attrs(const char *path, const char *name, +static int usbg_parse_gadget_attrs(char *path, char *name, usbg_gadget_attrs *g_attrs) { int buf, ret; @@ -1463,6 +998,12 @@ static int usbg_parse_gadget_attrs(const char *path, const char *name, else goto out; + ret = usbg_read_hex(path, name, "bcdDevice", &buf); + if (ret == USBG_SUCCESS) + g_attrs->bcdDevice = (uint16_t) buf; + else + goto out; + ret = usbg_read_hex(path, name, "bDeviceClass", &buf); if (ret == USBG_SUCCESS) g_attrs->bDeviceClass = (uint8_t)buf; @@ -1499,17 +1040,11 @@ static int usbg_parse_gadget_attrs(const char *path, const char *name, else goto out; - ret = usbg_read_hex(path, name, "bcdDevice", &buf); - if (ret == USBG_SUCCESS) - g_attrs->bcdDevice = (uint16_t) buf; - else - goto out; - out: return ret; } -static int usbg_parse_gadget_strs(const char *path, const char *name, int lang, +static int usbg_parse_gadget_strs(char *path, char *name, int lang, usbg_gadget_strs *g_strs) { int ret; @@ -1550,17 +1085,12 @@ out: static inline int usbg_parse_gadget(usbg_gadget *g) { int ret; - char buf[USBG_MAX_STR_LENGTH]; /* UDC bound to, if any */ - ret = usbg_read_string(g->path, g->name, "UDC", buf); + ret = usbg_read_string(g->path, g->name, "UDC", g->udc); if (ret != USBG_SUCCESS) goto out; - g->udc = usbg_get_udc(g->parent, buf); - if (g->udc) - g->udc->gadget = g; - ret = usbg_parse_functions(g->path, g); if (ret != USBG_SUCCESS) goto out; @@ -1570,7 +1100,7 @@ out: return ret; } -static int usbg_parse_gadgets(const char *path, usbg_state *s) +static int usbg_parse_gadgets(char *path, usbg_state *s) { usbg_gadget *g; int i, n; @@ -1605,86 +1135,18 @@ static int usbg_parse_gadgets(const char *path, usbg_state *s) return ret; } -static int usbg_parse_udcs(usbg_state *s) +static int usbg_init_state(char *path, usbg_state *s) { - usbg_udc *u; - int n, i; int ret = USBG_SUCCESS; - struct dirent **dent; - - n = scandir("/sys/class/udc", &dent, file_select, alphasort); - if (n < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - for (i = 0; i < n; ++i) { - if (ret == USBG_SUCCESS) { - u = usbg_allocate_udc(s, dent[i]->d_name); - if (u) - TAILQ_INSERT_TAIL(&s->udcs, u, unode); - else - ret = USBG_ERROR_NO_MEM; - } - - free(dent[i]); - } - free(dent); - -out: - return ret; -} - -static usbg_state *usbg_allocate_state(const char *configfs_path, char *path) -{ - usbg_state *s; - - s = malloc(sizeof(*s)); - if (!s) - goto err; - - s->configfs_path = strdup(configfs_path); - if (!s->configfs_path) - goto cpath_failed; /* State takes the ownership of path and should free it */ s->path = path; - s->last_failed_import = NULL; TAILQ_INIT(&s->gadgets); - TAILQ_INIT(&s->udcs); - - return s; -cpath_failed: - free(s); -err: - return NULL; -} - -static int usbg_parse_state(usbg_state *s) -{ - int ret = USBG_SUCCESS; - - /* - * USBG_ERROR_NOT_FOUND is returned if we are running on machine where - * there is no udc support in kernel (no /sys/class/udc dir). - * This check allows to run library on such machine or if we don't - * have rights to read this directory. - * User will be able to finish init function and manage gadgets but - * wont be able to bind it as there is no UDC. - */ - ret = usbg_parse_udcs(s); - if (ret != USBG_SUCCESS && ret != USBG_ERROR_NOT_FOUND && - ret != USBG_ERROR_NO_ACCESS) { - ERROR("Unable to parse udcs"); - goto out; - } - - ret = usbg_parse_gadgets(s->path, s); + ret = usbg_parse_gadgets(path, s); if (ret != USBG_SUCCESS) - ERROR("unable to parse %s\n", s->path); + ERRORNO("unable to parse %s\n", path); -out: return ret; } @@ -1692,14 +1154,13 @@ out: * User API */ -int usbg_init(const char *configfs_path, usbg_state **state) +int usbg_init(char *configfs_path, usbg_state **state) { int ret = USBG_SUCCESS; DIR *dir; char *path; - usbg_state *s; - ret = asprintf(&path, "%s/" GADGETS_DIR, configfs_path); + ret = asprintf(&path, "%s/usb_gadget", configfs_path); if (ret < 0) return USBG_ERROR_NO_MEM; else @@ -1707,33 +1168,21 @@ int usbg_init(const char *configfs_path, usbg_state **state) /* Check if directory exist */ dir = opendir(path); - if (!dir) { + if (dir) { + closedir(dir); + *state = malloc(sizeof(usbg_state)); + ret = *state ? usbg_init_state(path, *state) + : USBG_ERROR_NO_MEM; + if (*state && ret != USBG_SUCCESS) { + ERRORNO("couldn't init gadget state\n"); + usbg_free_state(*state); + } + } else { ERRORNO("couldn't init gadget state\n"); ret = usbg_translate_error(errno); - goto err; + free(path); } - closedir(dir); - s = usbg_allocate_state(configfs_path, path); - if (!s) { - ret = USBG_ERROR_NO_MEM; - goto err; - } - - ret = usbg_parse_state(s); - if (ret != USBG_SUCCESS) { - ERROR("couldn't init gadget state\n"); - usbg_free_state(s); - goto out; - } - - *state = s; - - return ret; - -err: - free(path); -out: return ret; } @@ -1742,25 +1191,20 @@ void usbg_cleanup(usbg_state *s) usbg_free_state(s); } -const char *usbg_get_configfs_path(usbg_state *s) -{ - return s ? s->configfs_path : NULL; -} - size_t usbg_get_configfs_path_len(usbg_state *s) { - return s ? strlen(s->configfs_path) : USBG_ERROR_INVALID_PARAM; + return s ? strlen(s->path) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_configfs_path(usbg_state *s, char *buf, size_t len) +int usbg_get_configfs_path(usbg_state *s, char *buf, size_t len) { - if (!s || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, s->configfs_path, len); + int ret = USBG_SUCCESS; + if (s && buf) + strncpy(buf, s->path, len); + else + ret = USBG_ERROR_INVALID_PARAM; - return USBG_SUCCESS; + return ret; } usbg_gadget *usbg_get_gadget(usbg_state *s, const char *name) @@ -1797,17 +1241,6 @@ usbg_config *usbg_get_config(usbg_gadget *g, int id, const char *label) return c; } -usbg_udc *usbg_get_udc(usbg_state *s, const char *name) -{ - usbg_udc *u; - - TAILQ_FOREACH(u, &s->udcs, unode) - if (!strcmp(u->name, name)) - return u; - - return NULL; -} - usbg_binding *usbg_get_binding(usbg_config *c, const char *name) { usbg_binding *b; @@ -1830,259 +1263,10 @@ usbg_binding *usbg_get_link_binding(usbg_config *c, usbg_function *f) return NULL; } -int usbg_rm_binding(usbg_binding *b) -{ - int ret = USBG_SUCCESS; - usbg_config *c; - - if (!b) - return USBG_ERROR_INVALID_PARAM; - - c = b->parent; - - ret = ubsg_rm_file(b->path, b->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(c->bindings), b, bnode); - usbg_free_binding(b); - } - - return ret; -} - -int usbg_rm_config(usbg_config *c, int opts) -{ - int ret = USBG_ERROR_INVALID_PARAM; - usbg_gadget *g; - - if (!c) - return ret; - - g = c->parent; - - if (opts & USBG_RM_RECURSE) { - /* Recursive flag was given - * so remove all bindings and strings */ - char spath[USBG_MAX_PATH_LENGTH]; - int nmb; - usbg_binding *b; - - while (!TAILQ_EMPTY(&c->bindings)) { - b = TAILQ_FIRST(&c->bindings); - ret = usbg_rm_binding(b); - if (ret != USBG_SUCCESS) - goto out; - } - - nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", c->path, - c->name, STRINGS_DIR); - if (nmb >= sizeof(spath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - ret = usbg_rm_all_dirs(spath); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = usbg_rm_dir(c->path, c->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(g->configs), c, cnode); - usbg_free_config(c); - } - -out: - return ret; -} - -static int usbg_rm_ms_function(usbg_function *f, int opts) -{ - int ret; - int nmb; - int i; - char lpath[USBG_MAX_PATH_LENGTH]; - struct dirent **dent; - - ret = snprintf(lpath, sizeof(lpath), "%s/%s/", f->path, f->name); - if (ret >= sizeof(lpath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - nmb = scandir(lpath, &dent, lun_select, lun_sort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - for (i = nmb - 1; i > 0; --i) { - ret = usbg_rm_dir(lpath, dent[i]->d_name); - free(dent[i]); - if (ret) - goto err_free_dent_loop; - } - free(dent[0]); - free(dent); - - return USBG_SUCCESS; - -err_free_dent_loop: - while (--i >= 0) - free(dent[i]); - free(dent[i]); -out: - return ret; -} - -int usbg_rm_function(usbg_function *f, int opts) -{ - int ret = USBG_ERROR_INVALID_PARAM; - usbg_gadget *g; - - if (!f) - return ret; - - g = f->parent; - - if (opts & USBG_RM_RECURSE) { - /* Recursive flag was given - * so remove all bindings to this function */ - usbg_config *c; - usbg_binding *b; - - TAILQ_FOREACH(c, &g->configs, cnode) { - b = TAILQ_FIRST(&c->bindings); - while (b != NULL) { - if (b->target == f) { - usbg_binding *b_next = TAILQ_NEXT(b, bnode); - ret = usbg_rm_binding(b); - if (ret != USBG_SUCCESS) - return ret; - - b = b_next; - } else { - b = TAILQ_NEXT(b, bnode); - } - } /* while */ - } /* TAILQ_FOREACH */ - } - - if (f->rm_callback) { - ret = f->rm_callback(f, opts); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = usbg_rm_dir(f->path, f->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(g->functions), f, fnode); - usbg_free_function(f); - } - -out: - return ret; -} - -int usbg_rm_gadget(usbg_gadget *g, int opts) -{ - int ret = USBG_ERROR_INVALID_PARAM; - usbg_state *s; - if (!g) - goto out; - - s = g->parent; - - if (opts & USBG_RM_RECURSE) { - /* Recursive flag was given - * so remove all configs and functions - * using recursive flags */ - usbg_config *c; - usbg_function *f; - int nmb; - char spath[USBG_MAX_PATH_LENGTH]; - - while (!TAILQ_EMPTY(&g->configs)) { - c = TAILQ_FIRST(&g->configs); - ret = usbg_rm_config(c, opts); - if (ret != USBG_SUCCESS) - goto out; - } - - while (!TAILQ_EMPTY(&g->functions)) { - f = TAILQ_FIRST(&g->functions); - ret = usbg_rm_function(f, opts); - if (ret != USBG_SUCCESS) - goto out; - } - - nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", g->path, - g->name, STRINGS_DIR); - if (nmb >= sizeof(spath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - ret = usbg_rm_all_dirs(spath); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = usbg_rm_dir(g->path, g->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(s->gadgets), g, gnode); - usbg_free_gadget(g); - } - -out: - return ret; -} - -int usbg_rm_config_strs(usbg_config *c, int lang) -{ - int ret = USBG_SUCCESS; - int nmb; - char path[USBG_MAX_PATH_LENGTH]; - - if (!c) - return USBG_ERROR_INVALID_PARAM; - - nmb = snprintf(path, sizeof(path), "%s/%s/%s/0x%x", c->path, c->name, - STRINGS_DIR, lang); - if (nmb < sizeof(path)) - ret = usbg_rm_dir(path, ""); - else - ret = USBG_ERROR_PATH_TOO_LONG; - - return ret; -} - -int usbg_rm_gadget_strs(usbg_gadget *g, int lang) -{ - int ret = USBG_SUCCESS; - int nmb; - char path[USBG_MAX_PATH_LENGTH]; - - if (!g) - return USBG_ERROR_INVALID_PARAM; - - nmb = snprintf(path, sizeof(path), "%s/%s/%s/0x%x", g->path, g->name, - STRINGS_DIR, lang); - if (nmb < sizeof(path)) - ret = usbg_rm_dir(path, ""); - else - ret = USBG_ERROR_PATH_TOO_LONG; - - return ret; -} - - -static int usbg_create_empty_gadget(usbg_state *s, const char *name, - usbg_gadget **g) +static int usbg_create_empty_gadget(usbg_state *s, char *name, usbg_gadget **g) { char gpath[USBG_MAX_PATH_LENGTH]; - char buf[USBG_MAX_STR_LENGTH]; int nmb; - usbg_gadget *gad; int ret = USBG_SUCCESS; nmb = snprintf(gpath, sizeof(gpath), "%s/%s", s->path, name); @@ -2092,39 +1276,33 @@ static int usbg_create_empty_gadget(usbg_state *s, const char *name, } *g = usbg_allocate_gadget(s->path, name, s); - if (!*g) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - gad = *g; /* alias only */ + if (*g) { + usbg_gadget *gad = *g; /* alias only */ + + ret = mkdir(gpath, S_IRWXU|S_IRWXG|S_IRWXO); + if (ret == 0) { + /* Should be empty but read the default */ + ret = usbg_read_string(gad->path, gad->name, "UDC", + gad->udc); + if (ret != USBG_SUCCESS) + rmdir(gpath); + } else { + ret = usbg_translate_error(errno); + } - ret = mkdir(gpath, S_IRWXU|S_IRWXG|S_IRWXO); - if (ret == 0) { - /* Should be empty but read the default */ - ret = usbg_read_string(gad->path, gad->name, - "UDC", buf); if (ret != USBG_SUCCESS) { - rmdir(gpath); - } else { - gad->udc = usbg_get_udc(s, buf); - if (gad->udc) - gad->udc->gadget = gad; + usbg_free_gadget(*g); + *g = NULL; } } else { - ret = usbg_translate_error(errno); - } - - if (ret != USBG_SUCCESS) { - usbg_free_gadget(*g); - *g = NULL; + ret = USBG_ERROR_NO_MEM; } out: return ret; } -int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, +int usbg_create_gadget_vid_pid(usbg_state *s, char *name, uint16_t idVendor, uint16_t idProduct, usbg_gadget **g) { int ret; @@ -2158,9 +1336,8 @@ int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, return ret; } -int usbg_create_gadget(usbg_state *s, const char *name, - const usbg_gadget_attrs *g_attrs, const usbg_gadget_strs *g_strs, - usbg_gadget **g) +int usbg_create_gadget(usbg_state *s, char *name, + usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, usbg_gadget **g) { usbg_gadget *gad; int ret; @@ -2200,147 +1377,39 @@ int usbg_get_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs) : USBG_ERROR_INVALID_PARAM; } -const char *usbg_get_gadget_name(usbg_gadget *g) -{ - return g ? g->name : NULL; -} - size_t usbg_get_gadget_name_len(usbg_gadget *g) { return g ? strlen(g->name) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_gadget_name(usbg_gadget *g, char *buf, size_t len) -{ - if (!g || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, g->name, len); - - return USBG_SUCCESS; -} - -const char *usbg_get_udc_name(usbg_udc *u) -{ - return u ? u->name : NULL; -} - -size_t usbg_get_udc_name_len(usbg_udc *u) -{ - return u ? strlen(u->name) : USBG_ERROR_INVALID_PARAM; -} - -int usbg_cpy_udc_name(usbg_udc *u, char *buf, size_t len) -{ - if (!u || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, u->name, len); - - return USBG_SUCCESS; -} - -int usbg_set_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr, int val) -{ - const char *attr_name; - int ret = USBG_ERROR_INVALID_PARAM; - - if (!g) - goto out; - - attr_name = usbg_get_gadget_attr_str(attr); - if (!attr_name) - goto out; - - ret = usbg_write_hex(g->path, g->name, attr_name, val); - -out: - return ret; -} - -int usbg_get_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr) +int usbg_get_gadget_name(usbg_gadget *g, char *buf, size_t len) { - const char *attr_name; - int ret = USBG_ERROR_INVALID_PARAM; - - if (!g) - goto out; - - attr_name = usbg_get_gadget_attr_str(attr); - if (!attr_name) - goto out; - - usbg_read_hex(g->path, g->name, attr_name, &ret); + int ret = USBG_SUCCESS; + if (g && buf) + strncpy(buf, g->name, len); + else + ret = USBG_ERROR_INVALID_PARAM; -out: return ret; } -usbg_udc *usbg_get_gadget_udc(usbg_gadget *g) +size_t usbg_get_gadget_udc_len(usbg_gadget *g) { - usbg_udc *u = NULL; - - if (!g) - goto out; - /* - * if gadget was enabled we have to check if kernel - * didn't modify the UDC file due to some errors. - * For example some FFS daemon could just get - * a segmentation fault or sth - */ - if (g->udc) { - char buf[USBG_MAX_STR_LENGTH]; - int ret; - - ret = usbg_read_string(g->path, g->name, "UDC", buf); - if (ret != USBG_SUCCESS) - goto out; - - if (!strcmp(g->udc->name, buf)) { - /* Gadget is still assigned to this UDC */ - u = g->udc; - } else { - /* Kernel decided to detach this gadget */ - g->udc->gadget = NULL; - g->udc = NULL; - } - } - -out: - return u; + return g ? strlen(g->udc) : USBG_ERROR_INVALID_PARAM; } -usbg_gadget *usbg_get_udc_gadget(usbg_udc *u) +int usbg_get_gadget_udc(usbg_gadget *g, char *buf, size_t len) { - usbg_gadget *g = NULL; - - if (!u) - goto out; - /* - * if gadget was enabled on this UDC we have to check if kernel - * didn't modify this due to some errors. - * For example some FFS daemon could just get a segmentation fault - * what causes detach of gadget - */ - if (u->gadget) { - usbg_udc *u_checked; - - u_checked = usbg_get_gadget_udc(u->gadget); - if (u_checked) { - g = u->gadget; - } else { - u->gadget->udc = NULL; - u->gadget = NULL; - } - } + int ret = USBG_SUCCESS; + if (g && buf) + strncpy(buf, g->udc, len); + else + ret = USBG_ERROR_INVALID_PARAM; -out: - return g; + return ret; } -int usbg_set_gadget_attrs(usbg_gadget *g, const usbg_gadget_attrs *g_attrs) +int usbg_set_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs) { int ret; if (!g || !g_attrs) @@ -2442,7 +1511,7 @@ int usbg_get_gadget_strs(usbg_gadget *g, int lang, g_strs) : USBG_ERROR_INVALID_PARAM; } -static int usbg_check_dir(const char *path) +static int usbg_check_dir(char *path) { int ret = USBG_SUCCESS; DIR *dir; @@ -2457,40 +1526,8 @@ static int usbg_check_dir(const char *path) return ret; } -int usbg_set_gadget_str(usbg_gadget *g, usbg_gadget_str str, int lang, - const char *val) -{ - const char *str_name; - int ret = USBG_ERROR_INVALID_PARAM; - char path[USBG_MAX_PATH_LENGTH]; - int nmb; - - if (!g) - goto out; - - str_name = usbg_get_gadget_str_name(str); - if (!str_name) - goto out; - - nmb = snprintf(path, sizeof(path), "%s/%s/%s/0x%x", g->path, g->name, - STRINGS_DIR, lang); - if (nmb >= sizeof(path)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - ret = usbg_check_dir(path); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_string(path, "", str_name, val); - -out: - return ret; -} - int usbg_set_gadget_strs(usbg_gadget *g, int lang, - const usbg_gadget_strs *g_strs) + usbg_gadget_strs *g_strs) { char path[USBG_MAX_PATH_LENGTH]; int nmb; @@ -2523,7 +1560,7 @@ out: return ret; } -int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, const char *serno) +int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *serno) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2544,7 +1581,7 @@ int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, const char *serno) return ret; } -int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, const char *mnf) +int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, char *mnf) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2565,7 +1602,7 @@ int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, const char *mnf) return ret; } -int usbg_set_gadget_product(usbg_gadget *g, int lang, const char *prd) +int usbg_set_gadget_product(usbg_gadget *g, int lang, char *prd) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2587,36 +1624,16 @@ int usbg_set_gadget_product(usbg_gadget *g, int lang, const char *prd) } int usbg_create_function(usbg_gadget *g, usbg_function_type type, - const char *instance, const usbg_function_attrs *f_attrs, - usbg_function **f) + char *instance, usbg_function_attrs *f_attrs, usbg_function **f) { char fpath[USBG_MAX_PATH_LENGTH]; usbg_function *func; int ret = USBG_ERROR_INVALID_PARAM; int n, free_space; - if (!g || !f) + if (!g || !f || !instance) return ret; - /* if attrs type is set, check if it has correct type */ - if (f_attrs && f_attrs->header.attrs_type) { - int attrs_type; - attrs_type = usbg_lookup_function_attrs_type(type); - if (attrs_type < 0 || attrs_type != f_attrs->header.attrs_type) - return ret; - } - - if (!instance) { - /* If someone creates ffs function and doesn't pass instance name - this means that device name from attrs should be used */ - if (type == F_FFS && f_attrs && f_attrs->attrs.ffs.dev_name) { - instance = f_attrs->attrs.ffs.dev_name; - f_attrs = NULL; - } else { - return ret; - } - } - func = usbg_get_function(g, type, instance); if (func) { ERROR("duplicate function name\n"); @@ -2634,9 +1651,8 @@ int usbg_create_function(usbg_gadget *g, usbg_function_type type, *f = usbg_allocate_function(fpath, type, instance, g); func = *f; if (!func) { - ERROR("allocating function\n"); + ERRORNO("allocating function\n"); ret = USBG_ERROR_NO_MEM; - goto out; } free_space = sizeof(fpath) - n; @@ -2664,11 +1680,10 @@ out: } int usbg_create_config(usbg_gadget *g, int id, const char *label, - const usbg_config_attrs *c_attrs, const usbg_config_strs *c_strs, - usbg_config **c) + usbg_config_attrs *c_attrs, usbg_config_strs *c_strs, usbg_config **c) { char cpath[USBG_MAX_PATH_LENGTH]; - usbg_config *conf = NULL; + usbg_config *conf; int ret = USBG_ERROR_INVALID_PARAM; int n, free_space; @@ -2695,7 +1710,7 @@ int usbg_create_config(usbg_gadget *g, int id, const char *label, *c = usbg_allocate_config(cpath, label, id, g); conf = *c; if (!conf) { - ERROR("allocating configuration\n"); + ERRORNO("allocating configuration\n"); ret = USBG_ERROR_NO_MEM; goto out; } @@ -2703,10 +1718,8 @@ int usbg_create_config(usbg_gadget *g, int id, const char *label, free_space = sizeof(cpath) - n; /* Append string at the end of previous one */ n = snprintf(&(cpath[n]), free_space, "/%s", (*c)->name); - if (n >= free_space) { + if (n < free_space) { ret = USBG_ERROR_PATH_TOO_LONG; - usbg_free_config(conf); - goto out; } ret = mkdir(cpath, S_IRWXU | S_IRWXG | S_IRWXO); @@ -2732,25 +1745,20 @@ out: return ret; } -const char *usbg_get_config_label(usbg_config *c) -{ - return c ? c->label : NULL; -} - size_t usbg_get_config_label_len(usbg_config *c) { return c ? strlen(c->label) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_config_label(usbg_config *c, char *buf, size_t len) +int usbg_get_config_label(usbg_config *c, char *buf, size_t len) { - if (!c || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, c->label, len); + int ret = USBG_SUCCESS; + if (c && buf) + strncpy(buf, c->label, len); + else + ret = USBG_ERROR_INVALID_PARAM; - return USBG_SUCCESS; + return ret; } int usbg_get_config_id(usbg_config *c) @@ -2758,32 +1766,27 @@ int usbg_get_config_id(usbg_config *c) return c ? c->id : USBG_ERROR_INVALID_PARAM; } -const char *usbg_get_function_instance(usbg_function *f) -{ - return f ? f->instance : NULL; -} - size_t usbg_get_function_instance_len(usbg_function *f) { return f ? strlen(f->instance) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_function_instance(usbg_function *f, char *buf, size_t len) +int usbg_get_function_instance(usbg_function *f, char *buf, size_t len) { - if (!f || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, f->instance, len); + int ret = USBG_SUCCESS; + if (f && buf) + strncpy(buf, f->instance, len); + else + ret = USBG_ERROR_INVALID_PARAM; - return USBG_SUCCESS; + return ret; } -int usbg_set_config_attrs(usbg_config *c, const usbg_config_attrs *c_attrs) +int usbg_set_config_attrs(usbg_config *c, usbg_config_attrs *c_attrs) { int ret = USBG_ERROR_INVALID_PARAM; - if (c && c_attrs) { + if (c && !c_attrs) { ret = usbg_write_dec(c->path, c->name, "MaxPower", c_attrs->bMaxPower); if (ret == USBG_SUCCESS) ret = usbg_write_hex8(c->path, c->name, "bmAttributes", @@ -2819,12 +1822,12 @@ int usbg_get_config_strs(usbg_config *c, int lang, usbg_config_strs *c_strs) } int usbg_set_config_strs(usbg_config *c, int lang, - const usbg_config_strs *c_strs) + usbg_config_strs *c_strs) { return usbg_set_config_string(c, lang, c_strs->configuration); } -int usbg_set_config_string(usbg_config *c, int lang, const char *str) +int usbg_set_config_string(usbg_config *c, int lang, char *str) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2845,7 +1848,7 @@ int usbg_set_config_string(usbg_config *c, int lang, const char *str) return ret; } -int usbg_add_config_function(usbg_config *c, const char *name, usbg_function *f) +int usbg_add_config_function(usbg_config *c, char *name, usbg_function *f) { char bpath[USBG_MAX_PATH_LENGTH]; char fpath[USBG_MAX_PATH_LENGTH]; @@ -2858,9 +1861,6 @@ int usbg_add_config_function(usbg_config *c, const char *name, usbg_function *f) goto out; } - if (!name) - name = f->name; - b = usbg_get_binding(c, name); if (b) { ERROR("duplicate binding name\n"); @@ -2925,50 +1925,65 @@ usbg_function *usbg_get_binding_target(usbg_binding *b) return b ? b->target : NULL; } -const char *usbg_get_binding_name(usbg_binding *b) +size_t usbg_get_binding_name_len(usbg_binding *b) { - return b ? b->name : NULL; + return b ? strlen(b->name) : USBG_ERROR_INVALID_PARAM; } -size_t usbg_get_binding_name_len(usbg_binding *b) +int usbg_get_binding_name(usbg_binding *b, char *buf, size_t len) { - return b ? strlen(b->name) : USBG_ERROR_INVALID_PARAM; + int ret = USBG_SUCCESS; + if (b && buf) + strncpy(buf, b->name, len); + else + ret = USBG_ERROR_INVALID_PARAM; + + return ret; } -int usbg_cpy_binding_name(usbg_binding *b, char *buf, size_t len) +int usbg_get_udcs(struct dirent ***udc_list) { - if (!b || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; + int ret = USBG_ERROR_INVALID_PARAM; - buf[--len] = '\0'; - strncpy(buf, b->name, len); + if (udc_list) { + ret = scandir("/sys/class/udc", udc_list, file_select, alphasort); + if (ret < 0) + ret = usbg_translate_error(errno); + } - return USBG_SUCCESS; + return ret; } -int usbg_enable_gadget(usbg_gadget *g, usbg_udc *udc) +int usbg_enable_gadget(usbg_gadget *g, char *udc) { + char gudc[USBG_MAX_STR_LENGTH]; + struct dirent **udc_list; + int i; int ret = USBG_ERROR_INVALID_PARAM; if (!g) return ret; if (!udc) { - udc = usbg_get_first_udc(g->parent); - if (!udc) + ret = usbg_get_udcs(&udc_list); + if (ret >= 0) { + /* Look for default one - first in string order */ + strcpy(gudc, udc_list[0]->d_name); + udc = gudc; + + /** Free the memory */ + for (i = 0; i < ret; ++i) + free(udc_list[i]); + free(udc_list); + } else { return ret; + } } - ret = usbg_write_string(g->path, g->name, "UDC", udc->name); - if (ret == USBG_SUCCESS) { - /* If gadget has been detached and we didn't noticed - * it we have to clean up now. - */ - if (g->udc) - g->udc->gadget = NULL; - g->udc = udc; - udc->gadget = g; - } + ret = usbg_write_string(g->path, g->name, "UDC", udc); + + if (ret == USBG_SUCCESS) + strcpy(g->udc, udc); return ret; } @@ -2977,14 +1992,9 @@ int usbg_disable_gadget(usbg_gadget *g) { int ret = USBG_ERROR_INVALID_PARAM; - if (!g) - return ret; - - ret = usbg_write_string(g->path, g->name, "UDC", "\n"); - if (ret == USBG_SUCCESS) { - if (g->udc) - g->udc->gadget = NULL; - g->udc = NULL; + if (g) { + strcpy(g->udc, ""); + ret = usbg_write_string(g->path, g->name, "UDC", ""); } return ret; @@ -3005,380 +2015,57 @@ int usbg_get_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) : USBG_ERROR_INVALID_PARAM; } -static void usbg_cleanup_function_ms_lun_attrs(usbg_f_ms_lun_attrs *lun_attrs) -{ - if (!lun_attrs) - return; - - free((char*)lun_attrs->filename); - lun_attrs->id = -1; -} - -void usbg_cleanup_function_attrs(usbg_function_attrs *f_attrs) -{ - usbg_f_attrs *attrs; - - if (!f_attrs) - return; - - attrs = &f_attrs->attrs; - - switch (f_attrs->header.attrs_type) { - case USBG_F_ATTRS_SERIAL: - break; - - case USBG_F_ATTRS_NET: - free((char*)attrs->net.ifname); - attrs->net.ifname = NULL; - break; - - case USBG_F_ATTRS_PHONET: - free((char*)attrs->phonet.ifname); - attrs->phonet.ifname = NULL; - break; - - case USBG_F_ATTRS_FFS: - free((char*)attrs->ffs.dev_name); - attrs->ffs.dev_name = NULL; - break; - - case USBG_F_ATTRS_MS: - { - int i; - usbg_f_ms_attrs *ms_attrs = &attrs->ms; - - if (!ms_attrs->luns) - goto ms_break; - - for (i = 0; i < ms_attrs->nluns; ++i) { - if (!ms_attrs->luns[i]) - continue; - - usbg_cleanup_function_ms_lun_attrs(ms_attrs->luns[i]); - free(ms_attrs->luns[i]); - } - free(ms_attrs->luns); - ms_attrs->luns = NULL; - ms_attrs->nluns = -1; - ms_break: - break; - } - - case USBG_F_ATTRS_MIDI: - free((char*)attrs->midi.id); - attrs->midi.id = NULL; - break; - - case USBG_F_ATTRS_LOOPBACK: - break; - - default: - ERROR("Unsupported attrs type\n"); - break; - } -} - -int usbg_set_function_net_attrs(usbg_function *f, const usbg_f_net_attrs *attrs) +int usbg_set_function_net_attrs(usbg_function *f, usbg_f_net_attrs *attrs) { int ret = USBG_SUCCESS; - char addr_buf[USBG_MAX_STR_LENGTH]; char *addr; - /* ifname is read only so we accept only empty string for this param */ - if (attrs->ifname && attrs->ifname[0]) { - ret = USBG_ERROR_INVALID_PARAM; - goto out; - } - - addr = usbg_ether_ntoa_r(&attrs->dev_addr, addr_buf); + addr = ether_ntoa(&attrs->dev_addr); ret = usbg_write_string(f->path, f->name, "dev_addr", addr); if (ret != USBG_SUCCESS) goto out; - addr = usbg_ether_ntoa_r(&attrs->host_addr, addr_buf); + addr = ether_ntoa(&attrs->host_addr); ret = usbg_write_string(f->path, f->name, "host_addr", addr); if (ret != USBG_SUCCESS) goto out; - ret = usbg_write_dec(f->path, f->name, "qmult", attrs->qmult); - -out: - return ret; -} - -static int usbg_set_f_ms_lun_attrs(const char *path, const char *lun, - usbg_f_ms_lun_attrs *lun_attrs) -{ - int ret; - - ret = usbg_write_bool(path, lun, "cdrom", lun_attrs->cdrom); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_bool(path, lun, "ro", lun_attrs->ro); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_bool(path, lun, "nofua", lun_attrs->nofua); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_bool(path, lun, "removable", lun_attrs->removable); + ret = usbg_write_string(f->path, f->name, "ifname", attrs->ifname); if (ret != USBG_SUCCESS) goto out; - ret = usbg_write_string(path, lun, "file", - lun_attrs->filename); - -out: - return ret; -} - -static int usbg_set_function_ms_attrs(usbg_function *f, - const usbg_f_ms_attrs *f_attrs) -{ - int ret; - int i, nmb; - int space_left; - char *new_lun_mask; - char lpath[USBG_MAX_PATH_LENGTH]; - char *lpath_end; - DIR *dir; - struct dirent **dent; - - ret = usbg_write_bool(f->path, f->name, "stall", f_attrs->stall); - if (ret != USBG_SUCCESS) - goto out; - - /* lun0 cannot be removed */ - if (!f_attrs->luns || f_attrs->nluns <= 0) - goto out; - - ret = snprintf(lpath, sizeof(lpath), "%s/%s/", f->path, f->name); - if (ret >= sizeof(lpath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - lpath_end = lpath + strlen(lpath); - space_left = sizeof(lpath) - (lpath_end - lpath); - - new_lun_mask = calloc(f_attrs->nluns, sizeof (char)); - if (!new_lun_mask) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - for (i = 0; i < f_attrs->nluns; ++i) { - usbg_f_ms_lun_attrs *lun = f_attrs->luns[i]; - - /* - * id may be left unset in lun attrs but - * if it is set it has to be equal to position - * in lun array - */ - if (lun && lun->id >= 0 && lun->id != i) { - ret = USBG_ERROR_INVALID_PARAM; - goto err_lun_loop; - } - - ret = snprintf(lpath_end, space_left, "/lun.%d/", i); - if (ret >= space_left) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto err_lun_loop; - } - - /* - * Check if dir exist and create it if needed - */ - dir = opendir(lpath); - if (dir) { - closedir(dir); - } else if (errno != ENOENT) { - ret = usbg_translate_error(errno); - goto err_lun_loop; - } else { - ret = mkdir(lpath, S_IRWXU|S_IRWXG|S_IRWXO); - if (!ret) { - /* - * If we have created a new directory in - * this function let's mark it so we can - * cleanup in case of error - */ - new_lun_mask[i] = 1; - } else { - ret = usbg_translate_error(errno); - goto err_lun_loop; - } - } - - /* if attributes has not been provided just go to next one */ - if (!lun) - continue; - - ret = usbg_set_f_ms_lun_attrs(lpath, "", lun); - if (ret != USBG_SUCCESS) - goto err_lun_loop; - } - - /* Check if function has more luns and remove them */ - *lpath_end = '\0'; - i = 0; - nmb = scandir(lpath, &dent, lun_select, lun_sort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto err_lun_loop; - } - - for (i = 0; i < f_attrs->nluns; ++i) - free(dent[i]); - - for (; i < nmb; ++i) { - ret = usbg_rm_dir(lpath, dent[i]->d_name); - free(dent[i]); - /* There is no good way to recover form this */ - if (ret != USBG_SUCCESS) - goto err_rm_loop; - } - free(dent); - free(new_lun_mask); - - return USBG_SUCCESS; - -err_rm_loop: - while (++i < nmb) - free(dent[i]); - free(dent); - - i = f_attrs->nluns; -err_lun_loop: - /* array is null terminated so we may access lun[nluns] */ - for (; i >= 0; --i) { - if (!new_lun_mask[i]) - continue; - - ret = snprintf(lpath_end, space_left, "/lun.%d/", i); - if (ret >= space_left) { - /* - * This should not happen because if we were - * able to create this directory we should be - * also able to remove it. - */ - continue; - } - rmdir(lpath); - } - free(new_lun_mask); - -out: - return ret; -} - -int usbg_set_function_midi_attrs(usbg_function *f, - const usbg_f_midi_attrs *attrs) -{ - int ret; - - ret = usbg_write_dec(f->path, f->name, "index", attrs->index); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_string(f->path, f->name, "id", attrs->id); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "in_ports", attrs->in_ports); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "out_ports", attrs->out_ports); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "buflen", attrs->buflen); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "qlen", attrs->qlen); - -out: - return ret; -} - -int usbg_set_function_loopback_attrs(usbg_function *f, - const usbg_f_loopback_attrs *attrs) -{ - int ret; - - ret = usbg_write_dec(f->path, f->name, "buflen", attrs->buflen); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "qlen", attrs->qlen); + ret = usbg_write_dec(f->path, f->name, "qmult", attrs->qmult); out: return ret; } -int usbg_set_function_attrs(usbg_function *f, - const usbg_function_attrs *f_attrs) +int usbg_set_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) { int ret = USBG_ERROR_INVALID_PARAM; - int attrs_type; if (!f || !f_attrs) - return ret; - - attrs_type = usbg_lookup_function_attrs_type(f->type); - if (attrs_type < 0) - return ret; - - /* if attrs type is set, check if it has correct type */ - if (f_attrs->header.attrs_type && attrs_type != f_attrs->header.attrs_type) - return ret; - - switch (attrs_type) { - case USBG_F_ATTRS_SERIAL: - /* port_num attribute is read only so we accept only 0 - * and do nothing with it */ - ret = f_attrs->attrs.serial.port_num ? USBG_ERROR_INVALID_PARAM - : USBG_SUCCESS; - break; - - case USBG_F_ATTRS_NET: - ret = usbg_set_function_net_attrs(f, &f_attrs->attrs.net); - break; - - case USBG_F_ATTRS_PHONET: - /* ifname attribute is read only - * so we accept only empty string */ - ret = f_attrs->attrs.phonet.ifname && f_attrs->attrs.phonet.ifname[0] ? - USBG_ERROR_INVALID_PARAM : USBG_SUCCESS; - break; - - case USBG_F_ATTRS_FFS: - /* dev_name is a virtual attribute so allow only to use empty - * empty string which means nop */ - ret = f_attrs->attrs.ffs.dev_name && f_attrs->attrs.ffs.dev_name[0] ? - USBG_ERROR_INVALID_PARAM : USBG_SUCCESS; - break; + return USBG_ERROR_INVALID_PARAM; - case USBG_F_ATTRS_MS: - ret = usbg_set_function_ms_attrs(f, &f_attrs->attrs.ms); + switch (f->type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: + ret = usbg_write_dec(f->path, f->name, "port_num", f_attrs->serial.port_num); break; - - case USBG_F_ATTRS_MIDI: - ret = usbg_set_function_midi_attrs(f, &f_attrs->attrs.midi); + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: + ret = usbg_set_function_net_attrs(f, &f_attrs->net); break; - - case USBG_F_ATTRS_LOOPBACK: - ret = usbg_set_function_loopback_attrs(f, &f_attrs->attrs.loopback); + case F_PHONET: + ret = usbg_write_string(f->path, f->name, "ifname", f_attrs->phonet.ifname); break; - default: ERROR("Unsupported function type\n"); ret = USBG_ERROR_NOT_SUPPORTED; - break; } return ret; @@ -3389,8 +2076,7 @@ int usbg_set_net_dev_addr(usbg_function *f, struct ether_addr *dev_addr) int ret = USBG_SUCCESS; if (f && dev_addr) { - char str_buf[USBG_MAX_STR_LENGTH]; - char *str_addr = usbg_ether_ntoa_r(dev_addr, str_buf); + char *str_addr = ether_ntoa(dev_addr); ret = usbg_write_string(f->path, f->name, "dev_addr", str_addr); } else { ret = USBG_ERROR_INVALID_PARAM; @@ -3404,8 +2090,7 @@ int usbg_set_net_host_addr(usbg_function *f, struct ether_addr *host_addr) int ret = USBG_SUCCESS; if (f && host_addr) { - char str_buf[USBG_MAX_STR_LENGTH]; - char *str_addr = usbg_ether_ntoa_r(host_addr, str_buf); + char *str_addr = ether_ntoa(host_addr); ret = usbg_write_string(f->path, f->name, "host_addr", str_addr); } else { ret = USBG_ERROR_INVALID_PARAM; @@ -3440,11 +2125,6 @@ usbg_binding *usbg_get_first_binding(usbg_config *c) return c ? TAILQ_FIRST(&c->bindings) : NULL; } -usbg_udc *usbg_get_first_udc(usbg_state *s) -{ - return s ? TAILQ_FIRST(&s->udcs) : NULL; -} - usbg_gadget *usbg_get_next_gadget(usbg_gadget *g) { return g ? TAILQ_NEXT(g, gnode) : NULL; @@ -3464,9 +2144,3 @@ usbg_binding *usbg_get_next_binding(usbg_binding *b) { return b ? TAILQ_NEXT(b, bnode) : NULL; } - -usbg_udc *usbg_get_next_udc(usbg_udc *u) -{ - return u ? TAILQ_NEXT(u, unode) : NULL; -} - diff --git a/src/usbg_schemes_libconfig.c b/src/usbg_schemes_libconfig.c deleted file mode 100644 index c8944ed..0000000 --- a/src/usbg_schemes_libconfig.c +++ /dev/null @@ -1,2184 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <libconfig.h> - -#include "usbg/usbg_internal.h" - -#define USBG_NAME_TAG "name" -#define USBG_ATTRS_TAG "attrs" -#define USBG_STRINGS_TAG "strings" -#define USBG_FUNCTIONS_TAG "functions" -#define USBG_CONFIGS_TAG "configs" -#define USBG_LANG_TAG "lang" -#define USBG_TYPE_TAG "type" -#define USBG_INSTANCE_TAG "instance" -#define USBG_ID_TAG "id" -#define USBG_FUNCTION_TAG "function" -#define USBG_TAB_WIDTH 4 - -static inline int generate_function_label(usbg_function *f, char *buf, int size) -{ - return snprintf(buf, size, "%s_%s", - usbg_get_function_type_str(f->type), f->instance); - -} - -static int usbg_export_binding(usbg_binding *b, config_setting_t *root) -{ - config_setting_t *node; - int ret = USBG_ERROR_NO_MEM; - int cfg_ret; - char label[USBG_MAX_NAME_LENGTH]; - int nmb; - -#define CRETAE_ATTR_STRING(SOURCE, NAME) \ - do { \ - node = config_setting_add(root, NAME, CONFIG_TYPE_STRING); \ - if (!node) \ - goto out; \ - cfg_ret = config_setting_set_string(node, SOURCE); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - } while (0) - - CRETAE_ATTR_STRING(b->name, USBG_NAME_TAG); - - nmb = generate_function_label(b->target, label, sizeof(label)); - if (nmb >= sizeof(label)) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - CRETAE_ATTR_STRING(label, USBG_FUNCTION_TAG); - -#undef CRETAE_ATTR_STRING - - ret = USBG_SUCCESS; - -out: - return ret; -} - -static int usbg_export_config_bindings(usbg_config *c, config_setting_t *root) -{ - usbg_binding *b; - config_setting_t *node; - int ret = USBG_SUCCESS; - - TAILQ_FOREACH(b, &c->bindings, bnode) { - node = config_setting_add(root, NULL, CONFIG_TYPE_GROUP); - if (!node) { - ret = USBG_ERROR_NO_MEM; - break; - } - - ret = usbg_export_binding(b, node); - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - -static int usbg_export_config_strs_lang(usbg_config *c, char *lang_str, - config_setting_t *root) -{ - config_setting_t *node; - usbg_config_strs strs; - int lang; - int usbg_ret, cfg_ret, ret2; - int ret = USBG_ERROR_NO_MEM; - - ret2 = sscanf(lang_str, "%x", &lang); - if (ret2 != 1) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - usbg_ret = usbg_get_config_strs(c, lang, &strs); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_LANG_TAG, CONFIG_TYPE_INT); - if (!node) - goto out; - - cfg_ret = config_setting_set_format(node, CONFIG_FORMAT_HEX); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - cfg_ret = config_setting_set_int(node, lang); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - node = config_setting_add(root, "configuration" , CONFIG_TYPE_STRING); - if (!node) - goto out; - - cfg_ret = config_setting_set_string(node, strs.configuration); - - ret = cfg_ret == CONFIG_TRUE ? USBG_SUCCESS : USBG_ERROR_OTHER_ERROR; -out: - return ret; - -} - -static int usbg_export_config_strings(usbg_config *c, config_setting_t *root) -{ - config_setting_t *node; - int usbg_ret = USBG_SUCCESS; - int nmb, i; - int ret = USBG_ERROR_NO_MEM; - char spath[USBG_MAX_PATH_LENGTH]; - struct dirent **dent; - - nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", c->path, - c->name, STRINGS_DIR); - if (nmb >= sizeof(spath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - nmb = scandir(spath, &dent, file_select, alphasort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - for (i = 0; i < nmb; ++i) { - node = config_setting_add(root, NULL, CONFIG_TYPE_GROUP); - if (!node) - goto out; - - usbg_ret = usbg_export_config_strs_lang(c, dent[i]->d_name, - node); - if (usbg_ret != USBG_SUCCESS) - break; - - free(dent[i]); - } - /* This loop will be executed only if error occurred in previous one */ - for (; i < nmb; ++i) - free(dent[i]); - - free(dent); - ret = usbg_ret; -out: - return ret; -} - -static int usbg_export_config_attrs(usbg_config *c, config_setting_t *root) -{ - config_setting_t *node; - usbg_config_attrs attrs; - int usbg_ret, cfg_ret; - int ret = USBG_ERROR_NO_MEM; - - usbg_ret = usbg_get_config_attrs(c, &attrs); - if (usbg_ret) { - ret = usbg_ret; - goto out; - } - -#define ADD_CONFIG_ATTR(attr_name) \ - do { \ - node = config_setting_add(root, #attr_name, CONFIG_TYPE_INT); \ - if (!node) \ - goto out; \ - cfg_ret = config_setting_set_format(node, CONFIG_FORMAT_HEX); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - cfg_ret = config_setting_set_int(node, attrs.attr_name); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - } while (0) - - ADD_CONFIG_ATTR(bmAttributes); - ADD_CONFIG_ATTR(bMaxPower); - -#undef ADD_CONFIG_ATTR - - ret = USBG_SUCCESS; -out: - return ret; - -} - -/* This function does not export configuration id because it is more of - * a property of gadget which contains this config than config itself */ -static int usbg_export_config_prep(usbg_config *c, config_setting_t *root) -{ - config_setting_t *node; - int ret = USBG_ERROR_NO_MEM; - int usbg_ret; - int cfg_ret; - - node = config_setting_add(root, USBG_NAME_TAG, CONFIG_TYPE_STRING); - if (!node) - goto out; - - cfg_ret = config_setting_set_string(node, c->label); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - node = config_setting_add(root, USBG_ATTRS_TAG, CONFIG_TYPE_GROUP); - if (!node) - goto out; - - usbg_ret = usbg_export_config_attrs(c, node); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_STRINGS_TAG, CONFIG_TYPE_LIST); - if (!node) - goto out; - - usbg_ret = usbg_export_config_strings(c, node); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_FUNCTIONS_TAG, CONFIG_TYPE_LIST); - if (!node) - goto out; - - ret = usbg_export_config_bindings(c, node); -out: - return ret; - -} - -static int usbg_export_gadget_configs(usbg_gadget *g, config_setting_t *root) -{ - usbg_config *c; - config_setting_t *node, *id_node; - int ret = USBG_SUCCESS; - int cfg_ret; - - TAILQ_FOREACH(c, &g->configs, cnode) { - node = config_setting_add(root, NULL, CONFIG_TYPE_GROUP); - if (!node) { - ret = USBG_ERROR_NO_MEM; - break; - } - - id_node = config_setting_add(node, USBG_ID_TAG, - CONFIG_TYPE_INT); - if (!id_node) { - ret = USBG_ERROR_NO_MEM; - break; - } - - cfg_ret = config_setting_set_int(id_node, c->id); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - - ret = usbg_export_config_prep(c, node); - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - -static int usbg_export_f_net_attrs(usbg_f_net_attrs *attrs, - config_setting_t *root) -{ - config_setting_t *node; - char *addr; - char addr_buf[USBG_MAX_STR_LENGTH]; - int cfg_ret; - int ret = USBG_ERROR_NO_MEM; - - node = config_setting_add(root, "dev_addr", CONFIG_TYPE_STRING); - if (!node) - goto out; - - addr = usbg_ether_ntoa_r(&attrs->dev_addr, addr_buf); - cfg_ret = config_setting_set_string(node, addr); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - node = config_setting_add(root, "host_addr", CONFIG_TYPE_STRING); - if (!node) - goto out; - - addr = usbg_ether_ntoa_r(&attrs->host_addr, addr_buf); - cfg_ret = config_setting_set_string(node, addr); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - node = config_setting_add(root, "qmult", CONFIG_TYPE_INT); - if (!node) - goto out; - - cfg_ret = config_setting_set_int(node, attrs->qmult); - ret = cfg_ret == CONFIG_TRUE ? 0 : USBG_ERROR_OTHER_ERROR; - - /* if name is read only so we don't export it */ -out: - return ret; - -} - -static int usbg_export_f_ms_lun_attrs(usbg_f_ms_lun_attrs *lattrs, - config_setting_t *root) -{ - config_setting_t *node; - int cfg_ret; - int i; - int ret = USBG_ERROR_NO_MEM; - -#define BOOL_ATTR(_name) { .name = #_name, .value = &lattrs->_name, } - struct { - char *name; - bool *value; - } bool_attrs[] = { - BOOL_ATTR(cdrom), - BOOL_ATTR(ro), - BOOL_ATTR(nofua), - BOOL_ATTR(removable), - }; -#undef BOOL_ATTR - - for (i = 0; i < ARRAY_SIZE(bool_attrs); ++i) { - node = config_setting_add(root, bool_attrs[i].name, CONFIG_TYPE_BOOL); - if (!node) - goto out; - - cfg_ret = config_setting_set_bool(node, *(bool_attrs[i].value)); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - } - - node = config_setting_add(root, "filename", CONFIG_TYPE_STRING); - if (!node) - goto out; - - cfg_ret = config_setting_set_string(node, lattrs->filename); - ret = cfg_ret == CONFIG_TRUE ? USBG_SUCCESS : USBG_ERROR_OTHER_ERROR; - -out: - return ret; -} - -static int usbg_export_f_ms_attrs(usbg_f_ms_attrs *attrs, - config_setting_t *root) -{ - config_setting_t *luns_node, *node; - int i; - int cfg_ret; - int ret = USBG_ERROR_NO_MEM; - - node = config_setting_add(root, "stall", CONFIG_TYPE_BOOL); - if (!node) - goto out; - - cfg_ret = config_setting_set_bool(node, attrs->stall); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - luns_node = config_setting_add(root, "luns", CONFIG_TYPE_LIST); - if (!luns_node) - goto out; - - for (i = 0; i < attrs->nluns; ++i) { - node = config_setting_add(luns_node, "", CONFIG_TYPE_GROUP); - if (!node) - goto out; - - ret = usbg_export_f_ms_lun_attrs(attrs->luns[i], node); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = USBG_SUCCESS; -out: - return ret; - -} - -static int usbg_export_f_midi_attrs(usbg_f_midi_attrs *attrs, - config_setting_t *root) -{ - config_setting_t *node; - int cfg_ret; - int ret = USBG_ERROR_NO_MEM; - -#define ADD_F_MIDI_INT_ATTR(attr, minval) \ - do { \ - if ((int)attrs->attr < minval) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - node = config_setting_add(root, #attr, CONFIG_TYPE_INT);\ - if (!node) \ - goto out; \ - cfg_ret = config_setting_set_int(node, attrs->attr); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - } while (0) - - ADD_F_MIDI_INT_ATTR(index, INT_MIN); - - node = config_setting_add(root, "id", CONFIG_TYPE_STRING); - if (!node) - goto out; - - cfg_ret = config_setting_set_string(node, attrs->id); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - ADD_F_MIDI_INT_ATTR(in_ports, 0); - ADD_F_MIDI_INT_ATTR(out_ports, 0); - ADD_F_MIDI_INT_ATTR(buflen, 0); - ADD_F_MIDI_INT_ATTR(qlen, 0); - -#undef ADD_F_MIDI_INT_ATTR - - ret = USBG_SUCCESS; -out: - return ret; -} - -static int usbg_export_f_loopback_attrs(usbg_f_loopback_attrs *attrs, - config_setting_t *root) -{ - config_setting_t *node; - int cfg_ret; - int ret = USBG_ERROR_NO_MEM; - -#define ADD_F_LOOPBACK_INT_ATTR(attr, minval) \ - do { \ - if ((int)attrs->attr < minval) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - node = config_setting_add(root, #attr, CONFIG_TYPE_INT);\ - if (!node) \ - goto out; \ - cfg_ret = config_setting_set_int(node, attrs->attr); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - } while (0) - - ADD_F_LOOPBACK_INT_ATTR(buflen, 0); - ADD_F_LOOPBACK_INT_ATTR(qlen, 0); - -#undef ADD_F_LOOPBACK_INT_ATTR - - ret = USBG_SUCCESS; -out: - return ret; -} - -static int usbg_export_function_attrs(usbg_function *f, config_setting_t *root) -{ - config_setting_t *node; - usbg_function_attrs f_attrs; - int usbg_ret, cfg_ret; - int ret = USBG_ERROR_NO_MEM; - - usbg_ret = usbg_get_function_attrs(f, &f_attrs); - if (usbg_ret) { - ret = usbg_ret; - goto out; - } - - switch (f_attrs.header.attrs_type) { - case USBG_F_ATTRS_SERIAL: - node = config_setting_add(root, "port_num", CONFIG_TYPE_INT); - if (!node) - goto out; - - cfg_ret = config_setting_set_int(node, f_attrs.attrs.serial.port_num); - ret = cfg_ret == CONFIG_TRUE ? 0 : USBG_ERROR_OTHER_ERROR; - break; - - case USBG_F_ATTRS_NET: - ret = usbg_export_f_net_attrs(&f_attrs.attrs.net, root); - break; - - case USBG_F_ATTRS_MS: - ret = usbg_export_f_ms_attrs(&f_attrs.attrs.ms, root); - break; - - case USBG_F_ATTRS_MIDI: - ret = usbg_export_f_midi_attrs(&f_attrs.attrs.midi, root); - break; - - case USBG_F_ATTRS_LOOPBACK: - ret = usbg_export_f_loopback_attrs(&f_attrs.attrs.loopback, root); - break; - - case USBG_F_ATTRS_PHONET: - /* Don't export ifname because it is read only */ - case USBG_F_ATTRS_FFS: - /* We don't need to export ffs attributes - * due to instance name export */ - ret = USBG_SUCCESS; - break; - default: - ERROR("Unsupported function type\n"); - ret = USBG_ERROR_NOT_SUPPORTED; - } - - usbg_cleanup_function_attrs(&f_attrs); -out: - return ret; -} - -/* This function does not import instance name because this is more property - * of a gadget than a function itself */ -static int usbg_export_function_prep(usbg_function *f, config_setting_t *root) -{ - config_setting_t *node; - int ret = USBG_ERROR_NO_MEM; - int cfg_ret; - - node = config_setting_add(root, USBG_TYPE_TAG, CONFIG_TYPE_STRING); - if (!node) - goto out; - - cfg_ret = config_setting_set_string(node, usbg_get_function_type_str( - f->type)); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - node = config_setting_add(root, USBG_ATTRS_TAG, CONFIG_TYPE_GROUP); - if (!node) - goto out; - - ret = usbg_export_function_attrs(f, node); -out: - return ret; -} - - -static int usbg_export_gadget_functions(usbg_gadget *g, config_setting_t *root) -{ - usbg_function *f; - config_setting_t *node, *inst_node; - int ret = USBG_SUCCESS; - int cfg_ret; - char label[USBG_MAX_NAME_LENGTH]; - char *func_label; - int nmb; - - TAILQ_FOREACH(f, &g->functions, fnode) { - if (f->label) { - func_label = f->label; - } else { - nmb = generate_function_label(f, label, sizeof(label)); - if (nmb >= sizeof(label)) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - func_label = label; - } - - node = config_setting_add(root, func_label, CONFIG_TYPE_GROUP); - if (!node) { - ret = USBG_ERROR_NO_MEM; - break; - } - - /* Add instance name to identify in this gadget */ - inst_node = config_setting_add(node, USBG_INSTANCE_TAG, - CONFIG_TYPE_STRING); - if (!inst_node) { - ret = USBG_ERROR_NO_MEM; - break; - } - - cfg_ret = config_setting_set_string(inst_node, f->instance); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - - ret = usbg_export_function_prep(f, node); - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - -static int usbg_export_gadget_strs_lang(usbg_gadget *g, const char *lang_str, - config_setting_t *root) -{ - config_setting_t *node; - usbg_gadget_strs strs; - int lang; - int usbg_ret, cfg_ret; - int ret = USBG_ERROR_NO_MEM; - - ret = sscanf(lang_str, "%x", &lang); - if (ret != 1) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - usbg_ret = usbg_get_gadget_strs(g, lang, &strs); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_LANG_TAG, CONFIG_TYPE_INT); - if (!node) - goto out; - - cfg_ret = config_setting_set_format(node, CONFIG_FORMAT_HEX); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - cfg_ret = config_setting_set_int(node, lang); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - -#define ADD_GADGET_STR(str_name, field) \ - do { \ - node = config_setting_add(root, str_name, CONFIG_TYPE_STRING); \ - if (!node) \ - goto out; \ - cfg_ret = config_setting_set_string(node, strs.field); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - } while (0) - - ADD_GADGET_STR("manufacturer", str_mnf); - ADD_GADGET_STR("product", str_prd); - ADD_GADGET_STR("serialnumber", str_ser); - -#undef ADD_GADGET_STR - ret = USBG_SUCCESS; -out: - return ret; -} - -static int usbg_export_gadget_strings(usbg_gadget *g, config_setting_t *root) -{ - config_setting_t *node; - int usbg_ret = USBG_SUCCESS; - int nmb, i; - int ret = USBG_ERROR_NO_MEM; - char spath[USBG_MAX_PATH_LENGTH]; - struct dirent **dent; - - nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", g->path, - g->name, STRINGS_DIR); - if (nmb >= sizeof(spath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - nmb = scandir(spath, &dent, file_select, alphasort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - for (i = 0; i < nmb; ++i) { - node = config_setting_add(root, NULL, CONFIG_TYPE_GROUP); - if (!node) - break; - - usbg_ret = usbg_export_gadget_strs_lang(g, dent[i]->d_name, - node); - if (usbg_ret != USBG_SUCCESS) - break; - - free(dent[i]); - } - /* This loop will be executed only if error occurred in previous one */ - for (; i < nmb; ++i) - free(dent[i]); - - free(dent); - ret = usbg_ret; -out: - return ret; -} - -static int usbg_export_gadget_attrs(usbg_gadget *g, config_setting_t *root) -{ - config_setting_t *node; - usbg_gadget_attrs attrs; - int usbg_ret, cfg_ret; - int ret = USBG_ERROR_NO_MEM; - - usbg_ret = usbg_get_gadget_attrs(g, &attrs); - if (usbg_ret) { - ret = usbg_ret; - goto out; - } - -#define ADD_GADGET_ATTR(attr_name) \ - do { \ - node = config_setting_add(root, #attr_name, CONFIG_TYPE_INT); \ - if (!node) \ - goto out; \ - cfg_ret = config_setting_set_format(node, CONFIG_FORMAT_HEX); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - cfg_ret = config_setting_set_int(node, attrs.attr_name); \ - if (cfg_ret != CONFIG_TRUE) { \ - ret = USBG_ERROR_OTHER_ERROR; \ - goto out; \ - } \ - } while (0) - - ADD_GADGET_ATTR(bcdUSB); - ADD_GADGET_ATTR(bDeviceClass); - ADD_GADGET_ATTR(bDeviceSubClass); - ADD_GADGET_ATTR(bDeviceProtocol); - ADD_GADGET_ATTR(bMaxPacketSize0); - ADD_GADGET_ATTR(idVendor); - ADD_GADGET_ATTR(idProduct); - ADD_GADGET_ATTR(bcdDevice); - -#undef ADD_GADGET_ATTR - - ret = 0; -out: - return ret; -} - -static int usbg_export_gadget_prep(usbg_gadget *g, config_setting_t *root) -{ - config_setting_t *node; - int ret = USBG_ERROR_NO_MEM; - int usbg_ret; - - /* We don't export name tag because name should be given during - * loading of gadget */ - - node = config_setting_add(root, USBG_ATTRS_TAG, CONFIG_TYPE_GROUP); - if (!node) - goto out; - - usbg_ret = usbg_export_gadget_attrs(g, node); - if (usbg_ret) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_STRINGS_TAG, - CONFIG_TYPE_LIST); - if (!node) - goto out; - - usbg_ret = usbg_export_gadget_strings(g, node); - if (usbg_ret) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_FUNCTIONS_TAG, - CONFIG_TYPE_GROUP); - if (!node) - goto out; - - usbg_ret = usbg_export_gadget_functions(g, node); - if (usbg_ret) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, USBG_CONFIGS_TAG, - CONFIG_TYPE_LIST); - if (!node) - goto out; - - usbg_ret = usbg_export_gadget_configs(g, node); - ret = usbg_ret; -out: - return ret; -} - -/* Export gadget/function/config API implementation */ - -int usbg_export_function(usbg_function *f, FILE *stream) -{ - config_t cfg; - config_setting_t *root; - int ret; - - if (!f || !stream) - return USBG_ERROR_INVALID_PARAM; - - config_init(&cfg); - - /* Set format */ - config_set_tab_width(&cfg, USBG_TAB_WIDTH); - - /* Always successful */ - root = config_root_setting(&cfg); - - ret = usbg_export_function_prep(f, root); - if (ret != USBG_SUCCESS) - goto out; - - config_write(&cfg, stream); -out: - config_destroy(&cfg); - return ret; -} - -int usbg_export_config(usbg_config *c, FILE *stream) -{ - config_t cfg; - config_setting_t *root; - int ret; - - if (!c || !stream) - return USBG_ERROR_INVALID_PARAM; - - config_init(&cfg); - - /* Set format */ - config_set_tab_width(&cfg, USBG_TAB_WIDTH); - - /* Always successful */ - root = config_root_setting(&cfg); - - ret = usbg_export_config_prep(c, root); - if (ret != USBG_SUCCESS) - goto out; - - config_write(&cfg, stream); -out: - config_destroy(&cfg); - return ret; -} - -int usbg_export_gadget(usbg_gadget *g, FILE *stream) -{ - config_t cfg; - config_setting_t *root; - int ret; - - if (!g || !stream) - return USBG_ERROR_INVALID_PARAM; - - config_init(&cfg); - - /* Set format */ - config_set_tab_width(&cfg, USBG_TAB_WIDTH); - - /* Always successful */ - root = config_root_setting(&cfg); - - ret = usbg_export_gadget_prep(g, root); - if (ret != USBG_SUCCESS) - goto out; - - config_write(&cfg, stream); -out: - config_destroy(&cfg); - return ret; -} - -#define usbg_config_is_int(node) (config_setting_type(node) == CONFIG_TYPE_INT) -#define usbg_config_is_string(node) \ - (config_setting_type(node) == CONFIG_TYPE_STRING) - -static int split_function_label(const char *label, usbg_function_type *type, - const char **instance) -{ - const char *floor; - char buf[USBG_MAX_NAME_LENGTH]; - int len; - int function_type; - int ret = USBG_ERROR_NOT_FOUND; - - /* We assume that function type string doesn't contain '_' */ - floor = strchr(label, '_'); - /* if phrase before _ is longer than max name length we may - * stop looking */ - len = floor - label; - if (len >= USBG_MAX_NAME_LENGTH || floor == label) - goto out; - - strncpy(buf, label, len); - buf[len] = '\0'; - - function_type = usbg_lookup_function_type(buf); - if (function_type < 0) - goto out; - - *type = (usbg_function_type)function_type; - *instance = floor + 1; - - ret = USBG_SUCCESS; -out: - return ret; -} - -static void usbg_set_failed_import(config_t **to_set, config_t *failed) -{ - if (*to_set != NULL) { - config_destroy(*to_set); - free(*to_set); - } - - *to_set = failed; -} - -static int usbg_import_f_net_attrs(config_setting_t *root, usbg_function *f) -{ - config_setting_t *node; - int ret = USBG_SUCCESS; - int qmult; - struct ether_addr *addr; - struct ether_addr addr_buf; - const char *str; - -#define GET_OPTIONAL_ADDR(NAME) \ - do { \ - node = config_setting_get_member(root, #NAME); \ - if (node) { \ - str = config_setting_get_string(node); \ - if (!str) { \ - ret = USBG_ERROR_INVALID_TYPE; \ - goto out; \ - } \ - \ - addr = ether_aton_r(str, &addr_buf); \ - if (!addr) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - ret = usbg_set_net_##NAME(f, addr); \ - if (ret != USBG_SUCCESS) \ - goto out; \ - } \ - } while (0) - - GET_OPTIONAL_ADDR(host_addr); - GET_OPTIONAL_ADDR(dev_addr); - -#undef GET_OPTIONAL_ADDR - - node = config_setting_get_member(root, "qmult"); - if (node) { - if (!usbg_config_is_int(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - qmult = config_setting_get_int(node); - ret = usbg_set_net_qmult(f, qmult); - } - -out: - return ret; -} - -static int usbg_import_f_ms_lun_attrs(usbg_f_ms_lun_attrs *lattrs, - config_setting_t *root) -{ - config_setting_t *node; - int i; - int ret = USBG_ERROR_NO_MEM; - -#define BOOL_ATTR(_name, _default_val) \ - { .name = #_name, .value = &lattrs->_name, } - struct { - char *name; - bool *value; - bool default_val; - } bool_attrs[] = { - BOOL_ATTR(cdrom, false), - BOOL_ATTR(ro, false), - BOOL_ATTR(nofua, false), - BOOL_ATTR(removable, true), - }; -#undef BOOL_ATTR - - memset(lattrs, 0, sizeof(*lattrs)); - lattrs->id = -1; - - for (i = 0; i < ARRAY_SIZE(bool_attrs); ++i) { - *(bool_attrs[i].value) = bool_attrs[i].default_val; - - node = config_setting_get_member(root, bool_attrs[i].name); - if (!node) - continue; - - ret = config_setting_type(node); - switch (ret) { - case CONFIG_TYPE_INT: - *(bool_attrs[i].value) = !!config_setting_get_int(node); - break; - case CONFIG_TYPE_BOOL: - *(bool_attrs[i].value) = config_setting_get_bool(node); - break; - default: - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - } - - node = config_setting_get_member(root, "filename"); - if (node) { - if (!usbg_config_is_string(node)) { - ret = USBG_ERROR_INVALID_PARAM; - goto out; - } - lattrs->filename = (char *)config_setting_get_string(node); - } else { - lattrs->filename = ""; - } - - ret = USBG_SUCCESS; -out: - return ret; -} - -static int usbg_import_f_ms_attrs(config_setting_t *root, usbg_function *f) -{ - config_setting_t *luns_node, *node; - int i; - int ret = USBG_ERROR_NO_MEM; - usbg_function_attrs attrs; - usbg_f_ms_attrs *ms_attrs = &attrs.attrs.ms; - - memset(&attrs, 0, sizeof(attrs)); - - node = config_setting_get_member(root, "stall"); - if (node) { - ret = config_setting_type(node); - switch (ret) { - case CONFIG_TYPE_INT: - ms_attrs->stall = !!config_setting_get_int(node); - break; - case CONFIG_TYPE_BOOL: - ms_attrs->stall = config_setting_get_bool(node); - break; - default: - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - } - - luns_node = config_setting_get_member(root, "luns"); - if (!node) { - ret = USBG_ERROR_INVALID_PARAM; - goto out; - } - - if (!config_setting_is_list(luns_node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - - ms_attrs->nluns = config_setting_length(luns_node); - - ms_attrs->luns = calloc(ms_attrs->nluns + 1, sizeof(*(ms_attrs->luns))); - if (!ms_attrs->luns) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - for (i = 0; i < ms_attrs->nluns; ++i) { - node = config_setting_get_elem(luns_node, i); - if (!node) { - ret = USBG_ERROR_INVALID_FORMAT; - goto free_luns; - } - - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto free_luns; - } - - ms_attrs->luns[i] = malloc(sizeof(*(ms_attrs->luns[i]))); - if (!ms_attrs->luns[i]) { - ret = USBG_ERROR_NO_MEM; - goto free_luns; - } - - ret = usbg_import_f_ms_lun_attrs(ms_attrs->luns[i], node); - if (ret != USBG_SUCCESS) - goto free_luns; - } - - ret = usbg_set_function_attrs(f, &attrs); - -free_luns: - while (--i >= 0) - if (ms_attrs->luns[i]) - free(ms_attrs->luns[i]); - free(ms_attrs->luns); -out: - return ret; - -} - -static int usbg_import_f_midi_attrs(config_setting_t *root, usbg_function *f) -{ - config_setting_t *node; - int ret = USBG_ERROR_NO_MEM; - int tmp; - usbg_function_attrs attrs; - usbg_f_midi_attrs *midi_attrs = &attrs.attrs.midi; - - attrs.header.attrs_type = USBG_F_ATTRS_MIDI; - -#define ADD_F_MIDI_INT_ATTR(attr, defval, minval) \ - do { \ - node = config_setting_get_member(root, #attr); \ - if (node) { \ - if (!usbg_config_is_int(node)) { \ - ret = USBG_ERROR_INVALID_TYPE; \ - goto out; \ - } \ - tmp = config_setting_get_int(node); \ - if (tmp < minval) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - midi_attrs->attr = tmp; \ - } else { \ - midi_attrs->attr = defval; \ - } \ - } while (0) - - ADD_F_MIDI_INT_ATTR(index, -1, INT_MIN); - ADD_F_MIDI_INT_ATTR(in_ports, 1, 0); - ADD_F_MIDI_INT_ATTR(out_ports, 1, 0); - ADD_F_MIDI_INT_ATTR(buflen, 256, 0); - ADD_F_MIDI_INT_ATTR(qlen, 32, 0); - -#undef ADD_F_MIDI_INT_ATTR - - node = config_setting_get_member(root, "id"); - if (node) { - if (!usbg_config_is_string(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - - midi_attrs->id = config_setting_get_string(node); - } else { - midi_attrs->id = ""; - } - - - ret = usbg_set_function_attrs(f, &attrs); -out: - return ret; -} - -static int usbg_import_f_loopback_attrs(config_setting_t *root, usbg_function *f) -{ - config_setting_t *node; - int ret = USBG_ERROR_NO_MEM; - int tmp; - usbg_function_attrs attrs; - usbg_f_loopback_attrs *loopback_attrs = &attrs.attrs.loopback; - - attrs.header.attrs_type = USBG_F_ATTRS_LOOPBACK; - -#define ADD_F_LOOPBACK_INT_ATTR(attr, defval, minval) \ - do { \ - node = config_setting_get_member(root, #attr); \ - if (node) { \ - if (!usbg_config_is_int(node)) { \ - ret = USBG_ERROR_INVALID_TYPE; \ - goto out; \ - } \ - tmp = config_setting_get_int(node); \ - if (tmp < minval) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - loopback_attrs->attr = tmp; \ - } else { \ - loopback_attrs->attr = defval; \ - } \ - } while (0) - - ADD_F_LOOPBACK_INT_ATTR(buflen, 4096, 0); - ADD_F_LOOPBACK_INT_ATTR(qlen, 32, 0); - -#undef ADD_F_LOOPBACK_INT_ATTR - - ret = usbg_set_function_attrs(f, &attrs); -out: - return ret; -} - -static int usbg_import_function_attrs(config_setting_t *root, usbg_function *f) -{ - int ret = USBG_SUCCESS; - int attrs_type; - - attrs_type = usbg_lookup_function_attrs_type(f->type); - if (attrs_type < 0) { - ret = attrs_type; - goto out; - } - - switch (attrs_type) { - case USBG_F_ATTRS_SERIAL: - /* Don't import port_num because it is read only */ - break; - - case USBG_F_ATTRS_NET: - ret = usbg_import_f_net_attrs(root, f); - break; - - case USBG_F_ATTRS_PHONET: - /* Don't import ifname because it is read only */ - break; - - case USBG_F_ATTRS_FFS: - /* We don't need to import ffs attributes - * due to instance name import */ - break; - - case USBG_F_ATTRS_MS: - ret = usbg_import_f_ms_attrs(root, f); - break; - - case USBG_F_ATTRS_MIDI: - ret = usbg_import_f_midi_attrs(root, f); - break; - - case USBG_F_ATTRS_LOOPBACK: - ret = usbg_import_f_loopback_attrs(root, f); - break; - - default: - ERROR("Unsupported function type\n"); - ret = USBG_ERROR_NOT_SUPPORTED; - break; - } - -out: - return ret; -} - -static int usbg_import_function_run(usbg_gadget *g, config_setting_t *root, - const char *instance, usbg_function **f) -{ - config_setting_t *node; - const char *type_str; - int usbg_ret; - int function_type; - int ret = USBG_ERROR_MISSING_TAG; - - /* function type is mandatory */ - node = config_setting_get_member(root, USBG_TYPE_TAG); - if (!node) - goto out; - - type_str = config_setting_get_string(node); - if (!type_str) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - - /* Check if this type is supported */ - function_type = usbg_lookup_function_type(type_str); - if (function_type < 0) { - ret = USBG_ERROR_NOT_SUPPORTED; - goto out; - } - - /* All data collected, let's get to work and create this function */ - ret = usbg_create_function(g, (usbg_function_type)function_type, - instance, NULL, f); - - if (ret != USBG_SUCCESS) - goto out; - - /* Attrs are optional */ - node = config_setting_get_member(root, USBG_ATTRS_TAG); - if (node) { - usbg_ret = usbg_import_function_attrs(node, *f); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - } -out: - return ret; -} - -static usbg_function *usbg_lookup_function(usbg_gadget *g, const char *label) -{ - usbg_function *f; - int usbg_ret; - - /* check if such function has also been imported */ - TAILQ_FOREACH(f, &g->functions, fnode) { - if (f->label && !strcmp(f->label, label)) - break; - } - - /* if not let's check if label follows the naming convention */ - if (!f) { - usbg_function_type type; - const char *instance; - - usbg_ret = split_function_label(label, &type, &instance); - if (usbg_ret != USBG_SUCCESS) - goto out; - - /* check if such function exist */ - f = usbg_get_function(g, type, instance); - } - -out: - return f; -} - -/* We have a string which should match with one of function names */ -static int usbg_import_binding_string(config_setting_t *root, usbg_config *c) -{ - const char *func_label; - usbg_function *target; - int ret; - - func_label = config_setting_get_string(root); - if (!func_label) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - target = usbg_lookup_function(c->parent, func_label); - if (!target) { - ret = USBG_ERROR_NOT_FOUND; - goto out; - } - - ret = usbg_add_config_function(c, target->name, target); -out: - return ret; -} - -static int usbg_import_binding_group(config_setting_t *root, usbg_config *c) -{ - config_setting_t *node; - const char *func_label, *name; - usbg_function *target; - int ret; - - node = config_setting_get_member(root, USBG_FUNCTION_TAG); - if (!node) { - ret = USBG_ERROR_MISSING_TAG; - goto out; - } - - /* It is allowed to provide link to existing function - * or define unlabeled instance of function in this place */ - if (usbg_config_is_string(node)) { - func_label = config_setting_get_string(node); - if (!func_label) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - target = usbg_lookup_function(c->parent, func_label); - if (!target) { - ret = USBG_ERROR_NOT_FOUND; - goto out; - } - } else if (config_setting_is_group(node)) { - config_setting_t *inst_node; - const char *instance; - - inst_node = config_setting_get_member(node, USBG_INSTANCE_TAG); - if (!inst_node) { - ret = USBG_ERROR_MISSING_TAG; - goto out; - } - - instance = config_setting_get_string(inst_node); - if (!instance) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - - ret = usbg_import_function_run(c->parent, node, - instance, &target); - if (ret != USBG_SUCCESS) - goto out; - } else { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - - /* Name tag is optional. When no such tag, default one will be used */ - node = config_setting_get_member(root, USBG_NAME_TAG); - if (node) { - if (!usbg_config_is_string(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - - name = config_setting_get_string(node); - if (!name) { - ret = USBG_ERROR_OTHER_ERROR; - goto out; - } - } else { - name = target->name; - } - - ret = usbg_add_config_function(c, name, target); -out: - return ret; -} - -static int usbg_import_config_bindings(config_setting_t *root, usbg_config *c) -{ - config_setting_t *node; - int ret = USBG_SUCCESS; - int count, i; - - count = config_setting_length(root); - - for (i = 0; i < count; ++i) { - node = config_setting_get_elem(root, i); - - if (usbg_config_is_string(node)) - ret = usbg_import_binding_string(node, c); - else if (config_setting_is_group(node)) - ret = usbg_import_binding_group(node, c); - else - ret = USBG_ERROR_INVALID_TYPE; - - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - -static int usbg_import_config_strs_lang(config_setting_t *root, usbg_config *c) -{ - config_setting_t *node; - int lang; - const char *str; - usbg_config_strs c_strs = {{0}}; - int ret = USBG_ERROR_INVALID_TYPE; - - node = config_setting_get_member(root, USBG_LANG_TAG); - if (!node) { - ret = USBG_ERROR_MISSING_TAG; - goto out; - } - - if (!usbg_config_is_int(node)) - goto out; - - lang = config_setting_get_int(node); - - /* Configuration string is optional */ - node = config_setting_get_member(root, "configuration"); - if (node) { - if (!usbg_config_is_string(node)) - goto out; - - str = config_setting_get_string(node); - - /* Auto truncate the string to max length */ - strncpy(c_strs.configuration, str, USBG_MAX_STR_LENGTH); - c_strs.configuration[USBG_MAX_STR_LENGTH - 1] = 0; - } - - ret = usbg_set_config_strs(c, lang, &c_strs); - -out: - return ret; -} - -static int usbg_import_config_strings(config_setting_t *root, usbg_config *c) -{ - config_setting_t *node; - int ret = USBG_SUCCESS; - int count, i; - - count = config_setting_length(root); - - for (i = 0; i < count; ++i) { - node = config_setting_get_elem(root, i); - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - break; - } - - ret = usbg_import_config_strs_lang(node, c); - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - -static int usbg_import_config_attrs(config_setting_t *root, usbg_config *c) -{ - config_setting_t *node; - int usbg_ret; - int bmAttributes, bMaxPower; - int ret = USBG_ERROR_INVALID_TYPE; - - node = config_setting_get_member(root, "bmAttributes"); - if (node) { - if (!usbg_config_is_int(node)) - goto out; - - bmAttributes = config_setting_get_int(node); - usbg_ret = usbg_set_config_bm_attrs(c, bmAttributes); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - } - - node = config_setting_get_member(root, "bMaxPower"); - if (node) { - if (!usbg_config_is_int(node)) - goto out; - - bMaxPower = config_setting_get_int(node); - usbg_ret = usbg_set_config_max_power(c, bMaxPower); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - } - - /* Empty attrs section is also considered to be valid */ - ret = USBG_SUCCESS; -out: - return ret; - -} - -static int usbg_import_config_run(usbg_gadget *g, config_setting_t *root, - int id, usbg_config **c) -{ - config_setting_t *node; - const char *name; - usbg_config *newc; - int usbg_ret; - int ret = USBG_ERROR_MISSING_TAG; - - /* - * Label is mandatory, - * if attrs aren't present defaults are used - */ - node = config_setting_get_member(root, USBG_NAME_TAG); - if (!node) - goto out; - - name = config_setting_get_string(node); - if (!name) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - - /* Required data collected, let's create our config */ - usbg_ret = usbg_create_config(g, id, name, NULL, NULL, &newc); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - /* Attrs are optional */ - node = config_setting_get_member(root, USBG_ATTRS_TAG); - if (node) { - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - - usbg_ret = usbg_import_config_attrs(node, newc); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - /* Strings are also optional */ - node = config_setting_get_member(root, USBG_STRINGS_TAG); - if (node) { - if (!config_setting_is_list(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - - usbg_ret = usbg_import_config_strings(node, newc); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - /* Functions too, because some config may not be - * fully configured and not contain any function */ - node = config_setting_get_member(root, USBG_FUNCTIONS_TAG); - if (node) { - if (!config_setting_is_list(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - - usbg_ret = usbg_import_config_bindings(node, newc); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - *c = newc; - ret = USBG_SUCCESS; -out: - return ret; - -error: - ret = usbg_ret; -error2: - /* We ignore returned value, if function fails - * there is no way to handle it */ - usbg_rm_config(newc, USBG_RM_RECURSE); - return ret; -} - -static int usbg_import_gadget_configs(config_setting_t *root, usbg_gadget *g) -{ - config_setting_t *node, *id_node; - int id; - usbg_config *c; - int ret = USBG_SUCCESS; - int count, i; - - count = config_setting_length(root); - - for (i = 0; i < count; ++i) { - node = config_setting_get_elem(root, i); - if (!node) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - break; - } - - /* Look for id */ - id_node = config_setting_get_member(node, USBG_ID_TAG); - if (!id_node) { - ret = USBG_ERROR_MISSING_TAG; - break; - } - - if (!usbg_config_is_int(id_node)) { - ret = USBG_ERROR_INVALID_TYPE; - break; - } - - id = config_setting_get_int(id_node); - - ret = usbg_import_config_run(g, node, id, &c); - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - -static int usbg_import_gadget_functions(config_setting_t *root, usbg_gadget *g) -{ - config_setting_t *node, *inst_node; - const char *instance; - const char *label; - usbg_function *f; - int ret = USBG_SUCCESS; - int count, i; - - count = config_setting_length(root); - - for (i = 0; i < count; ++i) { - node = config_setting_get_elem(root, i); - if (!node) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - break; - } - - /* Look for instance name */ - inst_node = config_setting_get_member(node, USBG_INSTANCE_TAG); - if (!inst_node) { - ret = USBG_ERROR_MISSING_TAG; - break; - } - - if (!usbg_config_is_string(inst_node)) { - ret = USBG_ERROR_INVALID_TYPE; - break; - } - - instance = config_setting_get_string(inst_node); - if (!instance) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - - ret = usbg_import_function_run(g, node, instance, &f); - if (ret != USBG_SUCCESS) - break; - - /* Set the label given by user */ - label = config_setting_name(node); - if (!label) { - ret = USBG_ERROR_OTHER_ERROR; - break; - } - - f->label = strdup(label); - if (!f->label) { - ret = USBG_ERROR_NO_MEM; - break; - } - } - - return ret; -} - -static int usbg_import_gadget_strs_lang(config_setting_t *root, usbg_gadget *g) -{ - config_setting_t *node; - int lang; - const char *str; - usbg_gadget_strs g_strs = {{0}}; - int ret = USBG_ERROR_INVALID_TYPE; - - node = config_setting_get_member(root, USBG_LANG_TAG); - if (!node) { - ret = USBG_ERROR_MISSING_TAG; - goto out; - } - - if (!usbg_config_is_int(node)) - goto out; - - lang = config_setting_get_int(node); - - /* Auto truncate the string to max length */ -#define GET_OPTIONAL_GADGET_STR(NAME, FIELD) \ - do { \ - node = config_setting_get_member(root, #NAME); \ - if (node) { \ - if (!usbg_config_is_string(node)) \ - goto out; \ - str = config_setting_get_string(node); \ - strncpy(g_strs.FIELD, str, USBG_MAX_STR_LENGTH); \ - g_strs.FIELD[USBG_MAX_STR_LENGTH - 1] = '\0'; \ - } \ - } while (0) - - GET_OPTIONAL_GADGET_STR(manufacturer, str_mnf); - GET_OPTIONAL_GADGET_STR(product, str_prd); - GET_OPTIONAL_GADGET_STR(serialnumber, str_ser); - -#undef GET_OPTIONAL_GADGET_STR - - ret = usbg_set_gadget_strs(g, lang, &g_strs); - -out: - return ret; -} - -static int usbg_import_gadget_strings(config_setting_t *root, usbg_gadget *g) -{ - config_setting_t *node; - int ret = USBG_SUCCESS; - int count, i; - - count = config_setting_length(root); - - for (i = 0; i < count; ++i) { - node = config_setting_get_elem(root, i); - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - break; - } - - ret = usbg_import_gadget_strs_lang(node, g); - if (ret != USBG_SUCCESS) - break; - } - - return ret; -} - - -static int usbg_import_gadget_attrs(config_setting_t *root, usbg_gadget *g) -{ - config_setting_t *node; - int usbg_ret; - int val; - int ret = USBG_ERROR_INVALID_TYPE; - -#define GET_OPTIONAL_GADGET_ATTR(NAME, FUNC_END, TYPE) \ - do { \ - node = config_setting_get_member(root, #NAME); \ - if (node) { \ - if (!usbg_config_is_int(node)) \ - goto out; \ - val = config_setting_get_int(node); \ - if (val < 0 || val > ((1L << (sizeof(TYPE)*8)) - 1)) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - usbg_ret = usbg_set_gadget_##FUNC_END(g, (TYPE)val); \ - if (usbg_ret != USBG_SUCCESS) { \ - ret = usbg_ret; \ - goto out; \ - } \ - } \ - } while (0) - - GET_OPTIONAL_GADGET_ATTR(bcdUSB, device_bcd_usb, uint16_t); - GET_OPTIONAL_GADGET_ATTR(bDeviceClass, device_class, uint8_t); - GET_OPTIONAL_GADGET_ATTR(bDeviceSubClass, device_subclass, uint8_t); - GET_OPTIONAL_GADGET_ATTR(bDeviceProtocol, device_protocol, uint8_t); - GET_OPTIONAL_GADGET_ATTR(bMaxPacketSize0, device_max_packet, uint8_t); - GET_OPTIONAL_GADGET_ATTR(idVendor, vendor_id, uint16_t); - GET_OPTIONAL_GADGET_ATTR(idProduct, product_id, uint16_t); - GET_OPTIONAL_GADGET_ATTR(bcdDevice, device_bcd_device, uint16_t); - -#undef GET_OPTIONAL_GADGET_ATTR - - /* Empty attrs section is also considered to be valid */ - ret = USBG_SUCCESS; -out: - return ret; - -} - -static int usbg_import_gadget_run(usbg_state *s, config_setting_t *root, - const char *name, usbg_gadget **g) -{ - config_setting_t *node; - usbg_gadget *newg; - int usbg_ret; - int ret = USBG_ERROR_MISSING_TAG; - - /* There is no mandatory data in gadget so let's start with - * creating a new gadget */ - usbg_ret = usbg_create_gadget(s, name, NULL, NULL, &newg); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - /* Attrs are optional */ - node = config_setting_get_member(root, USBG_ATTRS_TAG); - if (node) { - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - - usbg_ret = usbg_import_gadget_attrs(node, newg); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - /* Strings are also optional */ - node = config_setting_get_member(root, USBG_STRINGS_TAG); - if (node) { - if (!config_setting_is_list(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - - usbg_ret = usbg_import_gadget_strings(node, newg); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - /* Functions too, because some gadgets may not be fully - * configured and don't have any function or have all functions - * defined inline in configurations */ - node = config_setting_get_member(root, USBG_FUNCTIONS_TAG); - if (node) { - if (!config_setting_is_group(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - usbg_ret = usbg_import_gadget_functions(node, newg); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - /* Some gadget may not be fully configured - * so configs are also optional */ - node = config_setting_get_member(root, USBG_CONFIGS_TAG); - if (node) { - if (!config_setting_is_list(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto error2; - } - usbg_ret = usbg_import_gadget_configs(node, newg); - if (usbg_ret != USBG_SUCCESS) - goto error; - } - - *g = newg; - ret = USBG_SUCCESS; -out: - return ret; - -error: - ret = usbg_ret; -error2: - /* We ignore returned value, if function fails - * there is no way to handle it */ - usbg_rm_gadget(newg, USBG_RM_RECURSE); - return ret; -} - -int usbg_import_function(usbg_gadget *g, FILE *stream, const char *instance, - usbg_function **f) -{ - config_t *cfg; - config_setting_t *root; - usbg_function *newf; - int ret, cfg_ret; - - if (!g || !stream || !instance) - return USBG_ERROR_INVALID_PARAM; - - cfg = malloc(sizeof(*cfg)); - if (!cfg) - return USBG_ERROR_NO_MEM; - - config_init(cfg); - - cfg_ret = config_read(cfg, stream); - if (cfg_ret != CONFIG_TRUE) { - usbg_set_failed_import(&g->last_failed_import, cfg); - ret = USBG_ERROR_INVALID_FORMAT; - goto out; - } - - /* Always successful */ - root = config_root_setting(cfg); - - ret = usbg_import_function_run(g, root, instance, &newf); - if (ret != USBG_SUCCESS) { - usbg_set_failed_import(&g->last_failed_import, cfg); - goto out; - } - - if (f) - *f = newf; - - config_destroy(cfg); - free(cfg); - /* Clean last error */ - usbg_set_failed_import(&g->last_failed_import, NULL); -out: - return ret; - -} - -int usbg_import_config(usbg_gadget *g, FILE *stream, int id, usbg_config **c) -{ - config_t *cfg; - config_setting_t *root; - usbg_config *newc; - int ret, cfg_ret; - - if (!g || !stream || id < 0) - return USBG_ERROR_INVALID_PARAM; - - cfg = malloc(sizeof(*cfg)); - if (!cfg) - return USBG_ERROR_NO_MEM; - - config_init(cfg); - - cfg_ret = config_read(cfg, stream); - if (cfg_ret != CONFIG_TRUE) { - usbg_set_failed_import(&g->last_failed_import, cfg); - ret = USBG_ERROR_INVALID_FORMAT; - goto out; - } - - /* Always successful */ - root = config_root_setting(cfg); - - ret = usbg_import_config_run(g, root, id, &newc); - if (ret != USBG_SUCCESS) { - usbg_set_failed_import(&g->last_failed_import, cfg); - goto out; - } - - if (c) - *c = newc; - - config_destroy(cfg); - free(cfg); - /* Clean last error */ - usbg_set_failed_import(&g->last_failed_import, NULL); -out: - return ret; -} - -int usbg_import_gadget(usbg_state *s, FILE *stream, const char *name, - usbg_gadget **g) -{ - config_t *cfg; - config_setting_t *root; - usbg_gadget *newg; - int ret, cfg_ret; - - if (!s || !stream || !name) - return USBG_ERROR_INVALID_PARAM; - - cfg = malloc(sizeof(*cfg)); - if (!cfg) - return USBG_ERROR_NO_MEM; - - config_init(cfg); - - cfg_ret = config_read(cfg, stream); - if (cfg_ret != CONFIG_TRUE) { - usbg_set_failed_import(&s->last_failed_import, cfg); - ret = USBG_ERROR_INVALID_FORMAT; - goto out; - } - - /* Always successful */ - root = config_root_setting(cfg); - - ret = usbg_import_gadget_run(s, root, name, &newg); - if (ret != USBG_SUCCESS) { - usbg_set_failed_import(&s->last_failed_import, cfg); - goto out; - } - - if (g) - *g = newg; - - config_destroy(cfg); - free(cfg); - /* Clean last error */ - usbg_set_failed_import(&s->last_failed_import, NULL); -out: - return ret; -} - -const char *usbg_get_func_import_error_text(usbg_gadget *g) -{ - if (!g || !g->last_failed_import) - return NULL; - - return config_error_text(g->last_failed_import); -} - -int usbg_get_func_import_error_line(usbg_gadget *g) -{ - if (!g || !g->last_failed_import) - return -1; - - return config_error_line(g->last_failed_import); -} - -const char *usbg_get_config_import_error_text(usbg_gadget *g) -{ - if (!g || !g->last_failed_import) - return NULL; - - return config_error_text(g->last_failed_import); -} - -int usbg_get_config_import_error_line(usbg_gadget *g) -{ - if (!g || !g->last_failed_import) - return -1; - - return config_error_line(g->last_failed_import); -} - -const char *usbg_get_gadget_import_error_text(usbg_state *s) -{ - if (!s || !s->last_failed_import) - return NULL; - - return config_error_text(s->last_failed_import); -} - -int usbg_get_gadget_import_error_line(usbg_state *s) -{ - if (!s || !s->last_failed_import) - return -1; - - return config_error_line(s->last_failed_import); -} - diff --git a/src/usbg_schemes_none.c b/src/usbg_schemes_none.c deleted file mode 100644 index 915890c..0000000 --- a/src/usbg_schemes_none.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -#include <usbg/usbg.h> -#include "usbg/usbg_internal.h" - -int usbg_export_function(__attribute__ ((unused)) usbg_function *f, - __attribute__ ((unused)) FILE *stream) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -int usbg_export_config(__attribute__ ((unused)) usbg_config *c, - __attribute__ ((unused)) FILE *stream) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -int usbg_export_gadget(__attribute__ ((unused)) usbg_gadget *g, - __attribute__ ((unused)) FILE *stream) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -int usbg_import_function(__attribute__ ((unused)) usbg_gadget *g, - __attribute__ ((unused)) FILE *stream, - __attribute__ ((unused)) const char *instance, - __attribute__ ((unused)) usbg_function **f) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -int usbg_import_config(__attribute__ ((unused)) usbg_gadget *g, - __attribute__ ((unused)) FILE *stream, - __attribute__ ((unused)) int id, - __attribute__ ((unused)) usbg_config **c) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -int usbg_import_gadget(__attribute__ ((unused)) usbg_state *s, - __attribute__ ((unused)) FILE *stream, - __attribute__ ((unused)) const char *name, - __attribute__ ((unused)) usbg_gadget **g) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -const char *usbg_get_func_import_error_text( - __attribute__ ((unused)) usbg_gadget *g) -{ - return NULL; -} - -int usbg_get_func_import_error_line(__attribute__ ((unused)) usbg_gadget *g) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -const char *usbg_get_config_import_error_text( - __attribute__ ((unused)) usbg_gadget *g) -{ - return NULL; -} - -int usbg_get_config_import_error_line(__attribute__ ((unused)) usbg_gadget *g) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -const char *usbg_get_gadget_import_error_text( - __attribute__ ((unused)) usbg_state *s) -{ - return NULL; -} - -int usbg_get_gadget_import_error_line(__attribute__ ((unused)) usbg_state *s) -{ - return USBG_ERROR_NOT_SUPPORTED; -} - -void config_destroy(__attribute__ ((unused)) config_t *config) -{ - return; -} diff --git a/tests/Makefile.am b/tests/Makefile.am deleted file mode 100644 index 01feea4..0000000 --- a/tests/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -check_PROGRAMS = test -test_SOURCES = test.c usbg-test.c usbg-io-wrappers.c -test_LDFLAGS = -ldl -test_LDFLAGS += $(CMOCKA_LIBS) -test_LDFLAGS += $(LIBCONFIG_LIBS) -test_LDADD = ./libusbgx.so -test_CPPFLAGS = -I$(top_srcdir)/include/ - -./libusbgx.so: - -ln -s $(top_srcdir)/src/.libs/libusbgx.so* . -CLEANFILES = libusbgx.so* - -check_SCRIPTS = ./test.sh -TESTS = $(check_SCRIPTS) diff --git a/tests/test.c b/tests/test.c deleted file mode 100644 index bd17af9..0000000 --- a/tests/test.c +++ /dev/null @@ -1,2697 +0,0 @@ -#include <usbg/usbg.h> -#include <stdio.h> -#include <stdarg.h> -#include <setjmp.h> -#include <cmocka.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <getopt.h> -#include <time.h> - -#ifdef HAS_LIBCONFIG -#include <libconfig.h> -#endif - -#include "usbg-test.h" - -/** - * @file tests/test.c - */ - -#define USBG_TEST(name, test, setup, teardown) \ - {name, test, setup, teardown} - -#define FILLED_STR(len, c) \ - { [0 ... len - 2] = c, [len - 1] = '\0' } - -/* two levels of macros allow to strigify result of macro expansion */ -#define STR(s) #s -#define XSTR(s) STR(s) -/* unique string */ -#define UNIQUE XSTR(__COUNTER__) - -#define FUNC_FROM_TYPE(t) { \ - .type = t, \ - .instance = "instance"UNIQUE \ -} - -#define CONF_FROM_BOUND(b) { \ - .label = "c", \ - .id = __COUNTER__, \ - .bound_funcs = b \ -} - -static usbg_gadget_attrs min_gadget_attrs = { - .bcdUSB = 0x0000, - .bDeviceClass = 0x0, - .bDeviceSubClass = 0x0, - .bDeviceProtocol = 0x0, - .bMaxPacketSize0 = 0x0, - .idVendor = 0x0000, - .idProduct = 0x0000, - .bcdDevice = 0x0000 -}; - -static usbg_gadget_attrs max_gadget_attrs = { - .bcdUSB = 0xffff, - .bDeviceClass = 0xff, - .bDeviceSubClass = 0xff, - .bDeviceProtocol = 0xff, - .bMaxPacketSize0 = 0xff, - .idVendor = 0xffff, - .idProduct = 0xffff, - .bcdDevice = 0xffff -}; - -/* PATH_MAX is limit for path length */ -#define LONG_PATH_LEN PATH_MAX/2 -static char long_path_str[] = FILLED_STR(LONG_PATH_LEN, 'x'); - -/* NAME_MAX is limit for filename length */ -static char long_usbg_string[] = FILLED_STR(NAME_MAX, 'x'); - -static usbg_config_strs simple_config_strs= { - .configuration = "configuration string" -}; - -static usbg_config_attrs max_config_attrs = { - .bmAttributes = 0xff, - .bMaxPower = 0xff -}; - -static usbg_config_attrs min_config_attrs = { - .bmAttributes = 0x00, - .bMaxPower = 0x00 -}; - -/** - * @brief Simplest udcs names - * @details Used to go through init when testing other things - */ -static char *simple_udcs[] = { - "UDC1", - "UDC2", - NULL -}; - -static char *long_udcs[] = { - long_usbg_string, - "UDC1", - NULL -}; - -/** - * @brief Simplest functions names - * @details Used to go through init when testing other things - */ -static struct test_function simple_funcs[] = { - FUNC_FROM_TYPE(F_ECM), - FUNC_FROM_TYPE(F_ACM), - TEST_FUNCTION_LIST_END -}; - -/** - * @brief All functions types - * @details When testing with this in state, check if all func types are - * processed correctly - */ -static struct test_function all_funcs[] = { - FUNC_FROM_TYPE(F_SERIAL), - FUNC_FROM_TYPE(F_ACM), - FUNC_FROM_TYPE(F_OBEX), - FUNC_FROM_TYPE(F_ECM), - FUNC_FROM_TYPE(F_SUBSET), - FUNC_FROM_TYPE(F_NCM), - FUNC_FROM_TYPE(F_EEM), - FUNC_FROM_TYPE(F_RNDIS), - FUNC_FROM_TYPE(F_PHONET), - FUNC_FROM_TYPE(F_FFS), - TEST_FUNCTION_LIST_END -}; - -static struct test_function same_type_funcs[] = { - FUNC_FROM_TYPE(F_SERIAL), - FUNC_FROM_TYPE(F_SERIAL), - FUNC_FROM_TYPE(F_SERIAL), - TEST_FUNCTION_LIST_END -}; - -/** - * @brief No functions at all - * @details Check if gadget with no functions (or config with no bindings) - * is processed correctly. - */ -static struct test_function no_funcs[] = { - TEST_FUNCTION_LIST_END -}; - -/** - * @brief Simple configs - * @details Used to pass through init when testing other things - */ -static struct test_config simple_confs[] = { - CONF_FROM_BOUND(simple_funcs), - TEST_CONFIG_LIST_END -}; - -/** - * @brief Configs bound to all avaible function types - */ -static struct test_config all_bindings_confs[] = { - CONF_FROM_BOUND(no_funcs), - CONF_FROM_BOUND(all_funcs), - TEST_CONFIG_LIST_END -}; - -#define GADGET(n, u, c, f) \ - { \ - .name = n, \ - .udc = u, \ - .configs = c, \ - .functions = f \ - } - -/** - * @brief Simplest gadget - */ -static struct test_gadget simple_gadgets[] = { - GADGET("g1", "UDC1", simple_confs, simple_funcs), - TEST_GADGET_LIST_END -}; - -/** - * @brief Gadgets with all avaible functions - */ -static struct test_gadget all_funcs_gadgets[] = { - GADGET("all_funcs_gadget1", "UDC1", all_bindings_confs, all_funcs), - TEST_GADGET_LIST_END -}; - -static struct test_gadget long_udc_gadgets[] = { - GADGET("long_udc_gadgets", long_usbg_string, simple_confs, simple_funcs), - TEST_GADGET_LIST_END -}; - -struct test_function_attrs_data { - struct test_state *state; - usbg_function_attrs *attrs; -}; -struct test_data { - struct test_state *state; - struct usbg_state *usbg_state; -}; - -#define FUNC_ATTRS(t, label, a...) { \ - .header = { \ - .attrs_type = t \ - }, \ - .attrs = { \ - .label = { a } \ - }, \ -} - -static usbg_function_attrs simple_serial_attrs = FUNC_ATTRS(USBG_F_ATTRS_SERIAL, serial, 42); -static usbg_function_attrs simple_net_attrs = FUNC_ATTRS(USBG_F_ATTRS_NET, net, {}, {}, "if", 1); -static usbg_function_attrs simple_phonet_attrs = FUNC_ATTRS(USBG_F_ATTRS_PHONET, phonet, "if"); -static usbg_function_attrs writable_serial_attrs = FUNC_ATTRS(USBG_F_ATTRS_SERIAL, serial, 0); -static usbg_function_attrs writable_net_attrs = FUNC_ATTRS(USBG_F_ATTRS_NET, net, {}, {}, "", 42); -static usbg_function_attrs writable_phonet_attrs = FUNC_ATTRS(USBG_F_ATTRS_PHONET, phonet, ""); -static usbg_function_attrs simple_ffs_attrs = FUNC_ATTRS(USBG_F_ATTRS_FFS, ffs, "0"); -static usbg_function_attrs writable_ffs_attrs = FUNC_ATTRS(USBG_F_ATTRS_FFS, ffs, ""); - -struct test_gadget_strs_data { - struct test_state *state; - usbg_gadget_strs *strs; -}; - -#define STATE(p, g, u) { \ - .configfs_path = p, \ - .gadgets = g, \ - .udcs = u \ -} - -/** - * @brief Simple state - */ -static struct test_state simple_state = STATE("config", simple_gadgets, simple_udcs); - -/** - * @brief State with all functions avaible - */ -static struct test_state all_funcs_state = STATE("all_funcs_configfs", all_funcs_gadgets, simple_udcs); - -static struct test_state long_path_state = STATE(long_path_str, simple_gadgets, simple_udcs); - -static struct test_state long_udc_state = STATE("simple_path", long_udc_gadgets, long_udcs); - -static usbg_config_attrs *get_random_config_attrs() -{ - usbg_config_attrs *ret; - - ret = safe_malloc(sizeof(*ret)); - - srand(time(NULL)); - ret->bmAttributes = rand() % max_config_attrs.bmAttributes; - ret->bMaxPower = rand() % max_config_attrs.bMaxPower; - - return ret; -} - -static usbg_gadget_attrs *get_random_gadget_attrs() -{ - usbg_gadget_attrs *ret; - - ret = safe_malloc(sizeof(*ret)); - - srand(time(NULL)); - ret->bcdUSB = rand() % max_gadget_attrs.bcdUSB; - ret->bDeviceClass = rand() % max_gadget_attrs.bDeviceClass; - ret->bDeviceSubClass = rand() % max_gadget_attrs.bDeviceSubClass; - ret->bDeviceProtocol = rand() % max_gadget_attrs.bDeviceProtocol; - ret->bMaxPacketSize0 = rand() % max_gadget_attrs.bMaxPacketSize0; - ret->idVendor = rand() % max_gadget_attrs.idVendor; - ret->idProduct = rand() % max_gadget_attrs.idProduct; - ret->bcdDevice = rand() % max_gadget_attrs.bcdDevice; - - return ret; -} - -/** - * @brief Add given attributes to all configs in state - * @return Prepared state where configs has given attributes - */ -static void *prepare_state_with_config_attrs(struct test_state *state, - usbg_config_attrs *attrs) -{ - struct test_gadget *tg; - struct test_config *tc; - - for (tg = state->gadgets; tg->name; ++tg) - for (tc = tg->configs; tc->label; ++tc) - tc->attrs = attrs; - - state = prepare_state(state); - return state; -} - -static int setup_max_config_attrs_state(void **state) -{ - *state = prepare_state_with_config_attrs(&simple_state, &max_config_attrs); - return 0; -} - -static int setup_min_config_attrs_state(void **state) -{ - *state = prepare_state_with_config_attrs(&simple_state, &min_config_attrs); - return 0; -} - -static int setup_random_config_attrs_state(void **state) -{ - *state = prepare_state_with_config_attrs(&simple_state, get_random_config_attrs()); - return 0; -} - -static int setup_simple_config_strs_state(void **state) -{ - struct test_gadget *tg; - struct test_config *tc; - - for (tg = simple_state.gadgets; tg->name; ++tg) - for (tc = tg->configs; tc->label; ++tc) - tc->strs = &simple_config_strs; - - *state = prepare_state(&simple_state); - return 0; -} - -/** - * @brief Prepare test_state with one gadget containing given function list - * @details For testing only functions. We put them in a gadget as simply - * as possible. - * @param[in] func Pointer to list of functions - * @return Pointer to test state with given functions - */ -static struct test_state *put_func_in_state(struct test_function *func) -{ - struct test_state *st; - struct test_gadget *g; - struct test_config *c; - char **udcs; - - st = safe_calloc(1, sizeof(*st)); - /* Do not need config */ - c = safe_calloc(1, sizeof(*c)); - g = safe_calloc(2, sizeof(*g)); - udcs = safe_calloc(2, sizeof(*udcs)); - - g[0].name = "g1"; - g[0].udc = "UDC1"; - g[0].configs = c; - g[0].functions = func; - g[0].writable = 1; - - udcs[0] = "UDC1"; - g[0].writable = 1; - - st->configfs_path = "config"; - st->gadgets = g; - st->udcs = udcs; - st->writable = 1; - - st = prepare_state(st); - - return st; -} - -/** - * @brief Setup simple state with some gadgets, configs and functions - */ -static int setup_simple_state(void **state) -{ - *state = prepare_state(&simple_state); - return 0; -} - -/** - * @brief Setup state with all avaible functions - */ -static int setup_all_funcs_state(void **state) -{ - *state = prepare_state(&all_funcs_state); - return 0; -} - -/** - * @brief Setup state with few functions of the same type - */ -static int setup_same_type_funcs_state(void **state) -{ - *state = put_func_in_state(same_type_funcs); - return 0; -} - -/** - * @brief Setup state with very long path name - */ -static int setup_long_path_state(void **state) -{ - *state = prepare_state(&long_path_state); - return 0; -} - -/** - * @brief Setup state with long udc name - */ -static int setup_long_udc_state(void **state) -{ - *state = prepare_state(&long_udc_state); - return 0; -} - -/** - * @brief Setup state with gadget strings of random length - * @param[out] state Pointer to pointer to test_gadget_strs_data structure - * with initialized state and strings - */ -static int setup_random_len_gadget_strs_data(void **state) -{ - usbg_gadget_strs *strs; - struct test_gadget_strs_data *data; - - /* will fill memory with zeros */ - strs = safe_calloc(1, sizeof(*strs)); - data = safe_malloc(sizeof(*data)); - - srand(time(NULL)); - - memset(strs->str_ser, 'x', rand() % USBG_MAX_STR_LENGTH); - memset(strs->str_mnf, 'x', rand() % USBG_MAX_STR_LENGTH); - memset(strs->str_prd, 'x', rand() % USBG_MAX_STR_LENGTH); - - data->strs = strs; - - data->state = prepare_state(&simple_state); - *state = data; - return 0; -} - -static void *setup_f_attrs(int f_type, usbg_function_attrs *attrs) -{ - struct test_function_attrs_data *data; - struct test_function *func; - - data = safe_malloc(sizeof(*data)); - - func = safe_calloc(2, sizeof(*func)); - func[0].type = f_type; - func[0].instance = "0"; - func[0].writable = 1; - - data->state = put_func_in_state(func); - data->attrs = attrs; - return data; -} - -static int setup_f_serial_attrs(void **state) -{ - *state = setup_f_attrs(F_SERIAL, &simple_serial_attrs); - return 0; -} - -static int setup_f_serial_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_SERIAL, &writable_serial_attrs); - return 0; -} - -static int setup_f_acm_attrs(void **state) -{ - *state = setup_f_attrs(F_ACM, &simple_serial_attrs); - return 0; -} - -static int setup_f_acm_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_ACM, &writable_serial_attrs); - return 0; -} - -static int setup_f_obex_attrs(void **state) -{ - *state = setup_f_attrs(F_OBEX, &simple_serial_attrs); - return 0; -} - -static int setup_f_obex_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_OBEX, &writable_serial_attrs); - return 0; -} - -static int setup_f_ecm_attrs(void **state) -{ - *state = setup_f_attrs(F_ECM, &simple_net_attrs); - return 0; -} - -static int setup_f_ecm_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_ECM, &writable_net_attrs); - return 0; -} - -static int setup_f_subset_attrs(void **state) -{ - *state = setup_f_attrs(F_SUBSET, &simple_net_attrs); - return 0; -} - -static int setup_f_subset_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_SUBSET, &writable_net_attrs); - return 0; -} - -static int setup_f_ncm_attrs(void **state) -{ - *state = setup_f_attrs(F_NCM, &simple_net_attrs); - return 0; -} - -static int setup_f_ncm_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_NCM, &writable_net_attrs); - return 0; -} - -static int setup_f_eem_attrs(void **state) -{ - *state = setup_f_attrs(F_EEM, &simple_net_attrs); - return 0; -} - -static int setup_f_eem_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_EEM, &writable_net_attrs); - return 0; -} - -static int setup_f_rndis_attrs(void **state) -{ - *state = setup_f_attrs(F_RNDIS, &simple_net_attrs); - return 0; -} - -static int setup_f_rndis_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_RNDIS, &writable_net_attrs); - return 0; -} - -static int setup_f_phonet_attrs(void **state) -{ - *state = setup_f_attrs(F_PHONET, &simple_phonet_attrs); - return 0; -} - -static int setup_f_phonet_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_PHONET, &writable_phonet_attrs); - return 0; -} - -static int setup_f_ffs_attrs(void **state) -{ - *state = setup_f_attrs(F_FFS, &simple_ffs_attrs); - return 0; -} - -static int setup_f_ffs_writable_attrs(void **state) -{ - *state = setup_f_attrs(F_FFS, &writable_ffs_attrs); - return 0; -} - -/** - * @brief Tests usbg_get_gadget function with given state - * @details Check if gadgets are returned correctly - */ -static void test_get_gadget(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_gadget(ts, s, assert_gadget_equal); -} - -/** - * @brief Tests usbg_get_gadget with non-existing gadget name - * @details Check if get_gadget will not find non-existing gadgets and - * will not cause crash. - */ -static void test_get_gadget_fail(void **state) -{ - usbg_gadget *g = NULL; - usbg_state *s = NULL; - struct test_state *st; - - safe_init_with_state(state, &st, &s); - - g = usbg_get_gadget(s, "non-existing-gadget"); - assert_null(g); -} - -/** - * @brief Tests usbg_get_first_gadget function - * @details Check if gadget returned by get_first_gadget is actually first one - */ -static void test_get_first_gadget(void **state) -{ - usbg_gadget *g = NULL; - usbg_state *s = NULL; - struct test_state *st; - - safe_init_with_state(state, &st, &s); - - g = usbg_get_first_gadget(s); - assert_non_null(g); - assert_gadget_equal(g, &st->gadgets[0]); -} - -/** - * @brief Tests get_first_gadget with invalid arguments - */ -static void test_get_first_gadget_fail(void **state) -{ - usbg_gadget *g; - - g = usbg_get_first_gadget(NULL); - assert_null(g); -} - -static void try_get_gadget_name(usbg_gadget *g, struct test_gadget *tg) -{ - const char *name; - - name = usbg_get_gadget_name(g); - assert_string_equal(name, tg->name); -} - -/** - * @brief Tests getting name of gadget - * @details Check if gadget name is returned correctly - */ -static void test_get_gadget_name(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_gadget(ts, s, try_get_gadget_name); -} - -static void try_get_gadget_name_len(usbg_gadget *g, struct test_gadget *tg) -{ - int len; - int expected; - - expected = strlen(tg->name); - len = usbg_get_gadget_name_len(g); - assert_int_equal(len, expected); -} - -/** - * @brief Tests getting name length of gadget - * @details Check if returned name length is equal original - */ -static void test_get_gadget_name_len(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_gadget(ts, s, try_get_gadget_name_len); -} - -/** - * @brief Tests getting name of gadget with invalid arguments - * @details Check if trying to get name of wrong (non-existing) gadget - * will not cause crash, but return NULL as expected. - */ -static void test_get_gadget_name_fail(void **state) -{ - const char *name; - - name = usbg_get_gadget_name(NULL); - assert_null(name); -} - -static void try_cpy_gadget_name(usbg_gadget *g, struct test_gadget *tg) -{ - char name[USBG_MAX_NAME_LENGTH]; - int ret; - - ret = usbg_cpy_gadget_name(g, name, USBG_MAX_NAME_LENGTH); - assert_int_equal(ret, USBG_SUCCESS); - assert_string_equal(name, tg->name); -} - -/** - * @brief Tests copying gadget's name - * @details Check if copying gadget name copy actual name correctly - */ -static void test_cpy_gadget_name(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_gadget(ts, s, try_cpy_gadget_name); -} - -/** - * @brief Test copying gadet name with invalid arguments - * @details Check if trying to copy gadget name into non-existing buffer, - * or give invalid buffer length, or invalid gadget will be handled by library - * and return correct error codes - */ -static void test_cpy_gadget_name_fail(void **state) -{ - usbg_gadget *g = NULL; - usbg_state *s = NULL; - struct test_state *st; - int i = 0; - char name[USBG_MAX_NAME_LENGTH]; - int ret; - - safe_init_with_state(state, &st, &s); - - for (i = 0; st->gadgets[i].name; i++) { - g = usbg_get_gadget(s, st->gadgets[i].name); - assert_non_null(g); - - ret = usbg_cpy_gadget_name(g, name, 0); - assert_int_equal(ret, USBG_ERROR_INVALID_PARAM); - - ret = usbg_cpy_gadget_name(g, NULL, USBG_MAX_NAME_LENGTH); - assert_int_equal(ret, USBG_ERROR_INVALID_PARAM); - } - - ret = usbg_cpy_gadget_name(NULL, name, USBG_MAX_NAME_LENGTH); - assert_int_equal(ret, USBG_ERROR_INVALID_PARAM); -} - -/** - * @brief Tests init by comparing test state and usbg state - * @details Check if usbg state after init match given state and - * if init returned success code - */ -static void test_init(void **state) -{ - usbg_state *s = NULL; - struct test_state *st; - - safe_init_with_state(state, &st, &s); - - assert_state_equal(s, st); -} - -/** - * @brief Test getting function by name - * @param[in] state Pointer to pointer to correctly initialized test_state structure - */ -static void test_get_function(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_function(ts, s, assert_func_equal); -} - -/** - * @brief Tests usbg_get_function with some non-existing functions - * @details Check if get function will return NULL, when invalid - * functions names and types are passed as arguments and will not cause crash. - * @param[in] state Pointer to pointer to correctly initialized test_state structure - */ -static void test_get_function_fail(void **state) -{ - usbg_state *s = NULL; - usbg_gadget *g = NULL; - usbg_function *f = NULL; - struct test_state *st; - - safe_init_with_state(state, &st, &s); - - g = usbg_get_first_gadget(s); - assert_non_null(g); - - f = usbg_get_function(g, F_ACM, "non-existing-instance"); - assert_null(f); - - f = usbg_get_function(g, 9001, "0"); - assert_null(f); -} - - -/** - * @brief Tests function type translation to string - * @param[in] state Pointer to pointer to correctly initialized test_state structure - * @details Check if get_function_type_str returns proper strings for all types. - */ -static void test_get_function_type_str(void **state) -{ - struct { - usbg_function_type type; - const char *str; - } types[] = { - {F_SERIAL, "gser"}, - {F_ACM, "acm"}, - {F_OBEX, "obex"}, - {F_ECM, "ecm"}, - {F_SUBSET, "geth"}, - {F_NCM, "ncm"}, - {F_EEM, "eem"}, - {F_RNDIS, "rndis"}, - {F_PHONET, "phonet"}, - {F_FFS, "ffs"}, - }; - - const char *str; - int i; - - for (i = 0; i < ARRAY_SIZE(types); i++) { - str = usbg_get_function_type_str(types[i].type); - assert_non_null(str); - assert_string_equal(str, types[i].str); - } -} - -static struct { - usbg_gadget_str code; - const char *name; -} gadget_str_names[] = { - {STR_PRODUCT, "product"}, - {STR_MANUFACTURER, "manufacturer"}, - {STR_SERIAL_NUMBER, "serialnumber"}, -}; - -/** - * @brief Tests gadget codeing name getting - * @param[in] state Pointer to pointer to correctly initialized test_state codeucture - * @details Check if usbg_get_gadget_code_name returns proper codeings for all types. - */ -static void test_get_gadget_str_name(void **state) -{ - const char *name; - int i; - - for (i = 0; i < ARRAY_SIZE(gadget_str_names); i++) { - name = usbg_get_gadget_str_name(gadget_str_names[i].code); - assert_non_null(name); - assert_string_equal(name, gadget_str_names[i].name); - } -} - -/** - * @brief Tests gadget codeing code getting by its name - * @param[in] state Pointer to pointer to correctly initialized test_state codeucture - * @details Check if usbg_lookup_gadget_code returns values matching codeings - */ -static void test_lookup_gadget_str(void **state) -{ - int i, code; - - for (i = 0; i < ARRAY_SIZE(gadget_str_names); i++) { - code = usbg_lookup_gadget_str(gadget_str_names[i].name); - assert_return_code(code, 0); - assert_int_equal(code, gadget_str_names[i].code); - } -} - -/** - * @brief Tests function type translation to string with unknown funcs - * @param[in] state Not used parameter - * @details Check if get_function_type_str returns NULL, when given - * function type is unknown. - */ -static void test_get_function_type_str_fail(void **state) -{ - const char *str; - - str = usbg_get_function_type_str(-1); - assert_null(str); -} - -/** - * @brief Get instance of given function and check it - * @param[in] f Usbg function - * @param[in] tf Test function which should match f - */ -static void try_get_function_instance(usbg_function *f, struct test_function *tf) -{ - const char *str; - - str = usbg_get_function_instance(f); - assert_string_equal(str, tf->instance); -} - -/** - * @brief Tests getting function instance from usbg_function structure - * @param[in] state Pointer to pointer to correctly initialized test_state structure - * @details Check if returned instance name is correct. - */ -static void test_get_function_instance(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_function(ts, s, try_get_function_instance); -} - -/** - * @brief Cpy instance of given usbg function and check it - * @param[in] f Usbg function - * @param[in] tf Test function which should match f - */ -static void try_cpy_function_instance(usbg_function *f, struct test_function *tf) -{ - char str[USBG_MAX_NAME_LENGTH]; - int ret; - int small_len = 2; - - ret = usbg_cpy_function_instance(f, str, USBG_MAX_NAME_LENGTH); - assert_int_equal(ret, USBG_SUCCESS); - assert_string_equal(str, tf->instance); - - ret = usbg_cpy_function_instance(f, str, small_len); - assert_int_equal(ret, USBG_SUCCESS); - assert_memory_equal(str, tf->instance, small_len - 1); - assert_int_equal(str[small_len - 1], '\0'); -} - -/** - * @brief Tests copying function instance from usbg_function structure into buffer - * @param[in] state Pointer to pointer to correctly initialized state - * @details Check if buffer contains expected string - */ -static void test_cpy_function_instance(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_function(ts, s, try_cpy_function_instance); -} - -/** - * @brief Get function type and check it - * @param[in] f Usbg function - * @param[in] tf Test function which should match f by type - */ -static void try_get_function_type(usbg_function *f, struct test_function *tf) -{ - usbg_function_type type; - - type = usbg_get_function_type(f); - assert_int_equal(type, tf->type); -} - -/** - * @brief Tests getting function type - * @details Check if getting function type returns what was expected. - * State must be proper (init must end with success). - * @param[in] state Pointer to pointer to correctly initialized state - */ -static void test_get_function_type(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_function(ts, s, try_get_function_type); -} - -/** - * @brief Check if function instance length is correct - * @param[in] f Usbg function - * @param[in] tf Test function which should match f - */ -static void try_get_function_instance_len(usbg_function *f, struct test_function *tf) -{ - size_t len; - len = usbg_get_function_instance_len(f); - assert_int_equal(len, strlen(tf->instance)); -} - -/** - * @brief Tests getting length of function instance name - * @details Check if returned instance name length matches - * actual length of instance name - * @param[in] state Pointer to pointer to correctly initialized state - */ -static void test_get_function_instance_len(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_function(ts, s, try_get_function_instance_len); -} - -/** - * @brief Tests getting configfs path from usbg state - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_get_configfs_path(void **state) -{ - usbg_state *s = NULL; - struct test_state *st; - const char *path; - - safe_init_with_state(state, &st, &s); - - path = usbg_get_configfs_path(s); - assert_path_equal(path, st->configfs_path); -} - -/** - * @brief Tests getting configfs path length from usbg state - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_get_configfs_path_len(void **state) -{ - usbg_state *s = NULL; - struct test_state *st; - int ret, len; - - safe_init_with_state(state, &st, &s); - - ret = usbg_get_configfs_path_len(s); - len = strlen(st->configfs_path); - assert_int_equal(ret, len); -} - -/** - * @brief Tests copying configfs path into buffer - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_cpy_configfs_path(void **state) -{ - usbg_state *s = NULL; - struct test_state *st; - char path[PATH_MAX]; - int ret; - - safe_init_with_state(state, &st, &s); - - ret = usbg_cpy_configfs_path(s, path, PATH_MAX); - assert_int_equal(ret, USBG_SUCCESS); - assert_path_equal(path, st->configfs_path); -} - -/** - * @brief Tests getting config by name - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_get_config(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, assert_config_equal); -} - -static void test_get_config_without_label(void **state) -{ - usbg_state *s = NULL; - usbg_gadget *g = NULL; - usbg_config *c = NULL; - struct test_state *ts; - struct test_gadget *tg; - struct test_config *tc; - - safe_init_with_state(state, &ts, &s); - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - for (tc = tg->configs; tc->label; tc++) { - c = usbg_get_config(g, tc->id, NULL); - assert_non_null(c); - assert_config_equal(c, tc); - } - } -} - -/** - * @bried Tests getting non-existing config - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_get_config_fail(void **state) -{ - usbg_state *s = NULL; - usbg_gadget *g = NULL; - usbg_config *c = NULL; - struct test_state *ts; - struct test_gadget *tg; - - safe_init_with_state(state, &ts, &s); - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - - c = usbg_get_config(g, 0, "non-existing-config"); - assert_null(c); - - c = usbg_get_config(g, -9001, "c"); - assert_null(c); - - c = usbg_get_config(g, -9001, NULL); - assert_null(c); - } -} - -/** - * @brief Get config label and check it - * @param[in] c Usbg config - * @param[in] tc Test config which should match c - */ -static void try_get_config_label(usbg_config *c, struct test_config *tc) -{ - const char *label; - label = usbg_get_config_label(c); - assert_string_equal(label, tc->label); -} - -/** - * @brief Tests getting config label - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_get_config_label(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_get_config_label); -} - -/** - * @brief Check config id with test structure - * @param[in] c Usbg config - * @param[in] tc Test config which should match c - */ -static void try_get_config_id(usbg_config *c, struct test_config *tc) -{ - int id; - id = usbg_get_config_id(c); - assert_int_equal(id, tc->id); -} - -/** - * @brief Tests getting config id - * @param[in,out] state Pointer to pointer to correctly initialized test state. - * When finished, it contains pointer to usbg_state which should be cleaned. - */ -static void test_get_config_id(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_get_config_id); -} - -/** - * @brief Test getting given attributes from gadgets present in state - * @param[in] s Pointer to usbg state - * @param[in] ts Pointer to test state matching given usbg state - * @param[in] attrs Pointer to gadget attributes which should be put in - * virtual filesystem for writting by usbg - */ -static void try_get_gadget_attrs(usbg_state *s, struct test_state *ts, - usbg_gadget_attrs *attrs) -{ - usbg_gadget *g = NULL; - usbg_gadget_attrs actual; - struct test_gadget *tg; - int ret; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - - push_gadget_attrs(tg, attrs); - ret = usbg_get_gadget_attrs(g, &actual); - - assert_int_equal(ret, 0); - assert_gadget_attrs_equal(&actual, attrs); - } -} - -/** - * @brief Tests getting gadget attributes - * @param[in] state Pointer to correctly initialized test_state structure - **/ -static void test_get_gadget_attrs(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - - try_get_gadget_attrs(s, ts, &min_gadget_attrs); - try_get_gadget_attrs(s, ts, &max_gadget_attrs); - try_get_gadget_attrs(s, ts, get_random_gadget_attrs()); -} - -/** - * @brief Test setting given attributes on gadgets present in state - * @param[in] s Pointer to usbg state - * @param[in] ts Pointer to test state matching given usbg state - * @param[in] attrs Pointer to gadget attributes to be set - */ -static void try_set_gadget_attrs(usbg_state *s, struct test_state *ts, - usbg_gadget_attrs *attrs) -{ - usbg_gadget *g = NULL; - struct test_gadget *tg; - int ret; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - - pull_gadget_attrs(tg, attrs); - ret = usbg_set_gadget_attrs(g, attrs); - - assert_int_equal(ret, 0); - } -} -/** - * @brief Tests setting gadget attributes - * @param[in] state Pointer to correctly initialized test_state structure - **/ -static void test_set_gadget_attrs(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - - try_set_gadget_attrs(s, ts, &min_gadget_attrs); - try_set_gadget_attrs(s, ts, &max_gadget_attrs); - try_set_gadget_attrs(s, ts, get_random_gadget_attrs()); -} - -/** - * @brief Test setting given attributes on gadgets present in state one by one, - * using functions specific for each attribute - * @param[in] s Pointer to usbg state - * @param[in] ts Pointer to test state matching given usbg state - * @param[in] attrs Pointer to gadget attributes to be set - */ -static void try_set_specific_gadget_attr(usbg_state *s, struct test_state *ts, - usbg_gadget_attrs *attrs) -{ - usbg_gadget *g = NULL; - struct test_gadget *tg; - int ret; - int i; - int attr; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - - for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) { - attr = get_gadget_attr(attrs, i); - pull_gadget_attribute(tg, i, attr); - usbg_set_gadget_attr(g, i, attr); - assert_int_equal(ret, 0); - } - } -} - -/** - * @brief Tests setting gadget attributes one by one - * @param[in] state Pointer to correctly initialized test_state structure - **/ -static void test_set_specific_gadget_attr(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - - try_set_specific_gadget_attr(s, ts, &min_gadget_attrs); - try_set_specific_gadget_attr(s, ts, &max_gadget_attrs); - try_set_specific_gadget_attr(s, ts, get_random_gadget_attrs()); -} - -/** - * @brief Tests getting udc from state - * @param[in] state Pointer to correctly initialized test_state structure - **/ -void test_get_udc(void **state) -{ - struct test_state *ts; - char **tu; - struct test_gadget *tg; - usbg_state *s = NULL; - usbg_udc *u = NULL; - usbg_gadget *g = NULL; - - safe_init_with_state(state, &ts, &s); - - for (tu = ts->udcs; *tu; tu++) { - u = usbg_get_udc(s, *tu); - assert_non_null(u); - assert_string_equal(*tu, u->name); - assert_int_equal(s, u->parent); - } - - for (tg = ts->gadgets; tg->name; tg++) { - u = usbg_get_udc(s, tg->udc); - g = usbg_get_gadget(s, tg->name); - assert_int_equal(u->gadget, g); - } -} - -static void test_get_gadget_attr_str(void **state) -{ - struct { - usbg_gadget_attr attr; - const char *str; - } attrs[] = { - {BCD_USB, "bcdUSB"}, - {B_DEVICE_CLASS, "bDeviceClass"}, - {B_DEVICE_SUB_CLASS, "bDeviceSubClass"}, - {B_DEVICE_PROTOCOL, "bDeviceProtocol"}, - {B_MAX_PACKET_SIZE_0, "bMaxPacketSize0"}, - {ID_VENDOR, "idVendor"}, - {ID_PRODUCT, "idProduct"}, - {BCD_DEVICE, "bcdDevice"}, - }; - - const char *str; - int i, j; - - for (i = 0; i < ARRAY_SIZE(attrs); i++) { - str = usbg_get_gadget_attr_str(attrs[i].attr); - assert_non_null(str); - assert_string_equal(str, attrs[i].str); - } - - /* Check if iteration over values works */ - for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; ++i) { - str = usbg_get_gadget_attr_str(i); - assert_non_null(str); - - for (j = 0; j < ARRAY_SIZE(attrs); ++j) - if (attrs[j].attr == i) { - assert_string_equal(str, attrs[j].str); - break; - } - - assert_int_not_equal(j, ARRAY_SIZE(attrs)); - } -} - -static void test_get_gadget_attr_str_fail(void **state) -{ - const char *str; - - str = usbg_get_gadget_attr_str(USBG_GADGET_ATTR_MIN - 1); - assert_null(str); - - str = usbg_get_gadget_attr_str(USBG_GADGET_ATTR_MAX); - assert_null(str); -} - -/** - * @brief set gadget strings - * @details Also do it one by one - * @param[in] data Pointer to correctly initialized test_gadget_strs_data structure - */ -static void test_set_gadget_strs(void **data) -{ - struct test_gadget_strs_data *ts; - struct test_gadget *tg; - usbg_state *s = NULL; - usbg_gadget *g = NULL; - int i; - int ret; - - ts = (struct test_gadget_strs_data *)(*data); - *data = NULL; - - init_with_state(ts->state, &s); - *data = s; - - for (tg = ts->state->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - - pull_gadget_strs(tg, LANG_US_ENG, ts->strs); - ret = usbg_set_gadget_strs(g, LANG_US_ENG, ts->strs); - assert_int_equal(ret, 0); - - for (i = 0; i < GADGET_STR_MAX; i++) - pull_gadget_string(tg, LANG_US_ENG, i, get_gadget_str(ts->strs, i)); - - ret = usbg_set_gadget_serial_number(g, LANG_US_ENG, ts->strs->str_ser); - assert_int_equal(ret, 0); - - ret = usbg_set_gadget_manufacturer(g, LANG_US_ENG, ts->strs->str_mnf); - assert_int_equal(ret, 0); - - ret = usbg_set_gadget_product(g, LANG_US_ENG, ts->strs->str_prd); - assert_int_equal(ret, 0); - - for (i = 0; i < GADGET_STR_MAX; i++) - pull_gadget_string(tg, LANG_US_ENG, i, get_gadget_str(ts->strs, i)); - - - ret = usbg_set_gadget_str(g, STR_SERIAL_NUMBER, LANG_US_ENG, ts->strs->str_ser); - assert_int_equal(ret, 0); - - ret = usbg_set_gadget_str(g, STR_MANUFACTURER, LANG_US_ENG, ts->strs->str_mnf); - assert_int_equal(ret, 0); - - ret = usbg_set_gadget_str(g, STR_PRODUCT, LANG_US_ENG, ts->strs->str_prd); - assert_int_equal(ret, 0); - } -} - -/** - * @brief get gadget strings - * @param[in] data Pointer to correctly initialized test_gadget_strs_data structure - */ -static void test_get_gadget_strs(void **data) -{ - struct test_gadget_strs_data *ts; - struct test_gadget *tg; - usbg_state *s = NULL; - usbg_gadget *g = NULL; - usbg_gadget_strs strs; - - ts = (struct test_gadget_strs_data *)(*data); - *data = NULL; - - init_with_state(ts->state, &s); - *data = s; - - for (tg = ts->state->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - push_gadget_strs(tg, LANG_US_ENG, ts->strs); - usbg_get_gadget_strs(g, LANG_US_ENG, &strs); - assert_gadget_strs_equal(&strs, ts->strs); - } -} - -/** - * @brief Get binding target - * @details Check if given function is target of given binding - * @param[in] tb Test function - * @param[in] b Binding - */ -static void try_get_binding_target(struct test_binding *tb, usbg_binding *b) -{ - usbg_function *f; - - f = usbg_get_binding_target(b); - assert_non_null(f); - assert_func_equal(f, tb->target); -} - -/** - * @brief Test get binding target - * @details Test all bindings present in given state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_get_binding_target(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_binding(ts, s, try_get_binding_target); -} - -/** - * @brief Get binding name - * @details Check if name of given binding is equal name of given function - * @param[in] tb Test function - * @param[in] b Binding - */ -static void try_get_binding_name(struct test_binding *tb, usbg_binding *b) -{ - const char *s; - - s = usbg_get_binding_name(b); - assert_non_null(s); - assert_string_equal(s, tb->name); -} - -/** - * @brief Test get bindig name from all binding present in state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_get_binding_name(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_binding(ts, s, try_get_binding_name); -} - -/** - * @brief Get binding name length - * @param[in] tb Test function - * @param[in] b Binding - */ -static void try_get_binding_name_len(struct test_binding *tb, usbg_binding *b) -{ - int n; - - n = usbg_get_binding_name_len(b); - assert_int_equal(n, strlen(tb->name)); -} - -/** - * @brief Test get binding name length from all bindings present in state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_get_binding_name_len(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_binding(ts, s, try_get_binding_name_len); -} - -/** - * @brief Set config strings - * @param[in] c Config on which string should be set - * @param[in] tc Test config containing strings to be set - */ -static void try_set_config_strs(usbg_config *c, struct test_config *tc) -{ - pull_config_strs(tc, LANG_US_ENG, tc->strs); - usbg_set_config_strs(c, LANG_US_ENG, tc->strs); -} - -/** - * @brief Test setting strings - * @details Set strings in all configs present in state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_set_config_strs(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_set_config_strs); -} - -/** - * @brief Set strings one by one on config - * @param[in] c Config on which string should be set - * @param[in] tc Test config containing strings to be set - */ -static void try_set_config_string(usbg_config *c, struct test_config *tc) -{ - pull_config_string(tc, LANG_US_ENG, tc->strs->configuration); - usbg_set_config_string(c, LANG_US_ENG, tc->strs->configuration); -} - -/** - * @brief Test setting strings one by one - * @details Set strings on all configs present in given state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_set_config_string(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_set_config_string); -} - -/** - * @brief Get config strings - * @details Assume that given configs have the same strings - * @param[in] c Config from which strings should be get - * @param[in] tc Test config expected to have the same string as c - */ -static void try_get_config_strs(usbg_config *c, struct test_config *tc) -{ - usbg_config_strs strs; - push_config_strs(tc, LANG_US_ENG, tc->strs); - usbg_get_config_strs(c, LANG_US_ENG, &strs); - assert_string_equal(tc->strs->configuration, strs.configuration); -} - -/** - * @brief Test getting congig strings - * @details Get config strings on all configs present in given state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_get_config_strs(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_get_config_strs); -} - -/** - * @brief Get config attributes - * @details Assume that attributes which will be returned are the same as - * given test state contains. - * @param[in] c Usbg config - * @param[in] tc Test config with set attributes - */ -static void try_get_config_attrs(usbg_config *c, struct test_config *tc) -{ - usbg_config_attrs attrs; - - push_config_attrs(tc, tc->attrs); - usbg_get_config_attrs(c, &attrs); - assert_config_attrs_equal(tc->attrs, &attrs); -} - -/** - * @brief Test getting config attributes - * @details Get config attributes on all configfs in state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_get_config_attrs(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_get_config_attrs); -} - -/** - * @brief Set config attributes in given config - * @param[in] c Usbg config - * @param[in] tc Test config with attributes which will be set - */ -static void try_set_config_attrs(usbg_config *c, struct test_config *tc) -{ - pull_config_attrs(tc, tc->attrs); - usbg_set_config_attrs(c, tc->attrs); -} - -/** - * @brief Test setting config attributes - * @details Set config attributes on all configs in state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_set_config_attrs(void **state) -{ - usbg_state *s = NULL; - struct test_state *ts; - - safe_init_with_state(state, &ts, &s); - for_each_test_config(ts, s, try_set_config_attrs); -} - -/** - * @brieg Test creating config - * @details Start with empty gadgets, add all functions from given state - * @param[in, out] state Pointer to pointer to correctly initialized test state, - * will point to usbg state when finished. - */ -static void test_create_config(void **state) -{ - usbg_state *s = NULL; - usbg_gadget *g = NULL; - usbg_config *c = NULL; - struct test_state *ts; - struct test_state *empty; - struct test_gadget *tg; - struct test_config *tc; - - ts = (struct test_state *)(*state); - *state = NULL; - - empty = build_empty_gadget_state(ts); - - init_with_state(empty, &s); - *state = s; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - for (tc = tg->configs; tc->label; tc++) { - pull_create_config(tc); - usbg_create_config(g, tc->id, tc->label, - tc->attrs, tc->strs, &c); - assert_config_equal(c, tc); - } - } -} - -/** - * @brief Start with empty gadget, add all functions from given one - */ -static void test_create_function(void **state) -{ - usbg_state *s = NULL; - usbg_gadget *g = NULL; - usbg_function *f = NULL; - struct test_state *ts; - struct test_state *empty; - struct test_gadget *tg; - struct test_function *tf; - - ts = (struct test_state *)(*state); - *state = NULL; - - empty = build_empty_gadget_state(ts); - - init_with_state(empty, &s); - *state = s; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - for (tf = tg->functions; tf->instance; tf++) { - pull_create_function(tf); - usbg_create_function(g, tf->type, tf->instance, - tf->attrs, &f); - assert_func_equal(f, tf); - } - } -} - -/** - * @brief Test only one given function for attribute getting - * @param[in] state Pointer to pointer to correctly initialized state - */ -static void test_get_function_attrs(void **state) -{ - struct test_function_attrs_data *data; - usbg_state *s; - usbg_function *f; - usbg_gadget *g; - usbg_function_attrs actual; - int ret; - - data = (struct test_function_attrs_data *)(*state); - *state = NULL; - - - init_with_state(data->state, &s); - *state = s; - - g = usbg_get_first_gadget(s); - assert_non_null(g); - f = usbg_get_first_function(g); - assert_non_null(f); - - push_function_attrs(&data->state->gadgets[0].functions[0], data->attrs); - ret = usbg_get_function_attrs(f, &actual); - - assert_int_equal(ret, 0); - assert_function_attrs_equal(&actual, data->attrs, data->attrs->header.attrs_type); - - usbg_cleanup_function_attrs(&actual); -} - -/** - * @brief Test setting attributes in only one given function - * @param[in] state Pointer to pointer to correctly initialized state - */ -static void test_set_function_attrs(void **state) -{ - struct test_function_attrs_data *data; - usbg_state *s; - usbg_function *f; - usbg_gadget *g; - int ret; - - data = (struct test_function_attrs_data *)(*state); - *state = NULL; - - init_with_state(data->state, &s); - *state = s; - - g = usbg_get_first_gadget(s); - assert_non_null(g); - f = usbg_get_first_function(g); - assert_non_null(f); - - pull_function_attrs(&data->state->gadgets[0].functions[0], data->attrs); - ret = usbg_set_function_attrs(f, data->attrs); - - assert_int_equal(ret, 0); -} - -/** - * - * @brief cleanup usbg state - */ -static int teardown_state(void **state) -{ - usbg_state *s = NULL; - - s = (usbg_state *)(*state); - if (s != NULL) - usbg_cleanup(s); - - cleanup_stack(); - return 0; -} - -/* Custom macro for defining test with given name and fixed teardown function */ -#define USBG_TEST_TS(name, test, setup) \ - USBG_TEST(name, test, setup, teardown_state) - -/** - * @page usbg_tests Tests - * @brief This is list of test cases - * @tests_start - */ - -#ifndef DOXYGEN -static struct CMUnitTest tests[] = { -#endif - - /** - * @usbg_test - * @test_desc{test_init_simple, - * Check if init was successfull on simple configfs state, - * usbg_init} - */ - USBG_TEST_TS("test_init_simple", - test_init, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_init_all_funcs, - * Check if init was successfull when all avaible functions - * are present in configfs, - * usbg_init} - */ - USBG_TEST_TS("test_init_all_funcs", - test_init, setup_all_funcs_state), - /** - * @usbg_test - * @test_desc{test_init_long_path, - * Try to initialize libusbg with long configfs path, - * usbg_init} - */ - USBG_TEST_TS("test_init_long_path", - test_init, setup_long_path_state), - /** - * @usbg_test - * @test_desc{test_init_long_udc, - * Try to initialize libusbg with long udc name, - * usbg_init} - */ - USBG_TEST_TS("test_init_long_udc", - test_init, setup_long_udc_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_simple, - * Check if simple gadget will be correcty returned, - * usbg_get_gadget} - */ - USBG_TEST_TS("test_get_gadget_simple", - test_get_gadget, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_fail_simple, - * Check if getting non-existing and wrong gadgets cause - * expected failure and error codes are correct, - * usbg_get_gadget} - */ - USBG_TEST_TS("test_get_gadget_fail_simple", - test_get_gadget_fail, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_first_gadget_simple, - * Check if gadget returned by get_first_gadget - * is actually first one, - * usbg_get_first_gadget} - */ - USBG_TEST_TS("test_get_first_gadget_simple", - test_get_first_gadget, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_first_gadget_fail, - * Check if getting first gadget from state returns NULL when - * invalid parameters are passed, - * usbg_get_first_gadget} - */ - unit_test(test_get_first_gadget_fail), - /** - * @usbg_test - * @test_desc{test_get_gadget_name_simple, - * Check if returned gadget name matches expected value, - * usbg_get_gadget_name} - */ - USBG_TEST_TS("test_get_gadget_name_simple", - test_get_gadget_name, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_name_len, - * Check if returned simple gadget name length matches expected value, - * usbg_get_gadget_name} - */ - USBG_TEST_TS("test_get_gadget_name_len_simple", - test_get_gadget_name_len, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_name_fail, - * Check if trying to get name of invalid gadget - * cause expected failure (name is null), - * usbg_get_gadget_name} - */ - unit_test(test_get_gadget_name_fail), - /** - * @usbg_test - * @test_desc{test_cpy_gadget_name_simple, - * Check if getting simple gadget name into buffer work as expected, - * usbg_cpy_gadget_name} - */ - USBG_TEST_TS("test_cpy_gadget_name_simple", - test_cpy_gadget_name, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_cpy_gadget_name_fail_simple, - * Check if writting gadget name into buffer fail when - * invalid parameters are passed, - * usbg_cpy_gadget_name} - */ - USBG_TEST_TS("test_cpy_gadget_name_fail_simple", - test_cpy_gadget_name_fail, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_function_simple, - * Check if function can be correctly get from simple state, - * usbg_get_function} - */ - USBG_TEST_TS("test_get_function_simple", - test_get_function, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_function_all_funcs, - * Check if getting function work on all function types, - * usbg_get_function} - */ - USBG_TEST_TS("test_get_function_all_funcs", - test_get_function, setup_all_funcs_state), - /** - * @usbg_test - * @test_desc{test_get_function_same_type_funcs, - * Check if having multiple functions with the same type does not - * cause failure - * usbg_get_function} - */ - USBG_TEST_TS("test_get_function_same_type_funcs", - test_get_function, setup_same_type_funcs_state), - /** - * @usbg_test - * @test_desc{test_get_function_fail_simple, - * Check if trying to get invalid function's name ends - * with expected error, - * usbg_get_function} - */ - USBG_TEST_TS("test_get_function_fail_simple", - test_get_function_fail, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_function_instance_simple, - * Check if getting simple instance returns what expected, - * usbg_get_function_instance} - */ - USBG_TEST_TS("test_get_function_instance_simple", - test_get_function_instance, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_cpy_function_instance_simple, - * Check if copying simple instance into buffer returns what expected, - * usbg_cpy_function_instance} - */ - USBG_TEST_TS("test_cpy_function_instance_simple", - test_cpy_function_instance, setup_all_funcs_state), - /** - * @usbg_test - * @test_desc{test_get_function_type_simple, - * Check if function type is returned correctly, - * usbg_get_function_type} - */ - USBG_TEST_TS("test_get_function_type_simple", - test_get_function_type, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_function_type_all_funcs, - * Check if all function types are returned correctly, - * usbg_get_function_type} - */ - USBG_TEST_TS("test_get_function_type_all_funcs", - test_get_function_type, setup_all_funcs_state), - /** - * @usbg_test - * @test_desc{test_get_function_instance_len_simple, - * Check if function instance length is returned correctly, - * usbg_get_function_instance_len} - */ - USBG_TEST_TS("test_get_function_instance_len_simple", - test_get_function_instance_len, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_function_type_str, - * Compare returned function types strings with expected values, - * usbg_get_function_type_str} - */ - unit_test(test_get_function_type_str), - /** - * @usbg_test - * @test_desc{test_get_function_type_str_fail, - * Try to get type string of unknown type, - * usbg_get_function_type_str} - */ - unit_test(test_get_function_type_str_fail), - /** - * @usbg_test - * @test_desc{test_get_configfs_path_simple, - * heck if simple configfs path was returned correctly, - * usbg_get_configfs_path} - */ - USBG_TEST_TS("test_get_configfs_path_simple", - test_get_configfs_path, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_configfs_path_len, - * Check if configfs path length is correctly calculated, - * usbg_get_configfs_path_len} - */ - USBG_TEST_TS("test_get_configfs_path_len_simple", - test_get_configfs_path_len, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_cpy_configfs_path_simple, - * Copy simple configfs path into buffer and compare with original, - * usbg_cpy_configfs_path} - */ - USBG_TEST_TS("test_cpy_configfs_path_simple", - test_cpy_configfs_path, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_config_simple, - * Check if returned simple config matches original one, - * usbg_get_config} - */ - USBG_TEST_TS("test_get_config_simple", - test_get_config, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_config_without_label_simple, - * Check if returned simple config matches original one, - * usbg_get_config} - */ - USBG_TEST_TS("test_get_config_without_label_simple", - test_get_config_without_label, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_config_fail, - * Check if trying to get non-existing or invalid config - * fails as expected, - * usbg_get_config}*/ - USBG_TEST_TS("test_get_config_fail", - test_get_config_fail, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_config_label_simple, - * Check if returned simple config label matches original one, - * usbg_get_config_label} - */ - USBG_TEST_TS("test_get_config_label_simple", - test_get_config_label, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_config_id_simple, - * Check if returned simple config id matches original one, - * usbg_get_config_id} - */ - USBG_TEST_TS("test_get_config_id_simple", - test_get_config_id, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_attrs_simple, - * Get gadget attributes list and compare them with original, - * usbg_get_gadget_attrs} - */ - USBG_TEST_TS("test_get_gadget_attrs_simple", - test_get_gadget_attrs, setup_simple_state), - /** - * @usbg_tets - * @test_desc{test_set_gadget_attrs_simple, - * Set gadget attributes list\, check if everything is wrote - * as expected, - * usbg_set_gadget_attrs} - */ - USBG_TEST_TS("test_set_gadget_attrs_simple", - test_set_gadget_attrs, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_set_specific_gadget_attr_simple, - * Set gadget attributes one by one, - * usbg_set_gadget_attrs} - */ - USBG_TEST_TS("test_set_specific_gadget_attr_simple", - test_set_specific_gadget_attr, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_udc_simple, - * Get udc name from state, - * usbg_get_udc} - */ - USBG_TEST_TS("test_get_udc_simple", - test_get_udc, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_udc_long, - * Get udc name witch very long name, - * usbg_get_udc} - */ - USBG_TEST_TS("test_get_udc_long", - test_get_udc, setup_long_udc_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_attr_str, - * Compare returned gadget attribute strings witch expected values - * usbg_get_gadget_attr_str} - */ - unit_test(test_get_gadget_attr_str), - /** - * @usbg_test - * @test_desc{test_get_gadget_attr_str_fail, - * Check returned gadget attribute strings for invalid arguments - * usbg_get_gadget_attr_str} - */ - unit_test(test_get_gadget_attr_str_fail), - /** - * @usbg_test - * @test_desc{test_set_gadget_strs_random, - * Set gadget strings of random length, - * usbg_set_gadget_strs} - */ - USBG_TEST_TS("test_set_gadget_strs_random", - test_set_gadget_strs, setup_random_len_gadget_strs_data), - /** - * @usbg_test - * @test_desc{test_get_gadget_strs_random, - * Get gadget strings, - * usbg_get_gadget_strs} - */ - USBG_TEST_TS("test_get_gadget_strs_random", - test_get_gadget_strs, setup_random_len_gadget_strs_data), - /** - * @usbg_test - * @test_desc{test_get_binding_target_simple, - * Get binding target, - * usbg_get_binding_target} - */ - USBG_TEST_TS("test_get_binding_target_simple", - test_get_binding_target, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_binding_name_simple, - * Get binding name, - * usbg_get_binding_name} - */ - USBG_TEST_TS("test_get_binding_name_simple", - test_get_binding_name, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_get_binding_name_len_simple, - * Get binding name length, - * usbg_get_binding_name_len} - */ - USBG_TEST_TS("test_get_binding_name_len_simple", - test_get_binding_name_len, setup_simple_state), - /** - * @usbg_test - * @test_desc{test_set_config_strs_simple, - * Set simple strings in set of configurations, - * usbg_set_config_strs} - */ - USBG_TEST_TS("test_set_config_strs_simple", - test_set_config_strs, setup_simple_config_strs_state), - /** - * @usbg_test - * @test_desc{test_set_config_string_simple, - * Set simple string in set of configurations, - * usbg_set_config_string} - */ - USBG_TEST_TS("test_set_config_string_simple", - test_set_config_string, setup_simple_config_strs_state), - /** - * @usbg_test - * @test_desc{test_get_config_strs_simple, - * Get simple strings from set of configurations, - * usbg_get_config_strs} - */ - USBG_TEST_TS("test_get_config_strs_simple", - test_get_config_strs, setup_simple_config_strs_state), - /** - * @usbg_test - * @test_desc{test_get_config_attrs_max, - * Get config attributes with max values, - * usbg_get_config_attrs} - */ - USBG_TEST_TS("test_get_config_attrs_max", - test_get_config_attrs, setup_max_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_get_config_attrs_min, - * Get config attributes with minimum values, - * usbg_get_config_attrs} - */ - USBG_TEST_TS("test_get_config_attrs_min", - test_get_config_attrs, setup_min_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_get_config_attrs_random, - * Get config attributes with random values, - * usbg_get_config_attrs} - */ - USBG_TEST_TS("test_get_config_attrs_random", - test_get_config_attrs, setup_random_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_set_config_attrs_max, - * Set config attributes with max values, - * usbg_set_config_attrs} - */ - USBG_TEST_TS("test_set_config_attrs_max", - test_set_config_attrs, setup_max_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_set_config_attrs_min, - * Set config attributes with minimum values, - * usbg_set_config_attrs} - */ - USBG_TEST_TS("test_set_config_attrs_min", - test_set_config_attrs, setup_min_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_set_config_attrs_random, - * Set config attributes with random values, - * usbg_set_config_attrs} - */ - USBG_TEST_TS("test_set_config_attrs_random", - test_set_config_attrs, setup_random_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_create_config_random, - * Create config with random attributes - * usbg_create_config} - */ - USBG_TEST_TS("test_create_config_random", - test_create_config, setup_random_config_attrs_state), - /** - * @usbg_test - * @test_desc{test_get_f_serial_attrs, - * Get f_serial function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_serial_attrs", - test_get_function_attrs, setup_f_serial_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_obex_attrs, - * Get f_obex function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_obex_attrs", - test_get_function_attrs, setup_f_obex_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_acm_attrs, - * Get f_acm function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_acm_attrs", - test_get_function_attrs, setup_f_acm_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_ecm_attrs, - * Get f_ecm function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_ecm_attrs", - test_get_function_attrs, setup_f_ecm_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_eem_attrs, - * Get f_eem function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_eem_attrs", - test_get_function_attrs, setup_f_eem_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_subset_attrs, - * Get f_subset function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_subset_attrs", - test_get_function_attrs, setup_f_subset_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_ncm_attrs, - * Get f_ncm function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_ncm_attrs", - test_get_function_attrs, setup_f_ncm_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_serial_attrs, - * Get f_rndis function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_rndis_attrs", - test_get_function_attrs, setup_f_rndis_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_phonet_attrs, - * Get f_phonet function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_phonet_attrs", - test_get_function_attrs, setup_f_phonet_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_serial_attrs, - * Get f_ffs function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_get_f_ffs_attrs", - test_get_function_attrs, setup_f_ffs_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_serial_attrs, - * Set f_serial function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_serial_attrs", - test_set_function_attrs, setup_f_serial_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_acm_attrs, - * Set f_acm function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_acm_attrs", - test_set_function_attrs, setup_f_acm_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_serial_obex, - * Set f_obex function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_obex_attrs", - test_set_function_attrs, setup_f_obex_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_ecm_attrs, - * Set f_ecm function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_ecm_attrs", - test_set_function_attrs, setup_f_ecm_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_eem_attrs, - * Set f_eem function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_eem_attrs", - test_set_function_attrs, setup_f_eem_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_subset_attrs, - * Set f_subset function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_subset_attrs", - test_set_function_attrs, setup_f_subset_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_ncm_attrs, - * Set f_ncm function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_ncm_attrs", - test_set_function_attrs, setup_f_ncm_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_serial_attrs, - * Set f_rndis function attributes, - * usbg_get_function_attrs} - */ - USBG_TEST_TS("test_set_f_rndis_attrs", - test_set_function_attrs, setup_f_rndis_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_phonet_attrs, - * Set f_phonet function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_phonet_attrs", - test_set_function_attrs, setup_f_phonet_writable_attrs), - /** - * @usbg_test - * @test_desc{test_get_f_serial_attrs, - * Set f_ffs function attributes, - * usbg_set_function_attrs} - */ - USBG_TEST_TS("test_set_f_ffs_attrs", - test_set_function_attrs, setup_f_ffs_writable_attrs), - /** - * @usbg_test - * @test_desc{test_create_all_functions, - * Create full set of functions in empty state, - * usbg_get_binding_name_len} - */ - USBG_TEST_TS("test_create_all_functions", - test_create_function, setup_all_funcs_state), - /** - * @usbg_test - * @test_desc{test_get_gadget_str_name, - * Compare returned gadget string name with expected - * usbg_get_gadget_str_name} - */ - unit_test(test_get_gadget_str_name), - /** - * @usbg_test - * @test_desc{test_lookup_gadget_str, - * Compare returned gadget string code with expected - * usbg_lookup_gadget_str} - */ - unit_test(test_lookup_gadget_str), - -#ifndef DOXYGEN -}; -#endif - -/** - * @usbg_test - * @tests_end - */ - -#define TESTS_TAG "tests" -/* for autotools compability */ -#define SKIPPED_CODE 77 - -#ifdef HAS_LIBCONFIG - -static int gen_test_config(FILE *output) -{ - config_t cfg; - config_setting_t *root; - config_setting_t *tests_node, *node; - int i; - int ret = SKIPPED_CODE, cfg_ret = 0; - - config_init(&cfg); - config_set_tab_width(&cfg, 4); - - root = config_root_setting(&cfg); - tests_node = config_setting_add(root, TESTS_TAG, CONFIG_TYPE_LIST); - if (!tests_node) { - ret = -ENOMEM; - goto out; - } - - for (i = 0; i < ARRAY_SIZE(tests); ++i) { - node = config_setting_add(tests_node, NULL, CONFIG_TYPE_STRING); - if (!node) { - ret = -ENOMEM; - goto out; - } - - cfg_ret = config_setting_set_string(node, tests[i].name); - if (cfg_ret != CONFIG_TRUE) { - ret = -EINVAL; - goto out; - } - } - - config_write(&cfg, output); -out: - config_destroy(&cfg); - return ret; -} - -#else - -static int gen_test_config(FILE *output) -{ - fprintf(stderr, "Libconfig is not supported\n"); - return -ENOTSUP; -} - -#endif /* HAS_LIBCONFIG */ - -static int lookup_test(const char *name) -{ - int i; - for (i = 0; i < ARRAY_SIZE(tests); ++i) - if (!strcmp(name, tests[i].name)) - return i; - - return -1; -} - -static void test_skipped(void **state) -{ - skip(); -} - -#ifdef HAS_LIBCONFIG -static int apply_test_config(FILE *input) -{ - config_t cfg; - config_setting_t *root; - config_setting_t *tests_node, *node; - int i, count, ind; - int ret = 0, cfg_ret = 0; - const char *test_name; - char selected[ARRAY_SIZE(tests)]; - - for (i = 0; i < ARRAY_SIZE(selected); ++i) - selected[i] = 0; - - config_init(&cfg); - - cfg_ret = config_read(&cfg, input); - if (cfg_ret != CONFIG_TRUE) { - fprintf(stderr, "Wrong config format\n"); - ret = -EINVAL; - goto out; - } - - root = config_root_setting(&cfg); - tests_node = config_setting_get_member(root, TESTS_TAG); - if (!tests_node || !config_setting_is_list(tests_node)) { - fprintf(stderr, "Missing or incorrect tests list\n"); - ret = -EINVAL; - goto out; - } - - count = config_setting_length(tests_node); - for (i = 0; i < count; ++i) { - node = config_setting_get_elem(tests_node, i); - if (!node) { - ret = -EINVAL; - goto out; - } - - test_name = config_setting_get_string(node); - if (!test_name) { - fprintf(stderr, "Incorrect tests list. Element %d\n", i); - ret = -EINVAL; - goto out; - } - - ind = lookup_test(test_name); - if (ind < 0) { - fprintf(stderr, "Test %s not found.\n", test_name); - ret = -EINVAL; - goto out; - } - - selected[ind] = 1; - } - - for (i = 0; i < ARRAY_SIZE(selected); ++i) { - if (selected[i]) - continue; - - tests[i].test_func = &test_skipped; - tests[i].setup_func = NULL; - tests[i].teardown_func = NULL; - } -out: - config_destroy(&cfg); - return ret; -} - -#else - -static int apply_test_config(FILE *input) -{ - fprintf(stderr, "Libconfig is not supported\n"); - return -ENOTSUP; -} - -#endif /* HAS_LIBCONFIG */ - -static void print_help() -{ - fprintf(stderr, - "libusbgx test suit:\n" - " --generate-config - generates config to stdout and exit\n" - " --use-config - runs test suit using config from stdin\n" - " -h --help - print this message\n" - ); -} - -int main(int argc, char **argv) -{ - enum { - GENERATE_CONFIG = 0x01, - USE_CONFIG = 0x02, - }; - - int options = 0; - int opt; - int ret = -EINVAL; - - static struct option long_options[] = { - {"generate-config", no_argument, 0, 1}, - {"use-config", no_argument, 0, 2}, - {"help", no_argument, 0, 'h'}, - {NULL, 0, 0, 0} - }; - - while (1) { - opt = getopt_long(argc, argv, "h", long_options, NULL); - if (opt < 0) - break; - - switch (opt) { - case 1: - options |= GENERATE_CONFIG; - break; - case 2: - options |= USE_CONFIG; - break; - case 'h': - default: - print_help(); - goto out; - } - } - - if (optind < argc || - ((options & GENERATE_CONFIG) && - (options & USE_CONFIG))) { - print_help(); - goto out; - } - - if (options & GENERATE_CONFIG) { - ret = gen_test_config(stdout); - goto out; - } - - if (options & USE_CONFIG) { - ret = apply_test_config(stdin); - if (ret) - goto out; - } - - ret = cmocka_run_group_tests(tests, NULL, NULL); - -out: - return ret; -} diff --git a/tests/test.sh b/tests/test.sh deleted file mode 100755 index 45b8e3e..0000000 --- a/tests/test.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -#USE_CONFIG=0 -#GENERATE_CONFIG=0 -#HELP=$HELP - -# for autotools compability (config can be passed by environment variable) -if [[ -n $USE_CONFIG ]] -then - CONFIG_FILE=$USE_CONFIG -elif [[ -n $GENERATE_CONFIG ]] -then - CONFIG_FILE=$GENERATE_CONFIG -fi - -function usage { - echo "libusbgx test suit" - echo "Usage: ./test.sh [option]" - echo "Options:" - echo " --generate-config filename - generates config to given file and exit" - echo " --use-config filename - runs test suit using config from given file" - echo " -h --help - print this message" -} - -# Parse arguments - -ARGS=$(getopt --long generate-config:,use-config:,help -o h -- "$@" ) - -if [ $? -ne 0 ] -then - HELP=1 -fi - -eval set -- $ARGS - -while true; do - case $1 in - -h|--help) - HELP=1 - shift - ;; - --use-config) - USE_CONFIG=1 - CONFIG_FILE=$2 - shift 2 - ;; - --generate-config) - GENERATE_CONFIG=1 - CONFIG_FILE=$2 - shift 2 - ;; - --) - shift - break - ;; - *) - HELP=1 - shift - ;; - esac -done - -# Run test with io functions ovverride - -if [[ -n $USE_CONFIG ]] -then - LD_LIBRARY_PATH=. ./test --use-config < $CONFIG_FILE -elif [[ -n $GENERATE_CONFIG ]] -then - LD_LIBRARY_PATH=. ./test --generate-config > $CONFIG_FILE -elif [[ -n $HELP ]] -then - usage - exit 77 # autotools consider it skipped -else - LD_LIBRARY_PATH=. ./test -fi - diff --git a/tests/usbg-io-wrappers.c b/tests/usbg-io-wrappers.c deleted file mode 100644 index d8f471a..0000000 --- a/tests/usbg-io-wrappers.c +++ /dev/null @@ -1,203 +0,0 @@ -#define _GNU_SOURCE -#include <dirent.h> -#include <stdio.h> -#include <stdarg.h> -#include <setjmp.h> -#include <stdlib.h> -#include <string.h> -#include <stddef.h> -#include <cmocka.h> -#include <dlfcn.h> -#include <errno.h> - -typedef int (*fputs_f_type)(const char *, FILE *); -typedef int (*fflush_f_type)(FILE *); -typedef fflush_f_type ferror_f_type; - -/** - * @brief Simulates opening file - * @details Checks if path is equal expected value and returns given pointer - * from cmocka queue - */ -FILE *fopen(const char *path, const char *mode) -{ - check_expected(path); - return mock_ptr_type(FILE *); -} - -/** - * @brief Simulates closing file - * @details Does absolutely nothing, always acts as successfull close - */ -int fclose(FILE *fp) -{ - check_expected(fp); - return mock_type(int); -} - -/** - * @brief Simulates reading file - * @details Does not read any file, instead returns value from cmocka queue - * @return value specified by caller previously - */ -char *fgets(char *s, int size, FILE *stream) -{ - check_expected(stream); - strncpy(s, mock_ptr_type(char *), size); - return s; -} - -/** - * @brief Simulates opening directory - * @details Does not open any dir, instead returns user-specified value - * @return value specified by caller previously - */ -DIR *opendir(const char *name) -{ - int err; - - check_expected(name); - err = mock_type(int); - if (err) - errno = err; - - return mock_ptr_type(DIR *); -} - -/** - * @brief Simulates closing directory - * @details Does nothing and ends successfully. - */ -int closedir(DIR *dirp) -{ - check_expected(dirp); - return mock_type(int); -} - -/** - * @brief Simulates scanning directory - * @details Checks if dirp has expected value. Then consecutive values from - * cmocka queue are proceed. First value must be integer and indicates number - * of directory entries which should be returned. Next number of values indicate - * names of directory entries. - */ -int scandir(const char *dirp, struct dirent ***namelist, - int (*filter)(const struct dirent *), - int (*compar)(const struct dirent **, const struct dirent **)) -{ - int count; - int i, j = 0; - char *name; - struct dirent **entries; - struct dirent *entry; - int tmp, expected; - - check_expected(dirp); - count = mock_type(int); - - if (count > 0) - entries = calloc(count, sizeof(*entries)); - else - entries = NULL; - - for (i = 0; i < count; i++) { - name = mock_ptr_type(char *); - entry = malloc(sizeof(*entry)); - if (strlen(name) >= NAME_MAX) - fail(); - - strcpy(entry->d_name, name); - entry->d_type = mock_type(unsigned char); - - expected = mock_type(int); - if (filter) { - tmp = filter(entry); - assert_int_equal(tmp, expected); - if (tmp) - entries[j++] = entry; - else - free(entry); - } - } - - if (compar) - qsort(entries, count, sizeof(*entries), - (int (*)(const void *,const void *))compar); - - *namelist = entries; - return j; -} - -/** - * @brief Simultes readlink, with user-specified behavior - * @datails Check if path and bufsiz equal expedted values and - * write to buf string given by cmocka - */ -ssize_t readlink(const char *path, char *buf, size_t bufsiz) -{ - char *res; - int reslen; - - check_expected(path); - check_expected(bufsiz); - res = mock_ptr_type(char *); - reslen = strlen(res); - if (bufsiz <= reslen) - fail(); - - strcpy(buf, res); - - return reslen; -} - -/** - * @brief Simulates puts, with user-specified behavior - * @details Check if user is trying to write expected data - * @return value received from cmocka queue - */ -int fputs(const char *s, FILE *stream) -{ - /* Cmocka (or anything else) may want to print some errors. - * Especially when running fputs itself */ - if (stream == stderr || stream == stdout) { - fputs_f_type orig_fputs; - orig_fputs = (fputs_f_type)dlsym(RTLD_NEXT, "fputs"); - return orig_fputs(s, stream); - } - - check_expected(stream); - check_expected(s); - return mock_type(int); -} - -int mkdir(const char *pathname, mode_t mode) -{ - check_expected(pathname); - check_expected(mode); - return mock_type(int); -} - -/** - * @brief Does nothing. - */ -int fflush(FILE *stream) -{ - if (stream == stderr || stream == stdout) { - fflush_f_type orig_fflush; - orig_fflush = (fflush_f_type)dlsym(RTLD_NEXT, "fflush"); - return orig_fflush(stream); - } - - return 0; -} - -int ferror(FILE *stream) -{ - if (stream == stderr || stream == stdout) { - ferror_f_type orig_ferror; - orig_ferror = (ferror_f_type)dlsym(RTLD_NEXT, "ferror"); - return orig_ferror(stream); - } - - return 0; -} diff --git a/tests/usbg-test.c b/tests/usbg-test.c deleted file mode 100644 index c332795..0000000 --- a/tests/usbg-test.c +++ /dev/null @@ -1,1389 +0,0 @@ -#include <usbg/usbg.h> -#include <stdio.h> -#include <stdarg.h> -#include <setjmp.h> -#include <cmocka.h> -#include <stdlib.h> -#include <string.h> -#include <stddef.h> -#include <limits.h> -#include <errno.h> -#include <time.h> - -#include "usbg-test.h" - -static struct simple_stack{ - void *ptr; - struct simple_stack *next; -} *cleanup_top = NULL; - -static const char *gadget_str_names[] = { - "serialnumber", - "manufacturer", - "product" -}; - -static const char *config_attr_names[] = { - "MaxPower", - "bmAttributes" -}; - -static attr_format config_attr_format[] = { - [MAX_POWER] = FORMAT_DEC, - [BM_ATTRIBUTES] = FORMAT_HEX -}; - -void free_later(void *ptr) -{ - struct simple_stack *t; - - t = malloc(sizeof(*t)); - t->ptr = ptr; - t->next = cleanup_top; - cleanup_top = t; -} - -void cleanup_stack() -{ - struct simple_stack *t; - - while (cleanup_top) { - free(cleanup_top->ptr); - t = cleanup_top->next; - free(cleanup_top); - cleanup_top = t; - } -} - -/* Represent last file/dir opened, next should have bigger numbers.*/ -static int file_id = 0; -static int dir_id = 0; - -#define PUSH_FILE(file, content) do {\ - file_id++;\ - expect_path(fopen, path, file);\ - will_return(fopen, file_id);\ - expect_value(fgets, stream, file_id);\ - will_return(fgets, content);\ - expect_value(fclose, fp, file_id);\ - will_return(fclose, 0);\ -} while(0) - -#define PUSH_FILE_ALWAYS(dflt) do {\ - expect_any_count(fopen, path, -1);\ - will_return_always(fopen, 1);\ - expect_any_count(fgets, stream, 1);\ - will_return_always(fgets, dflt);\ - expect_any_count(fclose, fp, 1);\ - will_return_always(fclose, 0);\ -} while(0) - -#define PUSH_EMPTY_DIR(p) do {\ - expect_string(scandir, dirp, p);\ - will_return(scandir, 0);\ -} while(0) - -#define EXPECT_OPENDIR(n) do {\ - dir_id++;\ - expect_path(opendir, name, n);\ - will_return(opendir, 0);\ - will_return(opendir, dir_id);\ - expect_value(closedir, dirp, dir_id);\ - will_return(closedir, 0);\ -} while(0) - -#define EXPECT_OPENDIR_ERROR(n, e) do {\ - expect_path(opendir, name, n);\ - will_return(opendir, e);\ - will_return(opendir, NULL);\ -} while(0) - -#define PUSH_DIR(p, c) do {\ - expect_path(scandir, dirp, p);\ - will_return(scandir, c);\ -} while(0) - -#define PUSH_DIR_ENTRY(name, type) do {\ - will_return(scandir, name);\ - will_return(scandir, type);\ - will_return(scandir, 1);\ -} while(0) - -#define PUSH_LINK(p, c, len) do {\ - expect_path(readlink, path, p);\ - expect_in_range(readlink, bufsiz, len, INT_MAX);\ - will_return(readlink, c);\ -} while(0) - -#define EXPECT_WRITE(file, content) do {\ - file_id++;\ - expect_path(fopen, path, file);\ - will_return(fopen, file_id);\ - expect_value(fputs, stream, file_id);\ - expect_string(fputs, s, content);\ - will_return(fputs, 0);\ - expect_value(fclose, fp, file_id);\ - will_return(fclose, 0);\ -} while(0) - -#define EXPECT_HEX_WRITE(file, content) do {\ - file_id++;\ - expect_path(fopen, path, file);\ - will_return(fopen, file_id);\ - expect_value(fputs, stream, file_id);\ - expect_check(fputs, s, hex_str_equal_display_error, content);\ - will_return(fputs, 0);\ - expect_value(fclose, fp, file_id);\ - will_return(fclose, 0);\ -} while(0) - -#define EXPECT_MKDIR(p) do {\ - expect_path(mkdir, pathname, p);\ - expect_value(mkdir, mode, 00777);\ - will_return(mkdir, 0);\ -} while(0) - -/** - * @brief Compare test gadgets' names - */ -static int test_gadget_cmp(struct test_gadget *a, struct test_gadget *b) -{ - return strcoll(a->name, b->name); -} - -/** - * @brief Compare test functions' names - */ -static int test_function_cmp(struct test_function *a, struct test_function *b) -{ - return strcoll(a->name, b->name); -} - -/** - * @brief Compare test bindings' names - */ -static int test_binding_cmp(struct test_binding *a, struct test_binding *b) -{ - return strcoll(a->name, b->name); -} - -/** - * @brief Compare test configs' names - */ -static int test_config_cmp(struct test_config *a, struct test_config *b) -{ - return strcoll(a->name, b->name); -} - -void prepare_binding(struct test_binding *b, struct test_function *f, char *fpath) -{ - if (!f->name) - prepare_function(f, fpath); - - if (!b->name) { - b->name = strdup(f->name); - if (b->name == NULL) - fail(); - free_later(b->name); - } - - b->target = f; -} - -void prepare_config(struct test_config *c, char *cpath, char *fpath) -{ - int count = 0; - struct test_function *f; - struct test_binding *b; - int i; - - safe_asprintf(&c->name, "%s.%d", c->label, c->id); - - c->path = cpath; - - /* check if bindings has been already filled */ - if (!c->bindings) { - for (f = c->bound_funcs; f->instance; f++) - count++; - - c->bindings = safe_calloc(count + 1, sizeof(*c->bindings)); - } else { - for (b = c->bindings; b->name; b++) - count++; - } - - for (i = 0; i < count; i++) - prepare_binding(&c->bindings[i], &c->bound_funcs[i], fpath); - - qsort(c->bindings, count, sizeof(*c->bindings), - (int (*)(const void *, const void *))test_binding_cmp); - -} - -void prepare_function(struct test_function *f, char *path) -{ - const char *func_type; - - func_type = usbg_get_function_type_str(f->type); - if (func_type == NULL) - fail(); - - safe_asprintf(&f->name, "%s.%s", func_type, f->instance); - - f->path = path; -} - -void prepare_gadget(struct test_state *state, struct test_gadget *g) -{ - struct test_config *c; - struct test_function *f; - char *fpath; - char *cpath; - int count; - - g->path = strdup(state->path); - if (!g->path) - fail(); - - free_later(g->path); - - safe_asprintf(&fpath, "%s/%s/functions", g->path, g->name); - - count = 0; - for (f = g->functions; f->instance; f++) { - prepare_function(f, fpath); - count++; - } - - /* Path needs to be known somehow when list is empty */ - f->path = fpath; - - qsort(g->functions, count, sizeof(*g->functions), - (int (*)(const void *, const void *))test_function_cmp); - - safe_asprintf(&cpath, "%s/%s/configs", g->path, g->name); - - count = 0; - for (c = g->configs; c->label; c++) { - prepare_config(c, cpath, fpath); - count++; - } - - /* Path needs to be known somehow when list is empty */ - c->path = cpath; - - qsort(g->configs, count, sizeof(*g->configs), - (int (*)(const void *, const void *))test_config_cmp); - -} - -static void cpy_test_function(struct test_function *to, - struct test_function *from) -{ - /* Reuse instance */ - to->instance = from->instance; - to->type = from->type; - /* path and name is not being copied because - it has not been allocated now */ - - to->writable = 1; -} - -static struct test_function *dup_test_functions(struct test_function *functions) -{ - struct test_function *f, *nf, *new_functions; - int count = 0; - - for (f = functions; f->instance; ++f) - ++count; - - new_functions = safe_calloc(count + 1, sizeof(*f)); - - for (f = functions, nf = new_functions; f->instance; ++f, ++nf) - cpy_test_function(nf, f); - - return new_functions; -} - -static struct test_function *get_new_binding_target(struct test_function *which, - struct test_function *old, - int count, - struct test_function *new) -{ - struct test_function *ret = NULL; - - /* Should duplicate function? */ - if (which < old || ((which - old) > count)) { - /* We may need to do a deep copy */ - if (!which->writable) { - ret = safe_calloc(1, sizeof(*ret)); - cpy_test_function(ret, which); - } else { - ret = which; - } - } else if (old != new) { - /* Function has been copied in bound_funcs so just - set new address */ - ret = which - old + new; - } else { - /* Functions are reused so leave address as is */ - ret = which; - } - - return ret; -} - -static void cpy_test_binding(struct test_binding *to, - struct test_binding *from, - struct test_function *old, - int func_count, - struct test_function *new) -{ - /* Reuse name */ - to->name = from->name; - to->target = get_new_binding_target(from->target, old, func_count, new); - - to->writable = 1; -} - -static struct test_binding *dup_test_bindings(struct test_binding *bindings, - struct test_function *old, - int func_count, - struct test_function *new) -{ - struct test_binding *b, *nb, *new_bindings; - int count = 0; - - for (b = bindings; b->name; ++b) - ++count; - - new_bindings = safe_calloc(count + 1, sizeof(*b)); - - for (b = bindings, nb = new_bindings; b->name; ++b, ++nb) - cpy_test_binding(nb, b, old, func_count, new); - - return new_bindings; -} - -static void cpy_test_config(struct test_config *to, - struct test_config *from) -{ - int func_count = 0; - struct test_function *f; - struct test_binding *b; - - /* Reuse label */ - to->label = from->label; - to->id = from->id; - to->strs = from->strs; - to->attrs = from->attrs; - - if (from->bound_funcs) { - /* If at least one function is not writable - we have to copy all of them */ - for (f = from->bound_funcs; f->instance; ++f) { - ++func_count; - if (!f->writable && !to->bound_funcs) { - to->bound_funcs = - dup_test_functions(from->bound_funcs); - } - } - - if (!f->name && !to->bound_funcs) - to->bound_funcs = from->bound_funcs; - } - - /* If bindings are set copy also them */ - if (from->bindings) { - /* If at least one function is not writable - we have to copy all of them */ - for (b = from->bindings; b->name; ++b) - if (!b->writable) - to->bindings = - dup_test_bindings(from->bindings, - from->bound_funcs, - func_count, - to->bound_funcs); - - /* if we are reusing binding we have to translate target - address to new one which is writable */ - if (!b->name && !to->bindings) { - to->bindings = from->bindings; - for (b = from->bindings; b->name; ++b) - b->target = - get_new_binding_target( - b->target, - from->bound_funcs, - func_count, - to->bound_funcs); - } - } - - to->writable = 1; -} - -static struct test_config *dup_test_configs(struct test_config *configs) -{ - struct test_config *c, *nc, *new_configs; - int count = 0; - - for (c = configs; c->label; ++c) - ++count; - - new_configs = safe_calloc(count + 1, sizeof(*c)); - - for (c = configs, nc = new_configs; c->label; ++c, ++nc) - cpy_test_config(nc, c); - - return new_configs; -} - -static void cpy_test_gadget(struct test_gadget *to, struct test_gadget *from) -{ - struct test_function *f; - struct test_config *c; - - /* Reuse name and udc */ - to->name = from->name; - to->udc = from->udc; - /* path is not being copied because it has not been allocated */ - - /* If at least one function is not writable - we have to copy all of them */ - for (f = from->functions; f->instance; ++f) - if (!f->writable) { - to->functions = - dup_test_functions(from->functions); - break; - } - - if (!f->name && !to->functions) - to->functions = from->functions; - - - /* If at least one config is not writable - we have to copy all of them */ - for (c = from->configs; c->label; ++c) - if (!c->writable) { - to->configs = dup_test_configs(from->configs); - break; - } - - if (!c->name && !to->configs) - to->configs = from->configs; - - to->writable = 1; -} - -static struct test_gadget *dup_test_gadgets(struct test_gadget *gadgets) -{ - struct test_gadget *g, *ng, *new_gadgets; - int count = 0; - - for (g = gadgets; g->name; ++g) - ++count; - - new_gadgets = safe_calloc(count + 1, sizeof(*g)); - - for (g = gadgets, ng = new_gadgets; g->name; ++g, ++ng) - cpy_test_gadget(ng, g); - - return new_gadgets; -} - -static struct test_state *dup_test_state(struct test_state *state) -{ - struct test_state *new_state; - struct test_gadget *g; - - new_state = safe_calloc(1, sizeof(*new_state)); - - /* We don't copy configfs path because it is never changed - if you would like to free it before test end replace - this code with strdup */ - new_state->configfs_path = state->configfs_path; - - /* path is not being copied because it has not been allocated */ - - /* If at least one gadget is not writable we have to copy all of them */ - for (g = state->gadgets; g->name; ++g) - if (!g->writable) { - new_state->gadgets = - dup_test_gadgets(state->gadgets); - break; - } - - if (!g->name && !new_state->gadgets) - new_state->gadgets = state->gadgets; - - /* udcs are also never changed so leave them as they are */ - new_state->udcs = state->udcs; - - new_state->writable = 1; - - return new_state; -} - -struct test_state *prepare_state(struct test_state *state) -{ - struct test_gadget *g; - struct test_state *new_state; - int count = 0; - - if (!state->writable) - new_state = dup_test_state(state); - else - new_state = state; - - safe_asprintf(&(new_state->path), "%s/usb_gadget", - new_state->configfs_path); - - for (g = new_state->gadgets; g->name; g++) { - prepare_gadget(new_state, g); - count++; - } - - qsort(new_state->gadgets, count, sizeof(*new_state->gadgets), - (int (*)(const void *, const void *))test_gadget_cmp); - - return new_state; -} - -struct test_state *build_empty_gadget_state(struct test_state *ts) -{ - struct test_state *ret; - struct test_gadget *tg; - int count = 0; - - ret = safe_malloc(sizeof(*ret)); - ret->udcs = ts->udcs; - ret->configfs_path = ts->configfs_path; - - for (tg = ts->gadgets; tg->name; ++tg) - count++; - - ret->gadgets = safe_calloc(count+1, sizeof(*ts->gadgets)); - memcpy(ret->gadgets, ts->gadgets, count*sizeof(*ts->gadgets)); - - for (tg = ret->gadgets; tg->name; ++tg) { - tg->configs = safe_calloc(1, sizeof(*tg->configs)); - tg->functions = safe_calloc(1, sizeof(*tg->functions)); - } - - return prepare_state(ret); -} - -/* Simulation of configfs for init */ - -static void push_binding(struct test_config *conf, struct test_binding *binding) -{ - char *s_path; - char *d_path; - - safe_asprintf(&s_path, "%s/%s/%s", conf->path, conf->name, binding->name); - safe_asprintf(&d_path, "%s/%s", binding->target->path, binding->target->name); - - PUSH_LINK(s_path, d_path, USBG_MAX_PATH_LENGTH - 1); -} - -static void push_config(struct test_config *c) -{ - struct test_binding *b; - int count = 0; - char *path; - - safe_asprintf(&path, "%s/%s", c->path, c->name); - - for (b = c->bindings; b->name; b++) - count++; - - PUSH_DIR(path, count); - for (b = c->bindings; b->name; b++) { - PUSH_DIR_ENTRY(b->name, DT_LNK); - push_binding(c, b); - } -} - -static void push_gadget(struct test_gadget *g) -{ - int count; - struct test_config *c; - struct test_function *f; - char *path; - - safe_asprintf(&path, "%s/%s/UDC", g->path, g->name); - PUSH_FILE(path, g->udc); - - count = 0; - for (f = g->functions; f->instance; f++) - count++; - - PUSH_DIR(f->path, count); - for (f = g->functions; f->instance; f++) - PUSH_DIR_ENTRY(f->name, DT_DIR); - - count = 0; - for (c = g->configs; c->label; c++) - count++; - - PUSH_DIR(c->path, count); - for (c = g->configs; c->label; c++) - PUSH_DIR_ENTRY(c->name, DT_DIR); - - for (c = g->configs; c->label; c++) - push_config(c); -} - -void push_init(struct test_state *state) -{ - char **udc; - struct test_gadget *g; - int count = 0; - - EXPECT_OPENDIR(state->path); - - for (udc = state->udcs; *udc; udc++) - count++; - - PUSH_DIR("/sys/class/udc", count); - for (udc = state->udcs; *udc; udc++) - PUSH_DIR_ENTRY(*udc, DT_REG); - - count = 0; - for (g = state->gadgets; g->name; g++) - count++; - - PUSH_DIR(state->path, count); - for (g = state->gadgets; g->name; g++) { - PUSH_DIR_ENTRY(g->name, DT_DIR); - } - - for (g = state->gadgets; g->name; g++) - push_gadget(g); -} - -int get_gadget_attr(usbg_gadget_attrs *attrs, usbg_gadget_attr attr) -{ - int ret = -1; - - switch (attr) { - case BCD_USB: - ret = attrs->bcdUSB; - break; - case B_DEVICE_CLASS: - ret = attrs->bDeviceClass; - break; - case B_DEVICE_SUB_CLASS: - ret = attrs->bDeviceSubClass; - break; - case B_DEVICE_PROTOCOL: - ret = attrs->bDeviceProtocol; - break; - case B_MAX_PACKET_SIZE_0: - ret = attrs->bMaxPacketSize0; - break; - case ID_VENDOR: - ret = attrs->idVendor; - break; - case ID_PRODUCT: - ret = attrs->idProduct; - break; - case BCD_DEVICE: - ret = attrs->bcdDevice; - break; - default: - ret = -1; - break; - } - - return ret; -} - -void pull_gadget_attribute(struct test_gadget *gadget, - usbg_gadget_attr attr, int value) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/%s", - gadget->path, gadget->name, usbg_get_gadget_attr_str(attr)); - - safe_asprintf(&content, "0x%x\n", value); - - EXPECT_HEX_WRITE(path, content); -} - -void push_gadget_attribute(struct test_gadget *gadget, - usbg_gadget_attr attr, int value) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/%s", - gadget->path, gadget->name, usbg_get_gadget_attr_str(attr)); - safe_asprintf(&content, "0x%x\n", value); - - PUSH_FILE(path, content); -} - -void push_gadget_attrs(struct test_gadget *gadget, usbg_gadget_attrs *attrs) -{ - int i; - - for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) - push_gadget_attribute(gadget, i, get_gadget_attr(attrs, i)); -} - -void pull_gadget_attrs(struct test_gadget *gadget, usbg_gadget_attrs *attrs) -{ - int i; - - for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) - pull_gadget_attribute(gadget, i, get_gadget_attr(attrs, i)); -} - -void init_with_state(struct test_state *in, usbg_state **out) -{ - int usbg_ret; - - push_init(in); - usbg_ret = usbg_init(in->configfs_path, out); - assert_int_equal(usbg_ret, USBG_SUCCESS); -} - -void safe_init_with_state(void **state, struct test_state **ts, usbg_state **s) -{ - *ts = (struct test_state *)(*state); - *state = NULL; - - init_with_state(*ts, s); - *state = *s; -} - -static int get_config_attr(usbg_config_attrs *attrs, config_attr attr) -{ - int ret; - - switch (attr) { - case MAX_POWER: - ret = attrs->bMaxPower; - break; - case BM_ATTRIBUTES: - ret = attrs->bmAttributes; - break; - default: - ret = -1; - break; - } - - return ret; -} - -void push_config_attribute(struct test_config *config, config_attr attr, - int value) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/%s", config->path, config->name, config_attr_names[attr]); - - switch (config_attr_format[attr]) { - case FORMAT_HEX: - safe_asprintf(&content, "0x%x\n", value); - break; - case FORMAT_DEC: - safe_asprintf(&content, "%d\n", value); - break; - } - - PUSH_FILE(path, content); -} - - -void push_config_attrs(struct test_config *config, usbg_config_attrs *attrs) -{ - int i; - - for (i = 0; i < CONFIG_ATTR_MAX; ++i) - push_config_attribute(config, i, get_config_attr(attrs, i)); -} - -void pull_config_attribute(struct test_config *config, config_attr attr, - int value) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/%s", config->path, config->name, config_attr_names[attr]); - - switch (config_attr_format[attr]) { - case FORMAT_HEX: - safe_asprintf(&content, "0x%x\n", value); - break; - case FORMAT_DEC: - safe_asprintf(&content, "%d\n", value); - break; - } - - switch (config_attr_format[attr]) { - case FORMAT_HEX: - EXPECT_HEX_WRITE(path, content); - break; - case FORMAT_DEC: - EXPECT_WRITE(path, content); - break; - } -} - -void pull_config_attrs(struct test_config *config, usbg_config_attrs *attrs) -{ - int i; - - for (i = 0; i < CONFIG_ATTR_MAX; ++i) - pull_config_attribute(config, i, get_config_attr(attrs, i)); -} - -const char *get_gadget_str(usbg_gadget_strs *strs, gadget_str str) -{ - const char *ret = NULL; - - switch (str) { - case STR_SER: - ret = strs->str_ser; - break; - case STR_MNF: - ret = strs->str_mnf; - break; - case STR_PRD: - ret = strs->str_prd; - break; - default: - ret = NULL; - break; - } - - return ret; -} - -static void pull_gadget_str_dir(struct test_gadget *gadget, int lang) -{ - char *dir; - int tmp; - - safe_asprintf(&dir, "%s/%s/strings/0x%x", - gadget->path, gadget->name, lang); - - srand(time(NULL)); - tmp = rand() % 2; - - if (tmp) { - EXPECT_OPENDIR(dir); - } else { - EXPECT_OPENDIR_ERROR(dir, ENOENT); - EXPECT_MKDIR(dir); - } -} - -static void pull_gadget_str(struct test_gadget *gadget, const char *attr_name, - int lang, const char *content) -{ - char *path; - - safe_asprintf(&path, "%s/%s/strings/0x%x/%s", - gadget->path, gadget->name, lang, attr_name); - EXPECT_WRITE(path, content); -} - -void pull_gadget_string(struct test_gadget *gadget, int lang, - gadget_str str, const char *content) -{ - pull_gadget_str_dir(gadget, lang); - pull_gadget_str(gadget, gadget_str_names[str], lang, content); -} - -void pull_gadget_strs(struct test_gadget *gadget, int lang, usbg_gadget_strs *strs) -{ - int i; - - pull_gadget_str_dir(gadget, lang); - for (i = 0; i < GADGET_STR_MAX; i++) - pull_gadget_str(gadget, gadget_str_names[i], lang, get_gadget_str(strs, i)); -} - -static void push_gadget_str_dir(struct test_gadget *gadget, int lang) -{ - char *dir; - - safe_asprintf(&dir, "%s/%s/strings/0x%x", - gadget->path, gadget->name, lang); - - EXPECT_OPENDIR(dir); -} - -static void push_gadget_str(struct test_gadget *gadget, const char *attr_name, - int lang, const char *content) -{ - char *path; - - safe_asprintf(&path, "%s/%s/strings/0x%x/%s", - gadget->path, gadget->name, lang, attr_name); - PUSH_FILE(path, content); -} - -void push_gadget_strs(struct test_gadget *gadget, int lang, usbg_gadget_strs *strs) -{ - int i; - - push_gadget_str_dir(gadget, lang); - for (i = 0; i < GADGET_STR_MAX; i++) - push_gadget_str(gadget, gadget_str_names[i], lang, get_gadget_str(strs, i)); -} - -void pull_config_string(struct test_config *config, int lang, const char *str) -{ - char *path; - int tmp; - - - safe_asprintf(&path, "%s/%s/strings/0x%x", - config->path, config->name, lang); - - srand(time(NULL)); - tmp = rand() % 2; - - if (tmp) { - EXPECT_OPENDIR(path); - } else { - EXPECT_OPENDIR_ERROR(path, ENOENT); - EXPECT_MKDIR(path); - } - - safe_asprintf(&path, "%s/configuration", path); - - EXPECT_WRITE(path, str); -} - -void pull_config_strs(struct test_config *config, int lang, usbg_config_strs *strs) -{ - pull_config_string(config, lang, strs->configuration); -} - -void push_config_string(struct test_config *config, int lang, const char *str) -{ - char *path; - - safe_asprintf(&path, "%s/%s/strings/0x%x", - config->path, config->name, lang); - - EXPECT_OPENDIR(path); - - safe_asprintf(&path, "%s/configuration", path); - - PUSH_FILE(path, str); -} - -void push_config_strs(struct test_config *config, int lang, usbg_config_strs *strs) -{ - push_config_string(config, lang, strs->configuration); -} - -void assert_config_attrs_equal(usbg_config_attrs *actual, usbg_config_attrs *expected) -{ - assert_int_equal(actual->bmAttributes, expected->bmAttributes); - assert_int_equal(actual->bMaxPower, expected->bMaxPower); -} - -void pull_create_config(struct test_config *tc) -{ - char *path; - - safe_asprintf(&path, "%s/%s", tc->path, tc->name); - EXPECT_MKDIR(path); - - if (tc->attrs) - pull_config_attrs(tc, tc->attrs); - if (tc->strs) - pull_config_strs(tc, LANG_US_ENG, tc->strs); -} - -#define ETHER_ADDR_STR_LEN 19 - -static void push_serial_attrs(struct test_function *func, - usbg_f_serial_attrs *attrs) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/port_num", func->path, func->name); - safe_asprintf(&content, "%d\n", attrs->port_num); - PUSH_FILE(path, content); -} - -static void push_net_attrs(struct test_function *func, - usbg_f_net_attrs *attrs) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/dev_addr", func->path, func->name); - - content = safe_malloc(ETHER_ADDR_STR_LEN * sizeof(char)); - ether_ntoa_r(&attrs->dev_addr, content); - - PUSH_FILE(path, content); - - path = safe_malloc(USBG_MAX_PATH_LENGTH * sizeof(char)); - sprintf(path, "%s/%s/host_addr", - func->path, func->name); - - content = safe_malloc(ETHER_ADDR_STR_LEN * sizeof(char)); - ether_ntoa_r(&attrs->host_addr, content); - - PUSH_FILE(path, content); - - safe_asprintf(&path, "%s/%s/qmult", func->path, func->name); - safe_asprintf(&content, "%d\n", attrs->qmult); - PUSH_FILE(path, content); - - safe_asprintf(&path, "%s/%s/ifname", func->path, func->name); - safe_asprintf(&content, "%s\n", attrs->ifname); - PUSH_FILE(path, content); -} - -static void push_phonet_attrs(struct test_function *func, - usbg_f_phonet_attrs *attrs) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/ifname", func->path, func->name); - safe_asprintf(&content, "%s\n", attrs->ifname); - PUSH_FILE(path, content); -} - -void push_function_attrs(struct test_function *func, usbg_function_attrs *function_attrs) -{ - int attrs_type; - usbg_f_attrs *attrs = &function_attrs->attrs; - - attrs_type = usbg_lookup_function_attrs_type(func->type); - - switch (attrs_type) { - case USBG_F_ATTRS_SERIAL: - push_serial_attrs(func, &attrs->serial); - break; - case USBG_F_ATTRS_NET: - push_net_attrs(func, &attrs->net); - break; - case USBG_F_ATTRS_PHONET: - push_phonet_attrs(func, &attrs->phonet); - break; - case USBG_F_ATTRS_FFS: - // ffs does not exist in filesystem - default: - break; - } -} - -static void pull_function_net_attrs(struct test_function *func, usbg_f_net_attrs *attrs) -{ - char *path; - char *content; - - safe_asprintf(&path, "%s/%s/dev_addr", func->path, func->name); - - content = safe_malloc(ETHER_ADDR_STR_LEN * sizeof(char)); - usbg_ether_ntoa_r(&attrs->dev_addr, content); - - EXPECT_WRITE(path, content); - - safe_asprintf(&path, "%s/%s/host_addr", func->path, func->name); - - content = safe_malloc(ETHER_ADDR_STR_LEN * sizeof(char)); - usbg_ether_ntoa_r(&attrs->host_addr, content); - - EXPECT_WRITE(path, content); - - safe_asprintf(&path, "%s/%s/qmult", func->path, func->name); - safe_asprintf(&content, "%d\n", attrs->qmult); - EXPECT_WRITE(path, content); -} - -void pull_function_attrs(struct test_function *func, usbg_function_attrs *attrs) -{ - /* only net attributes are writtable */ - if (attrs->header.attrs_type == USBG_F_ATTRS_NET) - pull_function_net_attrs(func, &attrs->attrs.net); -} - -void pull_create_function(struct test_function *tf) -{ - char *path; - int tmp; - - tmp = asprintf(&path, "%s/%s", tf->path, tf->name); - if (tmp < 0) - fail(); - free_later(path); - - EXPECT_MKDIR(path); - if (tf->attrs) - pull_function_attrs(tf, tf->attrs); -} - -void assert_func_equal(usbg_function *f, struct test_function *expected) -{ - assert_string_equal(f->instance, expected->instance); - assert_int_equal(f->type, expected->type); - assert_path_equal(f->path, expected->path); -} - -void assert_binding_equal(usbg_binding *b, struct test_binding *expected) -{ - assert_string_equal(b->name, expected->name); - assert_func_equal(b->target, expected->target); -} - -void assert_config_equal(usbg_config *c, struct test_config *expected) -{ - int i = 0; - usbg_binding *b; - - assert_int_equal(c->id, expected->id); - assert_string_equal(c->label, expected->label); - assert_path_equal(c->path, expected->path); - usbg_for_each_binding(b, c) - assert_binding_equal(b, &expected->bindings[i++]); -} - -void assert_gadget_equal(usbg_gadget *g, struct test_gadget *expected) -{ - usbg_config *c; - usbg_function *f; - int i; - - assert_string_equal(g->name, expected->name); - assert_path_equal(g->path, expected->path); - - i = 0; - usbg_for_each_function(f, g) - assert_func_equal(f, &expected->functions[i++]); - - i = 0; - usbg_for_each_config(c, g) - assert_config_equal(c, &expected->configs[i++]); -} - -void assert_state_equal(usbg_state *s, struct test_state *expected) -{ - usbg_gadget *g; - int i = 0; - - assert_path_equal(s->path, expected->path); - assert_path_equal(s->configfs_path, expected->configfs_path); - - usbg_for_each_gadget(g, s) - assert_gadget_equal(g, &expected->gadgets[i++]); -} - -#define SIGNUM(x) (((x) > 0) - ((x) < 0)) - -int path_cmp(const char *actual, const char *expected) -{ - const char *a = actual; - const char *b = expected; - - while (*a != '\0' && *b != '\0') { - if (*a != *b) - break; - do - ++a; - while (*a == '/'); - - do - ++b; - while (*b == '/'); - } - - return SIGNUM(*a - *b); -} - -int path_equal_display_error(const LargestIntegralType actual, const LargestIntegralType expected) -{ - if (path_cmp((const char *)actual, (const char *)expected) == 0) { - return 1; - } - - fprintf(stderr, "%s != %s\n", (const char *)actual, (const char *)expected); - return 0; -} - -void assert_path_equal(const char *actual, const char *expected) -{ - if (path_equal_display_error( - cast_to_largest_integral_type(actual), - cast_to_largest_integral_type(expected)) == 0) - fail(); -} - -int hex_str_cmp(const char *actual, const char *expected) -{ - int a, b; - - sscanf(actual, "%x", &a); - sscanf(expected, "%x", &b); - - return SIGNUM(a - b); -} - -int hex_str_equal_display_error(const LargestIntegralType actual, const LargestIntegralType expected) -{ - if (hex_str_cmp((const char *)actual, (const char *)expected) == 0) { - return 1; - } - - fprintf(stderr, "%s != %s\n", (const char *)actual, (const char *)expected); - return 0; -} - -void assert_gadget_attrs_equal(usbg_gadget_attrs *actual, - usbg_gadget_attrs *expected) -{ - int i; - - for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) - assert_int_equal(get_gadget_attr(actual, i), get_gadget_attr(expected, i)); -} - -void assert_gadget_strs_equal(usbg_gadget_strs *actual, usbg_gadget_strs *expected) -{ - int i; - for (i = 0; i < GADGET_STR_MAX; i++) - assert_string_equal(get_gadget_str(actual, i), get_gadget_str(expected, i)); -} - -void assert_f_serial_attrs_equal(usbg_f_serial_attrs *actual, - usbg_f_serial_attrs *expected) -{ - assert_int_equal(actual->port_num, expected->port_num); -} - -static void assert_ether_addrs_equal(const struct ether_addr *ea1, - const struct ether_addr *ea2) -{ - assert_memory_equal(ea1->ether_addr_octet, ea2->ether_addr_octet, - ETHER_ADDR_LEN); -} - -void assert_f_net_attrs_equal(usbg_f_net_attrs *actual, usbg_f_net_attrs *expected) -{ - assert_ether_addrs_equal(&actual->dev_addr, &expected->dev_addr); - assert_ether_addrs_equal(&actual->host_addr, &expected->host_addr); - assert_string_equal(actual->ifname, expected->ifname); - assert_int_equal(actual->qmult, expected->qmult); -} - -void assert_f_phonet_attrs_equal(usbg_f_phonet_attrs *actual, - usbg_f_phonet_attrs *expected) -{ - assert_string_equal(actual->ifname, expected->ifname); -} - -void assert_f_ffs_attrs_equal(usbg_f_ffs_attrs *actual, usbg_f_ffs_attrs *expected) -{ - assert_string_equal(actual->dev_name, expected->dev_name); -} - -void assert_function_attrs_equal(usbg_function_attrs *actual, - usbg_function_attrs *expected, usbg_f_attrs_type type) -{ - switch (type) { - case USBG_F_ATTRS_SERIAL: - assert_f_serial_attrs_equal(&actual->attrs.serial, &expected->attrs.serial); - break; - case USBG_F_ATTRS_NET: - assert_f_net_attrs_equal(&actual->attrs.net, &expected->attrs.net); - break; - case USBG_F_ATTRS_PHONET: - assert_f_phonet_attrs_equal(&actual->attrs.phonet, &expected->attrs.phonet); - break; - case USBG_F_ATTRS_FFS: - assert_f_ffs_attrs_equal(&actual->attrs.ffs, &expected->attrs.ffs); - break; - default: - fail(); - } -} - - -void for_each_test_function(struct test_state *ts, usbg_state *s, FunctionTest fun) -{ - struct test_gadget *tg; - struct test_function *tf; - usbg_gadget *g = NULL; - usbg_function *f = NULL; - - for (tg = ts->gadgets; tg->name; ++tg) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - for (tf = tg->functions; tf->instance; ++tf) { - f = usbg_get_function(g, tf->type, tf->instance); - fun(f, tf); - } - } -} - -void for_each_test_config(struct test_state *ts, usbg_state *s, ConfigTest fun) -{ - usbg_gadget *g = NULL; - usbg_config *c = NULL; - struct test_gadget *tg; - struct test_config *tc; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - for (tc = tg->configs; tc->label; tc++) { - c = usbg_get_config(g, tc->id, tc->label); - fun(c, tc); - } - } -} - -void for_each_binding(struct test_state *ts, usbg_state *s, BindingTestFunc fun) -{ - struct test_gadget *tg; - struct test_config *tc; - struct test_binding *tb; - usbg_gadget *g = NULL; - usbg_config *c = NULL; - usbg_binding *b = NULL; - - for (tg = ts->gadgets; tg->name; tg++) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - for (tc = tg->configs; tc->label; tc++) { - c = usbg_get_config(g, tc->id, tc->label); - assert_non_null(c); - - b = usbg_get_first_binding(c); - for (tb = tc->bindings; tb->name; ++tb) { - assert_non_null(b); - fun(tb, b); - b = usbg_get_next_binding(b); - } - } - } -} - -void for_each_test_gadget(struct test_state *ts, usbg_state *s, GadgetTestFunc fun) -{ - struct test_gadget *tg; - usbg_gadget *g = NULL; - - for (tg = ts->gadgets; tg->name; ++tg) { - g = usbg_get_gadget(s, tg->name); - assert_non_null(g); - fun(g, tg); - } -} diff --git a/tests/usbg-test.h b/tests/usbg-test.h deleted file mode 100644 index 127b90e..0000000 --- a/tests/usbg-test.h +++ /dev/null @@ -1,549 +0,0 @@ -#ifndef USBG_TEST_H -#define USBG_TEST_H - -#include <usbg/usbg.h> -#include <sys/queue.h> -#include "usbg/usbg_internal.h" - -/* Simple structures for defining gadgets. All arrays should be null-terminated.*/ - -/** - * @file tests/usbg-test.h - */ - -struct test_function -{ - usbg_function_type type; - char *instance; - - char *path; - char *name; - usbg_function_attrs *attrs; - int writable; -}; - -struct test_binding -{ - struct test_function *target; - char *name; - int writable; -}; - -struct test_config -{ - char *label; - int id; - struct test_function *bound_funcs; - - struct test_binding *bindings; - char *path; - char *name; - int writable; - usbg_config_strs *strs; - usbg_config_attrs *attrs; -}; - -struct test_gadget -{ - char *name; - char *udc; - struct test_config *configs; - struct test_function *functions; - - char *path; - int writable; -}; - -struct test_state -{ - char *configfs_path; - /* filled by prepare_state() */ - char *path; - struct test_gadget *gadgets; - char **udcs; - int writable; -}; - -typedef enum { - STR_SER = 0, - STR_MNF, - STR_PRD, - GADGET_STR_MAX -} gadget_str; - -typedef enum { - MAX_POWER = 0, - BM_ATTRIBUTES, - CONFIG_ATTR_MAX -} config_attr; - -typedef enum { - FORMAT_HEX, - FORMAT_DEC -} attr_format; - -#define TEST_FUNCTION_LIST_END { \ - .instance = NULL, \ - } - -#define TEST_CONFIG_LIST_END { \ - .label = NULL, \ - .bindings = NULL, \ - } - -#define TEST_GADGET_LIST_END { \ - .name = NULL, \ - .udc = NULL, \ - .configs = NULL, \ - .functions = NULL, \ - } - -#define expect_path(function, param, data) \ - expect_check(function, param, \ - (CheckParameterValue)(path_equal_display_error), data) - -/** - * @brief Prepare given state for using in tests - * @details Generate full pathes to state elements and sort state's content. - * Must be called before pasing state to push_* and pull_* functions. - * @param[in] state State schema used to genrate test state - * @return Pointer to state which can be used for testing. Returned value is - * equal to #state if writable attribute has been set to 1 or pointer - * to newly allocated test_state filled with suitable values. All memory - * allocated in this function is scheduled to free using free_later(). - */ -struct test_state *prepare_state(struct test_state *state); - -/** - * @brief Prepare given config for using in tests - * @details Generate required pathes for given config and sort content - * (i.e. binding list) - * @param[in] c Config to be filled out - * @param[in] cpath Path to configs directory - * @param[in] fpath Path to functions directory - */ -void prepare_config(struct test_config *c, char *cpath, char *fpath); - -/** - * @brief Prepare given function for using in tests - * @details Generate required pathes for given function - * @param[in] f Function to be filled out - * @param[in] path Path to functions directory - */ -void prepare_function(struct test_function *f, char *path); - -/** - * @brief Prepare given gadget for using in tests - * @details Generate required paths for given gadget and sort it's content - * (i.e. functions list and config list) - * @param[in] state Pointer to gadget's parent state - * @param[in] g Gadget to be filled out - */ -void prepare_gadget(struct test_state *state, struct test_gadget *g); - -/** - * @brief Fill given binding with required values - * @details Make given binding point to a function - * @param[in] b Test binding to be prepared - * @param[in] f Function to which binding will point - * @param[in] fpath Path to functions directory - */ -void prepare_binding(struct test_binding *b, struct test_function *f, char *fpath); - -/** - * @brief Prepare fake filesystem to init usbg with given test state - * @details Use wrapped i/o functions to simulate configfs state for usbg. - * Calling usbg_init without preparation and with mocked i/o functions - * may fail. - * @param[in] state Fake state of configfs defined in test - */ -void push_init(struct test_state *state); - -/** - * Prepare specific attributes writting/reading - **/ - -/** - * @brief Prepare for getting config attributes - * @param[in] config Configuration from which attributes will be get - * @param[in] attrs Attributes which will be present in virtual filesystem - */ -void push_config_attrs(struct test_config *config, usbg_config_attrs *attrs); - -/** - * @brief Preapre for setting config attributes - * @param[in] config Configuration on which attributes will be set - * @param[in] attrs Attributes which will be set on given config - */ -void pull_config_attrs(struct test_config *config, usbg_config_attrs *attrs); - -/** - * @brief Get gadget attribute - * @param[in] attrs - * @param[in] attr - */ -int get_gadget_attr(usbg_gadget_attrs *attrs, usbg_gadget_attr attr); - -/** - * @brief Prepare to write given attribute by libusbg - * @param[in] gadget Test gadget related to given attribute - * @param[in] attr Attribute - * @param[in] value Attributes value - **/ -void push_gadget_attribute(struct test_gadget *gadget, - usbg_gadget_attr attr, int value); - -/** - * @brief Prepare to read given attribute by libusbg - * @param[in] gadget Test gadget related to given attribute - * @param[in] attr Attribute - * @param[in] value Attributes value - **/ -void pull_gadget_attribute(struct test_gadget *gadget, - usbg_gadget_attr attr, int value); - -/** - * @brief Prepare fake filesystem to get given gadget attributes - * @details Prepare queue of values passed to wrapped i/o functions, - * all values got from given attributes structure. - * @param[in] gadget Pointer to gadget - * @param[in] attrs Pointer to attributes which gadget should have - * @warning Calling usbg_get_gadget_attrs function whithout this - * preparation and with wrapped i/o may fail. - */ -void push_gadget_attrs(struct test_gadget *gadget, usbg_gadget_attrs *attrs); - -/** - * @brief Prepare fake filesystem for attributes setting attempt. - * @details Prepare queue of values passed to wrapped i/o functions, - * corresponding to functions called on attributes setting - * @param[in] gadget Pointer to gadget - * @param[in] attrs Pointer to expected attributes - * @warning Calling usbg_get_gadget_attrs function whithout this - * preparation and with wrapped i/o may fail. - */ -void pull_gadget_attrs(struct test_gadget *gadget, usbg_gadget_attrs *attrs); - -/** - * @brief Prepare fake filesystem to get given function attributes - * @details Prepare queue of values passed to wrapped i/o functions, - * all values got from given attributes structure. - * @warning Calling usbg_get_function_attrs function whithout this - * preparation and with wrapped i/o may fail. - */ -void push_function_attrs(struct test_function *func, usbg_function_attrs *attrs); - -/** - * @brief Prepare fake filesystem to set given function attributes - * @details Prepare queue of values passed to wrapped i/o functions, - * all values got from given attributes structure. - * @warning Calling usbg_set_function_attrs function whithout this - * preparation and with wrapped i/o may fail. - */ -void pull_function_attrs(struct test_function *func, usbg_function_attrs *attrs); - -/** - * @brief Get gadget string - * @param[in] strs Set of gadget strings - * @param[in] str Identifier of string which should be returned - * @return Selected string from given set of strings - */ -const char *get_gadget_str(usbg_gadget_strs *strs, gadget_str str); - -/** - * @brief Prepare filesystem to set selected gadget string - * @param[in] gadget Gadget on which str will be set - * @param[in] lang Language of string - * @param[in] str String identifier - * @param[in] content String expected to be set - */ -void pull_gadget_string(struct test_gadget *gadget, int lang, - gadget_str str, const char *content); - -/** - * @brief Prepare filesystem to set given gadget strings - * @param[in] gadget Gadget on which strings will be set - * @param[in] lang Language of strings - * @param[in] strs Strings expected to be set - */ -void pull_gadget_strs(struct test_gadget *gadget, int lang, usbg_gadget_strs *strs); - -/** - * @brief prepare for reading gadget's strings - */ -void push_gadget_strs(struct test_gadget *gadget, int lang, usbg_gadget_strs *strs); - -/** - * @brief Prepare for /ref usbg_set_config_string calling - * @details Expect setting the same string as given one - * @param[in] config on which strings will be set - * @param[in] lang Language of strings - * @param[in] str string to be set as configuration string - */ -void pull_config_string(struct test_config *config, int lang, const char *str); - -/** - * @brief Prepare for writting given config strings - * @param[in] config on which strings will be set - * @param[in] lang Language of strings - * @param[in] strs Strings expected to be set - */ -void pull_config_strs(struct test_config *config, int lang, usbg_config_strs *strs); - -/** - * @brief Prepare for /ref usbg_get_config_string calling - * @details Expect setting the same string as given one - * @param[in] config from which strings will be get - * @param[in] lang Language of strings - * @param[in] str string which should be returned as configuration string - */ -void push_config_string(struct test_config *config, int lang, const char *str); - -/** - * @brief Prepare for reading config strings - * @param[in] config from which strings will be get - * @param[in] lang Language of strings - * @param[in] strs Strings which should be returned - */ -void push_config_strs(struct test_config *config, int lang, usbg_config_strs *strs); - -/** - * @brief Prepare for creating config - * @param[in] tc Test config to be created - */ -void pull_create_config(struct test_config *tc); - -/** - * @brief Prepare for creating function - * @param[in] tf Test function to be created - */ -void pull_create_function(struct test_function *tf); - -/** - * @brief Copy state without configs and functions - * @param[in] ts State to bo copied - * @return State with empty gadgets - */ -struct test_state *build_empty_gadget_state(struct test_state *ts); - -/** - * @brief Store given pointer on cleanup stack - * @details All stacked pointers will be freed by calling cleanup_queue. - * This can be used to manage memory needed for single test casees. - */ -void free_later(void *ptr); - -/** - * @brief Cleans up memory no longer needed - * @details Frees all pointer stored on cleanup stack by calling free_later - * @warning Calling this function before end of single test usually make test state - * unusable. Use it only when you no longer need allocated data (at the end of - * test case, in most cases) - */ -void cleanup_stack(); - -/** - * @brief init usbg with given test state - */ -void init_with_state(struct test_state *in, usbg_state **out); - -/** - * @brief Safely initialize usbg state from pointer given to test - * @param[in] state Pointer given to test function - * @param[out] ts Pointer to be filled with test state - * @param[out] s Pointer to be filled with usbg state - */ -void safe_init_with_state(void **state, struct test_state **ts, usbg_state **s); - -/** - * @brief Assert that given config attributes are equal - */ -void assert_config_attrs_equal(usbg_config_attrs *actual, usbg_config_attrs *expected); - -/** - * @brief Assert that given usbg binding matches given test binding - * @param[in] f Pointer to usbg binding struct - * @param[in] expected Pointer to test binding struct with expected values - */ -void assert_binding_equal(usbg_binding *b, struct test_binding *expected); - -/** - * @brief Assert that given usbg function matches given test function - * @param[in] f Pointer to usbg function struct - * @param[in] expected Pointer to test function struct with expected values - */ -void assert_func_equal(usbg_function *f, struct test_function *expected); - -/** - * @brief Assert that given usbg config matches given test config - * @param[in] c Pointer to usbg config struct - * @param[in] expected Pointer to test config struct with expected values - */ -void assert_config_equal(usbg_config *c, struct test_config *expected); - -/** - * @brief Assert that given usbg gadget matches given test gadget - * @param[in] g Pointer to usbg gadget struct - * @param[in] expected Pointer to test gadget struct with expected values - */ -void assert_gadget_equal(usbg_gadget *g, struct test_gadget *expected); - -/** - * @brief Assert that given usbg state matches given test state - * @param[in] s Pointer to usbg state struct - * @param[in] expected Pointer to test state struct with expected values - */ -void assert_state_equal(usbg_state *s, struct test_state *expected); - -/** - * @brief Compare path names - * @details Given pathes don't need to exist - * @return Integer less than, equal to, or greater than zero if a is (respectively) - * less than, equal to, or greater than b. - */ -int path_cmp(const char *a, const char *b); - -/** - * @brief Print error when given paths are not equal - * @return 1 if paths are equal, 0 otherwise - * @note Argument type is defined by cmocka. This specific function type is defined - * as custom comparing function in cmocka framework. - */ -int path_equal_display_error(const LargestIntegralType actual, const LargestIntegralType expected); - -/** - * @brief Compare attributes (as strings) - * @return Integer less than, equal to, or greater than zero if a is (respectively) - * less than, equal to, or greater than b. - */ -int hex_str_cmp(const char *actual, const char *expected); - -/** - * @brief Print error when given attributes are not equal - * @return 1 if attributes are equal, 0 otherwise - * @note Argument type is defined by cmocka. This specific function type is defined - * as custom comparing function in cmocka framework. - */ -int hex_str_equal_display_error(const LargestIntegralType actual, const LargestIntegralType expected); - -/** - * @brief Assert that given path strings are equal - * @details Given pathes don't need to exist - */ -void assert_path_equal(const char *actual, const char *expected); - -/** - * @brief Assert that given usbg gadget attributes sets are equal - * @param[in] actual Pointer to actual gadget attributes structure - * @param[in] expected Pointer to expeced gadget attributes structure - */ -void assert_gadget_attrs_equal(usbg_gadget_attrs *actual, - usbg_gadget_attrs *expected); - -/** - * @brief Assert that given function attributes are the same. - * @param[in] actual Pointer to actual attributes object - * @param[in] expected Pointer to expected attributes obejct - * @param[in] type Type of function, which attributes are checked - */ -void assert_function_attrs_equal(usbg_function_attrs *actual, - usbg_function_attrs *expected, usbg_f_attrs_type type); - -/** - * @brief Assert that given gadget strings are equal - */ -void assert_gadget_strs_equal(usbg_gadget_strs *actual, usbg_gadget_strs *expected); - -/** - * @brief Function that performs some test on given usbg function -*/ -typedef void (*FunctionTest)(usbg_function *f, struct test_function *tf); - -/** - * @brief Call given function for all usb functions present in given state - * @param[in] ts Test state to be tested - * @param[in] s Properly prepared usbg state to be tested - * @param[in] fun Function to be called on each usb function in state - */ -void for_each_test_function(struct test_state *ts, usbg_state *s, FunctionTest fun); - -/** - * @brief Function that performs some test on given usbg config -*/ -typedef void (*ConfigTest)(usbg_config *c, struct test_config *tc); - -/** - * @brief Call given function for all usb configs present in given state - * @param[in] ts Test state to be tested - * @param[in] s Properly prepared usbg state to be tested - * @param[in] fun Function to be called on each usb function in state - */ -void for_each_test_config(struct test_state *ts, usbg_state *s, ConfigTest fun); - -/** - * @brief Function that performs test on given usbg binding - */ -typedef void (*BindingTestFunc)(struct test_binding *tb, usbg_binding *b); - -/** - * @brief Call given function for all usb bindings present in given state - * @param[in] ts Test state to be tested - * @param[in] s Properly prepared usbg state to be tested - * @param[in] fun Function to be called on each usb binding in state - */ -void for_each_binding(struct test_state *ts, usbg_state *s, BindingTestFunc fun); - -/** - * @brief Function that performs test on given usbg gadget - */ -typedef void (*GadgetTestFunc)(usbg_gadget *g, struct test_gadget *tg); - -/** - * @brief Call given function for all usb gadgets present in given state - * @param[in] ts Test state to be tested - * @param[in] s Properly prepared usbg state to be tested - * @param[in] fun Function to be called on each usb gadget in state - */ -void for_each_test_gadget(struct test_state *ts, usbg_state *s, GadgetTestFunc fun); - -static inline void *safe_calloc(int count, size_t size) -{ - void *ptr; - - ptr = calloc(count, size); - if (ptr == NULL) - fail(); - - free_later(ptr); - return ptr; -} - -static inline void *safe_malloc(size_t size) -{ - void *ptr; - - ptr = malloc(size); - if (ptr == NULL) - fail(); - - free_later(ptr); - return ptr; -} - -static inline int safe_asprintf(char **ptr, const char *fmt, ...) -{ - va_list args; - int ret; - - va_start(args, fmt); - ret = vasprintf(ptr, fmt, args); - va_end(args); - - if (ret < 0) - fail(); - - free_later(*ptr); - return ret; -} - -#endif /* USBG_TEST_H */ |