Skip to content

Instantly share code, notes, and snippets.

@vshymanskyy
Last active April 19, 2016 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vshymanskyy/5085138 to your computer and use it in GitHub Desktop.
Save vshymanskyy/5085138 to your computer and use it in GitHub Desktop.
USSD requests using Huawei E1550 (probably other modems too) Tested on Win32 and Linux. requires Win32::SerialPort / Device::SerialPort and Device::Gsm::Pdu.
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Std;
use Device::Gsm::Pdu;
use XPlat::SerialPort;
# defaults
our ($opt_p, $opt_t, $opt_v, $opt_h, $opt_n);
$opt_t = 3;
my $USAGE = <<__EOU;
Usage: $0 -p io_port [-hvt] ussd_msg
Description:
Send and receive USSD messages using Huawei E1550 GSM/UMTS USB modem.
Options:
-p port Port to send and receive.
-t Timeout in seconds. Default: 3
-h Print this help.
-v Be verbose.
Examples:
Linux: $0 -p /dev/ttyUSB2 *100#
Win32: $0 -p COM6 *100#
__EOU
sub HELP_MESSAGE { print "$USAGE\n"; exit; }
sub VERSION_MESSAGE { };
getopts ('p:t:hv');
HELP_MESSAGE() if not $ARGV[0] or defined($opt_h) or not defined($opt_p);
my $ussd_req = Device::Gsm::Pdu::encode_text7($ARGV[0]);
$ussd_req =~ s/^..//;
print "Opening $opt_p\n" if $opt_v;
my $port = new XPlat::SerialPort($opt_p);
$port->baudrate(115200);
$port->databits(8);
$port->stopbits(1);
$port->parity("none");
$port->handshake("none");
$port->write_settings or die;
print "Sending PDU USSD request: $ussd_req ($ARGV[0])\n" if $opt_v;
$port->write("AT+CUSD=1,$ussd_req,15\r\n");
print "Waiting for USSD reply...\n" if $opt_v;
$port->read_char_time(0);
$port->read_const_time(1000*$opt_t);
my ($count, $buffer) = $port->read(4096);
my ($ussd_reply, $ussd_coding);
foreach (split(/\n/, $buffer)) {
chomp;
die "USSD error\n" if /^\+CUSD: 2$/;
if (/^\+CUSD: 0,\"([A-F0-9]*)\",([0-9]*)/) {
($ussd_reply, $ussd_coding) = ($1, $2);
print "USSD encoding: $ussd_coding\n" if $opt_v;
print "USSD reply: $ussd_reply\n" if $opt_v;
last;
}
die "Got unknown USSD message: $_\n" if /^\+CUSD:/;
}
$port->close or die;
if ($ussd_reply) {
print "Decoded: " if $opt_v;
if ($ussd_coding eq '15') {
print Device::Gsm::Pdu::pdu_to_latin1($ussd_reply), "\n";
} elsif ($ussd_coding eq '72') {
print Device::Gsm::Pdu::decode_text_UCS2('00'.$ussd_reply), "\n";
} else {
die "Could not decode: $ussd_reply,$ussd_coding\n";
}
} else {
die "No USSD reply!\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment