diff mbox series

[OpenWrt-Devel] usbgadget: Add new package

Message ID 1548772235-6139-1-git-send-email-ynezz@true.cz
State Changes Requested
Headers show
Series [OpenWrt-Devel] usbgadget: Add new package | expand

Commit Message

Petr Štetiar Jan. 29, 2019, 2:30 p.m. UTC
This package allows easier configuration of USB gadgets via standard UCI
interface. So far only CDC/ACM has been implemented and tested.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
 package/utils/usbgadget/Makefile               | 33 ++++++++++
 package/utils/usbgadget/files/usbgadget.config | 21 ++++++
 package/utils/usbgadget/files/usbgadget.init   | 90 ++++++++++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 package/utils/usbgadget/Makefile
 create mode 100644 package/utils/usbgadget/files/usbgadget.config
 create mode 100644 package/utils/usbgadget/files/usbgadget.init

Comments

Karl Palsson Jan. 29, 2019, 3:42 p.m. UTC | #1
Does this work for providing a console on the ACM interface?

Petr Štetiar  <ynezz@true.cz> wrote:
> This package allows easier configuration of USB gadgets via
> standard UCI interface. So far only CDC/ACM has been
> implemented and tested.
> 
> Signed-off-by: Petr Štetiar <ynezz@true.cz>
Petr Štetiar Jan. 29, 2019, 4:16 p.m. UTC | #2
Karl Palsson <karlp@tweak.net.au> [2019-01-29 15:42:05]:

> Does this work for providing a console on the ACM interface?

I haven't had this use case in my mind, but I've just tested it, and I'm able
to get console access over ACM interface if I change kernel cmdline to
console=ttyGS0.

BTW I've tried to do it first in procd, by adding following line in inittab

  ttyGS0::askconsolelate:/usr/libexec/login.sh

but it didn't worked for me, even after changing script run order to
START=11, so it would probably need more tweaks.

-- ynezz
Michael Heimpold Feb. 2, 2019, 9:09 a.m. UTC | #3
Hi Petr,

Am Dienstag, 29. Januar 2019, 15:30:35 CET schrieb Petr Štetiar:
> This package allows easier configuration of USB gadgets via standard UCI
> interface. So far only CDC/ACM has been implemented and tested.
> 

thanks for working on this. A few idea inside...

> Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ---
>  package/utils/usbgadget/Makefile               | 33 ++++++++++
>  package/utils/usbgadget/files/usbgadget.config | 21 ++++++
>  package/utils/usbgadget/files/usbgadget.init   | 90
> ++++++++++++++++++++++++++ 3 files changed, 144 insertions(+)
>  create mode 100644 package/utils/usbgadget/Makefile
>  create mode 100644 package/utils/usbgadget/files/usbgadget.config
>  create mode 100644 package/utils/usbgadget/files/usbgadget.init
> 
> diff --git a/package/utils/usbgadget/Makefile
> b/package/utils/usbgadget/Makefile new file mode 100644
> index 0000000..e45bfe4
> --- /dev/null
> +++ b/package/utils/usbgadget/Makefile
> @@ -0,0 +1,33 @@
> +include $(TOPDIR)/rules.mk
> +
> +PKG_NAME:=usbgadget
> +PKG_RELEASE:=1
> +
> +include $(INCLUDE_DIR)/package.mk
> +
> +define Package/usbgadget
> +  SECTION:=utils
> +  CATEGORY:=Utilities
> +  TITLE:=Utility for USB gadgets configuration
> +endef
> +
> +define Package/usbgadget/conffiles
> +/etc/config/usbgadget
> +endef
> +
> +define Package/usbgadget/description
> + This package contains a small script which could be used for
> + configuration of USB gadgets over configfs kernel interface.
> +endef
> +
> +define Build/Compile
> +endef
> +
> +define Package/usbgadget/install
> +	$(INSTALL_DIR) $(1)/etc/init.d
> +	$(INSTALL_DIR) $(1)/etc/config
> +	$(INSTALL_BIN) ./files/usbgadget.init $(1)/etc/init.d/usbgadget
> +	$(INSTALL_DATA) ./files/usbgadget.config $(1)/etc/config/usbgadget
> +endef
> +
> +$(eval $(call BuildPackage,usbgadget))
> diff --git a/package/utils/usbgadget/files/usbgadget.config
> b/package/utils/usbgadget/files/usbgadget.config new file mode 100644
> index 0000000..65f6b5c
> --- /dev/null
> +++ b/package/utils/usbgadget/files/usbgadget.config
> @@ -0,0 +1,21 @@
> +config gadget
> +	option type 'acm'
> +	option name 'gadget-acm'
> +	option manufacturer 'OpenWrt'
> +	option product 'OpenWrt USB CDC/ACM'
I think we could use defaults from /etc/device_info file in case
manufacturer and product are not set in config. This allow overriding the 
values by user and have sane defaults.

