-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathusb_gadget
executable file
·178 lines (143 loc) · 8.46 KB
/
usb_gadget
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/bin/bash
# Setup/tear down the libcomposite USB Gadget system through configfs
# draft template should it evolve into init script?
### BEGIN INIT INFO
# Provides: usb_gadge
# Required-Start: $remote_fs $syslog $time
# Required-Stop: $remote_fs $syslog $time
# Should-Start: $network $named slapd autofs ypbind nscd nslcd winbind sssd
# Should-Stop: $network $named slapd autofs ypbind nscd nslcd winbind sssd
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: uses configfs to configure libcomposite USB gadget subsystem
# Description: usb_gadget prepares the configfs structure ready to enable
# various USB devices to be exposed to a USB host.
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DESC="USB Gadget subsystem"
NAME=usb_gadget
#DAEMON=/usr/sbin/cron
#PIDFILE=/var/run/crond.pid
SCRIPTNAME=/etc/init.d/"$NAME"
. /lib/lsb/init-functions
# # PREREQUITES
# modprobe libcomposite # load libcomposite
# mount none $CONFIGFS_HOME -t configfs # mount configfs
# load default run-time env
[ -r /etc/default/${NAME} ] && . /etc/default/${NAME}
# # ENV
CONFIGFS_HOME=${CONFIGFS_HOME:-"/sys/kernel/config"}
GADGET_PROFILE="${GADGET_PROFILE:-"default"}"
GADGET_HOME="${CONFIGFS_HOME}/usb_gadget/${GADGET_PROFILE}"
GADGET_VENDOR_ID=${GADGET_VENDOR_ID:-"0x1d6b"} # 0x1d6b idVendor # Linux Foundation
GADGET_PRODUCT_ID=${GADGET_PRODUCT_ID:-"0x0104"} # 0x0104 idProduct # Multifunction Composite Gadget
# GADGET_PRODUCT_ID=${GADGET_PRODUCT_ID:-"0xa4a2"} # 0xa4a2 idProduct # Linux-USB Ethernet/RNDIS Gadget
GADGET_BCD_DEVICE=${GADGET_BCD_DEVICE:-"0x0100"} # BCD version 1.0.0
GADGET_BCD_USB=${GADGET_BCD_USB:-"0x0200"} # BCD USB version 2.0.0
# Create Gadget Profile directory
[ ! -d "${GADGET_HOME}" ] && mkdir -p "${GADGET_HOME}"
# Set Gadget Profile Vendor & Product IDs
echo ${GADGET_VENDOR_ID} > ${GADGET_HOME}/idVendor
echo ${GADGET_PRODUCT_ID} > ${GADGET_HOME}/idProduct
# Set Gadget Profile BCD versions
echo ${GADGET_BCD_DEVICE} > ${GADGET_HOME}/bcdDevice
echo ${GADGET_BCD_USB} > ${GADGET_HOME}/bcdUSB
# Create Gadget Description Strings directory
GADGET_STRINGS_LANG=${GADGET_STRINGS_LANG:-"0x409"} # English
GADGET_STRINGS_HOME="${GADGET_HOME}/strings/${GADGET_STRINGS_LANG}"
[ ! -d "${GADGET_STRINGS_HOME}" ] && mkdir -p "${GADGET_STRINGS_HOME}"
# Set Gadget Description Strings
GADGET_SERIAL_NUMBER_STR=${GADGET_SERIAL_NUMBER_STR:-"fedcba9876543211"}
GADGET_MANUFACTURER_STR=${GADGET_MANUFACTURER_STR:-"[email protected]"}
GADGET_PRODUCT_STR=${GADGET_GADGET_PRODUCT_STR:-"Devuan Pi USB Device"}
echo ${GADGET_SERIAL_NUMBER_STR} > ${GADGET_STRINGS_HOME}/serialnumber
echo ${GADGET_MANUFACTURER_STR} > ${GADGET_STRINGS_HOME}/manufacturer
echo ${GADGET_PRODUCT_STR} > ${GADGET_STRINGS_HOME}/product
# Create Gadget Configuration Profile
GADGET_CONFIG_PROFILE=${GADGET_CONFIG_PROFILE:-"c"}
GADGET_CONFIG_NUMBER=${GADGET_CONFIG_NUMBER:-1}
GADGET_CONFIG_HOME="${GADGET_HOME}/configs/${GADGET_CONFIG_PROFILE}.${GADGET_CONFIG_NUMBER}"
[ ! -d "${GADGET_CONFIG_HOME}" ] && mkdir -p "${GADGET_CONFIG_HOME}"
# Set Gadget Configuration Attributes
GADGET_CONFIG_MAXPOWER=${GADGET_CONFIG_MAXPOWER:-"250"}
echo "${GADGET_CONFIG_MAXPOWER}" > ${GADGET_CONFIG_HOME}/MaxPower
# Create Gadget Configuration Description Strings directory
GADGET_CONFIG_STR_HOME="${GADGET_CONFIG_HOME}/strings/${GADGET_STRINGS_LANG}"
[ ! -d "${GADGET_CONFIG_STR_HOME}" ] && mkdir -p "${GADGET_CONFIG_STR_HOME}"
# Set Gadget Configuration Strings
GADGET_CONFIG_DESCRIPTION_STR=${GADGET_CONFIG_DESCRIPTION_STR:-"Devuan Pi USB Config ${GADGET_CONFIG_PROFILE}.${GADGET_CONFIG_NUMBER}"}
## FUNCTIONS
############
# Create Gadget Function directory
GADGET_FUNCTIONS_HOME=${GADGET_HOME}/functions
[ ! -d "${GADGET_FUNCTIONS_HOME}" ] && mkdir -p "${GADGET_FUNCTION_HOME}"
# TODO: research split out each function to something like usb_gadget.d and run run-parts
# Add RNDIS Ethernet Function Profile
# according to https://github.com/RoganDawes/P4wnP1/blob/62b5c40d9461e4b80998c54830625d6c855833f0/boot/init_usb.sh#L178
# RNDIS has to be th efirst interface on composite device
GADGET_FUNCTION_NAME=rndis
GADGET_FUNCTION_INSTANCE=usb0
GADGET_FUNCTION_PROFILE="${GADGET_FUNCTION_NAME}.${GADGET_FUNCTION_INSTANCE}"
GADGET_FUNCTION_PROFILE_HOME="${GADGET_FUNCTIONS_HOME}/${GADGET_FUNCTION_PROFILE}"
[ ! -d "${GADGET_FUNCTION_PROFILE_HOME}" ] && mkdir -p "${GADGET_FUNCTION_PROFILE_HOME}"
# # first byte of address must be even
# GADGET_FUNCTION_ECM_HOST=${GADGET_FUNCTION_ECM_HOST:-"48:6f:73:74:50:43"} # "HostPC"
# echo "${GADGET_FUNCTION_ECM_HOST}" > ${GADGET_FUNCTION_PROFILE_HOME}/host_addr
# GADGET_FUNCTION_ECM_SELF=${GADGET_FUNCTION_ECM_SELF:-"42:61:64:55:53:42"} # "BadUSB"
# echo "${GADGET_FUNCTION_ECM_SELF}" > ${GADGET_FUNCTION_PROFILE_HOME}/self_addr
# add OS specific device descriptors to force Windows to load RNDIS drivers
# see https://github.com/RoganDawes/P4wnP1/blob/62b5c40d9461e4b80998c54830625d6c855833f0/boot/init_usb.sh#L150
[ ! -d "${GADGET_HOME}/os_desc" ] && mkdir -p "${GADGET_HOME}/os_desc"
echo "1" > ${GADGET_HOME}/os_desc/use
echo "0xbc" > ${GADGET_HOME}/os_desc/b_vendor_code
echo "MSFT100" > ${GADGET_HOME}/os_desc/qw_sign
[ ! -d "${GADGET_FUNCTION_PROFILE_HOME}/os_desc/interface.rndis" ] && mkdir -p "${GADGET_FUNCTION_PROFILE_HOME}/os_desc/interface.rndis"
echo "RNDIS" > ${GADGET_FUNCTION_PROFILE_HOME}/os_desc/interface.rndis/compatible_id
echo "5162001" > ${GADGET_FUNCTION_PROFILE_HOME}/os_desc/interface.rndis/sub_compatible_id
ln -s ${GADGET_FUNCTION_PROFILE_HOME} ${GADGET_CONFIG_HOME}/
ln -s ${GADGET_CONFIG_HOME} ${GADGET_HOME}/os_desc
# Add ECM Ethernet Function Profile
GADGET_FUNCTION_NAME=ecm
GADGET_FUNCTION_INSTANCE=usb1
GADGET_FUNCTION_PROFILE="${GADGET_FUNCTION_NAME}.${GADGET_FUNCTION_INSTANCE}"
GADGET_FUNCTION_PROFILE_HOME="${GADGET_FUNCTIONS_HOME}/${GADGET_FUNCTION_PROFILE}"
[ ! -d "${GADGET_FUNCTION_PROFILE_HOME}" ] && mkdir -p "${GADGET_FUNCTION_PROFILE_HOME}"
# # first byte of address must be even
# GADGET_FUNCTION_ECM_HOST=${GADGET_FUNCTION_ECM_HOST:-"48:6f:73:74:50:43"} # "HostPC"
# echo "${GADGET_FUNCTION_ECM_HOST}" > ${GADGET_FUNCTION_PROFILE_HOME}/host_addr
# GADGET_FUNCTION_ECM_SELF=${GADGET_FUNCTION_ECM_SELF:-"42:61:64:55:53:42"} # "BadUSB"
# echo "${GADGET_FUNCTION_ECM_SELF}" > ${GADGET_FUNCTION_PROFILE_HOME}/self_addr
ln -s ${GADGET_FUNCTION_PROFILE_HOME} ${GADGET_CONFIG_HOME}/
# Add Mass Storage Function Profile
GADGET_FUNCTION_NAME=mass_storage
GADGET_FUNCTION_INSTANCE=usb1
GADGET_FUNCTION_PROFILE="${GADGET_FUNCTION_NAME}.${GADGET_FUNCTION_INSTANCE}"
GADGET_FUNCTION_PROFILE_HOME="${GADGET_FUNCTIONS_HOME}/${GADGET_FUNCTION_PROFILE}"
[ ! -d "${GADGET_FUNCTION_PROFILE_HOME}" ] && mkdir -p "${GADGET_FUNCTION_PROFILE_HOME}"
# Check existance of home dir for image file
GADGET_STORAGE_IMAGE_HOME=${GADGET_STORAGE_IMAGE_HOME:-"/var/usb_gadget"}
[ ! -d "${GADGET_STORAGE_IMAGE_HOME}" ] && mkdir -p "${GADGET_STORAGE_IMAGE_HOME}"
# Check existance of file system image
GADGET_STORAGE_DEVICE_LABEL=${GADGET_STORAGE_DEVICE_LABEL:-${HOSTNAME:0:11}}
GADGET_STORAGE_IMAGE_FILE_SIZE=${GADGET_STORAGE_IMAGE_FILE_SIZE:-"10G"}
GADGET_STORAGE_IMAGE_FILE="${GADGET_STORAGE_IMAGE_HOME}/${GADGET_FUNCTION_PROFILE}.img"
#[ ! -r "${GADGET_STORAGE_IMAGE_FILE}" ] && dd if=/dev/zero of=${GADGET_STORAGE_IMAGE_FILE} bs=1M count=${GADGET_STORAGE_IMAGE_FILE_SIZE} status=progress && mkdosfs ${GADGET_STORAGE_IMAGE_FILE}
[ ! -r "${GADGET_STORAGE_IMAGE_FILE}" ] && fallocate -l ${GADGET_STORAGE_IMAGE_FILE_SIZE} ${GADGET_STORAGE_IMAGE_FILE} && mkdosfs -n ${GADGET_STORAGE_DEVICE_LABEL:0:11} ${GADGET_STORAGE_IMAGE_FILE}
# Check existance of mount directory
GADGET_STORAGE_MOUNT_DIR=${GADGET_STORAGE_MOUNT_DIR:-"${GADGET_STORAGE_IMAGE_FILE/img/d}"}
[ ! -d "${GADGET_STORAGE_MOUNT_DIR}" ] && mkdir -p "${GADGET_STORAGE_MOUNT_DIR}"
# Mount file system image in mount directory
mount -o loop,ro, -t vfat ${GADGET_STORAGE_IMAGE_FILE} ${GADGET_STORAGE_MOUNT_DIR} # FOR IMAGE CREATED WITH DD
echo "1" > ${GADGET_FUNCTION_PROFILE_HOME}/stall
echo "0" > ${GADGET_FUNCTION_PROFILE_HOME}/lun.0/cdrom
echo "0" > ${GADGET_FUNCTION_PROFILE_HOME}/lun.0/ro
echo "0" > ${GADGET_FUNCTION_PROFILE_HOME}/lun.0/nofua
echo "${GADGET_STORAGE_IMAGE_FILE}" > ${GADGET_FUNCTION_PROFILE_HOME}/lun.0/file
ln -s ${GADGET_FUNCTION_PROFILE_HOME} ${GADGET_CONFIG_HOME}/
# END FUNCTIONS
# In order to enable the gadget it must be bound to a UDC (USB Device Controller):
# Enable Gadget (RPi's only have one controller ...)
GADGET_UDC=$(ls /sys/class/udc | cut -f1 | head -n 1)
echo "${GADGET_UDC}" > ${GADGET_HOME}/UDC
# Disable Gadget
# echo "" > ${GADGET_HOME}/UDC