Skip to content

Commit

Permalink
Update USB gadget script to reflect bus-powered device requiring up t…
Browse files Browse the repository at this point in the history
…o 1A

- Changed `bmAttributes` to `0x80` to indicate the device is bus-powered.
- Updated `MaxPower` to `500` (units of 2 mA) to specify a power requirement of 1 amp.
- Added comments to clarify power source and requirements.
- Ensured script aligns with USB specifications for power negotiation.
- Maintained dual interface setup for CDC ECM (usb0) and RNDIS (usb1).
  • Loading branch information
jolla committed Dec 27, 2024
1 parent 63a4f57 commit fff70e4
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 81 deletions.
1 change: 1 addition & 0 deletions debian/install
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
etc/systemd/network/usb0.network etc/systemd/network/
etc/systemd/network/usb1.network etc/systemd/network/
etc/systemd/system/usb-gadget.service etc/systemd/system/
usr/bin/usb_otg_setup.sh usr/bin/

3 changes: 2 additions & 1 deletion etc/systemd/network/usb0.network
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ Scope=link

[Network]
DHCPServer=yes
LinkLocalAddressing=no
LinkLocalAddressing=yes
IPv6AcceptRA=no

[DHCPServer]
EmitRouter=no
EmitDNS=no
PoolSize=50
16 changes: 16 additions & 0 deletions etc/systemd/network/usb1.network
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Match]
Name=usb1

[Address]
Address=10.42.0.1/24
Scope=link

[Network]
DHCPServer=yes
LinkLocalAddressing=yes
IPv6AcceptRA=no

[DHCPServer]
EmitRouter=no
EmitDNS=no
PoolSize=50
182 changes: 102 additions & 80 deletions usr/bin/usb_otg_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,91 +3,113 @@
set -e
set -x

LOGFILE="/tmp/usb_gadget_setup.log"
LOGFILE="/tmp/usb_gadget_dual.log"
exec > >(tee -a "$LOGFILE") 2>&1

# Define gadget paths
# Constants
GADGET_DIR="/sys/kernel/config/usb_gadget/wlanpi"
UDC_PATH="/sys/class/udc"
USB_PRODUCT="WLAN Pi USB Ethernet"
MANUFACTURER="WLAN Pi"
CONFIG_POWER="500" # Max power in units of 2 mA (500 = 1 A)
CONFIG_ATTRIBUTES="0x80" # Bus-powered

# Helper Functions
cleanup_gadget() {
if [ -d "$GADGET_DIR" ]; then
echo "Cleaning up existing gadget configuration..."
echo "" > "$GADGET_DIR/UDC" || true
sleep 1
rm -rf "$GADGET_DIR"
fi
}

generate_mac_addresses() {
local serial
serial=$(awk '/Serial/ {print substr($3,5)}' /proc/cpuinfo)
if [ -z "$serial" ]; then
echo "Error: Could not retrieve Raspberry Pi serial number."
exit 1
fi
local mac_base
mac_base=$(echo "${serial}" | sed 's/\(..\)/:\1/g' | cut -b 2-)
echo "02${mac_base}" "12${mac_base}"
}

create_device_strings() {
mkdir -p "$GADGET_DIR/strings/0x409"
echo "$MANUFACTURER" > "$GADGET_DIR/strings/0x409/manufacturer"
echo "$USB_PRODUCT" > "$GADGET_DIR/strings/0x409/product"
echo "$SERIAL" > "$GADGET_DIR/strings/0x409/serialnumber"
}

create_configuration() {
local config="$1"
local description="$2"
mkdir -p "$GADGET_DIR/configs/$config/strings/0x409"
echo "$description" > "$GADGET_DIR/configs/$config/strings/0x409/configuration"
echo "$CONFIG_ATTRIBUTES" > "$GADGET_DIR/configs/$config/bmAttributes"
echo "$CONFIG_POWER" > "$GADGET_DIR/configs/$config/MaxPower"
}

create_cdc_ecm_function() {
mkdir -p "$GADGET_DIR/functions/ecm.usb0"
echo "$MAC_HOST" > "$GADGET_DIR/functions/ecm.usb0/host_addr"
echo "$MAC_DEVICE" > "$GADGET_DIR/functions/ecm.usb0/dev_addr"
ln -s "$GADGET_DIR/functions/ecm.usb0" "$GADGET_DIR/configs/c.1/"
}

create_rndis_function() {
mkdir -p "$GADGET_DIR/functions/rndis.usb1"
echo "$MAC_HOST" > "$GADGET_DIR/functions/rndis.usb1/host_addr"
echo "$MAC_DEVICE" > "$GADGET_DIR/functions/rndis.usb1/dev_addr"
mkdir -p "$GADGET_DIR/functions/rndis.usb1/os_desc/interface.rndis"
echo "RNDIS" > "$GADGET_DIR/functions/rndis.usb1/os_desc/interface.rndis/compatible_id"
echo "5162001" > "$GADGET_DIR/functions/rndis.usb1/os_desc/interface.rndis/sub_compatible_id"
ln -s "$GADGET_DIR/functions/rndis.usb1" "$GADGET_DIR/configs/c.2/"
}

configure_os_descriptors() {
mkdir -p "$GADGET_DIR/os_desc"
echo 1 > "$GADGET_DIR/os_desc/use"
echo 0xcd > "$GADGET_DIR/os_desc/b_vendor_code"
echo "MSFT100" > "$GADGET_DIR/os_desc/qw_sign"
ln -s "$GADGET_DIR/configs/c.2" "$GADGET_DIR/os_desc"
}

