From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Fri, 07 May 2021 08:08:19 +0200 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by lore.white.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1letet-0003uT-AY for lore@lore.pengutronix.de; Fri, 07 May 2021 08:08:19 +0200 Received: from localhost ([127.0.0.1] helo=metis.ext.pengutronix.de) by metis.ext.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1letes-0001sC-Ma; Fri, 07 May 2021 08:08:18 +0200 Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1letdn-0001ML-Q0; Fri, 07 May 2021 08:07:11 +0200 Received: from [2a0a:edc0:0:1101:1d::39] (helo=dude03.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1letdn-0002Is-A5; Fri, 07 May 2021 08:07:11 +0200 Received: from mol by dude03.red.stw.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1letdn-00GYwA-7v; Fri, 07 May 2021 08:07:11 +0200 From: Michael Olbrich To: ptxdist@pengutronix.de Date: Fri, 7 May 2021 08:07:11 +0200 Message-Id: <20210507060711.3947503-1-m.olbrich@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210428232410.15059-1-m.grzeschik@pengutronix.de> References: <20210428232410.15059-1-m.grzeschik@pengutronix.de> MIME-Version: 1.0 Subject: Re: [ptxdist] [APPLIED] libusbgx: new package X-BeenThere: ptxdist@pengutronix.de X-Mailman-Version: 2.1.29 Precedence: list List-Id: PTXdist Development Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ptxdist@pengutronix.de Cc: Michael Grzeschik Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "ptxdist" X-SA-Exim-Connect-IP: 127.0.0.1 X-SA-Exim-Mail-From: ptxdist-bounces@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false Thanks, applied as 6677792614505262f62e8b0a5dfbe1df130ed633. Michael [sent from post-receive hook] On Fri, 07 May 2021 08:07:11 +0200, Michael Grzeschik wrote: > This patch adds libusbgx support to ptxdist. It includes patches to work > with uvc gadgets. > > Signed-off-by: Michael Grzeschik > Message-Id: <20210428232410.15059-1-m.grzeschik@pengutronix.de> > Signed-off-by: Michael Olbrich > > diff --git a/patches/libusbgx-0.2.0/0001-Fix-39-Compilation-fails-on-gcc-v8.patch b/patches/libusbgx-0.2.0/0001-Fix-39-Compilation-fails-on-gcc-v8.patch > new file mode 100644 > index 000000000000..4e7ff0ca427e > --- /dev/null > +++ b/patches/libusbgx-0.2.0/0001-Fix-39-Compilation-fails-on-gcc-v8.patch > @@ -0,0 +1,20 @@ > +From: Federico Fuga > +Date: Thu, 23 May 2019 13:40:39 +0200 > +Subject: [PATCH] Fix #39 Compilation fails on gcc v8 > + > +--- > + src/usbg_common.c | 1 + > + 1 file changed, 1 insertion(+) > + > +diff --git a/src/usbg_common.c b/src/usbg_common.c > +index f8822fcf727f..f3aa8b053c44 100644 > +--- a/src/usbg_common.c > ++++ b/src/usbg_common.c > +@@ -20,6 +20,7 @@ > + #include > + #include > + #include > ++#include > + > + int usbg_read_buf_limited(const char *path, const char *name, > + const char *file, char *buf, int len) > diff --git a/patches/libusbgx-0.2.0/0002-libusbgx-fix-build-with-glibc-2.28-since-sys-sysmacr.patch b/patches/libusbgx-0.2.0/0002-libusbgx-fix-build-with-glibc-2.28-since-sys-sysmacr.patch > new file mode 100644 > index 000000000000..9670d469acb3 > --- /dev/null > +++ b/patches/libusbgx-0.2.0/0002-libusbgx-fix-build-with-glibc-2.28-since-sys-sysmacr.patch > @@ -0,0 +1,90 @@ > +From: Gwenhael Goavec-Merou > +Date: Mon, 10 Sep 2018 15:52:09 +0200 > +Subject: [PATCH] libusbgx: fix build with glibc-2.28 since > + is no more included by > + > +Signed-off-by: Sid Spry R030t1@gmail.com > +Signed-off-by: Gwenhael Goavec-Merou gwenhael.goavec-merou@trabucayre.com > +[Copy sign-offs from pull requst to commit msg] > +Signed-off-by: Krzysztof Opasiak > +--- > + examples/gadget-acm-ecm.c | 1 + > + examples/gadget-import.c | 1 + > + examples/gadget-ms.c | 1 + > + examples/show-gadgets.c | 1 + > + examples/show-udcs.c | 1 + > + include/usbg/usbg_internal_libconfig.h | 1 + > + 6 files changed, 6 insertions(+) > + > +diff --git a/examples/gadget-acm-ecm.c b/examples/gadget-acm-ecm.c > +index 1c5e2ca5161c..29360da15811 100644 > +--- a/examples/gadget-acm-ecm.c > ++++ b/examples/gadget-acm-ecm.c > +@@ -20,6 +20,7 @@ > + > + #include > + #include > ++#include > + #include > + #include > + > +diff --git a/examples/gadget-import.c b/examples/gadget-import.c > +index e684fdb861e8..63df4499926b 100644 > +--- a/examples/gadget-import.c > ++++ b/examples/gadget-import.c > +@@ -25,6 +25,7 @@ > + #include > + #include > + #include > ++#include > + #include > + > + int main(int argc, char **argv) > +diff --git a/examples/gadget-ms.c b/examples/gadget-ms.c > +index 478c37097397..a5c668187a96 100644 > +--- a/examples/gadget-ms.c > ++++ b/examples/gadget-ms.c > +@@ -23,6 +23,7 @@ > + > + #include > + #include > ++#include > + #include > + #include > + #include > +diff --git a/examples/show-gadgets.c b/examples/show-gadgets.c > +index 707d4488d16b..a2a21c883b27 100644 > +--- a/examples/show-gadgets.c > ++++ b/examples/show-gadgets.c > +@@ -21,6 +21,7 @@ > + #include > + #include > + #include > ++#include > + #include > + #include > + #include > +diff --git a/examples/show-udcs.c b/examples/show-udcs.c > +index 66e950f7bf85..2f5cc458ebb1 100644 > +--- a/examples/show-udcs.c > ++++ b/examples/show-udcs.c > +@@ -23,6 +23,7 @@ > + > + #include > + #include > ++#include > + #include > + > + int main(void) > +diff --git a/include/usbg/usbg_internal_libconfig.h b/include/usbg/usbg_internal_libconfig.h > +index ac51758b3d6c..3fa55c0b544b 100644 > +--- a/include/usbg/usbg_internal_libconfig.h > ++++ b/include/usbg/usbg_internal_libconfig.h > +@@ -12,6 +12,7 @@ > + #ifndef USBG_INTERNAL_LIBCONFIG_H > + #define USBG_INTERNAL_LIBCONFIG_H > + > ++#include > + #include > + #ifdef __cplusplus > + extern "C" { > diff --git a/patches/libusbgx-0.2.0/0003-examples-gadget-vid-pid-remove-add-dynamic-vid-pid-s.patch b/patches/libusbgx-0.2.0/0003-examples-gadget-vid-pid-remove-add-dynamic-vid-pid-s.patch > new file mode 100644 > index 000000000000..63ddf347f733 > --- /dev/null > +++ b/patches/libusbgx-0.2.0/0003-examples-gadget-vid-pid-remove-add-dynamic-vid-pid-s.patch > @@ -0,0 +1,67 @@ > +From: Michael Grzeschik > +Date: Wed, 28 Apr 2021 21:43:07 +0200 > +Subject: [PATCH] examples: gadget-vid-pid-remove: add dynamic vid pid support > + > +Signed-off-by: Michael Grzeschik > +--- > + examples/gadget-vid-pid-remove.c | 25 ++++++++++++++++++++----- > + 1 file changed, 20 insertions(+), 5 deletions(-) > + > +diff --git a/examples/gadget-vid-pid-remove.c b/examples/gadget-vid-pid-remove.c > +index f6b950b38da3..f5eb9664b721 100644 > +--- a/examples/gadget-vid-pid-remove.c > ++++ b/examples/gadget-vid-pid-remove.c > +@@ -23,11 +23,10 @@ > + > + #include > + #include > ++#include > ++#include > + #include > + > +-#define VENDOR 0x1d6b > +-#define PRODUCT 0x0104 > +- > + int remove_gadget(usbg_gadget *g) > + { > + int usbg_ret; > +@@ -60,13 +59,29 @@ out: > + return usbg_ret; > + } > + > +-int main(void) > ++int main(int argc, char **argv) > + { > + int usbg_ret; > + int ret = -EINVAL; > + usbg_state *s; > + usbg_gadget *g; > + struct usbg_gadget_attrs g_attrs; > ++ char *cp; > ++ int vendor = 0x1d6b, product = 0x0104; > ++ > ++ if (argc >= 2) { > ++ cp = strchr(argv[1], ':'); > ++ if (!cp) { > ++ ret = -EINVAL; > ++ fprintf(stderr, "Usage: gadget-vid-pid-remove vid:pid\n"); > ++ goto out1; > ++ } > ++ *cp++ = 0; > ++ if (&argv[1]) > ++ vendor = strtoul(argv[1], NULL, 16); > ++ if (*cp) > ++ product = strtoul(cp, NULL, 16); > ++ } > + > + usbg_ret = usbg_init("/sys/kernel/config", &s); > + if (usbg_ret != USBG_SUCCESS) { > +@@ -88,7 +103,7 @@ int main(void) > + } > + > + /* Compare attrs with given values and remove if suitable */ > +- if (g_attrs.idVendor == VENDOR && g_attrs.idProduct == PRODUCT) { > ++ if (g_attrs.idVendor == vendor && g_attrs.idProduct == product) { > + usbg_gadget *g_next = usbg_get_next_gadget(g); > + > + usbg_ret = remove_gadget(g); > diff --git a/patches/libusbgx-0.2.0/0004-libusbgx-Add-UVC-support.patch b/patches/libusbgx-0.2.0/0004-libusbgx-Add-UVC-support.patch > new file mode 100644 > index 000000000000..0217bb02d0ae > --- /dev/null > +++ b/patches/libusbgx-0.2.0/0004-libusbgx-Add-UVC-support.patch > @@ -0,0 +1,737 @@ > +From: Thomas Haemmerle > +Date: Wed, 8 Jan 2020 14:43:45 +0100 > +Subject: [PATCH] libusbgx: Add UVC support > + > +Signed-off-by: Thomas Haemmerle > +Signed-off-by: Michael Grzeschik > + > +Notes: > +v2 -> v3: - simplified exit paths of functions with reutrns instead of gotos > + - added cleanup code for remove > + - added gadget-uvc example file > + - simplified class link creation > + - added support for more than one format > +--- > + Makefile.am | 2 +- > + examples/Makefile.am | 3 +- > + examples/gadget-uvc.c | 156 ++++++++++++++++++ > + include/usbg/function/uvc.h | 90 +++++++++++ > + include/usbg/usbg.h | 1 + > + src/Makefile.am | 2 +- > + src/function/uvc.c | 378 ++++++++++++++++++++++++++++++++++++++++++++ > + src/usbg.c | 2 + > + 8 files changed, 631 insertions(+), 3 deletions(-) > + create mode 100644 examples/gadget-uvc.c > + create mode 100644 include/usbg/function/uvc.h > + create mode 100644 src/function/uvc.c > + > +diff --git a/Makefile.am b/Makefile.am > +index a3cc337c18da..b3cd097d9d32 100644 > +--- a/Makefile.am > ++++ b/Makefile.am > +@@ -14,6 +14,6 @@ EXTRA_DIST = doxygen.cfg > + library_includedir=$(includedir)/usbg > + library_include_HEADERS = include/usbg/usbg.h include/usbg/usbg_version.h > + function_includedir=$(includedir)/usbg/function > +-function_include_HEADERS = include/usbg/function/ffs.h include/usbg/function/loopback.h include/usbg/function/midi.h include/usbg/function/ms.h include/usbg/function/net.h include/usbg/function/phonet.h include/usbg/function/serial.h include/usbg/function/hid.h include/usbg/function/uac2.h > ++function_include_HEADERS = include/usbg/function/ffs.h include/usbg/function/loopback.h include/usbg/function/midi.h include/usbg/function/ms.h include/usbg/function/net.h include/usbg/function/phonet.h include/usbg/function/serial.h include/usbg/function/hid.h include/usbg/function/uac2.h include/usbg/function/uvc.h > + pkgconfigdir = $(libdir)/pkgconfig > + pkgconfig_DATA = libusbgx.pc > +diff --git a/examples/Makefile.am b/examples/Makefile.am > +index 993432156d6c..3217eb3bfd6f 100644 > +--- a/examples/Makefile.am > ++++ b/examples/Makefile.am > +@@ -1,5 +1,6 @@ > +-bin_PROGRAMS = show-gadgets gadget-acm-ecm gadget-vid-pid-remove gadget-ffs gadget-export gadget-import show-udcs gadget-ms gadget-midi gadget-hid gadget-rndis-os-desc gadget-uac2 > ++bin_PROGRAMS = show-gadgets gadget-acm-ecm gadget-vid-pid-remove gadget-uvc gadget-ffs gadget-export gadget-import show-udcs gadget-ms gadget-midi gadget-hid gadget-rndis-os-desc gadget-uac2 > + gadget_acm_ecm_SOURCES = gadget-acm-ecm.c > ++gadget_uvc_SOURCES = gadget-uvc.c > + show_gadgets_SOURCES = show-gadgets.c > + gadget_vid_pid_remove_SOURCES = gadget-vid-pid-remove.c > + gadget_ffs_SOURCES = gadget-ffs.c > +diff --git a/examples/gadget-uvc.c b/examples/gadget-uvc.c > +new file mode 100644 > +index 000000000000..d3efe2deaebe > +--- /dev/null > ++++ b/examples/gadget-uvc.c > +@@ -0,0 +1,156 @@ > ++/* > ++ * Copyright (C) 2021 Pengutronix > ++ * > ++ * Michael Grzeschik > ++ * > ++ * 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 > ++#include > ++#include > ++#include > ++#include > ++#include > ++ > ++/** > ++ * @file gadget-uvc.c > ++ * @example gadget-uvc.c > ++ * This is an example of how to create an UVC gadget device. > ++ */ > ++ > ++#define VENDOR 0x1d6b > ++#define PRODUCT 0x0104 > ++ > ++int main(void) > ++{ > ++ usbg_state *s; > ++ usbg_gadget *g; > ++ usbg_config *c; > ++ usbg_function *f_uvc; > ++ int ret = -EINVAL; > ++ int usbg_ret; > ++ > ++ struct 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 */ > ++ }; > ++ > ++ struct usbg_gadget_strs g_strs = { > ++ .serial = "0123456789", /* Serial number */ > ++ .manufacturer = "Foo Inc.", /* Manufacturer */ > ++ .product = "Bar Gadget" /* Product string */ > ++ }; > ++ > ++ struct usbg_config_strs c_strs = { > ++ .configuration = "UVC" > ++ }; > ++ > ++ struct usbg_f_uvc_format_attrs uvc_format_attrs_array[] = { > ++ { > ++ .format = UVC_FORMAT_MJPEG, > ++ .dwFrameInterval = "333333", > ++ .height = 1080, > ++ .width = 1920, > ++ }, { > ++ .format = UVC_FORMAT_MJPEG, > ++ .dwFrameInterval = "333333", > ++ .height = 3940, > ++ .width = 2160, > ++ }, { > ++ .format = UVC_FORMAT_UNCOMPRESSED, > ++ .dwFrameInterval = "333333", > ++ .height = 1080, > ++ .width = 1920, > ++ }, { > ++ .format = UVC_FORMAT_UNCOMPRESSED, > ++ .dwFrameInterval = "333333", > ++ .height = 3940, > ++ .width = 2160, > ++ } > ++ }; > ++ > ++ struct usbg_f_uvc_format_attrs *uvc_format_attrs[] = { > ++ &uvc_format_attrs_array[3], > ++ &uvc_format_attrs_array[2], > ++ &uvc_format_attrs_array[1], > ++ &uvc_format_attrs_array[0], > ++ NULL, > ++ }; > ++ > ++ struct usbg_f_uvc_attrs uvc_attrs = { > ++ .formats = uvc_format_attrs, > ++ }; > ++ > ++ 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, USBG_F_UVC, "uvc", &uvc_attrs, &f_uvc); > ++ if(usbg_ret != USBG_SUCCESS) > ++ { > ++ fprintf(stderr, "Error creating uvc 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, "uvc.cam", f_uvc); > ++ if (usbg_ret != USBG_SUCCESS) { > ++ fprintf(stderr, "Error adding acm.GS0\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/include/usbg/function/uvc.h b/include/usbg/function/uvc.h > +new file mode 100644 > +index 000000000000..4c641dacdfcb > +--- /dev/null > ++++ b/include/usbg/function/uvc.h > +@@ -0,0 +1,90 @@ > ++/* > ++ * 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_FUNCTION_UVC__ > ++#define USBG_FUNCTION_UVC__ > ++ > ++#include > ++ > ++#ifdef __cplusplus > ++extern "C" { > ++#endif > ++ > ++ > ++#define USBG_UVC_MAX_PATH_LENGTH 1024 > ++ > ++struct usbg_f_uvc; > ++typedef struct usbg_f_uvc usbg_f_uvc; > ++ > ++enum uvc_format > ++{ > ++ UVC_FORMAT_MJPEG, > ++ UVC_FORMAT_UNCOMPRESSED > ++}; > ++ > ++struct usbg_f_uvc_format_attrs > ++{ > ++ enum uvc_format format; > ++ const char *dwFrameInterval; > ++ int height; > ++ int width; > ++}; > ++ > ++struct usbg_f_uvc_attrs > ++{ > ++ struct usbg_f_uvc_format_attrs **formats; > ++}; > ++ > ++/** > ++ * @brief Cast from generic function to uvc function > ++ * @param[in] f function to be converted to uvc funciton. > ++ * Should be one of types: > ++ * ecm, subset, ncm, eem, rndis > ++ * @return Converted uvc function or NULL if function hasn't suitable type > ++ */ > ++usbg_f_uvc *usbg_to_uvc_function(usbg_function *f); > ++ > ++/** > ++ * @brief Cast form uvc function to generic one > ++ * @param[in] uvc function to be converted to generic one > ++ * @return Generic usbg function > ++ */ > ++usbg_function *usbg_from_uvc_function(usbg_f_uvc *ff); > ++ > ++/** > ++ * @brief Cleanup attributes structure after usage > ++ * @param[in] attrs to be cleaned up > ++ */ > ++static inline void usbg_f_uvc_cleanup_attrs(struct usbg_f_uvc_attrs *attrs) > ++{ > ++ struct usbg_f_uvc_format_attrs **format_attrs; > ++ int i; > ++ > ++ if (attrs) { > ++ for(format_attrs = attrs->formats, i = 0; format_attrs[i]; ++i) { > ++ if (format_attrs[i]) { > ++ free((char *)format_attrs[i]->dwFrameInterval); > ++ format_attrs[i]->dwFrameInterval = NULL; > ++ } > ++ } > ++ } > ++} > ++ > ++int usbg_f_uvc_get_attrs(usbg_f_uvc *uvcf, struct usbg_f_uvc_attrs *attrs); > ++int usbg_f_uvc_set_attrs(usbg_f_uvc *uvcf, const struct usbg_f_uvc_attrs *attrs); > ++ > ++ > ++#ifdef __cplusplus > ++} > ++#endif > ++ > ++#endif /* USBG_FUNCTION_UVC__ */ > +diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h > +index 55c52a1c3768..de72793ddcf0 100644 > +--- a/include/usbg/usbg.h > ++++ b/include/usbg/usbg.h > +@@ -219,6 +219,7 @@ typedef enum > + USBG_F_LOOPBACK, > + USBG_F_HID, > + USBG_F_UAC2, > ++ USBG_F_UVC, > + USBG_FUNCTION_TYPE_MAX, > + } usbg_function_type; > + > +diff --git a/src/Makefile.am b/src/Makefile.am > +index 6b2726ec5219..c51878fac2ff 100644 > +--- a/src/Makefile.am > ++++ b/src/Makefile.am > +@@ -1,6 +1,6 @@ > + AUTOMAKE_OPTIONS = std-options subdir-objects > + lib_LTLIBRARIES = libusbgx.la > +-libusbgx_la_SOURCES = usbg.c usbg_error.c usbg_common.c function/ether.c function/ffs.c function/midi.c function/ms.c function/phonet.c function/serial.c function/loopback.c function/hid.c function/uac2.c > ++libusbgx_la_SOURCES = usbg.c usbg_error.c usbg_common.c function/ether.c function/ffs.c function/midi.c function/ms.c function/phonet.c function/serial.c function/loopback.c function/hid.c function/uac2.c function/uvc.c > + if TEST_GADGET_SCHEMES > + libusbgx_la_SOURCES += usbg_schemes_libconfig.c usbg_common_libconfig.c > + else > +diff --git a/src/function/uvc.c b/src/function/uvc.c > +new file mode 100644 > +index 000000000000..92d738c5763c > +--- /dev/null > ++++ b/src/function/uvc.c > +@@ -0,0 +1,378 @@ > ++/* > ++ * 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" > ++#include "usbg/function/uvc.h" > ++ > ++#include > ++#include > ++#include > ++#include > ++#include > ++#ifdef HAS_GADGET_SCHEMES > ++#include > ++#endif > ++ > ++#define UVC_PATH_CONTROL "control" > ++#define UVC_PATH_HEADER "header/h" > ++#define UVC_PATH_CLASS_FS "class/fs/h" > ++#define UVC_PATH_CLASS_HS "class/hs/h" > ++#define UVC_PATH_CLASS_SS "class/ss/h" > ++#define UVC_PATH_STREAMING "streaming" > ++#define UVC_PATH_STREAMING_UNCOMPRESSED "uncompressed/u" > ++#define UVC_PATH_STREAMING_MJPEG "mjpeg/m" > ++ > ++struct usbg_f_uvc > ++{ > ++ struct usbg_function func; > ++}; > ++ > ++GENERIC_ALLOC_INST(uvc, struct usbg_f_uvc, func); > ++ > ++GENERIC_FREE_INST(uvc, struct usbg_f_uvc, func); > ++ > ++static int uvc_set_attrs(struct usbg_function *f, void *f_attrs) > ++{ > ++ return usbg_f_uvc_set_attrs(usbg_to_uvc_function(f), f_attrs); > ++} > ++ > ++static int uvc_get_attrs(struct usbg_function *f, void *f_attrs) > ++{ > ++ return usbg_f_uvc_get_attrs(usbg_to_uvc_function(f), f_attrs); > ++} > ++ > ++static void uvc_cleanup_attrs(struct usbg_function *f, void *f_attrs) > ++{ > ++ return usbg_f_uvc_cleanup_attrs(f_attrs); > ++} > ++ > ++static int uvc_libconfig_import(struct usbg_function *f, config_setting_t *root) > ++{ > ++ return USBG_SUCCESS; > ++} > ++ > ++static int uvc_libconfig_export(struct usbg_function *f, config_setting_t *root) > ++{ > ++ return USBG_SUCCESS; > ++} > ++ > ++static int uvc_create_dir(const char *path) > ++{ > ++ char tmp[USBG_MAX_PATH_LENGTH]; > ++ char *p = NULL; > ++ size_t len; > ++ int nmb, ret = USBG_SUCCESS; > ++ > ++ nmb = snprintf(tmp, sizeof(tmp), "%s", path); > ++ if(nmb >= sizeof(tmp)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ len = strlen(tmp); > ++ if(tmp[len - 1] == '/') > ++ tmp[len - 1] = 0; > ++ > ++ for (p = tmp + 1; *p; p++) { > ++ if(*p == '/') { > ++ *p = 0; > ++ if((mkdir(tmp, S_IRWXU | S_IRWXG | S_IRWXO) != 0) && errno != EEXIST) { > ++ ret = usbg_translate_error(errno); > ++ break; > ++ } > ++ *p = '/'; > ++ } > ++ } > ++ if(ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ if((mkdir(tmp, S_IRWXU | S_IRWXG | S_IRWXO) != 0) && errno != EEXIST) > ++ return usbg_translate_error(errno); > ++} > ++ > ++static int uvc_link(char *path, char *to, char *from) > ++{ > ++ char oldname[USBG_MAX_PATH_LENGTH]; > ++ char newname[USBG_MAX_PATH_LENGTH]; > ++ int nmb; > ++ > ++ nmb = snprintf(oldname, sizeof(oldname), "%s/%s", path, to); > ++ if (nmb >= sizeof(oldname)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ nmb = snprintf(newname, sizeof(newname), "%s/%s", path, from); > ++ if (nmb >= sizeof(newname)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ if(symlink(oldname, newname)) > ++ return usbg_translate_error(errno); > ++} > ++ > ++static int uvc_set_class(char *func_path, char *cs) > ++{ > ++ int ret, nmb; > ++ char path[USBG_MAX_PATH_LENGTH]; > ++ char header_path[USBG_MAX_PATH_LENGTH]; > ++ > ++ nmb = snprintf(path, sizeof(path), "%s/%s", func_path, cs); > ++ if (nmb >= sizeof(path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ nmb = snprintf(header_path, sizeof(header_path), "%s/" UVC_PATH_HEADER, path); > ++ if (nmb >= sizeof(header_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ ret = uvc_create_dir(header_path); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ if (!strncmp(cs, UVC_PATH_STREAMING, strlen(UVC_PATH_STREAMING))) { > ++ char check_path[USBG_MAX_PATH_LENGTH]; > ++ struct stat buffer; > ++ > ++ nmb = snprintf(check_path, sizeof(check_path), "%s/" UVC_PATH_STREAMING_UNCOMPRESSED, path); > ++ if (nmb >= sizeof(check_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ ret = stat(check_path, &buffer); > ++ if (!ret) { > ++ ret = uvc_link(path, UVC_PATH_STREAMING_UNCOMPRESSED, "header/h/u"); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ } > ++ > ++ nmb = snprintf(check_path, sizeof(check_path), "%s/" UVC_PATH_STREAMING_MJPEG, path); > ++ if (nmb >= sizeof(check_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ ret = stat(check_path, &buffer); > ++ if (!ret) { > ++ ret = uvc_link(path, UVC_PATH_STREAMING_MJPEG, "header/h/m"); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ } > ++ > ++ ret = uvc_link(path, UVC_PATH_HEADER, UVC_PATH_CLASS_HS); > ++ if (ret) > ++ return ret; > ++ } > ++ > ++ ret = uvc_link(path, UVC_PATH_HEADER, UVC_PATH_CLASS_FS); > ++ if (ret) > ++ return ret; > ++ > ++ return uvc_link(path, UVC_PATH_HEADER, UVC_PATH_CLASS_SS); > ++} > ++ > ++static int uvc_set_frame(char *format_path, char *format, const struct usbg_f_uvc_format_attrs *attrs) > ++{ > ++ int nmb, ret, i; > ++ char frame_path[USBG_MAX_PATH_LENGTH]; > ++ char full_frame_path[USBG_MAX_PATH_LENGTH]; > ++ char frame_interval[USBG_MAX_PATH_LENGTH]; > ++ char frame_name[32]; > ++ > ++ nmb = snprintf(frame_name, sizeof(frame_name), "%dp", attrs->height); > ++ if (nmb >= sizeof(frame_name)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ nmb = snprintf(frame_path, sizeof(frame_path), "%s/%s", format_path, format); > ++ if (nmb >= sizeof(frame_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ nmb = snprintf(full_frame_path, sizeof(frame_path), "%s/%s", frame_path, frame_name); > ++ if (nmb >= sizeof(full_frame_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ ret = uvc_create_dir(full_frame_path); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ ret = usbg_write_string(frame_path, frame_name, "dwFrameInterval", attrs->dwFrameInterval); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ ret = usbg_write_dec(frame_path, frame_name, "wHeight", attrs->height); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ return usbg_write_dec(frame_path, frame_name, "wWidth", attrs->width); > ++} > ++ > ++static int uvc_set_streaming(char *func_path, const struct usbg_f_uvc_format_attrs *attrs) > ++{ > ++ char streaming_path[USBG_MAX_PATH_LENGTH]; > ++ int ret, nmb; > ++ > ++ nmb = snprintf(streaming_path, sizeof(streaming_path), "%s/" UVC_PATH_STREAMING, func_path); > ++ if (nmb >= sizeof(streaming_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ if (attrs->format == UVC_FORMAT_UNCOMPRESSED) > ++ ret = uvc_set_frame(streaming_path, UVC_PATH_STREAMING_UNCOMPRESSED, attrs); > ++ else > ++ ret = uvc_set_frame(streaming_path, UVC_PATH_STREAMING_MJPEG, attrs); > ++ > ++ return ret; > ++} > ++ > ++static int dir_nftw_cb(const char *pathname, const struct stat *sbuf, int type, struct FTW *ftwb) > ++{ > ++ (void) sbuf; > ++ (void) type; > ++ (void) ftwb; > ++ int ret; > ++ > ++ ret = remove(pathname); > ++ if (ret < -1) > ++ ERROR("failed to remove %s - %s", pathname, strerror(ret)); > ++ > ++ return 0; > ++} > ++ > ++int remove_dir(const char *dirpath) > ++{ > ++ const int max_open_descs = 8; > ++ int ret; > ++ > ++ ret = nftw(dirpath, dir_nftw_cb, max_open_descs, FTW_DEPTH | FTW_MOUNT | FTW_PHYS); > ++ if (ret < 0) { > ++ ERROR("nftw failed"); > ++ return ret; > ++ } > ++ > ++ return 0; > ++} > ++ > ++static int content_nftw_cb(const char *pathname, const struct stat *sbuf, int type, struct FTW *ftwb) > ++{ > ++ (void) sbuf; > ++ (void) type; > ++ (void) ftwb; > ++ int ret; > ++ > ++ if(ftwb->level == 0) > ++ return 0; > ++ > ++ ret = remove(pathname); > ++ if(ret < -1) > ++ ERROR("failed to remove %s - %s", pathname, strerror(ret)); > ++ > ++ return 0; > ++} > ++ > ++int remove_dir_content(const char *dirpath) > ++{ > ++ const int max_open_descs = 8; > ++ int ret; > ++ > ++ /* traverse in reverse order (handle directory after it's content), stay within the same file system and do not follow symbolic links */ > ++ ret = nftw(dirpath, content_nftw_cb, max_open_descs, FTW_DEPTH | FTW_MOUNT | FTW_PHYS); > ++ if (ret < 0) { > ++ ERROR("nftw failed"); > ++ return ret; > ++ } > ++ > ++ return 0; > ++} > ++ > ++static int uvc_remove(struct usbg_function *f, int opts) > ++{ > ++ usbg_f_uvc *uvcf = usbg_to_uvc_function(f); > ++ char streaming_path[USBG_MAX_PATH_LENGTH]; > ++ char control_path[USBG_MAX_PATH_LENGTH]; > ++ char path[USBG_UVC_MAX_PATH_LENGTH]; > ++ int nmb, ret = USBG_SUCCESS; > ++ > ++ nmb = snprintf(path, sizeof(path), "%s/%s", uvcf->func.path, uvcf->func.name); > ++ if (nmb >= sizeof(path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ nmb = snprintf(streaming_path, sizeof(streaming_path), "%s/streaming", path); > ++ if (nmb >= sizeof(streaming_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ nmb = snprintf(control_path, sizeof(control_path), "%s/control", path); > ++ if (nmb >= sizeof(control_path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ if(remove_dir_content(streaming_path) < 0) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ if(remove_dir_content(control_path) < 0) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ if(remove_dir(streaming_path) < 0) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ if(remove_dir(control_path) < 0) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ return 0; > ++}; > ++ > ++struct usbg_function_type usbg_f_type_uvc = { > ++ .name = "uvc", > ++ .alloc_inst = uvc_alloc_inst, > ++ .free_inst = uvc_free_inst, > ++ .set_attrs = uvc_set_attrs, > ++ .get_attrs = uvc_get_attrs, > ++ .cleanup_attrs = uvc_cleanup_attrs, > ++ .import = uvc_libconfig_import, > ++ .export = uvc_libconfig_export, > ++ .remove = uvc_remove, > ++}; > ++ > ++/* API implementation */ > ++ > ++usbg_f_uvc *usbg_to_uvc_function(usbg_function *f) > ++{ > ++ return f->ops == &usbg_f_type_uvc ? > ++ container_of(f, struct usbg_f_uvc, func) : NULL; > ++} > ++ > ++usbg_function *usbg_from_uvc_function(usbg_f_uvc *ff) > ++{ > ++ return &ff->func; > ++} > ++ > ++int usbg_f_uvc_get_attrs(usbg_f_uvc *uvcf, struct usbg_f_uvc_attrs *attrs) > ++{ > ++ return USBG_SUCCESS; > ++} > ++ > ++int usbg_f_uvc_set_attrs(usbg_f_uvc *uvcf, const struct usbg_f_uvc_attrs *attrs) > ++{ > ++ int nmb, ret = USBG_SUCCESS; > ++ char path[USBG_UVC_MAX_PATH_LENGTH]; > ++ struct usbg_f_uvc_format_attrs **format_attrs; > ++ int i; > ++ > ++ nmb = snprintf(path, sizeof(path), "%s/%s", uvcf->func.path, uvcf->func.name); > ++ if (nmb >= sizeof(path)) > ++ return USBG_ERROR_PATH_TOO_LONG; > ++ > ++ for(format_attrs = attrs->formats, i = 0; format_attrs[i]; ++i) { > ++ ret = uvc_set_streaming(path, format_attrs[i]); > ++ if(ret != USBG_SUCCESS) > ++ ERROR("Error: %d", ret); > ++ } > ++ > ++ ret = uvc_set_class(path, "control"); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ ret = uvc_set_class(path, "streaming"); > ++ if (ret != USBG_SUCCESS) > ++ return ret; > ++ > ++ return ret; > ++} > +diff --git a/src/usbg.c b/src/usbg.c > +index d2bf38160358..b298ddc50ecf 100644 > +--- a/src/usbg.c > ++++ b/src/usbg.c > +@@ -52,6 +52,7 @@ extern struct usbg_function_type usbg_f_type_phonet; > + extern struct usbg_function_type usbg_f_type_loopback; > + extern struct usbg_function_type usbg_f_type_hid; > + extern struct usbg_function_type usbg_f_type_uac2; > ++extern struct usbg_function_type usbg_f_type_uvc; > + > + /** > + * @var function_types > +@@ -73,6 +74,7 @@ struct usbg_function_type* function_types[] = { > + [USBG_F_LOOPBACK] = &usbg_f_type_loopback, > + [USBG_F_HID] = &usbg_f_type_hid, > + [USBG_F_UAC2] = &usbg_f_type_uac2, > ++ [USBG_F_UVC] = &usbg_f_type_uvc, > + }; > + > + ARRAY_SIZE_SENTINEL(function_types, USBG_FUNCTION_TYPE_MAX); > diff --git a/patches/libusbgx-0.2.0/autogen.sh b/patches/libusbgx-0.2.0/autogen.sh > new file mode 100755 > index 000000000000..2459647bfd3f > --- /dev/null > +++ b/patches/libusbgx-0.2.0/autogen.sh > @@ -0,0 +1,16 @@ > +#!/bin/bash > + > +set -e > + > +aclocal $ACLOCAL_FLAGS > + > +libtoolize \ > + --force \ > + --copy > + > +autoreconf \ > + --force \ > + --install \ > + --warnings=syntax \ > + --warnings=obsolete \ > + --warnings=unsupported > diff --git a/patches/libusbgx-0.2.0/series b/patches/libusbgx-0.2.0/series > new file mode 100644 > index 000000000000..406d15accf05 > --- /dev/null > +++ b/patches/libusbgx-0.2.0/series > @@ -0,0 +1,7 @@ > +# generated by git-ptx-patches > +#tag:base --start-number 1 > +0001-Fix-39-Compilation-fails-on-gcc-v8.patch > +0002-libusbgx-fix-build-with-glibc-2.28-since-sys-sysmacr.patch > +0003-examples-gadget-vid-pid-remove-add-dynamic-vid-pid-s.patch > +0004-libusbgx-Add-UVC-support.patch > +# 55b4c63ca7f6b97ceb9cd9588e1eacdd - git-ptx-patches magic > diff --git a/rules/libusbgx.in b/rules/libusbgx.in > new file mode 100644 > index 000000000000..98776c02660e > --- /dev/null > +++ b/rules/libusbgx.in > @@ -0,0 +1,8 @@ > +## SECTION=communication > + > +config LIBUSBGX > + bool > + prompt "libusbgx" > + help > + libusbgx is a C library encapsulating the kernel USB gadget-configfs > + userspace API functionality. > diff --git a/rules/libusbgx.make b/rules/libusbgx.make > new file mode 100644 > index 000000000000..6c8fce429c34 > --- /dev/null > +++ b/rules/libusbgx.make > @@ -0,0 +1,66 @@ > +# -*-makefile-*- > +# > +# Copyright (C) 2018 by Thomas Haemmerle > +# > +# See CREDITS for details about who has contributed to this project. > +# > +# For further information about the PTXdist project and license conditions > +# see the README file. > +# > + > +# > +# We provide this package > +# > +PACKAGES-$(PTXCONF_LIBUSBGX) += libusbgx > + > +# > +# Paths and names > +# > +LIBUSBGX_VERSION := 0.2.0 > +LIBUSBGX_MD5 := a8ea2234c6355ac8ad2ca86c453297bd > +LIBUSBGX := libusbgx-$(LIBUSBGX_VERSION) > +LIBUSBGX_SUFFIX := zip > +LIBUSBGX_URL := \ > + https://github.com/libusbgx/libusbgx/archive/libusbgx-v$(LIBUSBGX_VERSION).zip > +LIBUSBGX_SOURCE := \ > + $(SRCDIR)/$(LIBUSBGX).$(LIBUSBGX_SUFFIX) > +LIBUSBGX_DIR := $(BUILDDIR)/$(LIBUSBGX) > +LIBUSBGX_LICENSE := GPLv2 > + > +# ---------------------------------------------------------------------------- > +# Prepare > +# ---------------------------------------------------------------------------- > + > +LIBUSBGX_CONF_ENV := $(CROSS_ENV) > + > +# > +# autoconf > +# > +LIBUSBGX_CONF_TOOL := autoconf > +LIBUSBGX_CONF_OPT := \ > + $(CROSS_AUTOCONF_USR) \ > + --without-libconfig \ > + --enable-examples \ > + --disable-gadget-schemes > + > +# ---------------------------------------------------------------------------- > +# Target-Install > +# ---------------------------------------------------------------------------- > + > +$(STATEDIR)/libusbgx.targetinstall: > + @$(call targetinfo) > + > + @$(call install_init, libusbgx) > + @$(call install_fixup, libusbgx, PRIORITY, optional) > + @$(call install_fixup, libusbgx, SECTION, base) > + @$(call install_fixup, libusbgx, AUTHOR, "Thomas Haemmerle ") > + @$(call install_fixup, libusbgx, DESCRIPTION, missing) > + > + @$(call install_lib, libusbgx, 0, 0, 0644, libusbgx) > + @$(call install_tree, libusbgx, 0, 0, -, /usr/bin) > + > + @$(call install_finish, libusbgx) > + > + @$(call touch) > + > +# vim: syntax=make _______________________________________________ ptxdist mailing list ptxdist@pengutronix.de To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de