> +	option serial_number '007'

Here too, I think we should provide a hook in the script to obtain a serial
e.g. from U-Boot environment by default, or from a OTP register or so, but
allow overriding it by user.

> +	option usb_vid '0xbeef'
> +	option usb_pid '0x1234'
I would use Linux' Foundation defaults so that drivers on the USB host side
can match (in case the functions classes are not used, I admit that I'm not
really sure about this because I tested only Linux USB host systems so far.)

> +	option udc_dev 'ci_hdrc.0'
> +	option disabled 1
> +
> +config gadget
> +	option type 'acm+rndis'
> +	option name 'gadget-acm-rndis'
> +	option manufacturer 'OpenWrt'
> +	option product 'OpenWrt USB CDC/ACM+RNDIS'
> +	option serial_number '009'
> +	option usb_vid '0xbeef'
> +	option usb_pid '0x9abc'
> +	option udc_dev 'ci_hdrc.0'
> +	option disabled 1

I would prefer to have "config gadget <a-gadget-name>" to configure one
(multi-function) gadget and then have individual "config function <...>" 
section to configure one function for a referenced gadget.
I think the functions are orthogonal and thus "acm+rndis" looks like 
wrong approach for me.
I know this will make the init script much more complicated.

Regards, Michael


> diff --git a/package/utils/usbgadget/files/usbgadget.init
> b/package/utils/usbgadget/files/usbgadget.init new file mode 100644
> index 0000000..b49b6f3
> --- /dev/null
> +++ b/package/utils/usbgadget/files/usbgadget.init
> @@ -0,0 +1,90 @@
> +#!/bin/sh /etc/rc.common
> +
> +START=97
> +
> +load_gadget() {
> +	local name
> +	local type
> +	local manufacturer
> +	local product
> +	local serial_number
> +	local usb_vid
> +	local usb_pid
> +	local udc_dev
> +	local disabled
> +
> +	config_get disabled $1 disabled
> +	[ "$disabled" = "1" ] && return
> +
> +	config_get usb_vid $1 usb_vid
> +	config_get usb_pid $1 usb_pid
> +	config_get udc_dev $1 udc_dev
> +	[ -z "$usb_vid" -o -z "$usb_pid" -o -z "$udc_dev" ] && return
> +
> +	config_get type $1 type "acm"
> +	config_get name $1 name "${usb_vid}-acm"
> +	config_get manufacturer $1 manufacturer "OpenWrt"
> +	config_get product $1 product "OpenWrt USB ${type}"
> +	config_get serial_number $1 serial_number "1922"
> +
> +	local path="/sys/kernel/config/usb_gadget/$name"
> +	mkdir -p "$path"
> +	echo "$usb_vid" > "$path/idVendor"
> +	echo "$usb_pid" > "$path/idProduct"
> +
> +	local strings="$path/strings/0x409"
> +	mkdir -p "$strings"
> +	echo "$product" > "$strings/product"
> +	echo "$manufacturer" > "$strings/manufacturer"
> +	echo "$serial_number" > "$strings/serialnumber"
> +
> +	mkdir -p "$path/configs/$name.1"
> +
> +	case "$type" in
> +	"acm")
> +		mkdir -p "$path/functions/acm.0"
> +		ln -sf "$path/functions/acm.0" "$path/configs/$name.1"
> +		;;
> +	"acm+rndis")
> +		mkdir -p "$path/functions/acm.0"
> +		mkdir -p "$path/functions/rndis.0"
> +		ln -sf "$path/functions/acm.0" "$path/configs/$name.1"
> +		ln -sf "$path/functions/rndis.0" "$path/configs/$name.1"
> +		;;
> +	esac
> +
> +	echo "$udc_dev" > "$path/UDC"
> +}
> +
> +unload_gadget() {
> +	local name
> +	local usb_vid
> +	local udc_dev
> +	local disabled
> +
> +	config_get disabled $1 disabled
> +	[ "$disabled" = "1" ] && return
> +
> +	config_get usb_vid $1 usb_vid
> +	config_get udc_dev $1 udc_dev
> +	[ -z "$usb_vid" -o -z "$udc_dev" ] && return
> +
> +	config_get name $1 name "${usb_vid}-acm"
> +	[ -d "/sys/kernel/config/usb_gadget/$name" ] || return
> +	echo '' > "/sys/kernel/config/usb_gadget/$name/UDC" > /dev/null
> +}
> +
> +stop() {
> +	[ -e /sys/kernel/config/usb_gadget ] || exit 0
> +	config_load usbgadget
> +	config_foreach unload_gadget gadget
> +}
> +
> +start() {
> +	grep -q configfs /proc/modules || exit 0
> +	grep -q configfs /proc/mounts || mount -t configfs none /sys/kernel/config
> +	[ -e /sys/kernel/config/usb_gadget ] || exit 0
> +
> +	config_load usbgadget
> +	config_foreach load_gadget gadget
> +}
Petr Štetiar Feb. 5, 2019, 5:39 p.m. UTC | #4
Michael Heimpold <mhei@heimpold.de> [2019-02-02 10:09:40]:

