Recently, while cleaning my flat, I found an old Huawei E3131 USB modem. I planed to throw it away, but then I reminded myself that this simple device, as virtually all modems, supports a primitive text based interface known as “AT commands”. And so I started thinking about spending a few hours of my time sending AT commands and figuring out what is actually possible. This post is the result of this few hours of hacking. Enjoy!
When I connected the modem to my PC it was immediately
recognized as both an USB Drive and an GSM modem.
Grepping through dmesg
revealed that three serial port
terminals where created at /dev/ttyUSB0
,
/dev/ttyUSB1
and /dev/ttyUSB2
:
$ dmesg | grep tty
[29167.640728] usb 3-9: GSM modem (1-port) converter now attached to ttyUSB0
[29167.640808] usb 3-9: GSM modem (1-port) converter now attached to ttyUSB1
[29167.640861] usb 3-9: GSM modem (1-port) converter now attached to ttyUSB2
To be honest I expected only a single tty
file…
Running stty
command on ttyUSB0
returned
some useful information, including
baud rate:
$ stty -F /dev/ttyUSB0
speed 9600 baud; line = 0;
eof = ^A; min = 1; time = 0;
-brkint -icrnl ixoff ixany -imaxbel
-opost -onlcr
-icanon -echo -echoe
-
before an option name means that this option is disabled.
Explanations for all options can be found in man stty
.
For example -echo
means that the characters that we
are writing, are not visible on the screen.
That is not very comfortable but can be changed easily
(you can try it yourself in bash by executing stty -echo
to disable
and stty echo
to enable echo).
To connect to ttyUSB0
I used minicom
:
sudo apt install minicom
We need to create a minicom
configuration first.
For some reason minicom
was not
able to save it’s config file in my home directory and
insisted on saving it into /etc/minicom/
and so I
have to run it with sudo
:
sudo minicom -s
Configuring minicom
is like a journey to 80s,
entire UI is text based:
First we need to go into “Serial port setup” section:
and change “Serial Device” to
/dev/ttyUSB0
(to do this press A, change the field value and press either
Enter to save or Escape to cancel).
Then we need to change baud rate (press E):
On this screen press C and then Enter.
Next we need to go into “Screen and Keyboard” section and
enable echo (press Q) and then Enter:
We need to enable local echo (on the minicom side)
because, as
stty
indicated
the serial port itself does not support it.
Then we need to return to the main menu (press Enter)
and select “Save setup as…” option. I saved
my config under huawei2
name. Then we should choose
“Exit from Minicom”. If you chose “Exit” use Ctrl+A
followed by X to exit.
Now we can start minicom
without sudo
:
minicom huawei2
and execute our first AT command which is just AT
.
The modem should respons with OK
if everything works:
To find out what options are supported by my modem, I googled for “huawei e3131 at command interface specification” and found a PDF document describing supported AT commands. By the way AT commands are de facto standard and could be used with any modem.
TIP: To exit minicom
press Ctrl+A followed by X (must be upper case).
WARNING: In the following sections I assume that we inserted a working SIM card into the modem.
Obtaining information from the modem
We can obtain a lot of information about our modem and the SIM card just by running AT commands. For example we may ask the modem for its phone number:
AT+CNUM
+CNUM: "NUMER WLASNY","+48999123999",145
OK
(“NUMER WLASNY” is “MY OWN NUMBER” in Polish), or for its IMEI number:
AT+CGSN
865459999999999
OK
To read a modem flag or a setting we need to run a command
in AT+CMD?
format.
For example to obtain the character set used by the modem
we send AT+CSCS?
command:
AT+CSCS?
+CSCS: "IRA"
OK
To check what values are acceptable for this flag
we run a command in AT+CMD=?
format:
AT+CSCS=?
+CSCS: ("IRA","UCS2","GSM")
OK
And to set flag/setting value we execute
a command in AT+CMD=value
format like AT+CSCS="GSM"
:
AT+CSCS="GSM"
OK
AT+CSCS?
+CSCS: "GSM"
OK
Network signal strength can be checked using AT+CSQ
command:
AT+CSQ
+CSQ: 23,99
OK
The response has format +CSQ: signal-strength, error-rate
.
Signal strength varies from 31 (very good)
to 0 (very poor / lack of signal).
In my case bit error rate is not supported (99) by the modem.
AT+COPS
command allows us to check the
current network and to get a list of
the present networks:
AT+COPS?
+COPS: 0,0,"Plus",0
OK
AT+COPS=?
+COPS: (2,"Plus","PLUS","26001",0),
(1,"Plus","PLUS","26001",2),
(3,"T-Mobile PL","T-Mobile PL","26002",2),
(3,"Orange PL","Orange","26003",2),
//... OUTPUT TRUNCATED
OK
Sending USSD codes
USSD codes (short codes) like “*100#” are quite useful,
we can use them to check money amount on our account or
to change the current tariff.
Let’s see how to send them using AT commands.
First hurdle to overcome is
the encoding used while sending an USSD code.
By default the codes must be encoded using
GSM7Bit encoding, which is not
related to 7-bit ASCII in any way.
I couldn’t find any online encoder/decoder for this
encoding, but fortunatelly
I found a pice of code that does exactly what we want:
MessagingUtils.java
And so I added a main
method and pasted the code to
www.compilejava.net
to obtain an online converter.
You can see the final, “paste ready” code
here.
Encoding *100#
in GSM7Bit gives us AA180C3602
.
Now we may issue our USSD request using AT+CUSD
command:
OK
AT+CUSD=1,"AA180C3602",15
OK
+CUSD: 0,"C135BD1E66BBF3A0393DEC06ADDF6E7A1844668741EE7ABB2CAF8368B85C2E97CBE572B91C48078AB160301094E97481966F37FD0DBA87F5EE3288FC0691DDE93048866BC1722D192C9603C5623A1A4D378301",15
1
(first value in the request) means that we want to see the response,
15
(the last value) is the encoding type that we are using.
Next we need to use our GSM7Bit decoder to obtain plain text from the network response (in Polish):
Aktualny stan konta dla numeru 48999999999 : 1,00 PLN.
Konto wazne do dnia 28-09-2019 11:44:30
Sending and receiving SMS
Our next step will be to send and to receive an SMS:
AT+CMGF=1
OK
AT+CMGS="+48333666999"
> Hello, world!
+CMGS: 7
OK
Before we send a message we must switch to the text mode,
which can be done by issuing AT+CMGF=1
command.
The default mode is the PDU mode, which requires
creating and parsing PDU binary frames.
To send an SMS AT+CMGS="phone-number"
command is used.
After executing AT+CMGS
, a command prompt (>
) will
appear allowing us to write our message.
When we are done we press Ctrl+Z,
few seconds later the message will be delivered.
To list received and sent messages we can use AT+CMGL
command:
AT+CMGL=?
+CMGL: ("REC UNREAD","REC READ","STO UNSENT","STO SENT","ALL")
OK
AT+CMGL="ALL"
+CMGL: 0,"REC READ","+48111222333",,"19/09/23,16:01:42+08"
Pszczolka Maja
OK
Remember to run this command in the text mode (AT+CMGF=1
),
otherwise you will see hex encoded binary PDU frames.
First value in the row is the message index (0
).
We may use this index to either read the message:
AT+CMGR=0
+CMGR: "REC READ","+48111222333",,"19/09/23,16:13:03+08"
Pszczolka Maja
or to remove it:
AT+CMGD=0
OK
AT+CMGL="ALL"
OK
Playing with the phone book entries
AT+CPBR
command can be used to read SIM card phone book entries:
AT+CPBR=?
+CPBR: (1-250),40,20
OK
AT+CPBR=1,10
+CPBR: 1,"*110#",129,"Obsluga konta"
+CPBR: 2,"112",129,"Nr.alarmowy112"
+CPBR: 3,"999",129,"Pogotowie Rat."
+CPBR: 4,"997",129,"Policja"
+CPBR: 5,"998",129,"Straz pozarna"
+CPBR: 6,"+48601100100",145,"WOPR"
+CPBR: 7,"+48601100300",145,"GOPR/TOPR"
+CPBR: 8,"+48601102601",145,"Biuro obslugi"
+CPBR: 9,"5555",129,"Zasil konto"
+CPBR: 10,"*100#",129,"Stan konta"
AT+CPBR=?
returns supported range of indexes ((1-250)
; some of them
may be empty), max. phone number length (40
) and max.
entry name length (20
).
Using this information we may read phone book entries using
AT+CPBR=<<index-range>>
command.
When the phone number starts with +
its type is 145
otherwise its type is 129
.
Adding a phone book entry is very simple:
AT+CPBW=25,"111222333",129,"foo"
OK
AT+CPBR=25
+CPBR: 25,"111222333",129,"foo"
OK
The same command can be used to remove a phone book entry:
AT+CPBW=25
OK
AT+CPBR=25
+CME ERROR: 22
RING RING RING
AT commands can also be used to make and receive phone calls.
Voice is send/received in WAVE format.
Unfortunately I cannot obtain even a simplest RING
notification
from my modem.