summaryrefslogtreecommitdiff
path: root/system/gpsd/gpsd.hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'system/gpsd/gpsd.hotplug')
-rw-r--r--system/gpsd/gpsd.hotplug124
1 files changed, 124 insertions, 0 deletions
diff --git a/system/gpsd/gpsd.hotplug b/system/gpsd/gpsd.hotplug
new file mode 100644
index 0000000000..805f941998
--- /dev/null
+++ b/system/gpsd/gpsd.hotplug
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+#
+# This file is Copyright (c) 2010 by the GPSD project
+# BSD terms apply: see the file COPYING in the distribution root for details.
+#
+# Hotplug script for gpsd by Eric S. Raymond, March 2005
+# This script is part of the gpsd distribution: see http://gpsd.berlios.de
+# Can be called like "gpsd.hotplug [add|remove] /dev/ttyUSB0" for test
+# purposes.
+import sys, time, os, syslog, glob, socket, stat
+
+CONTROL_SOCKET = os.getenv('GPSD_SOCKET') or "/var/run/gpsd.sock"
+GPSD_OPTIONS = os.getenv('GPSD_OPTIONS') or ""
+
+WHEREAMI = __file__
+
+def gpsd_control_connect(complain=True):
+ "Acquire a connection to the GPSD control socket."
+ if not os.path.exists(CONTROL_SOCKET):
+ syslog.syslog("socket %s doesn't exist" % CONTROL_SOCKET)
+ return None
+ try:
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
+ sock.connect(CONTROL_SOCKET)
+ except socket.error, msg:
+ if complain:
+ syslog.syslog("socket %s creation failure: %s" % (CONTROL_SOCKET, msg))
+ if sock:
+ sock.close()
+ sock = None
+ #else:
+ # syslog.syslog("socket %s created OK" % CONTROL_SOCKET)
+ return sock
+
+def gpsd_control(action, argument):
+ "Pass a command to gpsd; start the daemon if not already running."
+ syslog.syslog("gpsd_control(action=%s, arg=%s)" % (action, argument))
+ connect = gpsd_control_connect(complain=False)
+ if connect:
+ syslog.syslog("reached a running gpsd")
+ elif action == 'add':
+ gpsdcmd = "gpsd %s -F %s" % (GPSD_OPTIONS, CONTROL_SOCKET)
+ syslog.syslog("launching %s" % gpsdcmd)
+ os.system(gpsdcmd)
+ connect = gpsd_control_connect(complain=True)
+ if not connect:
+ syslog.syslog("can't reach gpsd")
+ return None
+ # We've got a live connection to the gpsd control socket. No
+ # need to parse the response, because gpsd will lock on to the
+ # device if it's really a GPS and ignore it if it's not.
+ if action == 'add':
+ # Force the group-read & group-write bits on, so gpsd will still be
+ # able to use this device after dropping root privileges.
+ os.chmod(argument, stat.S_IMODE(os.stat(argument)[stat.ST_MODE])|0660)
+ connect.sendall("+%s\r\n" % argument)
+ connect.recv(12)
+ elif action == 'remove':
+ connect.sendall("-%s\r\n" % argument)
+ connect.recv(12)
+ elif action == 'send':
+ connect.sendall("%s\r\n" % argument)
+ connect.recv(12)
+ connect.close()
+ #syslog.syslog("gpsd_control ends")
+ return action
+
+def hotplug(action, devpath):
+ #syslog.syslog("ACTION=%s DEVPATH=%s" % (action,devpath))
+ if not devpath:
+ syslog.syslog("No device")
+ else:
+ subnodes = glob.glob("/sys" + devpath + "/*")
+ subnodes = map(os.path.basename, subnodes)
+ subnodes = filter(lambda s: s.startswith("ttyUSB"), subnodes)
+ if len(subnodes) == 0:
+ syslog.syslog("no ttyUSB device under " + devpath)
+ return
+ elif len(subnodes) > 1:
+ syslog.syslog("too many ttyUSB devices under " + devpath)
+ return
+ else:
+ tty = "/dev/" + subnodes[0]
+
+ syslog.syslog("waiting for " + tty)
+ while not os.path.exists(tty):
+ time.sleep(1)
+ syslog.syslog(tty + " has gone active")
+
+ gpsd_control(action, tty)
+
+ remover = os.getenv("REMOVER")
+ #syslog.syslog("REMOVER=%s" % remover)
+ fp = open(remover, "w")
+ fp.write(WHEREAMI + " remove " + tty)
+ fp.close()
+ os.chmod(remover, stat.S_IRUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP)
+ return
+
+if __name__ == '__main__':
+ # In recent versions of udev, the gpsd script runs in series with
+ # the task that creates the real /dev/ttyUSB0 device
+ # node. Unfortunately, the gpsd script runs BEFORE the creation of
+ # the node, and the node is not created until after you kill the
+ # gpsd script, because the gpsd script waits forever for the node
+ # to appear.
+ #
+ # This is a race condition, and is best fixed by running the
+ # actual wait/hotplug portion in the background.
+ pid = os.fork()
+ if not pid:
+ syslog.openlog('gpsd.hotplug', 0, syslog.LOG_DAEMON)
+ try:
+ if len(sys.argv) == 1: # Called as hotplug script
+ hotplug(os.getenv("ACTION"), os.getenv("DEVPATH"))
+ else: # Called by hand for testing
+ gpsd_control(sys.argv[1], sys.argv[2])
+ except:
+ (exc_type, exc_value, exc_traceback) = sys.exc_info()
+ syslog.syslog("gpsd.hotplug: exception %s yields %s" % (exc_type, exc_value))
+ raise exc_type, exc_value, exc_traceback
+ #syslog.syslog("gpsd.hotplug ends")
+ syslog.closelog()
+