From 97d6055d05d62c48a3250344bfb1420e480e766c Mon Sep 17 00:00:00 2001 From: Miguel Fuertes Date: Sun, 14 Sep 2025 23:14:09 +0200 Subject: [PATCH] package for usb-gadget and idea for dumper --- msm89xx/base-files/etc/init.d/usb_network | 73 ++++ msm89xx/base-files/etc/msm916-usb-gadget.conf | 40 -- packages/msm8916-usb-gadget/Makefile | 37 ++ .../files/msm8916-usb-gadget.conf | 0 .../files/msm8916-usb-gadget.init | 16 + .../files}/msm8916-usb-gadget.sh | 0 .../files/etc/board.d/02_network | 11 - usb_gadget_with_configs/msm8916-usb-gadget.sh | 372 ------------------ 8 files changed, 126 insertions(+), 423 deletions(-) create mode 100755 msm89xx/base-files/etc/init.d/usb_network delete mode 100644 msm89xx/base-files/etc/msm916-usb-gadget.conf create mode 100644 packages/msm8916-usb-gadget/Makefile rename usb_gadget_with_configs/msm916-usb-gadget.conf => packages/msm8916-usb-gadget/files/msm8916-usb-gadget.conf (100%) create mode 100644 packages/msm8916-usb-gadget/files/msm8916-usb-gadget.init rename {msm89xx/base-files/etc/init.d => packages/msm8916-usb-gadget/files}/msm8916-usb-gadget.sh (100%) mode change 100755 => 100644 delete mode 100755 packages/usbgadget-uci/files/etc/board.d/02_network delete mode 100644 usb_gadget_with_configs/msm8916-usb-gadget.sh diff --git a/msm89xx/base-files/etc/init.d/usb_network b/msm89xx/base-files/etc/init.d/usb_network new file mode 100755 index 0000000..8b4ef47 --- /dev/null +++ b/msm89xx/base-files/etc/init.d/usb_network @@ -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 +} diff --git a/msm89xx/base-files/etc/msm916-usb-gadget.conf b/msm89xx/base-files/etc/msm916-usb-gadget.conf deleted file mode 100644 index 7199c7d..0000000 --- a/msm89xx/base-files/etc/msm916-usb-gadget.conf +++ /dev/null @@ -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" \ No newline at end of file diff --git a/packages/msm8916-usb-gadget/Makefile b/packages/msm8916-usb-gadget/Makefile new file mode 100644 index 0000000..2b99388 --- /dev/null +++ b/packages/msm8916-usb-gadget/Makefile @@ -0,0 +1,37 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=msm8916-usb-gadget +PKG_VERSION:=1.0 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=Utilities + CATEGORY:=Utilities + TITLE:=USB Gadget with config for msm8916 chipsets + DEPENDS:=+kmod-fs-configfs +kmod-usb-gadget +kmod-usb-lib-composite +kmod-usb-chipidea \ + +kmod-usb-gadget-eth +kmod-usb-gadget-ncm \ + +kmod-usb-gadget-serial +kmod-usb-gadget-mass-storage +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/etc + $(INSTALL_CONF) ./files/msm8916-usb-gadget.conf $(1)/etc/ + + # Script principal (llamado por init.d) + $(INSTALL_BIN) ./files/msm8916-usb-gadget.sh $(1)/etc/msm8916-usb-gadget.sh + + # Wrapper init.d (procd, rc.common) + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/msm8916-usb-gadget.init $(1)/etc/init.d/msm8916-usb-gadget +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/usb_gadget_with_configs/msm916-usb-gadget.conf b/packages/msm8916-usb-gadget/files/msm8916-usb-gadget.conf similarity index 100% rename from usb_gadget_with_configs/msm916-usb-gadget.conf rename to packages/msm8916-usb-gadget/files/msm8916-usb-gadget.conf diff --git a/packages/msm8916-usb-gadget/files/msm8916-usb-gadget.init b/packages/msm8916-usb-gadget/files/msm8916-usb-gadget.init new file mode 100644 index 0000000..9a3b196 --- /dev/null +++ b/packages/msm8916-usb-gadget/files/msm8916-usb-gadget.init @@ -0,0 +1,16 @@ +#!/bin/sh /etc/rc.common +START=95 +USE_PROCD=1 + +start_service() { + procd_open_instance + procd_set_param command /bin/sh /etc/msm8916-usb-gadget.sh start + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param respawn 1 5 5 + procd_close_instance +} + +stop_service() { + /bin/sh /etc/msm8916-usb-gadget.sh stop 2>/dev/null || true +} diff --git a/msm89xx/base-files/etc/init.d/msm8916-usb-gadget.sh b/packages/msm8916-usb-gadget/files/msm8916-usb-gadget.sh old mode 100755 new mode 100644 similarity index 100% rename from msm89xx/base-files/etc/init.d/msm8916-usb-gadget.sh rename to packages/msm8916-usb-gadget/files/msm8916-usb-gadget.sh diff --git a/packages/usbgadget-uci/files/etc/board.d/02_network b/packages/usbgadget-uci/files/etc/board.d/02_network deleted file mode 100755 index 6612147..0000000 --- a/packages/usbgadget-uci/files/etc/board.d/02_network +++ /dev/null @@ -1,11 +0,0 @@ -. /lib/functions/uci-defaults.sh -board_config_update - -case "$(board_name)" in -*) - ucidef_set_interface_lan "usb0" - ;; -esac - -board_config_flush -exit 0 diff --git a/usb_gadget_with_configs/msm8916-usb-gadget.sh b/usb_gadget_with_configs/msm8916-usb-gadget.sh deleted file mode 100644 index 827bf2d..0000000 --- a/usb_gadget_with_configs/msm8916-usb-gadget.sh +++ /dev/null @@ -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 \ No newline at end of file