|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +deviceinfo_name="USB Gadget Network" |
| 4 | +deviceinfo_manufacturer="Armbian" |
| 5 | +#deviceinfo_usb_idVendor= |
| 6 | +#deviceinfo_usb_idProduct= |
| 7 | +#deviceinfo_usb_serialnumber= |
| 8 | + |
| 9 | +setup_usb_network_configfs() { |
| 10 | + # See: https://www.kernel.org/doc/Documentation/usb/gadget_configfs.txt |
| 11 | + CONFIGFS=/sys/kernel/config/usb_gadget |
| 12 | + |
| 13 | + if ! [ -e "$CONFIGFS" ]; then |
| 14 | + echo " $CONFIGFS does not exist, skipping configfs usb gadget" |
| 15 | + return |
| 16 | + fi |
| 17 | + |
| 18 | + if [ -e "$CONFIGFS/g1" ]; then |
| 19 | + echo " $CONFIGFS/g1 already exists, skipping configfs usb gadget" |
| 20 | + return |
| 21 | + fi |
| 22 | + |
| 23 | + # Default values for USB-related deviceinfo variables |
| 24 | + usb_idVendor="${deviceinfo_usb_idVendor:-0x1D6B}" # Linux Foundation |
| 25 | + usb_idProduct="${deviceinfo_usb_idProduct:-0x0104}" # Multifunction Composite Gadget |
| 26 | + usb_serialnumber="${deviceinfo_usb_serialnumber:-0123456789}" |
| 27 | + usb_network_function="ncm.usb0" |
| 28 | + usb_serial_function="acm.usb0" |
| 29 | + |
| 30 | + echo " Setting up an USB gadget through configfs" |
| 31 | + # Create an usb gadet configuration |
| 32 | + mkdir $CONFIGFS/g1 || echo " Couldn't create $CONFIGFS/g1" |
| 33 | + echo "$usb_idVendor" > "$CONFIGFS/g1/idVendor" |
| 34 | + echo "$usb_idProduct" > "$CONFIGFS/g1/idProduct" |
| 35 | + echo 0x0404 > "$CONFIGFS/g1/bcdDevice" |
| 36 | + echo 0x0200 > "$CONFIGFS/g1/bcdUSB" |
| 37 | + |
| 38 | + # Create english (0x409) strings |
| 39 | + mkdir $CONFIGFS/g1/strings/0x409 || echo " Couldn't create $CONFIGFS/g1/strings/0x409" |
| 40 | + |
| 41 | + # shellcheck disable=SC2154 |
| 42 | + echo "$deviceinfo_manufacturer" > "$CONFIGFS/g1/strings/0x409/manufacturer" |
| 43 | + echo "$usb_serialnumber" > "$CONFIGFS/g1/strings/0x409/serialnumber" |
| 44 | + # shellcheck disable=SC2154 |
| 45 | + echo "$deviceinfo_name" > "$CONFIGFS/g1/strings/0x409/product" |
| 46 | + |
| 47 | + # Create network function. |
| 48 | + mkdir $CONFIGFS/g1/functions/"$usb_network_function" || |
| 49 | + echo " Couldn't create $CONFIGFS/g1/functions/$usb_network_function" |
| 50 | + |
| 51 | + # Create configuration instance for the gadget |
| 52 | + mkdir $CONFIGFS/g1/configs/c.1 || |
| 53 | + echo " Couldn't create $CONFIGFS/g1/configs/c.1" |
| 54 | + echo 250 > $CONFIGFS/g1/configs/c.1/MaxPower |
| 55 | + mkdir $CONFIGFS/g1/configs/c.1/strings/0x409 || |
| 56 | + echo " Couldn't create $CONFIGFS/g1/configs/c.1/strings/0x409" |
| 57 | + echo "NCM Configuration" > $CONFIGFS/g1/configs/c.1/strings/0x409/configuration || |
| 58 | + echo " Couldn't write configration name" |
| 59 | + |
| 60 | + # Link the network instance to the configuration |
| 61 | + ln -s $CONFIGFS/g1/functions/"$usb_network_function" $CONFIGFS/g1/configs/c.1 || |
| 62 | + echo " Couldn't symlink $usb_network_function" |
| 63 | + |
| 64 | + # Enable ACM if first-run is done. |
| 65 | + # Enabling it when armbian first-run executes seems to cause some kind of reset which kind of |
| 66 | + # concludes the config without any actual configuration. |
| 67 | + mkdir -p $CONFIGFS/g1/functions/"$usb_serial_function" || |
| 68 | + echo " Couldn't create $CONFIGFS/g1/functions/$usb_serial_function" |
| 69 | + ln -s $CONFIGFS/g1/functions/"$usb_serial_function" $CONFIGFS/g1/configs/c.1 || |
| 70 | + echo " Couldn't symlink $usb_serial_function" |
| 71 | + |
| 72 | + # Check if there's an USB Device Controller |
| 73 | + if [ -z "$(ls /sys/class/udc)" ]; then |
| 74 | + echo " No USB Device Controller available" |
| 75 | + return |
| 76 | + fi |
| 77 | + |
| 78 | + # Link the gadget instance to an USB Device Controller. This activates the gadget. |
| 79 | + # See also: https://github.com/postmarketOS/pmbootstrap/issues/338 |
| 80 | + # shellcheck disable=SC2005 |
| 81 | + echo "$(ls /sys/class/udc)" > $CONFIGFS/g1/UDC || echo " Couldn't write UDC" |
| 82 | +} |
| 83 | + |
| 84 | +set_usbgadget_ipaddress() { |
| 85 | + local host_ip="${unudhcpd_host_ip:-172.16.42.1}" |
| 86 | + local client_ip="${unudhcpd_client_ip:-172.16.42.2}" |
| 87 | + unudhcpd_pid=$(pgrep unudhcpd) |
| 88 | + if [ "x$unudhcpd_pid" != "x" ]; then |
| 89 | + echo "unudhcpd process already exists, skip setting usb gadget ip, unudhcpd_pid is $unudhcpd_pid" |
| 90 | + return |
| 91 | + fi |
| 92 | + echo "Starting dnsmasq with server ip $host_ip, client ip: $client_ip" |
| 93 | + # Get usb interface |
| 94 | + INTERFACE="" |
| 95 | + ip a add "${host_ip}/255.255.0.0" dev usb0 2> /dev/null && ip link set usb0 up && INTERFACE=usb0 |
| 96 | + if [ -z $INTERFACE ]; then |
| 97 | + ip a add "${host_ip}/255.255.0.0" dev eth0 2> /dev/null && eth0 && INTERFACE=eth0 |
| 98 | + fi |
| 99 | + |
| 100 | + if [ -z $INTERFACE ]; then |
| 101 | + echo " Could not find an interface to run a dhcp server on" |
| 102 | + echo " Interfaces:" |
| 103 | + ip link |
| 104 | + return |
| 105 | + fi |
| 106 | + |
| 107 | + echo " Using interface $INTERFACE" |
| 108 | + echo " Starting the DHCP daemon" |
| 109 | + ip a show $INTERFACE > /var/log/unudhcpd.log |
| 110 | + nohup /usr/bin/unudhcpd -i "$INTERFACE" -s "$host_ip" -c "$client_ip" >> /var/log/unudhcpd.log 2>&1 & |
| 111 | + return |
| 112 | +} |
| 113 | +setup_usb_network_configfs |
| 114 | +set_usbgadget_ipaddress |
0 commit comments