summaryrefslogtreecommitdiffstats
path: root/lib/network/connection/cellular_card.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/network/connection/cellular_card.pm')
-rw-r--r--lib/network/connection/cellular_card.pm180
1 files changed, 180 insertions, 0 deletions
diff --git a/lib/network/connection/cellular_card.pm b/lib/network/connection/cellular_card.pm
new file mode 100644
index 0000000..9132f49
--- /dev/null
+++ b/lib/network/connection/cellular_card.pm
@@ -0,0 +1,180 @@
+package network::connection::cellular_card;
+
+use base qw(network::connection::cellular);
+
+use strict;
+use common;
+
+sub get_type_name() { N("GPRS/Edge/3G") }
+sub get_type_icon() { 'cellular-24.png' }
+sub get_devices() {
+ require detect_devices;
+ my @maybe_usbserial_modules = ('usbserial_generic', 'unknown');
+ my @serial = grep { $_->{description} =~ /GPRS|EDGE|3G|UMTS|H.DPA/i } detect_devices::matching_driver('serial_cs', 'usbserial', @maybe_usbserial_modules);
+ member($_->{driver}, @maybe_usbserial_modules) and $_->{driver} = 'usbserial' foreach @serial;
+ @serial, detect_devices::probe_category('network/cellular');
+}
+sub get_metric { 40 }
+sub get_interface() { "ppp0" }
+
+sub get_packages { 'comgt', 'ppp' }
+
+my @thirdparty_settings = (
+ {
+ name => 'nozomi',
+ description => 'Option GlobeTrotter 3G/EDGE and FUSION+',
+ url => 'http://www.pharscape.org/',
+ kernel_module => 1,
+ },
+);
+
+sub get_thirdparty_settings() {
+ \@thirdparty_settings;
+}
+
+sub guess_hardware_settings {
+ my ($self) = @_;
+ $self->{hardware}{pin} ||= chomp_(cat_("/etc/sysconfig/network-scripts/pin-" . $self->get_interface));
+}
+
+sub get_tty_device {
+ my ($self) = @_;
+ $self->{device}{device} ?
+ "/dev/" . $self->{device}{device} :
+ $self->get_driver eq "nozomi" ?
+ "/dev/noz0" :
+ "/dev/ttyUSB0";
+}
+
+sub network_scan_is_slow() { 1 }
+
+sub get_networks {
+ my ($self) = @_;
+ my $cmd = "gcom -d " . $self->get_tty_device;
+ my ($network, $state) = `$cmd reg` =~ /^Registered on \w+ network: "(.*)",(\d+)$/m;
+ my ($strength) = `$cmd sig` =~ /^Signal Quality:\s+(\d+),\d+$/;
+ $self->{networks} = $network && {
+ $network => {
+ name => $network,
+ signal_strength => $strength * 5,
+ current => $state == 2,
+ }
+ };
+}
+
+sub get_hardware_settings {
+ my ($self) = @_;
+ [ { label => N("PIN number"), val => \$self->{hardware}{pin}, hidden => 1 } ];
+}
+
+sub get_peer_default_options {
+ my ($self) = @_;
+ $self->SUPER::get_peer_default_options,
+ "noccp", # disable CCP to avoid warning messages
+ "debug";
+}
+
+sub build_peer {
+ my ($self) = @_;
+ $self->SUPER::build_peer;
+ #- don't run gcom for now, it hangs on ttyUSB0 devices when run from pppd
+ #- $self->{access}{peer}->{init} = "gcom -d $dev < $pin_file"
+}
+
+sub write_settings {
+ my ($self) = @_;
+
+ $self->write_cellular_settings;
+
+ my $interface = $self->get_interface;
+ my $pin_file = "/etc/sysconfig/network-scripts/pin-$interface";
+
+ output_with_perm($pin_file, 0600, $self->{hardware}{pin} . "\n");
+
+ my $cid = 3;
+ $self->{access}{at_commands} = [
+ "AT+CPIN?",
+ # Set +CGEE to 2
+ "AT+CMEE=2",
+ qq(AT+CGDCONT=$cid,"IP","$self->{access}{apn}"),
+ # Setup +CGEQREG (QoS, don't set it for now)
+ # qq(AT+CGEQREQ=3,3,64,384,0,0,2,0,"0E0","0E0",3,0,0),
+ # Attached to network, will return 1
+ "AT+CGATT?",
+ ];
+ $self->{access}{dial_number} = "*99***$cid#";
+
+ $self->SUPER::write_settings;
+}
+
+sub prepare_device {
+ my ($self) = @_;
+
+ my $driver = $self->get_driver;
+ require modules;
+ my $modules_conf = !is_empty_hash_ref($::o) ? $::o->{modules_conf} : modules::any_conf->read;
+ modules::load_and_configure($modules_conf, $driver,
+ if_($driver eq 'usbserial', join(
+ ' ',
+ "vendor=0x" . sprintf("%4x", $self->{device}{vendor}),
+ "product=0x" . sprintf("%4x", $self->{device}{id}))));
+ $modules_conf->write if !ref $::o;
+ sleep 2 if $driver eq 'usbserial';
+}
+
+sub check_device {
+ my ($self) = @_;
+
+ my $dev = $self->get_tty_device;
+ if (! -e $dev) {
+ $self->{device}{error} = N("Unable to open device %s", $dev);
+ return;
+ }
+
+ 1;
+}
+
+sub check_hardware {
+ my ($self) = @_;
+
+ my $device_ready = 0;
+
+ require IPC::Open2;
+ require IO::Select;
+ require c;
+ use POSIX qw(:errno_h);
+
+ my $pid = IPC::Open2::open2(my $cmd_out, my $cmd_in, "gcom", "-d", $self->get_tty_device);
+ common::nonblock($cmd_out);
+ my $selector = IO::Select->new($cmd_out);
+ while ($selector->can_read) {
+ local $_;
+ my $rv = sysread($cmd_out, $_, 512);
+ $rv == 0 and $selector->remove($cmd_out);
+ if (/^\*\*\*SIM ERROR\*\*\*/m) {
+ $self->{hardware}{error} = N("Please check that your SIM card is inserted.");
+ last;
+ } elsif (/^Enter PIN number:/m) {
+ $self->{hardware}{pin} or last;
+ print $cmd_in $self->{hardware}{pin} . "\n";
+ } elsif (/^ERROR entering PIN/m) {
+ $self->{hardware}{error} = N("You entered a wrong PIN code.
+Entering the wrong PIN code multiple times may lock your SIM card!");
+ last;
+ } elsif (/^Waiting for Registration/m) {
+ #- the card seems to be resetted if gcom is killed right here, wait a bit
+ sleep 1;
+ #- don't wait the full scan
+ $device_ready = 1;
+ last;
+ }
+ }
+ kill 'TERM', $pid;
+ close($cmd_out);
+ close($cmd_in);
+ waitpid($pid, c::WNOHANG());
+
+ $device_ready;
+}
+
+1;