Hi,

> I would prefer to have "config gadget <a-gadget-name>" to configure one
> (multi-function) gadget and then have individual "config function <...>"
> section to configure one function for a referenced gadget.  I think the
> functions are orthogonal and thus "acm+rndis" looks like wrong approach for
> me.

I'm not sure I follow, please can you provide example configs? Thanks.

-- ynezz
Michael Heimpold Feb. 5, 2019, 9:59 p.m. UTC | #5
Hi,

Am Dienstag, 5. Februar 2019, 18:39:55 CET schrieb Petr Štetiar:
> Michael Heimpold <mhei@heimpold.de> [2019-02-02 10:09:40]:
> 
> Hi,
> 
> > I would prefer to have "config gadget <a-gadget-name>" to configure one
> > (multi-function) gadget and then have individual "config function <...>"
> > section to configure one function for a referenced gadget.  I think the
> > functions are orthogonal and thus "acm+rndis" looks like wrong approach
> > for
> > me.
> 
> I'm not sure I follow, please can you provide example configs? Thanks.

I hope the following will illustrate my idea (it should just show the idea,
no deeper sense):
I assume a CPU with two USB device ports, e.g. ci_hdrc.0 and ci_hdrc.1.
On ci_hdrc.0 a gadget with serial console and network is configured, on
ci_hdrc.1 a CD-ROM and a camera.

config gadget gadget1
    option manufacturer 'OpenWrt'
    option product 'OpenWrt USB CDC/ACM'
    option serial_number '007'
    option usb_vid '0xbeef'
    option usb_pid '0x1234'
    option udc_dev 'ci_hdrc.0'
    option disabled 0

config configuration config1
    option gadget gadget1
    option maxpower 120

config function console1
    option gadget gadget1
    option type 'acm'
    option disabled 0

config function network1
    option gadget gadget1          
    option type 'rndis'
    option host_addr 00:01:02:04:05:06
    option dev_addr 00:01:02:04:05:07
    option disabled 0

config gadget gadget2
    option manufacturer 'OpenWrt'
    option product 'OpenWrt USB CDC/ACM'
    option serial_number '007'
    option usb_vid '0xbeef'
    option usb_pid '0x1235'
    option udc_dev 'ci_hdrc.1'
    option disabled 0

config function msd
    option gadget gadget2
    option type 'mass_storage'
    option file '/path/to/backing/file'
    option removable 1
    option cdrom 1
    option disabled 0

config function network
    option gadget gadget2
    option type 'uvc'
    option disabled 1

Cheers,
mhei
diff mbox series

Patch

