Posts: 13
Joined: Fri Feb 06, 2015 12:25 pm

USB gadget using libcomposite

Thu May 23, 2019 12:41 am

I want to create USB gadget with ethernet, serial and keyboard, I have the following code, but it is not working, usb0 is created, but it is down without any connection, the keyboard does not work, but the device hidg0 is present.

Could you point to me any errors?

Code: Select all

#!/bin/bash -e

set -x
#set -euo pipefail

LANGUAGE="0x409" # English

SERIAL="$(grep Serial /proc/cpuinfo | sed 's/Serial\s*: 0000\(\w*\)/\1/')"
MAC="$(echo ${SERIAL} | sed 's/\(\w\w\)/:\1/g' | cut -b 2-)"
MAC_HOST="12$(echo ${MAC} | cut -b 3-)"
MAC_DEV="02$(echo ${MAC} | cut -b 3-)"

if [[ $EUID -ne 0 ]]; then
	echo "This script must be run as root"
	exit 1

if [ ! -d $CONFIGFS ]; then
	modprobe libcomposite

# Enter ConfigFS

# Cleaning
#echo "Cleaning up existing gadget"
#echo "Stopping getty"
#systemctl stop [email protected]
#echo "Removing config-level functions"
find ./$GADGET_NAME/configs/*/* -maxdepth 0 -type l -exec rm {} \; || true
#echo "Removing config-level strings"
find ./$GADGET_NAME/configs/*/strings/* -maxdepth 0 -type d -exec rmdir {} \; || true
#echo "Removing config-level OS descriptors"
find ./$GADGET_NAME/os_desc/* -maxdepth 0 -type l -exec rm {} \; || true
#echo "Removing gadget-level functions"
find ./$GADGET_NAME/functions/* -maxdepth 0 -type d -exec rmdir {} \; || true
#echo "Removing gadget-level strings"
find ./$GADGET_NAME/strings/* -maxdepth 0 -type d -exec rmdir {} \; || true
#echo "Removing gadget-level configs"
find ./$GADGET_NAME/configs/* -maxdepth 0 -type d -exec rmdir {} \; || true
#echo "Removing gadget"
rmdir ./$GADGET_NAME || true
#echo "Starting getty"
#systemctl start [email protected]

mkdir ./$GADGET_NAME && cd ./$GADGET_NAME

# Basic info

echo $ID_VENDOR 	> idVendor  # Linux Foundation
echo $ID_PRODUCT 	> idProduct # Multifunction Composite Gadget
echo 0x0100 		> bcdDevice # v1.0.0
echo 0x0200 		> bcdUSB    # USB 2.0

#echo "Configuring gadget as composite device"
# https://msdn.microsoft.com/en-us/library/windows/hardware/ff540054(v=vs.85).aspx
echo 0xEF 		> bDeviceClass
echo 0x02 		> bDeviceSubClass
echo 0x01 		> bDeviceProtocol

#echo "Configuring OS descriptors"
# https://msdn.microsoft.com/en-us/library/hh881271.aspx
# OS descriptors
# WIndows extensions to force config
echo 1			> os_desc/use
echo 0xcd		> os_desc/b_vendor_code
echo MSFT100		> os_desc/qw_sign

mkdir -p strings/$LANGUAGE
echo "7777777" 		> strings/$LANGUAGE/serialnumber
echo "eXander"        	> strings/$LANGUAGE/manufacturer
echo "exander's Gadget"	> strings/$LANGUAGE/product

# Config #1 for OSX / Linux

mkdir -p configs/c.1/strings/$LANGUAGE
echo 250 		> configs/c.1/MaxPower
echo "Config 1"		> configs/c.1/strings/$LANGUAGE/configuration

mkdir -p functions/acm.usb0	# serial
mkdir -p functions/rndis.usb0	# network Flippin' Windows
#mkdir -p functions/ecm.usb0	# OSX / Linux
mkdir -p functions/hid.usb0	# keyboard

# https://msdn.microsoft.com/en-us/windows/hardware/gg463179.aspx
echo RNDIS		> functions/rndis.usb0/os_desc/interface.rndis/compatible_id
echo 5162001		> functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id

echo $MAC_HOST		> functions/rndis.usb0/host_addr
echo $MAC_DEV		> functions/rndis.usb0/dev_addr
#echo $MAC_HOST		> functions/ecm.usb0/host_addr
#echo $MAC_DEV		> functions/ecm.usb0/dev_addr

# Set up the rndis device only first

ln -s functions/rndis.usb0 configs/c.1

# Tell Windows to use config #2

ln -s configs/c.1 os_desc
#ln -s configs/c.1 os_desc/c.1

# Show Windows the RNDIS device with
# bDeviceClass 0x02
# bDeviceSubClass 0x02

ls /sys/class/udc/	> UDC

# Give it time to install

sleep 5

# Yank it back

echo ""			> UDC

# Setup keyboard
echo 1			> functions/hid.usb0/protocol
echo 1			> functions/hid.usb0/subclass
echo 8			> functions/hid.usb0/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc

ln -s functions/acm.usb0 configs/c.1/
#ln -s functions/ecm.usb0 configs/c.1/
ln -s functions/hid.usb0 configs/c.1/

# Reset bDeviceClass to 0x00
# This is essential to make it work in Windows 10
# Basically forces it to use device information
# in the descriptors versus assuming a particular class.

echo "0x00"		> bDeviceClass

# Re-attach the gadget
udevadm settle -t 5 || :
ls /sys/class/udc/	> UDC


User avatar
Posts: 1464
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: USB gadget using libcomposite

Thu May 23, 2019 12:55 pm

What model Pi are you using?

What are you using for a USB host? What USB devices does it show? Has it installed all the necessary drivers?

What are you expecting to happen?

You need to send data via the hidg0 node for anything to happen. It's an outgoing connection not an incoming one (with a few exceptions).

I have some working USB HID gagdet code on github: https://github.com/thagrol/pwdgen
Note to self: don't feed the trolls

If I've asked you a question, please answer it. I'm unlikely to be able to help without that information.

Return to “Advanced users”