Friday, August 24, 2018

HUAWEI 3G MODEM & CHAN-DONGLE FOR ASTERISK 13

Huawei E1691 Specifications: AWS 1700/2100; GSM 1900/1800/900/850 MHz
lsusb: Bus 002 Device 003: ID 12d1:1446 Huawei Technologies Co., Ltd. Broadband stick (modem on)
sudo apt-get install usb-modeswitch
Edit /etc/usb_modeswitch.conf
#————–
# Huawei E1692
DefaultVendor= 0x12d1
DefaultProduct= 0x1446
TargetVendor= 0x12d1
TargetProduct= 0x140c
MessageContent=”55534243000000000000000000000011060000000000000000000000000000″
CheckSuccess=5
#—————————–
sudo usb_modeswitch -I -W -c /etc/usb_modeswitch.conf
#———-
found USB ID 12d1:140c
vendor ID matched
product ID matched
….
Found target device, open it
Found target device 004 on bus 002
Target device description data
————————-
Manufacturer: HUAWEI Technology
Product: HUAWEI Mobile
Serial No.: not provided
————————-
Found correct target device
Mode switch succeeded. Bye!
#—————————–
lsusb: Bus 002 Device 004: ID 12d1:140c Huawei Technologies Co., Ltd. E180v
USB device 12d1:140c is handled in recent kernels by the option driver.
Usage of chan_dongle in Asterisk
wget https://github.com/jstasiak/asterisk-chan-dongle/archive/asterisk11.zip
wget https://github.com/oleg-krv/asterisk-chan-dongle/archive/asterisk13.zip
Edit: dongle.conf
module load chan_dongle.so
chan_dongle CLI commands and dialplan howto: chan-dongle-use

What to do if ttyUSB number change?

For example, you plug two modems but in different order, and when plug modem X first it becomes /dev/ttyUSB[0-2] (dongle0 as defined in dongle.conf)
But if plug modem Y first it becomes /dev/ttyUSB[0-2] (dongle0) and modem X becomes /dev/ttyUSB[3-5] (dongle1)
The same can happen when rebooting computer, sometimes X becomes dongle0, but sometimes dongle1.
To avoid this indetermination you may use

udev rules

Create /etc/udev/rules.d/99-huawei-link.rules with the following lines
# add symlinks for device based on USB bus address i.e. physical USB slot 
ACTION!="add|change", GOTO="device_huawei_end" 
#SUBSYSTEM!="usb", GOTO="device_huawei_end" 
#ATTRS{idVendor}!="12d1", GOTO="device_huawei_end" 
#ATTRS{idProduct}=="1446", GOTO="device_huawei_link" 
#ATTRS{idProduct}=="140c", GOTO="device_huawei_link" 
#ATTRS{idProduct}=="1001", GOTO="device_huawei_link" 
#GOTO="device_huawei_end" 

LABEL="device_huawei_link" 

# USB slot from left to right (back look) 
# left 
KERNEL=="ttyUSB[0-9]*", ID=="1-1:1.0", SYMLINK+="hw-modem-0" 
KERNEL=="ttyUSB[0-9]*", ID=="1-1:1.1", SYMLINK+="hw-audio-0" 
KERNEL=="ttyUSB[0-9]*", ID=="1-1:1.2", SYMLINK+="hw-data-0" 
KERNEL=="ttyUSB[0-9]*", ID=="1-1:1.3", SYMLINK+="hw-net-0" 

# left middle
KERNEL=="ttyUSB[0-9]*", ID=="1-2:1.0", SYMLINK+="hw-modem-1" 
KERNEL=="ttyUSB[0-9]*", ID=="1-2:1.1", SYMLINK+="hw-audio-1" 
KERNEL=="ttyUSB[0-9]*", ID=="1-2:1.2", SYMLINK+="hw-data-1" 
KERNEL=="ttyUSB[0-9]*", ID=="1-2:1.3", SYMLINK+="hw-net-1" 

# right middle
KERNEL=="ttyUSB[0-9]*", ID=="1-3:1.0", SYMLINK+="hw-modem-2" 
KERNEL=="ttyUSB[0-9]*", ID=="1-3:1.1", SYMLINK+="hw-audio-2" 
KERNEL=="ttyUSB[0-9]*", ID=="1-3:1.2", SYMLINK+="hw-data-2" 
KERNEL=="ttyUSB[0-9]*", ID=="1-3:1.3", SYMLINK+="hw-net-2" 

