-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathev3-usb.sh
executable file
·182 lines (152 loc) · 6.23 KB
/
ev3-usb.sh
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
179
180
181
182
#!/bin/dash
# USB Gadget for LEGO MINDSTORMS EV3 hardware
#
# Copyright (C) 2015,2017 David Lechner <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
set -e
# command line parameters
command="$1" # "up" or "down"
udc_device="$2" # a udc device name, such as "musb-hdrc.1.auto"
g="/sys/kernel/config/usb_gadget/ev3dev"
ev3_usb_up() {
usb_ver="0x0200" # USB 2.0
dev_class="2" # Communications - LEGO firmware is 0
vid="0x0694" # LEGO Group
pid="0x0005" # EV3
device="0x3000" # this should be incremented any time there are breaking changes
# to this script so that the host OS sees it as a new device and
# re-enumerates everything rather than relying on cached values
mfg="LEGO Group" # matches LEGO firmware
prod="EV3+ev3dev" # LEGO firmware is just "EV3"
# Read bluetooth mac address from eeprom - this is what LEGO firmware uses for serial
serial="$(grep Serial /proc/cpuinfo | sed 's/Serial\s*: 0000\(\w*\)/\1/')"
attr="0xC0" # Self powered
pwr="1" # 2mA
cfg1="CDC"
cfg2="RNDIS"
# add colons for MAC address format
mac="$(echo ${serial} | sed 's/\(\w\w\)/:\1/g' | cut -b 2-)"
# Change the first number for each MAC address - the second digit of 2 indicates
# that these are "locally assigned (b2=1), unicast (b1=0)" addresses. This is
# so that they don't conflict with any existing vendors. Care should be taken
# not to change these two bits.
dev_mac1="02$(echo ${mac} | cut -b 3-)"
host_mac1="12$(echo ${mac} | cut -b 3-)"
dev_mac2="22$(echo ${mac} | cut -b 3-)"
host_mac2="32$(echo ${mac} | cut -b 3-)"
ms_vendor_code="0xcd" # Microsoft
ms_qw_sign="MSFT100" # also Microsoft (if you couldn't tell)
ms_compat_id="RNDIS" # matches Windows RNDIS Drivers
ms_subcompat_id="5162001" # matches Windows RNDIS 6.0 Driver
tmpdir=$(mktemp -d)
mount /dev/mmcblk0p1 $tmpdir
if [ -f $tmpdir/ev3dev.txt ]; then
cdc_only=$(grep -i "^cdc_only=\(true\|yes\|1\)" $tmpdir/ev3dev.txt | cut -b 10-)
fi
umount $tmpdir
if [ -d ${g} ]; then
if [ "$(cat ${g}/UDC)" != "" ]; then
echo "Gadget is already up."
exit 1
fi
echo "Cleaning up old directory..."
ev3_usb_down
fi
echo "Setting up gadget..."
# Create a new gadget
mkdir ${g}
echo "${usb_ver}" > ${g}/bcdUSB
echo "${dev_class}" > ${g}/bDeviceClass
echo "${vid}" > ${g}/idVendor
echo "${pid}" > ${g}/idProduct
echo "${device}" > ${g}/bcdDevice
mkdir ${g}/strings/0x409
echo "${mfg}" > ${g}/strings/0x409/manufacturer
echo "${prod}" > ${g}/strings/0x409/product
echo "${serial}" > ${g}/strings/0x409/serialnumber
# Create 2 configurations. The first will be CDC. The second will be RNDIS.
# Thanks to os_desc, Windows should use the second configuration.
# config 1 is for CDC
mkdir ${g}/configs/c.1
echo "${attr}" > ${g}/configs/c.1/bmAttributes
echo "${pwr}" > ${g}/configs/c.1/MaxPower
mkdir ${g}/configs/c.1/strings/0x409
echo "${cfg1}" > ${g}/configs/c.1/strings/0x409/configuration
# Create the CDC function
mkdir ${g}/functions/ecm.usb0
echo "${dev_mac1}" > ${g}/functions/ecm.usb0/dev_addr
echo "${host_mac1}" > ${g}/functions/ecm.usb0/host_addr
# config 2 is for RNDIS
mkdir ${g}/configs/c.2
echo "${attr}" > ${g}/configs/c.2/bmAttributes
echo "${pwr}" > ${g}/configs/c.2/MaxPower
mkdir ${g}/configs/c.2/strings/0x409
echo "${cfg2}" > ${g}/configs/c.2/strings/0x409/configuration
# On Windows 7 and later, the RNDIS 5.1 driver would be used by default,
# but it does not work very well. The RNDIS 6.0 driver works better. In
# order to get this driver to load automatically, we have to use a
# Microsoft-specific extension of USB.
echo "1" > ${g}/os_desc/use
echo "${ms_vendor_code}" > ${g}/os_desc/b_vendor_code
echo "${ms_qw_sign}" > ${g}/os_desc/qw_sign
# Create the RNDIS function, including the Microsoft-specific bits
mkdir ${g}/functions/rndis.usb0
echo "${dev_mac2}" > ${g}/functions/rndis.usb0/dev_addr
echo "${host_mac2}" > ${g}/functions/rndis.usb0/host_addr
echo "${ms_compat_id}" > ${g}/functions/rndis.usb0/os_desc/interface.rndis/compatible_id
echo "${ms_subcompat_id}" > ${g}/functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id
# Link everything up and bind the USB device
ln -s ${g}/functions/ecm.usb0 ${g}/configs/c.1
ln -s ${g}/functions/rndis.usb0 ${g}/configs/c.2
ln -s ${g}/configs/c.2 ${g}/os_desc
echo "${udc_device}" > ${g}/UDC
echo "Done."
}
ev3_usb_down() {
if [ ! -d ${g} ]; then
echo "Gadget is already down."
exit 1
fi
echo "Taking down gadget..."
# Have to unlink and remove directories in reverse order.
# Checks allow to finish takedown after error.
if [ "$(cat ${g}/UDC)" != "" ]; then
echo "" > ${g}/UDC
fi
rm -f ${g}/os_desc/c.2
rm -f ${g}/configs/c.2/rndis.usb0
rm -f ${g}/configs/c.1/ecm.usb0
[ -d ${g}/functions/ecm.usb0 ] && rmdir ${g}/functions/ecm.usb0
[ -d ${g}/functions/rndis.usb0 ] && rmdir ${g}/functions/rndis.usb0
[ -d ${g}/configs/c.2/strings/0x409 ] && rmdir ${g}/configs/c.2/strings/0x409
[ -d ${g}/configs/c.2 ] && rmdir ${g}/configs/c.2
[ -d ${g}/configs/c.1/strings/0x409 ] && rmdir ${g}/configs/c.1/strings/0x409
[ -d ${g}/configs/c.1 ] && rmdir ${g}/configs/c.1
[ -d ${g}/strings/0x409 ] && rmdir ${g}/strings/0x409
rmdir ${g}
echo "Done."
}
case ${command} in
up)
ev3_usb_up
;;
down)
ev3_usb_down
;;
*)
echo "Usage: ev3-usb.sh up|down <udc_device>"
exit 1
;;
esac