Thursday, January 19, 2017

Notes on GSM USB dongles on linux.

Analyzing Huawei GSM dongles

In the last few months I've been writing drivers for Huawei GSM dongles. In particular to be used in combination with the Android RIL (Radio Interface Layer). In general Android runs on top of a Linux Kernel. The drivers that ships with GSM dongles typically works with Windows software. So we often have to do some reverse engineering. 

Here are my notes:

My target environment is a Linux Kernel 2.6....  My first step is to see if it works with the Windows software. Does the dongle pick up a signal. Can it register to a network. etc. 
Next step, setup a connection by providing the relevant APN, username and password. 

Huawei dongles typically ships with variations of Mobinil software. There is an option to use different connection type. RAS (modem) or NDIS

Selecting RAS (modem) mode
When you select the RAS (modem) we can use a tool like USBlyzer to inspect the AT commands that are used to register the the GSM dongle to the network.

There are generic AT commands but  also vendor specific AT commands.

... to be continued.


When switching to Linux the first challenge you might run into is that the device nodes are not created. Typically their modem software is included inside the GSM dongle and will be installed by telling the OS that it is a mass storage device, or tells the OS is behaves as a CD-rom. And it launches the install software.

In order to stop fooling the OS, we can use a tool USBMode_switch. The site has good forum discussions and a lot of hints to get your specific vendor dongle recognized. Most linux distros have a very recent version installed. What you might notice is that the product id from the GSM dongle is changing. 
You can see this when you call 'lsusb' and do this a couple of times (every 5 sec) while putting in the GSM dongle. 
You will see the USB being recognized by linux. It disappears briefly and reappears with a different product id.  You can see with 'dmesg' that new device nodes are being created. If that is not the case you first have to go over this hump. 

AT commands 

AT+CLAC will reveal most (not all) supported commands for the stick
There are different options to send the commands and monitory the result.

I've used putty on linux and start a serial connection type. (the /dev/ttyUSB3 is just an example.)

A bit more primitive but still working is to open to shell sessions.
Monitor the output in one session:

cat /dev/ttyUSB1

And in another terminal session, send the at commands.:

echo "AT^SETPORT=?" > /dev/ttyUSB1

The question is to find out which node you can use. And I've only come to a trial and error mode.
I quickly try the commands
cat /dev/ttyUSB1
cat /dev/ttyUSB2
cat /dev/ttyUSB3
cat /dev/ttyUSB4
To find out on which node I can communication. You will often see some AT^BOOT messages, ^RSSI, ^CSNR, ^MODE messages  passing by. They are rather an annoyance when you use putty. So the first commands I use during a putty session is to

  • turn off the boot messages with  AT^BOOT=0,0
  • turn off RSSI reporting with AT^CURC=0

The output of the AT^SETPORT=?" will give you a list of the different 'ports'.


You can enable /disable these 'ports' by enumerating them in the AT^SETPORT="A1,A2;1,2"
This would enable modem and pcui on ttyUSB0 and ttyUSB1.

If you change the order AT^SETPORT="A1,A2;2,1"
The modem and pcui will be on ttyUSB1 and ttyUSB0.

I'm not sure how to reset a dongle to factory setting to restore the port mode. But you can imagine, you have to be carefull with these AT commands. If you disable the Application interface (PCUI) I would not know of a mechanism to undo you changes (maybe via the NDIS interface?)

echo -e "AT^GETPORTMODE" > /dev/ttyUSB1

output:: /

(suggesting it was 1,7,3,2)

# echo -e "AT^SETPORT=\"A1,A2;1,2\"" > /dev/ttyUSB1

plug in and out the dongle.
ls /dev/ttyU*
/dev/ttyUSB0  /dev/ttyUSB1

# echo "AT^GETPORTMODE" > /dev/ttyUSB1


E353 specific

TIGO dongle:

echo "AT^SYSCFG=?" > /dev/ttyUSB1
^SYSCFG:(2,13,14,16),(0-3),((400380,"GSM900/GSM1800/WCDMA2100"),(4a80000,"GSM850/GSM1900/WCDMA850/WCDMA1900"),(3fffffff,"All Bands")),(0-2),(0-4)

Probably default is 
echo -e "AT^SETPORT=\"A1,A2;1,7,3,2,A1\"" > /dev/ttyUSB1

3 Dongle:

echo "AT^GETPORTMODE" > /dev/ttyUSB4


"AT^SYSCFG=?" > /dev/ttyUSB4

make files explained if you did not grew up with them

Here is a nice post on how to define makefiles for a go project and actually teaching you some makefile constructs: