This patch adds libusbgx support to ptxdist. It includes patches to work
with uvc gadgets.

Signed-off-by: Michael Grzeschik <m.grzesc...@pengutronix.de>
---

This patches are already mainline or already in a merge request of the project.

https://github.com/libusbgx/libusbgx/pull/54
https://github.com/libusbgx/libusbgx/pull/55

 ...1-Fix-39-Compilation-fails-on-gcc-v8.patch |  20 +
 ...ld-with-glibc-2.28-since-sys-sysmacr.patch |  90 +++
 ...vid-pid-remove-add-dynamic-vid-pid-s.patch |  67 ++
 .../0004-libusbgx-Add-UVC-support.patch       | 737 ++++++++++++++++++
 patches/libusbgx-0.2.0/autogen.sh             |  16 +
 patches/libusbgx-0.2.0/series                 |   7 +
 rules/libusbgx.in                             |   8 +
 rules/libusbgx.make                           |  66 ++
 8 files changed, 1011 insertions(+)
 create mode 100644 
patches/libusbgx-0.2.0/0001-Fix-39-Compilation-fails-on-gcc-v8.patch
 create mode 100644 
patches/libusbgx-0.2.0/0002-libusbgx-fix-build-with-glibc-2.28-since-sys-sysmacr.patch
 create mode 100644 
patches/libusbgx-0.2.0/0003-examples-gadget-vid-pid-remove-add-dynamic-vid-pid-s.patch
 create mode 100644 patches/libusbgx-0.2.0/0004-libusbgx-Add-UVC-support.patch
 create mode 100755 patches/libusbgx-0.2.0/autogen.sh
 create mode 100644 patches/libusbgx-0.2.0/series
 create mode 100644 rules/libusbgx.in
 create mode 100644 rules/libusbgx.make

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 <f...@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-me...@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 r03...@gmail.com
+Signed-off-by: Gwenhael Goavec-Merou gwenhael.goavec-me...@trabucayre.com
+[Copy sign-offs from pull requst to commit msg]
+Signed-off-by: Krzysztof Opasiak <k.opas...@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.grzesc...@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.grzesc...@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.haemme...@wolfvision.net>
+Date: Wed, 8 Jan 2020 14:43:45 +0100
+Subject: [PATCH] libusbgx: Add UVC support
+
+Signed-off-by: Thomas Haemmerle <thomas.haemme...@wolfvision.net>
+Signed-off-by: Michael Grzeschik <m.grzesc...@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 <m...@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.haemme...@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.haemme...@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
-- 
2.29.2


_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to 
ptxdist-requ...@pengutronix.de

Reply via email to