diff --git a/package/utils/usbgadget/Makefile b/package/utils/usbgadget/Makefile
new file mode 100644
index 0000000..e45bfe4
--- /dev/null
+++ b/package/utils/usbgadget/Makefile
@@ -0,0 +1,33 @@ 
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=usbgadget
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/usbgadget
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Utility for USB gadgets configuration
+endef
+
+define Package/usbgadget/conffiles
+/etc/config/usbgadget
+endef
+
+define Package/usbgadget/description
+ This package contains a small script which could be used for
+ configuration of USB gadgets over configfs kernel interface.
+endef
+
+define Build/Compile
+endef
+
+define Package/usbgadget/install
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_DIR) $(1)/etc/config
+	$(INSTALL_BIN) ./files/usbgadget.init $(1)/etc/init.d/usbgadget
+	$(INSTALL_DATA) ./files/usbgadget.config $(1)/etc/config/usbgadget
+endef
+
+$(eval $(call BuildPackage,usbgadget))
diff --git a/package/utils/usbgadget/files/usbgadget.config b/package/utils/usbgadget/files/usbgadget.config
new file mode 100644
index 0000000..65f6b5c
--- /dev/null
+++ b/package/utils/usbgadget/files/usbgadget.config
@@ -0,0 +1,21 @@ 
+config gadget
+	option type 'acm'
+	option name 'gadget-acm'
+	option manufacturer 'OpenWrt'
+	option product 'OpenWrt USB CDC/ACM'
+	option serial_number '007'
+	option usb_vid '0xbeef'
+	option usb_pid '0x1234'
+	option udc_dev 'ci_hdrc.0'
+	option disabled 1
+
+config gadget
+	option type 'acm+rndis'
+	option name 'gadget-acm-rndis'
+	option manufacturer 'OpenWrt'
+	option product 'OpenWrt USB CDC/ACM+RNDIS'
+	option serial_number '009'
+	option usb_vid '0xbeef'
+	option usb_pid '0x9abc'
+	option udc_dev 'ci_hdrc.0'
+	option disabled 1
diff --git a/package/utils/usbgadget/files/usbgadget.init b/package/utils/usbgadget/files/usbgadget.init
new file mode 100644
index 0000000..b49b6f3
--- /dev/null
+++ b/package/utils/usbgadget/files/usbgadget.init
@@ -0,0 +1,90 @@ 
+#!/bin/sh /etc/rc.common
+
+START=97
+
+load_gadget() {
+	local name
+	local type
+	local manufacturer
+	local product
+	local serial_number
+	local usb_vid
+	local usb_pid
+	local udc_dev
+	local disabled
+
+	config_get disabled $1 disabled
+	[ "$disabled" = "1" ] && return
+
+	config_get usb_vid $1 usb_vid
+	config_get usb_pid $1 usb_pid
+	config_get udc_dev $1 udc_dev
+	[ -z "$usb_vid" -o -z "$usb_pid" -o -z "$udc_dev" ] && return
+
+	config_get type $1 type "acm"
+	config_get name $1 name "${usb_vid}-acm"
+	config_get manufacturer $1 manufacturer "OpenWrt"
+	config_get product $1 product "OpenWrt USB ${type}"
+	config_get serial_number $1 serial_number "1922"
+
+	local path="/sys/kernel/config/usb_gadget/$name"
+	mkdir -p "$path"
+	echo "$usb_vid" > "$path/idVendor"
+	echo "$usb_pid" > "$path/idProduct"
+
+	local strings="$path/strings/0x409"
+	mkdir -p "$strings"
+	echo "$product" > "$strings/product"
+	echo "$manufacturer" > "$strings/manufacturer"
+	echo "$serial_number" > "$strings/serialnumber"
+
+	mkdir -p "$path/configs/$name.1"
+
+	case "$type" in
+	"acm")
+		mkdir -p "$path/functions/acm.0"
+		ln -sf "$path/functions/acm.0" "$path/configs/$name.1"
+		;;
+	"acm+rndis")
+		mkdir -p "$path/functions/acm.0"
+		mkdir -p "$path/functions/rndis.0"
+		ln -sf "$path/functions/acm.0" "$path/configs/$name.1"
+		ln -sf "$path/functions/rndis.0" "$path/configs/$name.1"
+		;;
+	esac
+
+	echo "$udc_dev" > "$path/UDC"
+}
+
+unload_gadget() {
+	local name
+	local usb_vid
+	local udc_dev
+	local disabled
+
+	config_get disabled $1 disabled
+	[ "$disabled" = "1" ] && return
+
+	config_get usb_vid $1 usb_vid
+	config_get udc_dev $1 udc_dev
+	[ -z "$usb_vid" -o -z "$udc_dev" ] && return
+
+	config_get name $1 name "${usb_vid}-acm"
+	[ -d "/sys/kernel/config/usb_gadget/$name" ] || return
+	echo '' > "/sys/kernel/config/usb_gadget/$name/UDC" > /dev/null
+}
+
+stop() {
+	[ -e /sys/kernel/config/usb_gadget ] || exit 0
+	config_load usbgadget
+	config_foreach unload_gadget gadget
+}
+
+start() {
+	grep -q configfs /proc/modules || exit 0
+	grep -q configfs /proc/mounts || mount -t configfs none /sys/kernel/config
+	[ -e /sys/kernel/config/usb_gadget ] || exit 0
+
+	config_load usbgadget
+	config_foreach load_gadget gadget
+}