]> git.neil.brown.name Git - freerunner.git/commitdiff
gsmd: commit 'atchan.py' - missed that when committing gsmd.py
authorNeil Brown <neilb@suse.de>
Sun, 15 Feb 2009 11:40:51 +0000 (22:40 +1100)
committerNeil Brown <neilb@suse.de>
Sun, 15 Feb 2009 11:40:51 +0000 (22:40 +1100)
gsm/atchan.py [new file with mode: 0644]

diff --git a/gsm/atchan.py b/gsm/atchan.py
new file mode 100644 (file)
index 0000000..cb40dc1
--- /dev/null
@@ -0,0 +1,178 @@
+
+#
+# Handle a connection to an AT device via gsm0710muxd
+# If this is a 'master', we can reset the modem, else
+# any misbehaviour requires that we fail (FIXME not implemented)
+#
+# We directly support high level commands (get/set_power, reset_modem
+# etc) but don't know anything about AT commands - we just send them
+# through and hand back reply.  Replies also go via a callback
+# We also provide timeout support, but someone else needs to tell us
+# when to set a timeout, and when to clear it.
+#
+# This is usually subclassed by code with an agenda.
+
+import gobject, sys, os, time
+from trace import log
+from socket import *
+
+class AtChannel:
+    def __init__(self, path = '/var/run/gsm-mux', master = False):
+        self.master = False
+        self.path = path
+        self.connected = False
+        self.command_mode = False
+        self.watcher = None
+        self.sock = None
+        self.power = None
+        self.buf = ""
+        self.linelist = []
+
+        self.pending = False
+        self.timer = None
+
+    def disconnect(self):
+        if self.watcher:
+            gobject.source_remove(self.watcher)
+            self.watcher = None
+        if self.sock:
+            self.sock.close()
+            self.sock = None
+        self.connected = False
+
+    def connect(self):
+        log("connect to", self.path)
+        s = socket(AF_UNIX, SOCK_STREAM)
+        s.connect(self.path)
+        self.watcher = gobject.io_add_watch(s, gobject.IO_IN, self.readdata)
+        self.sock = s
+        self.connected = True
+        self.command_mode = True
+        self.command_pending = False
+
+    def command(self, str):
+        if not self.connected or not self.command_mode:
+            raise ValueError
+        log("send command", str)
+        if not self.command_pending:
+            self.command_pending = str
+        self.sock.sendall(str + '\n')
+        self.set_timeout(30000)
+
+    def readdata(self, io, arg):
+        r = self.sock.recv(1000)
+        r = self.buf + r
+        ra = r.split('\n')
+        self.buf = ra[-1];
+        del ra[-1]
+        for ln in ra:
+            ln = ln.strip('\r')
+            self.getline(ln)
+        return True
+
+    def getline(self, line):
+        if self.command_mode:
+            log("Receive cmd response", line, "to", self.command_pending)
+            if line == "OK" and self.command_pending == "connect":
+                log("Leaving command mode")
+                self.command_mode = False
+            if self.pending:
+                self.pending = False
+                gobject.source_remove(self.timer)
+                self.timer = None
+            if self.command_pending:
+                if line[0:2] == "OK" or line[0:5] == "ERROR":
+                    self.command_pending = False
+                    self.power_done(line)
+        else:
+            log("receive AT response", line)
+            if self.takeline(line):
+                if self.pending:
+                    self.pending = False
+                    gobject.source_remove(self.timer)
+                    self.timer = None
+
+    def set_power(self, state):
+        if state and self.power == True:
+            return gobject.idle_add(self.power_done)
+        if not state and self.power == False:
+            return gobject.idle_add(self.power_done)
+        # OK, I need to do something
+        if self.connected and not self.command_mode:
+            self.disconnect()
+        if not self.connected:
+            self.connect()
+        self.command_pending = "power"
+        if state:
+            self.command("set_power 1")
+            self.power = True
+        else:
+            self.command("set_power 0")
+            self.power = False
+
+    def reset(self):
+        if self.connected and not self.command_mode:
+            self.disconnect()
+        if not self.connected:
+            self.connect()
+        self.command_pending = "reset"
+        self.command("reset_modem")
+        self.power = True
+
+    def atconnect(self):
+        if not self.connected:
+            self.connect()
+        if not self.command_mode:
+            return self.power_done()
+        self.command_pending = "connect"
+        self.command("connect")
+        
+
+    def atcmd(self, cmd, timeout = 2000):
+        """
+        Send the command, preceeded by 'AT' and set a timeout.
+        self.takeline() should return True when the command
+        has been responded to, otherwise we will call
+        self.timedout() after the time.
+        """
+        self.set_timeout(timeout)
+        log("send AT command", cmd, timeout)
+        self.sock.sendall('AT' + cmd + '\r')
+
+    def timer_fired(self):
+        log("Timer Fired")
+        self.pending = False
+        self.timer = None
+        self.timedout()
+        return False
+    
+    def set_timeout(self, delay):
+        if self.pending:
+            raise ValueError
+        self.timer = gobject.timeout_add(delay, self.timer_fired)
+        self.pending = True
+
+    def cancel_timeout(self):
+        if self.pending:
+            gobject.source_remove(self.timer)
+            self.pending = False
+            
+    def abort_timeout(self):
+        if self.pending:
+            self.cancel_timeout()
+            self.set_timeout(0)
+
+    # these are likely to be over-ridden by a child class
+    def power_done(self, line=None):
+        self.linelist.append(line)
+    def takeline(self, line):
+        self.linelist.append(line)
+
+    def wait_line(self, timeout):
+        self.cancel_timeout()
+        c = gobject.main_context_default()
+        while not self.linelist:
+            c.iteration()
+        l = self.linelist[0]
+        del self.linelist[0]
+        return l