# right 
KERNEL=="ttyUSB[0-9]*", ID=="1-4:1.0", SYMLINK+="hw-modem-3" 
KERNEL=="ttyUSB[0-9]*", ID=="1-4:1.1", SYMLINK+="hw-audio-3" 
KERNEL=="ttyUSB[0-9]*", ID=="1-4:1.2", SYMLINK+="hw-data-3" 
KERNEL=="ttyUSB[0-9]*", ID=="1-4:1.3", SYMLINK+="hw-net-3" 

LABEL="device_huawei_end" 
In this case, ID == “” indicate what is displayed in your dmesg output after plug the modem in this USB port in lines of like
[ 4854.344460] option 1-1:1.0: GSM modem (1-port) converter detected 
In dongle.conf use this symbolic links instead of /dev/ttyUSBx files
[dongle0] 
audio=/dev/hw-audio-0 
data=/dev/hw-data-0 

modems discovery

Since Jan 08, 2011 and revision 150 of http://code.google.com/p/asterisk-chan-dongle you can use also simple but powerful feature - discovery modems by IMEI or/and IMSI numbers. For example:
[dongle0]
imei=123456789012345

[dongle1]
imsi=543210987654321

[dongle2]
imei=999999999999999
imsi=888888888888888
Each time before device opening chan_dongle will search for devices with predefined VendorID:ProductID pairs, detect ports or this devices, and check its IMEI and IMSI.

modem detaching from system when trying to call

When received incoming call or begining outgoing call chan_dongle lost connection to device and device disappears from system, but after a while, it comes back.
In asterisk CLI appears something like that
-- Attempting call on Dongle/dongle0/7495**** for application Playback(silence/10) (Retry 1) 
-- Dongle dongle0 has disconnected 
[Dec 30 16:12:09] NOTICE[26493]: pbx_spool.c:339 attempt_thread: Call failed to go through, reason (1) Hangup 
debian*CLI> 
-- Dongle dongle0 trying to connect on /dev/ttyUSB2... 
-- Dongle dongle0 has connected, initializing... 
-- Dongle dongle0 initialized and ready
In kernel log and dmesg
Dec 30 15:14:10 VoipGSM kernel: [ 864.438822] option: option_instat_callback: error -84 
Dec 30 15:14:10 VoipGSM kernel: [ 864.448060] usb 5-1: USB disconnect, address 3 
Dec 30 15:14:10 VoipGSM kernel: [ 864.448817] option: option_instat_callback: error -108
A possible reason is bad firmware 11.608.12.10.209 in Huawei E1550. This version of firmware allow voice calls in Windows with Mobile Partner, but seems not to work in Linux :)
Another reason is the lack of power for device at peak load when call is starting.

SMS and USSD truncated to first \n symbol

For example you send “Hello!\nHow are you?” but asterisk show only “Hello!”
The reason for this hidden in asterisk variable subsitution, and can be solved by use BASE64_DECODE function:
${BASE64_DECODE(${SMS_BASE64})}
${BASE64_DECODE(${USSD_BASE64})}

Caller party not hearing ringback tone

When forward call from GSM → SIP caller party does not hear ringback tone.
To solve this problem you can use add options 'm' (music on hold) or 'r' for Dial() application
exten => s,n,Dial(SIP/111@sip,30,m)
exten => s,n,Dial(SIP/111@sip,30,r)

DTMF symbols A,B,C,D not sent by chan_dongle

Sorry, but Huawei modems not support sending this symbols, and asterisk try to send these symbols in band.

DTMF symbols not received from dongle

At first, DTMF in GSM network are sent over a voice channel, this mean you must first answer to incoming call or establish outgoing for receive DTMF.
Other possible reason is usage of asterisk version 1.6.2.16-rc1, return back to 1.6.2.13 solve this trouble.
Check setting of dongle.conf
dtmf=inband
or
dtmf=relax
In case of problems with DTMF we recommend enable dtmf logging in logger.conf
dtmf => dtmf

DTMF symbols not sent to dongle

At first, DTMF in GSM network are sent over a voice channel, this mean you must first answer to incoming call or establish outgoing for send DTMF.

Duplicate of received DTMF symbols

Has several reasons of duplication of DTMF:
  • when asterisk receive DTMF symbol from chan_dongle it passed symbol to other leg of call but DTMF tones also passed in band. I.e. other side receive duplicated DTMF symbol
  • GSM network vulnerable for echo
  • GSM phone of party also produce echo
For these reasons DTMF symbol can walk infinitely from phone to phone if asterisk bridge GSM and GSM.

One way voice on Huawei E150

