def start(self): retval = self.io.start() if retval == self.io.RETURN_FAILURE: raise DriverError, "Start of device service failed, aborting!" self.st_m.start() info("Start device '%s' (COM: %s | AUX: %s)" % (self.path, self.io.modem_path, self.io.com_path))
def unregister(self, url): info("Unregister request for URL %s" % repr(url)) try: self.__hosts.__delitem__(url) return 0 except KeyError: raise DeviceLoggerError, "unregister(): URL %s doesn't exist." % url
def device_unlocked(self, object): info("Unlocked sending signal") """ [DBUS signal exported] The object path of the newly added device. """ pass
def __abort_tasks(self): while len(self.__tasks): _task = self.__pop() if _task is not None: info("Going to abort task %i" % _task.id()) _task.abort() else: time.sleep(0.100)
def device_unlocked(self, object): info("Unlocked sending signal") ''' [DBUS signal exported] The object path of the newly added device. ''' pass
def add(self, vid, pid, com_minor, aux_minor, driver=None): try: vendor = self.__vendors[vid.lower()] vendor.add(pid, com_minor, aux_minor, driver) info("Added new product (VID %s | PID %s) of vendor %s | Minors: %s COM and %s AUX" % (vid, pid, vendor.name(), com_minor, aux_minor)) self.__save() except Exception, err: raise TableError, "Couldn't add new device, %s" % err
def removeProduct(self, vid, pid): try: vendor = self.__vendors[vid.lower()] vendor.remove(pid) info("Removed product (VID %s | PID %s) of vendor %s" % (vid, pid, vendor.name())) self.__save() except Exception, err: raise TableError, "Couldn't remove the device %s:%s, %s" % (str(vid), str(pid), err)
def __init__(self, parent, bus_name, mm_path, dm_id): gobject.GObject.__init__(self) self.__vid = parent.get_property("ID_VENDOR_ID") self.__pid = parent.get_property("ID_MODEL_ID") # -- Hell! In some cases the get_property() of the parent is returning None if (self.__vid is None) or (self.__pid is None): raise DriverError, "Got 'None' for the parent's VID/PID!" self.__vid_pid = "%s:%s" % (self.__vid, self.__pid) self.__id = create_parent_id(parent) self.__sysfs_path = parent.get_sysfs_path() self.__devpath = parent.get_property("DEVPATH") self.__udev = gudev.Client("tty") self.__dev = parent self.__dm_id = dm_id # -- Get the libusb device for this parent self.__usbdev = None busses = usb.busses() for bus in busses: for dev in bus.devices: if (dev.idVendor == int(self.__vid, 16)) and (dev.idProduct == int(self.__pid, 16)): # -- @XXX: Dont know why but in some cases the HUB is passed to if dev.deviceClass == usb.CLASS_HUB: raise DriverError, "Device with VID %s PID %s is a HUB" % (self.__vid, self.__pid) self.__usbdev = dev break if self.__usbdev is None: raise DriverError, "No Libusb device with VID %s PID %s" % (self.__vid, self.__pid) # -- IMPORTANT: This dict uses the port minor numbers as keys! This is required for searching # -- the ports that belong to a product from the devices table self.__ports = DevicePort.PortsHandler() self.__ports_nr = self.__get_number_ports() if self.__ports_nr <= 1: raise DriverError, "USB parent %s has %i TTY ports (not enough)" % (self.__id, self.__ports_nr) self.__portCom = None self.__portAux = None self.__driver = None self.__portLock = threading.Lock() self.bus_name = bus_name self.__modem_id = alloc_modem_id() self.__mm_device_path = os.path.join(mm_path, str(self.__modem_id)) self.__device_service = None self.__devtable = DeviceTable.DeviceTable() self.__measure = DevicePort.TimeMeasure() info("Plugged-in USB parent %s | Ports %i | Sysfs %s" % (self.__vid_pid, self.__ports_nr, self.__sysfs_path)) thread.start_new_thread(self.__scan, ( ))
def mgu_respond(self, response): ussd_cmd = response def function(task): cmd = 'AT+CUSD=1,"%s",15' % ussd_cmd regex = '\+CUSD:.*(?P<code>\d),\"(?P<msg>.+)\",' r_values = ["code", "msg"] res = self.io.com.send_query({"type" : "regex", "cmd" : cmd, "task" : task, "regex" : regex, "r_values" : r_values, "alt_ok_value" : "+CUSD", }) if res != None: return int(res["code"]), res["msg"] return None if self.mgu_state_prop != 'user-response' : info("USSD session is not in user-response status") return '' task_msg = "Send USSD response -> ('%s')'" % (response) try: r = self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=20) except: self.cache["ussd_status"] = 'idle' return '' if r == None: ussd_cmd = self.mgu_to_gsm7(response) task_msg = "Send USSD response gsm7 encoded -> ('%s')" % (ussd_cmd) r = self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=20) if r == None : self.cache["ussd_status"] = 'idle' return '' else: c = r[0] if c == 0 : self.cache["ussd_status"] = 'idle' elif c == 1 : self.cache["ussd_status"] = 'user-response' else: self.cache["ussd_status"] = 'idle' return self.mgu_from_gsm7(r[1]) else: c = r[0] if c == 0 : self.cache["ussd_status"] = 'idle' elif c == 1 : self.cache["ussd_status"] = 'user-response' else: self.cache["ussd_status"] = 'idle' return r[1]
def stop(self): info("Stopping device : %s" % self.path) self.st_m.stop() self.io.stop() try: self.remove_from_connection(path = self.path) except: pass return True
def stop(self): info("Stopping device : %s" % self.path) self.st_m.stop() self.io.stop() try: self.remove_from_connection(path=self.path) except: pass return True
def removeProduct(self, vid, pid): try: vendor = self.__vendors[vid.lower()] vendor.remove(pid) info("Removed product (VID %s | PID %s) of vendor %s" % (vid, pid, vendor.name())) self.__save() except Exception, err: raise TableError, "Couldn't remove the device %s:%s, %s" % ( str(vid), str(pid), err)
def __get_ports_from_device_table(self): try: product = self.__devtable.product(self.__vid, self.__pid) comIdx = product.com() auxIdx = product.aux() info("Product needs ports with index %i and %i (COM and AUX)" % (comIdx, auxIdx)) return self.__ports.get_port_by_index(comIdx), self.__ports.get_port_by_index(auxIdx) except Exception, err: self.error("Failure reading a table product, %s" % err) raise DeviceTable.TableError, err
def add(self, vid, pid, com_minor, aux_minor, driver=None): try: vendor = self.__vendors[vid.lower()] vendor.add(pid, com_minor, aux_minor, driver) info( "Added new product (VID %s | PID %s) of vendor %s | Minors: %s COM and %s AUX" % (vid, pid, vendor.name(), com_minor, aux_minor)) self.__save() except Exception, err: raise TableError, "Couldn't add new device, %s" % err
def __check_available_devices(self): info("Checking tty's availables") for device in self.udev_client.query_by_subsystem("tty"): self.__on_tty_event(self.udev_client, "add", device) info("Checking tty's availables finished") for device in self.udev_client_usb.query_by_subsystem("usb"): self.__on_usb_event(self.udev_client_usb, "add", device) self.udev_client.connect("uevent", self.__on_tty_event) self.udev_client_usb.connect("uevent", self.__on_usb_event)
def __get_ports_from_device_table(self): try: product = self.__devtable.product(self.__vid, self.__pid) comIdx = product.com() auxIdx = product.aux() info("Product needs ports with index %i and %i (COM and AUX)" % (comIdx, auxIdx)) return self.__ports.get_port_by_index( comIdx), self.__ports.get_port_by_index(auxIdx) except Exception, err: self.error("Failure reading a table product, %s" % err) raise DeviceTable.TableError, err
def run(self): self.__result = self.RESULT_PENDING td = TimeMeasure() if self.__port.AT_test(self.__retries, self.__timeout, write=self.__write, read=self.__read) == self.__port.AT_TEST_OK: self.__result = self.RESULT_OK else: self.__result = self.RESULT_ERROR self.__duration = td.diff() # -- @XXX: This is probably not the correct place for this debug message msg = "AT" if self.__result == self.RESULT_OK else "No" info("%s answer on %s | Duration %s" % (msg, self.__port.devnode(), self.__duration))
def __init__(self, addr, port): server = SimpleXMLRPCServer.SimpleXMLRPCServer((addr, port), logRequests=False) self.__hosts = { } self.__server = server self.__addr = create_xmlrpc_addr(addr, port) server.register_introspection_functions() server.register_instance(self._Rpcs(self.__hosts)) # -- Get the repository revision for returning this value with the RPC self.__revision = "@TODO" info("Created new XML-RPC device logger (revision %s)" % self.__revision)
def mgn_set_apn(self, apn): info("************* APNNNNNNNN*************** ") def function(task): cmd = "AT+CGDCONT=1,\"IP\",\"%s\"" %apn self.io.com.send_query({"type" : "simple", "cmd" : cmd, "task" : task}) task_msg = "Modifying APN" self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=60) pass
def __init__(self, addr, port): server = SimpleXMLRPCServer.SimpleXMLRPCServer((addr, port), logRequests=False) self.__hosts = {} self.__server = server self.__addr = create_xmlrpc_addr(addr, port) server.register_introspection_functions() server.register_instance(self._Rpcs(self.__hosts)) # -- Get the repository revision for returning this value with the RPC self.__revision = "@TODO" info("Created new XML-RPC device logger (revision %s)" % self.__revision)
def mgn_set_apn(self, apn): info("************* APNNNNNNNN*************** ") def function(task): cmd = "AT+CGDCONT=1,\"IP\",\"%s\"" % apn self.io.com.send_query({ "type": "simple", "cmd": cmd, "task": task }) task_msg = "Modifying APN" self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=60) pass
def register(self, url): info("Register request for URL %s" % repr(url)) if type(url) != type(""): raise DeviceLoggerError, "register(): Got invalid URL (not a string), %s" % repr(url) elif len(url) == 0: raise DeviceLoggerError, "register(): Got empty string." if self.__hosts.has_key(url): raise DeviceLoggerError, "register(): Passed URL '%s' already registered" % url # -- Ok, we are safe, create the proxy object and store it for further operations try: srv = xmlrpclib.Server(url) #val = srv.ping_from_device_manager() self.__hosts[url] = srv return 0 except xmlrpclib.Fault, err: raise DeviceLoggerError, "xmlrpclib failure, %s" % err
def __init__(self): self.vids = [ ] self.__cfg = ConfigFile(os.path.join(mobilemanager.DEVICE_TABLE_DIR(), self.DEVICE_TABLE_XML)) try: self.__vendors = self.__cfg.read() info("Using XML devices table '%s'" % self.__cfg.fpath()) except Exception, err: warning("Error reading '%s', %s" % (self.__cfg.fpath(), err)) info("Using default vendors table") self.__vendors = { } self.__add( "Huawei" , "huawei" , HUAWEI_VID , [ ( '1003', 1, 0, None ) ] ) self.__add( "Novatel" , "novatel" , NOVATEL_VID , [ ] ) self.__add( "Sierra" , "sierra" , SIERRA_VID , [ ] ) self.__add( "ZTE" , "zte" , ZTE_VID , [ ] ) self.__add( "Option" , "option" , OPTION_VID , [ ] ) self.__add( "Alcatel" , "alcatel" , ALCATEL_VID , [ ] ) self.__save()
def register(self, url): info("Register request for URL %s" % repr(url)) if type(url) != type(""): raise DeviceLoggerError, "register(): Got invalid URL (not a string), %s" % repr( url) elif len(url) == 0: raise DeviceLoggerError, "register(): Got empty string." if self.__hosts.has_key(url): raise DeviceLoggerError, "register(): Passed URL '%s' already registered" % url # -- Ok, we are safe, create the proxy object and store it for further operations try: srv = xmlrpclib.Server(url) #val = srv.ping_from_device_manager() self.__hosts[url] = srv return 0 except xmlrpclib.Fault, err: raise DeviceLoggerError, "xmlrpclib failure, %s" % err
def __init__(self): self.vids = [] self.__cfg = ConfigFile( os.path.join(mobilemanager.DEVICE_TABLE_DIR(), self.DEVICE_TABLE_XML)) try: self.__vendors = self.__cfg.read() info("Using XML devices table '%s'" % self.__cfg.fpath()) except Exception, err: warning("Error reading '%s', %s" % (self.__cfg.fpath(), err)) info("Using default vendors table") self.__vendors = {} self.__add("Huawei", "huawei", HUAWEI_VID, [('1003', 1, 0, None)]) self.__add("Novatel", "novatel", NOVATEL_VID, []) self.__add("Sierra", "sierra", SIERRA_VID, []) self.__add("ZTE", "zte", ZTE_VID, []) self.__add("Option", "option", OPTION_VID, []) self.__add("Alcatel", "alcatel", ALCATEL_VID, []) self.__save()
def info(self, msg): if self.__logging is True: info(msg)
class TaskPool(): STATE_IDLE = 0 STATE_BUSY = 1 STATE_STOPPED = 2 STATE_FAILURE = 3 WAIT_TASK_ADDED_TIME = 0.010 # -- After this threshold is reached, a device reset is triggered! # -- Arbitraty value used for avoiding deadlocks in the task queue ERRORS_THRESHOLD = 20 class _TaskLog(): # -- Disables globally the filters DISABLED_FILTERS = False def __init__(self): # -- Disable the filters per default self.__enable(False) self.filters([ ]) def info(self, msg): if self.__logging is True: info(msg) def error(self, msg): error(msg) def warning(self, msg): warning(msg) def start(self, task): msg = task.msg() if self.__filters_enabled is True: self.__logging = False if (self.__task_filters.match(msg) is None) else True else: self.__logging = True self.info("Dispatching Task num=%i '%s' :" % (task.id(), task.msg())) def end(self, task): if self.__logging is True: self.info('-' * 20) def enable(self, value=None): if self.DISABLED_FILTERS is True: raise SystemError, "Filters feature is disabled" else: return self.__enable(value) def __enable(self, value=None): if value is not None: self.__filters_enabled = True if value else False return self.__filters_enabled def filters(self, commands=None): if (commands is not None): if not hasattr(commands, '__iter__'): commands = [ commands ] self.__task_filters = re.compile(r"%s" % '|'.join(map(lambda cmd: ".*%s.*" % cmd, commands))) self.__commands = commands if self.__filters_enabled is True: warning("IMPORTANT: Tasks filter(s) enabled: %s" % repr(commands)) return self.__commands def start(self): self.__stop = False thread.start_new_thread(self.__start, ( )) def __init__(self, device): self.__device = device self.__stop = False self.__task_added = threading.Event() self.__tasks_lock = threading.Lock() self.__tasks = [ ] self.__errors = 0 self.__state = self.STATE_IDLE # -- Set the external access to the logger self.__tasklog = self._TaskLog() self.filters_enable = self.__tasklog.enable self.filters_set = self.__tasklog.filters def info(self, msg): self.__tasklog.info(msg) def error(self, msg): self.__tasklog.error(msg) def __start(self): while self.__stop is False: try: self.__task_added.wait(self.WAIT_TASK_ADDED_TIME) self.__task_added.clear() # -- Now execute the next task of the queue _task = self.__pop() if _task is not None: # -- Change the state to busy self.__state = self.STATE_BUSY self.__tasklog.start(_task) retval = _task.execute() if retval == _task.RESULT_OK: self.__errors = 0 elif retval == _task.RESULT_ERROR: self.__errors += 1 # -- Failure threshold reached, so try to reset the device and stop the task queue if self.__errors == self.ERRORS_THRESHOLD: self.stop() self.__device.reset() break # -- Set the state to idle self.__state = self.STATE_IDLE self.__tasklog.end(_task) except Exception, err: error("Unexpected failure in TaskPool thread, %s" % err) self.__state = self.STATE_IDLE self.__state = self.STATE_STOPPED info("TaskPool stopped | Pending tasks %i" % len(self.__tasks)) self.__abort_tasks()
def debug(self, msg): info("%s: %s" % (self.__id, msg))
def __device_added(self, dm, obj): self.device_added(obj) info("DBUS (signal:DeviceAdded:(%s))" % (obj))
def __init__(self, parent, bus_name, mm_path, dm_id): gobject.GObject.__init__(self) self.__vid = parent.get_property("ID_VENDOR_ID") self.__pid = parent.get_property("ID_MODEL_ID") # -- Hell! In some cases the get_property() of the parent is returning None if (self.__vid is None) or (self.__pid is None): raise DriverError, "Got 'None' for the parent's VID/PID!" self.__vid_pid = "%s:%s" % (self.__vid, self.__pid) self.__id = create_parent_id(parent) self.__sysfs_path = parent.get_sysfs_path() self.__devpath = parent.get_property("DEVPATH") self.__udev = gudev.Client("tty") self.__dev = parent self.__dm_id = dm_id # -- Get the libusb device for this parent self.__usbdev = None busses = usb.busses() for bus in busses: for dev in bus.devices: if (dev.idVendor == int(self.__vid, 16)) and (dev.idProduct == int( self.__pid, 16)): # -- @XXX: Dont know why but in some cases the HUB is passed to if dev.deviceClass == usb.CLASS_HUB: raise DriverError, "Device with VID %s PID %s is a HUB" % ( self.__vid, self.__pid) self.__usbdev = dev break if self.__usbdev is None: raise DriverError, "No Libusb device with VID %s PID %s" % ( self.__vid, self.__pid) # -- IMPORTANT: This dict uses the port minor numbers as keys! This is required for searching # -- the ports that belong to a product from the devices table self.__ports = DevicePort.PortsHandler() self.__ports_nr = self.__get_number_ports() if self.__ports_nr <= 1: raise DriverError, "USB parent %s has %i TTY ports (not enough)" % ( self.__id, self.__ports_nr) self.__portCom = None self.__portAux = None self.__driver = None self.__portLock = threading.Lock() self.bus_name = bus_name self.__modem_id = alloc_modem_id() self.__mm_device_path = os.path.join(mm_path, str(self.__modem_id)) self.__device_service = None self.__devtable = DeviceTable.DeviceTable() self.__measure = DevicePort.TimeMeasure() info("Plugged-in USB parent %s | Ports %i | Sysfs %s" % (self.__vid_pid, self.__ports_nr, self.__sysfs_path)) thread.start_new_thread(self.__scan, ())
def __device_removed_cb(self, driver, mm_device_path): try: info("Going to remove the device '%s'" % mm_device_path) self.__remove(driver) except Exception, err: error("Unexpected failure removing device, %s" % err)
def info(self, msg): info("%s: %s" % (self.__vid_pid, msg))
def reset(self): info("Going to reset the device!") self.stop() self.driver.reset()
def start(self, background=True): info("Starting XML-RPC device logger (%s)" % self.__addr) if background is True: thread.start_new_thread(self.__start, ()) else: self.__start()
def __device_removed(self, dm, obj): self.device_removed(obj) info("DBUS (signal:DeviceRemoved:(%s))" % (obj))
def mgu_initiate(self, command): ussd_cmd = command def function(task): cmd = 'AT+CUSD=1,"%s",15' % ussd_cmd regex = '\+CUSD:.*(?P<code>\d),\"(?P<msg>.+)\",' r_values = ["code", "msg"] self.io.com.send_query({"cmd" : "AT^PORTSEL=0", "task" : task,}) res = self.io.com.send_query({"type" : "regex", "cmd" : cmd, "task" : task, "regex" : regex, "r_values" : r_values, "alt_ok_value" : "+CUSD", }) self.io.com.send_query({"cmd" : "AT^PORTSEL=1", "task" : task,}) if res != None: return int(res["code"]), res["msg"] return None if self.mgu_state_prop != 'idle' : info("ussd system not idle status") return '' self.cache["ussd_status"] = 'active' task_msg = "[Huawei] Send USSD msg -> ('%s')'" % (command) try: r = self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=20) except: self.cache["ussd_status"] = 'idle' return '' if r == None: ussd_cmd = self.mgu_to_gsm7(command) task_msg = "[Huawei] Send USSD msg gsm7 encoded -> ('%s')'" % (ussd_cmd) r = self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=20) if r == None : self.cache["ussd_status"] = 'idle' return '' else: c = r[0] if c == 0 : self.cache["ussd_status"] = 'idle' elif c == 1 : self.cache["ussd_status"] = 'user-response' else: self.cache["ussd_status"] = 'idle' return self.mgu_from_gsm7(r[1]) else: c = r[0] if c == 0 : self.cache["ussd_status"] = 'idle' elif c == 1 : self.cache["ussd_status"] = 'user-response' else: self.cache["ussd_status"] = 'idle' return r[1]
def mgu_initiate(self, command): ussd_cmd = command def function(task): cmd = 'AT+CUSD=1,"%s",15' % ussd_cmd regex = '\+CUSD:.*(?P<code>\d),\"(?P<msg>.+)\",' r_values = ["code", "msg"] self.io.com.send_query({ "cmd": "AT^PORTSEL=0", "task": task, }) res = self.io.com.send_query({ "type": "regex", "cmd": cmd, "task": task, "regex": regex, "r_values": r_values, "alt_ok_value": "+CUSD", }) self.io.com.send_query({ "cmd": "AT^PORTSEL=1", "task": task, }) if res != None: return int(res["code"]), res["msg"] return None if self.mgu_state_prop != 'idle': info("ussd system not idle status") return '' self.cache["ussd_status"] = 'active' task_msg = "[Huawei] Send USSD msg -> ('%s')'" % (command) try: r = self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=20) except: self.cache["ussd_status"] = 'idle' return '' if r == None: ussd_cmd = self.mgu_to_gsm7(command) task_msg = "[Huawei] Send USSD msg gsm7 encoded -> ('%s')'" % ( ussd_cmd) r = self.io.task_pool.exec_task(function, task_msg=task_msg, timeout=20) if r == None: self.cache["ussd_status"] = 'idle' return '' else: c = r[0] if c == 0: self.cache["ussd_status"] = 'idle' elif c == 1: self.cache["ussd_status"] = 'user-response' else: self.cache["ussd_status"] = 'idle' return self.mgu_from_gsm7(r[1]) else: c = r[0] if c == 0: self.cache["ussd_status"] = 'idle' elif c == 1: self.cache["ussd_status"] = 'user-response' else: self.cache["ussd_status"] = 'idle' return r[1]
def start(self, background=True): info("Starting XML-RPC device logger (%s)" % self.__addr) if background is True: thread.start_new_thread(self.__start, ( )) else: self.__start()