D-Link DWM-222 stick » History » Version 1
domi, 08/15/2018 07:08 PM
1 | 1 | domi | h1. D-Link DWM-222 stick |
---|---|---|---|
2 | |||
3 | !{width:300px}dwm222_pic.jpg! |
||
4 | |||
5 | This stick is available at multiple operators and it is quite cheap. If you want to get into Linux-based Qualcomm dongles that are easier to attach to your laptop than Quectel modems it might be a way to go. |
||
6 | *WARNING! |
||
7 | Current version of the DWM-222 does NOT expose ADB, so accessing the underlying Linux is currently not possible! HOWEVER there might be ways to enable this functionality, so keep reading, but BE AWARE BEFORE PUCHASING!* |
||
8 | |||
9 | It is just a D-Link branded version of cheaper dongles made in China. Some of them are WiFi access points with LTE backhaul using [[QCMAP]]. |
||
10 | Example of devices that are closely related: |
||
11 | * PTCL Charji Wingle R660 |
||
12 | * (?)D-Link DWR 901 (unsure, FIXME) |
||
13 | |||
14 | |||
15 | h2. Hardware |
||
16 | |||
17 | !{width:500px}pcb_pic.jpg! |
||
18 | |||
19 | Opening the stick requires just removing the back cover (which reveals the standard size SIM slot and the microSD card reader), then unscrewing the 3 screws. |
||
20 | The stick is based on the Qualcomm MDM9225 chipset. It is closely related to the MDM9625 apparently (based on the firmware analysis). |
||
21 | There are two antenna connectors (U.FL) exposed on the PCB. |
||
22 | |||
23 | h2. Software |
||
24 | |||
25 | The dongle is a typical USB WWAN modem. It requires usb_modeswitch to change from mass_storage mode (enables installation of driver) to modem mode. |
||
26 | Mass storage mode USB id: *2001:ab00* |
||
27 | WWAN USB id: *2001:7e35* |
||
28 | |||
29 | After the switch you'll see 4 @ttyUSB@ devices appearing in @/dev@. For me these devices only started to work after telling the @option@ driver about the USB id of the device: |
||
30 | <pre> |
||
31 | echo "2001 7e35" > /sys/bus/usb-serial/drivers/option1/new_id |
||
32 | </pre> |
||
33 | |||
34 | The devices are: |
||
35 | <pre> |
||
36 | /dev/ttyUSB0 --> DIAG |
||
37 | /dev/ttyUSB1 --> AT commands |
||
38 | /dev/ttyUSB2 |
||
39 | /dev/ttyUSB3 |
||
40 | /dev/cdc-wdm0 --> QMI |
||
41 | </pre> |
||
42 | |||
43 | h3. Drivers |
||
44 | |||
45 | If in mass_storage mode there is a Windows driver available with D-Link Connection Manager. It basically just switches the device to modem mode, and then provides a GUI to establish a connection. |
||
46 | Surprisingly D-Link provides Linux support for the dongle. A page is dedicated to guide you through the installation. https://eu.dlink.com/uk/en/support/faq/routers/mobile-routers/how-to-install-my-dwm-222-on-ubuntu |
||
47 | However it is not recommended to follow the instructions, because the 'driver' is just a collection of bash scripts that tries to configure PPP daemon. Interestingly it has a complete collection of MCC, MNC, APN triples for all operators around the world. Based on the IMSI queried from the SIM card it tries to find the right settings and feed them to pppd. |
||
48 | |||
49 | h2. Firmware |
||
50 | |||
51 | There are 2 firmware versions available for download currently: 2.0.1 and 2.0.8. https://eu.dlink.com/uk/en/products/dwm-222-4g-lte-usb-adapter#support |
||
52 | The dongle that I had came with an older version, 1.7.9. It doesn't really work for me, so I upgraded to 2.0.8: |
||
53 | |||
54 | h3. Upgrade process |
||
55 | |||
56 | Upgrade can only be done from Windows. The file provided is a self-extracting executable. After extracting the contents it turned out to be quite interesting: a collection of executables and batch files, as well as MBN and yaffs2 images. |
||
57 | After tracing the upgrade process I've established its steps roughly: |
||
58 | |||
59 | <pre> |
||
60 | Start 1key.bat -> Installs drivers (ADB, QDLoader, Fastboot) -> Runs dl.exe -> Device goes into QDL mode -> MBN files are flashed -> Device reboots. |
||
61 | </pre> |
||
62 | |||
63 | Now comes the tricky part: the bat files tries to reboot the device into @fastboot@ mode using ADB shell. However D-Link requested ADB to be turned off for the device, so the @fastboot@ part fails. Basically you'll end up with a device that has new DSP software, but the Android part is unchanged. Fortunately the device stays operational after the failed update, only its LED is stuck on white instead of different colors/blinking. |
||
64 | So the complete upgrade cycle would look like this (based on reading the bat files): |
||
65 | |||
66 | <pre> |
||
67 | Start 1key.bat -> Installs drivers (ADB, QDLoader, Fastboot) -> Runs dl.exe -> Device goes into QDL mode -> MBN files are flashed -> Device reboots |
||
68 | -> ADB shell to reboot into fastboot mode -> Android images are flashed using fastboot (rootfs, usr) -> Device rebooted again, check if it is not stuck in bootloader -> Done. |
||
69 | </pre> |
||
70 | |||
71 | h3. Analyzing the firmware |
||
72 | |||
73 | Since it is just YAFFS2 it was easy to unpack the firmware and poke around it. No encryption/signatures/etc. was in place. |
||
74 | It is, as suspected, Linux. |
||
75 | |||
76 | <pre> |
||
77 | # ls -lha |
||
78 | total 84K |
||
79 | drwxr-xr-x 20 root root 4,0K aug 10 14:58 . |
||
80 | drwxr-xr-x 5 root root 4,0K aug 10 15:30 .. |
||
81 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 bin |
||
82 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 boot |
||
83 | -rw-r--r-- 1 root root 47 aug 10 14:58 build.prop |
||
84 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 cache |
||
85 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 dev |
||
86 | drwxr-xr-x 30 root root 4,0K aug 10 14:58 etc |
||
87 | drwxr-xr-x 3 root root 4,0K aug 10 14:58 home |
||
88 | drwxr-xr-x 5 root root 4,0K aug 10 14:58 lib |
||
89 | lrwxrwxrwx 1 root root 12 aug 10 14:58 linuxrc -> /bin/busybox |
||
90 | drwxr-xr-x 10 root root 4,0K aug 10 14:58 media |
||
91 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 mnt |
||
92 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 proc |
||
93 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 sbin |
||
94 | lrwxrwxrwx 1 root root 11 aug 10 14:58 sdcard -> /media/card |
||
95 | drwxr-xr-x 3 root root 4,0K aug 10 14:58 share |
||
96 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 sys |
||
97 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 tmp |
||
98 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 usr |
||
99 | drwxr-xr-x 8 root root 4,0K aug 10 14:58 var |
||
100 | drwxr-xr-x 3 root root 4,0K aug 10 14:58 WEBSERVER |
||
101 | drwxr-xr-x 5 root root 4,0K aug 10 14:58 www |
||
102 | </pre> |
||
103 | |||
104 | The WEBSERVER and www directory are there for the WiFi router versions which use a web-based interface for settings. |
||
105 | |||
106 | I was mainly curious about ADB, so I followed the @/etc/init.d/usb@ script. It saves the USB device id of the device to a file, then based on the id it starts a bash script located in @/usr/bin/usb/compositions@ |
||
107 | |||
108 | <pre> |
||
109 | ls -lha bin/usb/compositions/ |
||
110 | total 228K |
||
111 | drwxr-xr-x 2 root root 4,0K aug 10 14:58 . |
||
112 | drwxr-xr-x 3 root root 4,0K aug 10 14:28 .. |
||
113 | -rw-r--r-- 1 root root 3,8K aug 10 14:28 2033 |
||
114 | -rw-r--r-- 1 root root 4,0K aug 10 14:28 2034 |
||
115 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 2037 |
||
116 | -rw-r--r-- 1 root root 3,8K aug 10 14:28 3443 |
||
117 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 3444 |
||
118 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 4030 |
||
119 | -rw-r--r-- 1 root root 3,8K aug 10 14:58 7e35 |
||
120 | -rw-r--r-- 1 root root 4,6K aug 10 14:28 7e35A |
||
121 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 7e37 |
||
122 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 7e38 |
||
123 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 7e39 |
||
124 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 7e3c |
||
125 | -rw-r--r-- 1 root root 3,8K aug 10 14:28 7e3d |
||
126 | -rw-r--r-- 1 root root 2,3K aug 10 14:28 9002 |
||
127 | -rw-r--r-- 1 root root 2,2K aug 10 14:28 901C |
||
128 | -rw-r--r-- 1 root root 2,8K aug 10 14:28 901D |
||
129 | -rw-r--r-- 1 root root 3,4K aug 10 14:28 9021 |
||
130 | -rw-r--r-- 1 root root 3,4K aug 10 14:28 9022 |
||
131 | -rw-r--r-- 1 root root 2,7K aug 10 14:28 9024 |
||
132 | -rw-r--r-- 1 root root 3,6K aug 10 14:28 9025 |
||
133 | -rw-r--r-- 1 root root 3,5K aug 10 14:28 9026 |
||
134 | -rw-r--r-- 1 root root 2,7K aug 10 14:28 902A |
||
135 | -rw-r--r-- 1 root root 2,7K aug 10 14:28 902B |
||
136 | -rw-r--r-- 1 root root 2,7K aug 10 14:28 902C |
||
137 | -rw-r--r-- 1 root root 2,8K aug 10 14:28 902D |
||
138 | -rw-r--r-- 1 root root 3,9K aug 10 14:28 902E |
||
139 | -rw-r--r-- 1 root root 3,3K aug 10 14:28 9043 |
||
140 | -rw-r--r-- 1 root root 3,0K aug 10 14:28 9046 |
||
141 | -rw-r--r-- 1 root root 2,4K aug 10 14:28 9047 |
||
142 | -rw-r--r-- 1 root root 3,5K aug 10 14:28 9049 |
||
143 | -rw-r--r-- 1 root root 2,2K aug 10 14:28 904A |
||
144 | -rw-r--r-- 1 root root 3,6K aug 10 14:28 9056 |
||
145 | -rw-r--r-- 1 root root 2,7K aug 10 14:28 9057 |
||
146 | -rw-r--r-- 1 root root 2,9K aug 10 14:28 9059 |
||
147 | -rw-r--r-- 1 root root 3,2K aug 10 14:28 905A |
||
148 | -rw-r--r-- 1 root root 3,0K aug 10 14:28 905B |
||
149 | -rw-r--r-- 1 root root 2,2K aug 10 14:28 9060 |
||
150 | -rw-r--r-- 1 root root 3,2K aug 10 14:28 9063 |
||
151 | -rw-r--r-- 1 root root 4,4K aug 10 14:28 9064 |
||
152 | -rw-r--r-- 1 root root 4,0K aug 10 14:28 9067 |
||
153 | -rw-r--r-- 1 root root 3,0K aug 10 14:28 9083 |
||
154 | -rw-r--r-- 1 root root 3,0K aug 10 14:28 9084 |
||
155 | -rw-r--r-- 1 root root 3,1K aug 10 14:28 9085 |
||
156 | -rw-r--r-- 1 root root 127 aug 10 14:28 empty |
||
157 | -rw-r--r-- 1 root root 2 aug 10 14:28 hsic_next |
||
158 | -rw-r--r-- 1 root root 5 aug 10 14:28 hsusb_next |
||
159 | </pre> |
||
160 | |||
161 | Looking into the file @7e35@ (the id of the D-Link device) reveals why ADB is missing - the Android USB Gadget is configured without ADB: |
||
162 | |||
163 | <pre> |
||
164 | # cat bin/usb/compositions/7e35 |
||
165 | |||
166 | #!/bin/sh |
||
167 | # |
||
168 | # Copyright (c) 2012, The Linux Foundation. All rights reserved. |
||
169 | # |
||
170 | # Redistribution and use in source and binary forms, with or without |
||
171 | # modification, are permitted provided that the following conditions are met: |
||
172 | # * Redistributions of source code must retain the above copyright |
||
173 | # notice, this list of conditions and the following disclaimer. |
||
174 | # * Redistributions in binary form must reproduce the above copyright |
||
175 | # notice, this list of conditions and the following disclaimer in the |
||
176 | # documentation and/or other materials provided with the distribution. |
||
177 | # * Neither the name of The Linux Foundation nor the names of its |
||
178 | # contributors may be used to endorse or promote products derived from |
||
179 | # this software without specific prior written permission. |
||
180 | # |
||
181 | # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||
182 | # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, |
||
183 | # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO |
||
184 | # EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
||
185 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
186 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
187 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
188 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
189 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
190 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
191 | |||
192 | # DESCRIPTION: DIAG + MODEM + AT + NMEA + QMI_RMNET + ADB + Mass Storage (Android) |
||
193 | |||
194 | echo "Switching to composition number 0x7e35" |
||
195 | |||
196 | if [ "$1" = "y" ]; then |
||
197 | num="1" |
||
198 | else |
||
199 | num="0" |
||
200 | fi |
||
201 | |||
202 | echo 0 > /sys/class/android_usb/android$num/enable |
||
203 | if [ "$2" = "y" ]; then |
||
204 | echo 0xAB00 > /sys/class/android_usb/android$num/idProduct |
||
205 | echo 0x2001 > /sys/class/android_usb/android$num/idVendor |
||
206 | echo mass_storage > /sys/class/android_usb/android$num/functions |
||
207 | echo 1 > /sys/class/android_usb/android$num/enable |
||
208 | else |
||
209 | run_9x15() { |
||
210 | echo 0x7e35 > /sys/class/android_usb/android$num/idProduct |
||
211 | echo 0x2001 > /sys/class/android_usb/android$num/idVendor |
||
212 | echo diag > /sys/class/android_usb/android0/f_diag/clients |
||
213 | echo smd,smd,tty > /sys/class/android_usb/android0/f_serial/transports |
||
214 | echo SMD,BAM2BAM > /sys/class/android_usb/android0/f_rmnet/transports |
||
215 | echo diag,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
216 | echo 1 > /sys/class/android_usb/android$num/enable |
||
217 | } |
||
218 | |||
219 | run_9x25() { |
||
220 | echo 0x7e35 > /sys/class/android_usb/android$num/idProduct |
||
221 | echo 0x2001 > /sys/class/android_usb/android$num/idVendor |
||
222 | echo diag > /sys/class/android_usb/android0/f_diag/clients |
||
223 | echo smd,smd,tty > /sys/class/android_usb/android0/f_serial/transports |
||
224 | echo SMD,BAM2BAM_IPA > /sys/class/android_usb/android0/f_rmnet/transports |
||
225 | echo diag,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
226 | echo 1 > /sys/class/android_usb/android$num/enable |
||
227 | } |
||
228 | |||
229 | run_9x25_v2() { |
||
230 | echo 0x7e35 > /sys/class/android_usb/android$num/idProduct |
||
231 | echo 0x2001 > /sys/class/android_usb/android$num/idVendor |
||
232 | echo 0123456789ABCDEF > /sys/class/android_usb/android$num/iSerial |
||
233 | echo diag > /sys/class/android_usb/android0/f_diag/clients |
||
234 | echo smd,smd,tty > /sys/class/android_usb/android0/f_serial/transports |
||
235 | echo QTI,BAM2BAM_IPA > /sys/class/android_usb/android0/f_rmnet/transports |
||
236 | echo diag,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
237 | echo 1 > /sys/class/android_usb/android$num/enable |
||
238 | } |
||
239 | |||
240 | case `source /usr/bin/usb/target` in |
||
241 | *9x15* ) |
||
242 | run_9x15 & |
||
243 | ;; |
||
244 | *9x25* ) |
||
245 | case `cat /sys/devices/soc0/revision` in |
||
246 | *1.0* ) |
||
247 | run_9x25 & |
||
248 | ;; |
||
249 | *2.* ) |
||
250 | run_9x25_v2 & |
||
251 | ;; |
||
252 | * ) |
||
253 | run_9x25 & |
||
254 | ;; |
||
255 | esac |
||
256 | ;; |
||
257 | * ) |
||
258 | run_9x15 & |
||
259 | ;; |
||
260 | esac |
||
261 | fi |
||
262 | |||
263 | </pre> |
||
264 | |||
265 | Simple adding @adb@ to the echos should be enough, based on the other script files. |
||
266 | |||
267 | So now the question arises: what kind of dongle would you need to buy that has ADB out of the box? I could tell you the USB device id of such devices: |
||
268 | |||
269 | <pre> |
||
270 | grep -r adb . |
||
271 | ./905A: echo diag,adb,usb_mbim:ecm_qc > /sys/class/android_usb/android$num/functions |
||
272 | ./905A: echo diag,adb,usb_mbim:ecm_qc > /sys/class/android_usb/android$num/functions |
||
273 | ./9025: echo diag,adb,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
274 | ./9025: echo diag,adb,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
275 | ./9025: echo diag,adb,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
276 | ./9022: echo diag,adb,rmnet > /sys/class/android_usb/android$num/functions |
||
277 | ./9022: echo diag,adb,rmnet > /sys/class/android_usb/android$num/functions |
||
278 | ./9022: echo diag,adb,rmnet > /sys/class/android_usb/android$num/functions |
||
279 | ./9059: echo rndis_qc,diag,adb:ecm_qc > /sys/class/android_usb/android$num/functions |
||
280 | ./9059: echo rndis,diag,adb:ecm_qc > /sys/class/android_usb/android$num/functions |
||
281 | ./9064: echo diag,adb,serial,rmnet:ecm_qc:usb_mbim > /sys/class/android_usb/android$num/functions |
||
282 | ./9064: echo diag,adb,serial,rmnet:ecm:usb_mbim > /sys/class/android_usb/android$num/functions |
||
283 | ./9064: echo diag,adb,serial,rmnet:ecm_qc:usb_mbim > /sys/class/android_usb/android$num/functions |
||
284 | ./9046: echo diag,adb,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
285 | ./9046: echo diag,adb,serial,rmnet,mass_storage > /sys/class/android_usb/android$num/functions |
||
286 | ./9024: echo rndis_qc,adb > /sys/class/android_usb/android$num/functions |
||
287 | ./9024: echo rndis,adb > /sys/class/android_usb/android$num/functions |
||
288 | ./9049: echo diag,adb,serial,rmnet,mass_storage,qdss > /sys/class/android_usb/android$num/functions |
||
289 | ./9049: echo diag,adb,serial,rmnet,mass_storage,qdss > /sys/class/android_usb/android$num/functions |
||
290 | ./9049: echo diag,adb,serial,rmnet,mass_storage,qdss > /sys/class/android_usb/android$num/functions |
||
291 | ./902D: echo rndis_qc,diag,adb > /sys/class/android_usb/android$num/functions |
||
292 | ./902D: echo rndis,diag,adb > /sys/class/android_usb/android$num/functions |
||
293 | ./901D: echo diag,adb > /sys/class/android_usb/android$num/functions |
||
294 | ./901D: echo diag,adb > /sys/class/android_usb/android$num/functions |
||
295 | ./9084: echo diag,qdss,adb,rmnet > /sys/class/android_usb/android$num/functions |
||
296 | ./9084: echo diag,qdss,adb,rmnet > /sys/class/android_usb/android$num/functions |
||
297 | ./902B: echo rndis_qc,adb,mass_storage > /sys/class/android_usb/android$num/functions |
||
298 | ./902B: echo rndis,adb,mass_storage > /sys/class/android_usb/android$num/functions |
||
299 | ./9085: echo diag,adb,usb_mbim,gps > /sys/class/android_usb/android$num/functions |
||
300 | ./9085: echo diag,adb,usb_mbim,gps > /sys/class/android_usb/android$num/functions |
||
301 | ./2034: echo rndis_qc,diag,serial,adb,mass_storage > /sys/class/android_usb/android$num/functions |
||
302 | ./2034: echo rndis,diag,serial,adb,mass_storage > /sys/class/android_usb/android$num/functions |
||
303 | ./2034: echo rndis,diag,serial,adb,mass_storage > /sys/class/android_usb/android$num/functions |
||
304 | ./9060: echo diag,qdss,adb > /sys/class/android_usb/android$num/functions |
||
305 | ./9056: echo diag,adb,serial,rmnet,mass_storage,audio > /sys/class/android_usb/android$num/functions |
||
306 | ./9056: echo diag,adb,serial,rmnet,mass_storage,audio > /sys/class/android_usb/android$num/functions |
||
307 | ./9056: echo diag,adb,serial,rmnet,mass_storage,audio > /sys/class/android_usb/android$num/functions |
||
308 | </pre> |
||
309 | |||
310 | It would be great to find out the actual vendor of these device IDs, so we can offer people ideas what to buy. |