By default with E150 local party can listen what talking GSM party, but GSM party listen silence.
E150 require write zero length frame after each 320 bytes 20ms of voice data written. But linux driver named option, nothing know about this E150 'feature'.
Solution is build special versions of option driver and driver for only diagnostic port of E150. The sources of these can be found on https://github.com/Novax/kmod-huawei-voice
Brief instruction for debian and ubuntu: Install git
sudo apt-get install git
Install linux kernel headers for version of your kernel
sudo apt-get install linux-headers-2.6.35-22 
Install sources of kmod-huawei-voice
cd /usr/src
git clone git://github.com/Novax/kmod-huawei-voice.git
Build kernel module
cd kmod-huawei-voice
make
Install module (not fully yet)
/etc/init.d/asterisk stop
rmmod option
insmod ./option.ko
insmod ./huawei_voice.ko
/etc/init.d/asterisk start
Other solution implemented in private chan_dongle and custom patch to option driver.
This working by calling new ioctl for write zero URB to device for 'push' data.
This way allow have E150 and other dongles in one system without colissions.
Note: E150 is USB1.1 and can be working unstable.

Running asterisk as non-root

A lot of people is running Asterisk as “asterisk” user. This may cause chan_dongle not detecting USB modems properly. In that case, you need to give permissions for ttyUSB ports. You can do that automatically by creating file /etc/udev/rules.d/92-dongle.rules and adding:
KERNEL=="ttyUSB*", MODE="0666", OWNER="asterisk", GROUP="uucp"
Other posible solution is to set runuser/rungroup settings in asterisk.conf file.
rungroup = dialout
In other words owner, group, permissions on /dev/ttyUSBx files must allow read and write operations for asterisk's EUID, EGID

Console AT commands

You can send AT commands to any modem using
CLI>dongle cmd <device> <AT_command>
Some useful AT commands:
AT commandDescription
AT+CCWA=0,0,1disable call-waiting
AT+CFUN=1,1reboot modem
AT^CARDLOCK=“<code>”send unlock code
AT^SYSCFG=13,0,3FFFFFFF,0,3modem 2G only, automatic search any band, no roaming
AT^SYSCFG=2,0,3FFFFFFF,2,4Any
AT^SYSCFG=13,1,3FFFFFFF,2,42G only
AT^SYSCFG=14,2,3FFFFFFF,2,43G only
AT^SYSCFG=2,1,3FFFFFFF,2,42G preferred
AT^SYSCFG=2,2,3FFFFFFF,2,43G preferred
AT^U2DIAG=0enable modem function only
ATIget relevant information from modem
ATZreset modem configuration
AT+CIMIread IMSI
AT+CLCK=“SC”,0,“<pin>”disable PIN verification

Receive SMS and USSD

You can handle received SMS and USSD using sms and ussd exten, respectively.
Example for received sms
[dongle-incoming-sms]
exten => sms,1,Noop(Incoming SMS from ${CALLERID(num)} ${BASE64_DECODE(${SMS_BASE64})})
exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLENAME} - ${CALLERID(num)}: ${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/asterisk/sms.txt)
exten => sms,n,Hangup()
Example for received USSD
[dongle-incoming-ussd]
exten => ussd,1,Noop(Incoming USSD: ${BASE64_DECODE(${USSD_BASE64})})
exten => ussd,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLENAME}: ${BASE64_DECODE(${USSD_BASE64})}' >> /var/log/asterisk/ussd.txt)
exten => ussd,n,Hangup()
Also note, execution of this exten takes place in a “Local” channel.
Always define sms and ussd extens for context where you handle incoming calls for dongle device! Otherwise, incoming SMS or USSD can execute extensions for voice call with unpredictable results.
[dongle-incoming]
include => dongle-incoming-sms
include => dongle-incoming-ussd
Also note that h exten is executed for SMS/USSD just before Local channel is destroyed.

Receive SMS and USSD

You can handle received SMS and USSD using sms and ussd exten, respectively.
Example for received sms
[dongle-incoming-sms]
exten => sms,1,Noop(Incoming SMS from ${CALLERID(num)} ${BASE64_DECODE(${SMS_BASE64})})
exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLENAME} - ${CALLERID(num)}: ${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/asterisk/sms.txt)
exten => sms,n,Hangup()
Example for received USSD
[dongle-incoming-ussd]
exten => ussd,1,Noop(Incoming USSD: ${BASE64_DECODE(${USSD_BASE64})})
exten => ussd,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLENAME}: ${BASE64_DECODE(${USSD_BASE64})}' >> /var/log/asterisk/ussd.txt)
exten => ussd,n,Hangup()
Also note, execution of this exten takes place in a “Local” channel.
Always define sms and ussd extens for context where you handle incoming calls for dongle device! Otherwise, incoming SMS or USSD can execute extensions for voice call with unpredictable results.
[dongle-incoming]
include => dongle-incoming-sms
include => dongle-incoming-ussd
Also note that h exten is executed for SMS/USSD just before Local channel is destroyed.