bind_gadget_to_udc() {
udevadm settle -t 5 || true
local udc
udc=$(ls "$UDC_PATH" | head -n 1)
if [ -n "$udc" ]; then
echo "$udc" > "$GADGET_DIR/UDC"
else
echo "Error: No UDC device found."
exit 1
fi
}

# Check permissions
if [ ! -w "/sys/kernel/config" ]; then
echo "Error: /sys/kernel/config is not writable. Are you running as root?"
exit 1
fi

# Remove existing gadget configuration
if [ -d "$GADGET_DIR" ]; then
echo "Cleaning up existing gadget configuration..."
echo "" > "$GADGET_DIR/UDC" || true
rm -rf "$GADGET_DIR"
fi
# Main Script
cleanup_gadget
modprobe libcomposite

# Create new gadget
mkdir -p "$GADGET_DIR"
echo 0x1d6b > "$GADGET_DIR/idVendor" # Linux Foundation
echo 0x0104 > "$GADGET_DIR/idProduct" # Multifunction Composite Gadget
echo 0x0100 > "$GADGET_DIR/bcdDevice"
echo 0x0200 > "$GADGET_DIR/bcdUSB"

mkdir -p "$GADGET_DIR/strings/0x409"
echo "serialnumber123456" > "$GADGET_DIR/strings/0x409/serialnumber"
echo "WLAN Pi" > "$GADGET_DIR/strings/0x409/manufacturer"
echo "$USB_PRODUCT" > "$GADGET_DIR/strings/0x409/product"

# Add device descriptors for RNDIS compatibility
echo 0xEF > "$GADGET_DIR/bDeviceClass" # Miscellaneous Device
echo 0x02 > "$GADGET_DIR/bDeviceSubClass" # Common Class
echo 0x01 > "$GADGET_DIR/bDeviceProtocol" # Interface Association Descriptor

# Create configuration
mkdir -p "$GADGET_DIR/configs/c.1/strings/0x409"
echo "CDC and RNDIS" > "$GADGET_DIR/configs/c.1/strings/0x409/configuration"
echo 120 > "$GADGET_DIR/configs/c.1/MaxPower"

# Add ECM (Linux/macOS/iOS support)
mkdir -p "$GADGET_DIR/functions/ecm.usb0"
echo "02:01:02:03:04:08" > "$GADGET_DIR/functions/ecm.usb0/dev_addr"
echo "02:01:02:03:04:09" > "$GADGET_DIR/functions/ecm.usb0/host_addr"

# Add RNDIS (Windows support)
mkdir -p "$GADGET_DIR/functions/rndis.usb0"
mkdir -p "$GADGET_DIR/functions/rndis.usb0/os_desc/interface.rndis"
echo "02:01:02:03:04:0A" > "$GADGET_DIR/functions/rndis.usb0/dev_addr"
echo "02:01:02:03:04:0B" > "$GADGET_DIR/functions/rndis.usb0/host_addr"
echo "RNDIS" > "$GADGET_DIR/functions/rndis.usb0/os_desc/interface.rndis/compatible_id"
echo "5162001" > "$GADGET_DIR/functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id"
echo 0xE0 > "$GADGET_DIR/functions/rndis.usb0/class" # Wireless Controller
echo 0x01 > "$GADGET_DIR/functions/rndis.usb0/subclass" # Abstract (modem)
echo 0x03 > "$GADGET_DIR/functions/rndis.usb0/protocol" # RNDIS

# Link functions to configuration
ln -s "$GADGET_DIR/functions/ecm.usb0" "$GADGET_DIR/configs/c.1/"
ln -s "$GADGET_DIR/functions/rndis.usb0" "$GADGET_DIR/configs/c.1/"

# OS descriptors for Windows
mkdir -p "$GADGET_DIR/os_desc"
echo 1 > "$GADGET_DIR/os_desc/use"
echo 0xcd > "$GADGET_DIR/os_desc/b_vendor_code"
echo "MSFT100" > "$GADGET_DIR/os_desc/qw_sign"

# Correctly link os_desc configuration
ln -s "$GADGET_DIR/configs/c.1" "$GADGET_DIR/os_desc/configuration"

# Bind gadget to UDC
for attempt in {1..5}; do
UDC=$(ls "$UDC_PATH" | head -n 1)
if [ -n "$UDC" ]; then
echo "$UDC" > "$GADGET_DIR/UDC"
echo "Gadget bound to UDC: $UDC"
break
fi
echo "Waiting for UDC device to appear... (attempt $attempt)"
sleep 1
done

if [ -z "$UDC" ]; then
echo "Error: No UDC device found after 5 attempts."
exit 1
fi
echo "0x1d6b" > "$GADGET_DIR/idVendor" # Linux Foundation
echo "0x0104" > "$GADGET_DIR/idProduct" # Multifunction Composite Gadget
echo "0x0100" > "$GADGET_DIR/bcdDevice"
echo "0x0200" > "$GADGET_DIR/bcdUSB"

read MAC_DEVICE MAC_HOST <<< "$(generate_mac_addresses)"
SERIAL=$(awk '/Serial/ {print substr($3,5)}' /proc/cpuinfo)
create_device_strings

create_configuration "c.1" "CDC ECM Configuration"
create_configuration "c.2" "RNDIS Configuration"

create_cdc_ecm_function
create_rndis_function
configure_os_descriptors

bind_gadget_to_udc

echo "USB Ethernet gadget configured with dual interfaces: CDC ECM (usb0) and RNDIS (usb1)."

0 comments on commit fff70e4

Please sign in to comment.