summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Grzeschik <m.grzeschik@pengutronix.de>2021-04-29 01:24:10 +0200
committerMichael Olbrich <m.olbrich@pengutronix.de>2021-04-30 13:48:41 +0200
commit6677792614505262f62e8b0a5dfbe1df130ed633 (patch)
tree5b2285f03f7ee98935dae15def161cce271383c6
parente0e1674f4dc3265734dbe985b0aaf3ec5ee4bd04 (diff)
downloadptxdist-6677792614505262f62e8b0a5dfbe1df130ed633.tar.gz
ptxdist-6677792614505262f62e8b0a5dfbe1df130ed633.tar.xz
libusbgx: new package
This patch adds libusbgx support to ptxdist. It includes patches to work with uvc gadgets. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Message-Id: <20210428232410.15059-1-m.grzeschik@pengutronix.de> Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
-rw-r--r--patches/libusbgx-0.2.0/0001-Fix-39-Compilation-fails-on-gcc-v8.patch20
-rw-r--r--patches/libusbgx-0.2.0/0002-libusbgx-fix-build-with-glibc-2.28-since-sys-sysmacr.patch90
-rw-r--r--patches/libusbgx-0.2.0/0003-examples-gadget-vid-pid-remove-add-dynamic-vid-pid-s.patch67
-rw-r--r--patches/libusbgx-0.2.0/0004-libusbgx-Add-UVC-support.patch737
-rwxr-xr-xpatches/libusbgx-0.2.0/autogen.sh16
-rw-r--r--patches/libusbgx-0.2.0/series7
-rw-r--r--rules/libusbgx.in8
-rw-r--r--rules/libusbgx.make66
8 files changed, 1011 insertions, 0 deletions
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 000000000..4e7ff0ca4
--- /dev/null
+++ b/patches/libusbgx-0.2.0/0001-Fix-39-Compilation-fails-on-gcc-v8.patch
@@ -0,0 +1,20 @@
+From: Federico Fuga <fuga@studiofuga.com>
+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 <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <sys/sysmacros.h>
+
+ 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 000000000..9670d469a
--- /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 <gwenhael.goavec-merou@trabucayre.com>
+Date: Mon, 10 Sep 2018 15:52:09 +0200
+Subject: [PATCH] libusbgx: fix build with glibc-2.28 since <sys/sysmacros.h>
+ is no more included by <sys/types.h>
+
+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 <k.opasiak@samsung.com>
+---
+ 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 <errno.h>
+ #include <stdio.h>
++#include <sys/sysmacros.h>
+ #include <linux/usb/ch9.h>
+ #include <usbg/usbg.h>
+
+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 <errno.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <sys/sysmacros.h>
+ #include <usbg/usbg.h>
+
+ 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 <errno.h>
+ #include <stdio.h>
++#include <sys/sysmacros.h>
+ #include <linux/usb/ch9.h>
+ #include <usbg/usbg.h>
+ #include <usbg/function/ms.h>
+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 <errno.h>
+ #include <stdio.h>
+ #include <string.h>
++#include <sys/sysmacros.h>
+ #include <netinet/ether.h>
+ #include <usbg/usbg.h>
+ #include <usbg/function/ms.h>
+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 <errno.h>
+ #include <stdio.h>
++#include <sys/sysmacros.h>
+ #include <usbg/usbg.h>
+
+ 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 <sys/sysmacros.h>
+ #include <libconfig.h>
+ #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 000000000..63ddf347f
--- /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 <m.grzeschik@pengutronix.de>
+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 <m.grzeschik@pengutronix.de>
+---
+ 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 <errno.h>
+ #include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
+ #include <usbg/usbg.h>
+
+-#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 000000000..0217bb02d
--- /dev/null
+++ b/patches/libusbgx-0.2.0/0004-libusbgx-Add-UVC-support.patch
@@ -0,0 +1,737 @@
+From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
+Date: Wed, 8 Jan 2020 14:43:45 +0100
+Subject: [PATCH] libusbgx: Add UVC support
+
+Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+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 <mgr@pengutronix.de>
++ *
++ * 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 <sys/sysmacros.h>
++#include <linux/usb/ch9.h>
++#include <usbg/usbg.h>
++#include <usbg/function/uvc.h>
++
++/**
++ * @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 <usbg/usbg.h>
++
++#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 <errno.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <malloc.h>
++#include <ftw.h>
++#ifdef HAS_GADGET_SCHEMES
++#include <libconfig.h>
++#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 000000000..2459647bf
--- /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 000000000..406d15acc
--- /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 000000000..98776c026
--- /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 000000000..6c8fce429
--- /dev/null
+++ b/rules/libusbgx.make
@@ -0,0 +1,66 @@
+# -*-makefile-*-
+#
+# Copyright (C) 2018 by Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
+#
+# 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 <thomas.haemmerle@wolfvision.net>")
+ @$(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