package for usb-gadget and idea for dumper
This commit is contained in:
1 parent
7bbe036760
commit
97d6055d05
8 files changed
+126
-423
No files matched your search
@@ -1,372 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Main script for MSM8916 USB Gadget
|
||||
|
||||
#SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
||||
#CONFIG_FILE="${SCRIPT_DIR}/msm8916-usb-gadget.conf"
|
||||
CONFIG_FILE="/etc/msm8916-usb-gadget.conf"
|
||||
GADGET_PATH="/sys/kernel/config/usb_gadget/msm8916"
|
||||
|
||||
# Load configuration
|
||||
[ -f "${CONFIG_FILE}" ] && . "${CONFIG_FILE}"
|
||||
|
||||
# Set defaults if not configured
|
||||
: ${USB_VENDOR_ID:="0x1d6b"}
|
||||
: ${USB_PRODUCT_ID:="0x0104"}
|
||||
: ${USB_DEVICE_VERSION:="0x0100"}
|
||||
: ${USB_MANUFACTURER:="MSM8916"}
|
||||
: ${USB_PRODUCT:="USB Gadget"}
|
||||
: ${NETWORK_BRIDGE:="br0"}
|
||||
|
||||
# Helper functions
|
||||
log() {
|
||||
logger -t msm8916-usb-gadget "$@"
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') $@"
|
||||
}
|
||||
|
||||
error() {
|
||||
log "ERROR: $@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
find_udc_device() {
|
||||
if [ -n "${UDC_DEVICE}" ]; then
|
||||
echo "${UDC_DEVICE}"
|
||||
return
|
||||
fi
|
||||
|
||||
# MSM8916 typically uses ci_hdrc.0
|
||||
if [ -e "/sys/class/udc/ci_hdrc.0" ]; then
|
||||
echo "ci_hdrc.0"
|
||||
return
|
||||
fi
|
||||
|
||||
# Fallback: first available UDC
|
||||
udc=$(ls /sys/class/udc/ 2>/dev/null | head -1)
|
||||
if [ -n "${udc}" ]; then
|
||||
echo "${udc}"
|
||||
else
|
||||
error "No UDC device found"
|
||||
fi
|
||||
}
|
||||
|
||||
get_serial_number() {
|
||||
# Use machine-id as the source of uniqueness
|
||||
if [ -f /etc/machine-id ]; then
|
||||
sha256sum < /etc/machine-id | cut -d' ' -f1 | cut -c1-16
|
||||
else
|
||||
# Fallback to random if machine-id doesn't exist
|
||||
echo "$(date +%s)-$(shuf -i 1000-9999 -n 1)"
|
||||
fi
|
||||
}
|
||||
|
||||
generate_mac_address() {
|
||||
local prefix="$1"
|
||||
local serial="$(get_serial_number)"
|
||||
local hash="$(echo "${serial}${prefix}" | md5sum | cut -c1-12)"
|
||||
|
||||
# Extract bytes
|
||||
local b1="${hash:0:2}"
|
||||
local b2="${hash:2:2}"
|
||||
local b3="${hash:4:2}"
|
||||
local b4="${hash:6:2}"
|
||||
local b5="${hash:8:2}"
|
||||
local b6="${hash:10:2}"
|
||||
|
||||
# Set locally administered, unicast
|
||||
b1="$(printf '%02x' $((0x${b1} & 0xfe | 0x02)))"
|
||||
|
||||
echo "${b1}:${b2}:${b3}:${b4}:${b5}:${b6}"
|
||||
}
|
||||
|
||||
load_mac_addresses() {
|
||||
# Generate new MAC addresses for enabled functions
|
||||
[ "${ENABLE_RNDIS}" = "1" ] && {
|
||||
MAC_RNDIS_HOST="$(generate_mac_address "rndis-host")"
|
||||
MAC_RNDIS_DEV="$(generate_mac_address "rndis-dev")"
|
||||
}
|
||||
[ "${ENABLE_ECM}" = "1" ] && {
|
||||
MAC_ECM_HOST="$(generate_mac_address "ecm-host")"
|
||||
MAC_ECM_DEV="$(generate_mac_address "ecm-dev")"
|
||||
}
|
||||
[ "${ENABLE_NCM}" = "1" ] && {
|
||||
MAC_NCM_HOST="$(generate_mac_address "ncm-host")"
|
||||
MAC_NCM_DEV="$(generate_mac_address "ncm-dev")"
|
||||
}
|
||||
}
|
||||
|
||||
create_storage_image() {
|
||||
local image_path="$1"
|
||||
local size="${UMS_IMAGE_SIZE:-100M}"
|
||||
|
||||
log "Creating storage image: ${image_path} (${size})"
|
||||
|
||||
# Create the raw image file
|
||||
truncate -s "${size}" "${image_path}" || \
|
||||
dd if=/dev/zero of="${image_path}" bs=1M count="${size%M}"
|
||||
|
||||
log "Storage image created successfully (raw format)"
|
||||
}
|
||||
|
||||
setup_gadget() {
|
||||
log "Setting up USB gadget"
|
||||
|
||||
# Load required modules
|
||||
modprobe libcomposite
|
||||
|
||||
# Mount configfs if not already mounted
|
||||
if ! mountpoint -q /sys/kernel/config; then
|
||||
log "Mounting configfs"
|
||||
mount -t configfs none /sys/kernel/config
|
||||
fi
|
||||
|
||||
# Create storage image if needed and UMS is enabled
|
||||
if [ "${ENABLE_UMS}" = "1" ] && [ ! -f "${UMS_IMAGE}" ]; then
|
||||
mkdir -p "$(dirname "${UMS_IMAGE}")"
|
||||
create_storage_image "${UMS_IMAGE}"
|
||||
fi
|
||||
|
||||
# Create gadget
|
||||
mkdir -p "${GADGET_PATH}" || error "Failed to create gadget directory"
|
||||
cd "${GADGET_PATH}" || error "Failed to change to gadget directory"
|
||||
|
||||
# Basic device info
|
||||
echo "${USB_VENDOR_ID}" > idVendor || error "Failed to set vendor ID"
|
||||
echo "${USB_PRODUCT_ID}" > idProduct || error "Failed to set product ID"
|
||||
echo "${USB_DEVICE_VERSION}" > bcdDevice || error "Failed to set device version"
|
||||
|
||||
# Composite device descriptors
|
||||
echo "0xEF" > bDeviceClass
|
||||
echo "0x02" > bDeviceSubClass
|
||||
echo "0x01" > bDeviceProtocol
|
||||
|
||||
# Strings
|
||||
mkdir -p strings/0x409
|
||||
echo "$(get_serial_number)" > strings/0x409/serialnumber
|
||||
echo "${USB_MANUFACTURER}" > strings/0x409/manufacturer
|
||||
echo "${USB_PRODUCT}" > strings/0x409/product
|
||||
|
||||
# Load MAC addresses
|
||||
load_mac_addresses
|
||||
|
||||
local cfg="configs/c.1"
|
||||
mkdir -p "${cfg}/strings/0x409"
|
||||
local cfg_str=""
|
||||
local has_wakeup=0
|
||||
|
||||
# RNDIS (must be first for Windows compatibility)
|
||||
if [ "${ENABLE_RNDIS}" = "1" ]; then
|
||||
log "Enabling RNDIS"
|
||||
cfg_str="${cfg_str}+RNDIS"
|
||||
|
||||
mkdir -p functions/rndis.usb0
|
||||
echo "${MAC_RNDIS_HOST}" > functions/rndis.usb0/host_addr
|
||||
echo "${MAC_RNDIS_DEV}" > functions/rndis.usb0/dev_addr
|
||||
ln -sf functions/rndis.usb0 "${cfg}"
|
||||
|
||||
# Windows compatibility
|
||||
echo 1 > os_desc/use
|
||||
echo 0xcd > os_desc/b_vendor_code
|
||||
echo MSFT100 > os_desc/qw_sign
|
||||
echo RNDIS > functions/rndis.usb0/os_desc/interface.rndis/compatible_id
|
||||
echo 5162001 > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id
|
||||
ln -sf "${cfg}" os_desc
|
||||
|
||||
has_wakeup=1
|
||||
fi
|
||||
|
||||
# ACM Serial ports
|
||||
if [ "${ENABLE_ACM}" = "1" ]; then
|
||||
log "Enabling ACM serial (${ACM_COUNT:-1} ports)"
|
||||
|
||||
# Create multiple ACM ports if requested
|
||||
acm_count="${ACM_COUNT:-1}"
|
||||
for i in $(seq 0 $((acm_count - 1))); do
|
||||
cfg_str="${cfg_str}+ACM"
|
||||
mkdir -p functions/acm.GS${i}
|
||||
# Link directly to config
|
||||
ln -sf functions/acm.GS${i} "${cfg}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ECM
|
||||
if [ "${ENABLE_ECM}" = "1" ] && [ "${ENABLE_NCM}" != "1" ]; then
|
||||
log "Enabling ECM"
|
||||
cfg_str="${cfg_str}+ECM"
|
||||
|
||||
mkdir -p functions/ecm.usb0
|
||||
echo "${MAC_ECM_HOST}" > functions/ecm.usb0/host_addr
|
||||
echo "${MAC_ECM_DEV}" > functions/ecm.usb0/dev_addr
|
||||
ln -sf functions/ecm.usb0 "${cfg}"
|
||||
|
||||
has_wakeup=1
|
||||
fi
|
||||
|
||||
# NCM (preferred over ECM)
|
||||
if [ "${ENABLE_NCM}" = "1" ]; then
|
||||
log "Enabling NCM"
|
||||
cfg_str="${cfg_str}+NCM"
|
||||
|
||||
mkdir -p functions/ncm.usb0
|
||||
echo "${MAC_NCM_HOST}" > functions/ncm.usb0/host_addr
|
||||
echo "${MAC_NCM_DEV}" > functions/ncm.usb0/dev_addr
|
||||
ln -sf functions/ncm.usb0 "${cfg}"
|
||||
|
||||
has_wakeup=1
|
||||
fi
|
||||
|
||||
# Mass Storage
|
||||
if [ "${ENABLE_UMS}" = "1" ]; then
|
||||
if [ ! -f "${UMS_IMAGE}" ]; then
|
||||
log "Warning: UMS image ${UMS_IMAGE} not found"
|
||||
else
|
||||
log "Enabling UMS"
|
||||
cfg_str="${cfg_str}+UMS"
|
||||
|
||||
mkdir -p functions/mass_storage.0
|
||||
echo "${UMS_READONLY:-0}" > functions/mass_storage.0/lun.0/ro
|
||||
echo "${UMS_IMAGE}" > functions/mass_storage.0/lun.0/file
|
||||
ln -sf functions/mass_storage.0 "${cfg}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set configuration attributes
|
||||
if [ "${has_wakeup}" = "1" ]; then
|
||||
echo "0xe0" > "${cfg}/bmAttributes" # Self-powered with remote wakeup
|
||||
else
|
||||
echo "0xc0" > "${cfg}/bmAttributes" # Self-powered
|
||||
fi
|
||||
|
||||
echo "${cfg_str:1}" > "${cfg}/strings/0x409/configuration"
|
||||
|
||||
# Enable gadget
|
||||
local udc="$(find_udc_device)"
|
||||
log "Using UDC: ${udc}"
|
||||
echo "${udc}" > UDC || error "Failed to enable UDC"
|
||||
|
||||
# Configure network interfaces
|
||||
# setup_network()
|
||||
# Use uci instead!
|
||||
}
|
||||
|
||||
setup_network() {
|
||||
log "Configuring network interfaces"
|
||||
|
||||
# Wait for interfaces to appear
|
||||
sleep 1
|
||||
|
||||
# Check if bridge exists
|
||||
if ! ip link show "${NETWORK_BRIDGE}" >/dev/null 2>&1; then
|
||||
log "Warning: Bridge ${NETWORK_BRIDGE} does not exist"
|
||||
return
|
||||
fi
|
||||
|
||||
# Add interfaces to bridge
|
||||
if [ "${ENABLE_RNDIS}" = "1" ] && [ -f functions/rndis.usb0/ifname ]; then
|
||||
rndis_if="$(cat functions/rndis.usb0/ifname)"
|
||||
log "Adding ${rndis_if} to bridge ${NETWORK_BRIDGE}"
|
||||
ip link set "${rndis_if}" up
|
||||
ip link set "${rndis_if}" master "${NETWORK_BRIDGE}" || true
|
||||
fi
|
||||
|
||||
if [ "${ENABLE_ECM}" = "1" ] && [ -f functions/ecm.usb0/ifname ]; then
|
||||
ecm_if="$(cat functions/ecm.usb0/ifname)"
|
||||
log "Adding ${ecm_if} to bridge ${NETWORK_BRIDGE}"
|
||||
ip link set "${ecm_if}" up
|
||||
ip link set "${ecm_if}" master "${NETWORK_BRIDGE}" || true
|
||||
fi
|
||||
|
||||
if [ "${ENABLE_NCM}" = "1" ] && [ -f functions/ncm.usb0/ifname ]; then
|
||||
ncm_if="$(cat functions/ncm.usb0/ifname)"
|
||||
log "Adding ${ncm_if} to bridge ${NETWORK_BRIDGE}"
|
||||
ip link set "${ncm_if}" up
|
||||
ip link set "${ncm_if}" master "${NETWORK_BRIDGE}" || true
|
||||
fi
|
||||
}
|
||||
|
||||
teardown_gadget() {
|
||||
log "Tearing down USB gadget"
|
||||
|
||||
# Check if configfs is mounted
|
||||
if ! mountpoint -q /sys/kernel/config; then
|
||||
log "Configfs not mounted, nothing to tear down"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if gadget directory exists
|
||||
if [ ! -d "/sys/kernel/config/usb_gadget" ]; then
|
||||
log "USB gadget configfs not available"
|
||||
return
|
||||
fi
|
||||
|
||||
cd /sys/kernel/config/usb_gadget
|
||||
|
||||
if [ ! -d msm8916 ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
cd msm8916
|
||||
|
||||
# Disable gadget
|
||||
echo "" > UDC || true
|
||||
|
||||
# Remove network interfaces from bridge
|
||||
for func in functions/*/ifname; do
|
||||
if [ -f "${func}" ]; then
|
||||
iface="$(cat "${func}")"
|
||||
ip link set "${iface}" nomaster || true
|
||||
ip link set "${iface}" down || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove configuration - use wildcard to catch all links
|
||||
rm -f configs/c.1/* 2>/dev/null || true
|
||||
rm -f os_desc/c.1 2>/dev/null || true
|
||||
rmdir configs/c.1/strings/0x409 2>/dev/null || true
|
||||
rmdir configs/c.1 2>/dev/null || true
|
||||
|
||||
# Remove functions
|
||||
for func in functions/*; do
|
||||
[ -d "${func}" ] && rmdir "${func}" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Remove strings
|
||||
rmdir strings/0x409 2>/dev/null || true
|
||||
|
||||
# Remove gadget
|
||||
cd ..
|
||||
rmdir msm8916 2>/dev/null || true
|
||||
}
|
||||
|
||||
status() {
|
||||
if [ -d "${GADGET_PATH}" ] && [ -s "${GADGET_PATH}/UDC" ]; then
|
||||
echo "USB Gadget is active"
|
||||
echo "UDC: $(cat ${GADGET_PATH}/UDC)"
|
||||
echo "Functions:"
|
||||
ls -1 ${GADGET_PATH}/configs/c.1/ 2>/dev/null | grep -v strings
|
||||
return 0
|
||||
else
|
||||
echo "USB Gadget is inactive"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
teardown_gadget
|
||||
setup_gadget
|
||||
;;
|
||||
stop)
|
||||
teardown_gadget
|
||||
;;
|
||||
restart)
|
||||
teardown_gadget
|
||||
setup_gadget
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This file is based on postmarketOS initfs code.
|
||||
# See: https://gitlab.com/postmarketOS/pmaports/-/blob/master/main/postmarketos-mkinitfs/
|
||||
|
||||
START=20
|
||||
|
||||
deviceinfo_manufacturer="Generic"
|
||||
deviceinfo_usb_serialnumber="123456"
|
||||
|
||||
setup_usb_network_configfs() {
|
||||
# See: https://www.kernel.org/doc/Documentation/usb/gadget_configfs.txt
|
||||
CONFIGFS=/sys/kernel/config/usb_gadget
|
||||
|
||||
if ! [ -e "$CONFIGFS" ]; then
|
||||
echo " /config/usb_gadget does not exist, skipping configfs usb gadget"
|
||||
return
|
||||
fi
|
||||
|
||||
# Default values for USB-related deviceinfo variables
|
||||
usb_idVendor="${deviceinfo_usb_idVendor:-0x18D1}" # default: Google Inc.
|
||||
usb_idProduct="${deviceinfo_usb_idProduct:-0xD001}" # default: Nexus 4 (fastboot)
|
||||
usb_serialnumber="${deviceinfo_usb_serialnumber:-OpenWRT}"
|
||||
usb_rndis_function="${deviceinfo_usb_rndis_function:-rndis.usb0}"
|
||||
|
||||
echo " Setting up an USB gadget through configfs"
|
||||
# Create an usb gadet configuration
|
||||
mkdir $CONFIGFS/g1 || echo " Couldn't create $CONFIGFS/g1"
|
||||
echo "$usb_idVendor" > "$CONFIGFS/g1/idVendor"
|
||||
echo "$usb_idProduct" > "$CONFIGFS/g1/idProduct"
|
||||
|
||||
# Create english (0x409) strings
|
||||
mkdir $CONFIGFS/g1/strings/0x409 || echo " Couldn't create $CONFIGFS/g1/strings/0x409"
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
echo "$deviceinfo_manufacturer" > "$CONFIGFS/g1/strings/0x409/manufacturer"
|
||||
echo "$usb_serialnumber" > "$CONFIGFS/g1/strings/0x409/serialnumber"
|
||||
# shellcheck disable=SC2154
|
||||
echo "$deviceinfo_name" > "$CONFIGFS/g1/strings/0x409/product"
|
||||
|
||||
# Create rndis function. The function can be named differently in downstream kernels.
|
||||
mkdir $CONFIGFS/g1/functions/"$usb_rndis_function" \
|
||||
|| echo " Couldn't create $CONFIGFS/g1/functions/$usb_rndis_function"
|
||||
|
||||
# Create configuration instance for the gadget
|
||||
mkdir $CONFIGFS/g1/configs/c.1 \
|
||||
|| echo " Couldn't create $CONFIGFS/g1/configs/c.1"
|
||||
mkdir $CONFIGFS/g1/configs/c.1/strings/0x409 \
|
||||
|| echo " Couldn't create $CONFIGFS/g1/configs/c.1/strings/0x409"
|
||||
echo "rndis" > $CONFIGFS/g1/configs/c.1/strings/0x409/configuration \
|
||||
|| echo " Couldn't write configration name"
|
||||
|
||||
# Link the rndis instance to the configuration
|
||||
ln -s $CONFIGFS/g1/functions/"$usb_rndis_function" $CONFIGFS/g1/configs/c.1 \
|
||||
|| echo " Couldn't symlink $usb_rndis_function"
|
||||
|
||||
# Check if there's an USB Device Controller
|
||||
if [ -z "$(ls /sys/class/udc)" ]; then
|
||||
echo " No USB Device Controller available"
|
||||
return
|
||||
fi
|
||||
|
||||
# Link the gadget instance to an USB Device Controller. This activates the gadget.
|
||||
# See also: https://github.com/postmarketOS/pmbootstrap/issues/338
|
||||
# shellcheck disable=SC2005
|
||||
echo "$(ls /sys/class/udc)" > $CONFIGFS/g1/UDC || echo " Couldn't write UDC"
|
||||
}
|
||||
|
||||
start() {
|
||||
mount -t configfs none /sys/kernel/config
|
||||
setup_usb_network_configfs
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
# MSM8916 USB Gadget Configuration
|
||||
|
||||
### USB protocols and OS support:
|
||||
# - RNDIS Ethernet: Linux/Windows supported automatically, macOS needs HoRNDIS driver
|
||||
# - CDC ECM Ethernet: Linux/macOS 10.14 and earlier supported automatically.
|
||||
# - CDC NCM Ethernet: Linux/macOS 10.15 and later supported automatically, Windows 11 supported automatically.
|
||||
# - UMS USB Mass storage: All OS supported automatically.
|
||||
# - CDC ACM Serial: All OS supported automatically. (Windows <10 needs a custom .inf)
|
||||
###
|
||||
|
||||
# USB Functions Enable/Disable
|
||||
ENABLE_RNDIS=1 # MS-Windows compatible ethernet
|
||||
ENABLE_ECM=0 # CDC ECM ethernet
|
||||
ENABLE_NCM=0 # CDC NCM ethernet (Best Performance)
|
||||
ENABLE_UMS=0 # Mass storage
|
||||
ENABLE_ACM=1 # Serial console
|
||||
|
||||
# Network Configuration
|
||||
# Bridge to attach USB Ethernet interfaces to
|
||||
NETWORK_BRIDGE="br0"
|
||||
|
||||
# UMS Configuration (if enabled)
|
||||
UMS_IMAGE="/var/lib/msm8916-gadget/usb_mass_storage.img"
|
||||
UMS_IMAGE_SIZE="100M" # Size to create if image doesn't exist (M/G suffix supported)
|
||||
UMS_READONLY=0
|
||||
|
||||
# ACM Configuration (if enabled)
|
||||
# NOTE: MSM8916 hardware supports maximum 3 ACM serial ports
|
||||
ACM_COUNT=1 # Number of Serial ports
|
||||
|
||||
# UDC Device (auto-detect if empty)
|
||||
UDC_DEVICE=""
|
||||
|
||||
# USB Device Identification
|
||||
USB_VENDOR_ID="0x1d6b" # Linux Foundation
|
||||
USB_PRODUCT_ID="0x0104" # Multifunction Composite Gadget
|
||||
USB_DEVICE_VERSION="0x0100" # v1.0.0
|
||||
USB_MANUFACTURER="MSM8916"
|
||||
USB_PRODUCT="USB Gadget"
|
||||
Reference in new issue
Block a user