Support turbo2.
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / 3GModemManager / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
5 from Screens.DefaultWizard import DefaultWizard
6 from Screens.Standby import TryQuitMainloop
7 from Screens.VirtualKeyBoard import VirtualKeyBoard
8
9 from Components.Label import Label
10 from Components.Sources.StaticText import StaticText
11 from Components.ActionMap import NumberActionMap, ActionMap
12 from Components.Network import iNetwork
13 from Components.MenuList import MenuList
14 from Components.config import config, getConfigListEntry, ConfigInteger, ConfigSubsection, ConfigSelection, ConfigText, ConfigYesNo, NoSave, ConfigNothing
15 from Components.ConfigList import ConfigListScreen
16 from Components.Pixmap import Pixmap
17
18 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN
19
20 from enigma import eTimer, eConsoleAppContainer, eSocketNotifier, getDesktop
21 from select import POLLIN, POLLPRI
22 from xml.sax import make_parser, handler
23 import os, socket, time
24
25 debug_mode_modem_mgr = False
26 def printDebugModemMgr(msg):
27         global debug_mode_modem_mgr
28         if debug_mode_modem_mgr:
29                 print "[ModemManager Plugin] Debug >>", msg
30
31 def printInfoModemMgr(msg):
32         print "[ModemManager Plugin] Info >>", msg
33
34 isEmpty = lambda x: x is None or len(x)==0
35
36
37 def read_file(path, key):
38     if os.path.exists(path):
39         return key + open(path).read()
40     return ""
41
42 def parse_usb_uevent(datas):
43     uevent_map = {}
44     datas_lines = datas.splitlines()
45     for data in datas_lines:
46         kv = data.split('=')
47         if kv[0] in ('BUSNUM', 'DRIVER', 'PRODUCT', 'SERIAL', 'PNAME', 'MANUFACTUER', 'PRODUCTID', 'VENDORID'):
48             uevent_map[kv[0]] = kv[1]
49     return uevent_map
50
51
52 def read_usb_uevent(dir_path):
53     uevent_data = open(dir_path + "/uevent").read()
54     if uevent_data.find('DRIVER=hub') == -1:
55         uevent_data += read_file(dir_path + "/serial", "SERIAL=")
56         uevent_data += read_file(dir_path + "/product", "PNAME=")
57         uevent_data += read_file(dir_path + "/idProduct", "PRODUCTID=")
58         uevent_data += read_file(dir_path + "/idVendor", "VENDORID=")
59         uevent_data += read_file(dir_path + "/manufacturer", "MANUFACTUER=")
60         return uevent_data
61     return None
62
63 def make_script(item):
64     script = ""
65     try:
66         script += 'T:  Bus=%s\n' % (item['BUSNUM'])
67     except: pass
68     try:
69         script += 'P:  Vendor=%s ProdID=%s\n' % (item['VENDORID'], item['PRODUCTID'])
70     except: pass
71     try:
72         script += 'S:  Manufacturer=%s\n' % (item['MANUFACTUER'])
73     except: pass
74     try:
75         script += 'S:  Product=%s\n' % (item['PNAME'])
76     except: pass
77     try:
78         script += 'S:  SerialNumber=%s\n' % (item['SERIAL'])
79     except: pass
80     try:
81         script += 'I:* Driver=%s\n' % (item['DRIVER'])
82     except: pass
83     script += "\n"
84     return script
85
86 def lsusb_devices():
87     all_script = ""
88
89     devices_list = []
90     for root, dirs, files in os.walk('/sys/bus/usb/devices', topdown=False):
91         for name in dirs:
92             if name.startswith('usb'):
93                 continue
94             uevnet_data = read_usb_uevent(os.path.join(root, name))
95             if uevnet_data is not None:
96                 uevent_map = parse_usb_uevent(uevnet_data)
97                 devices_list.append(uevent_map)
98
99     usbstorage_list = []
100     for item in devices_list:
101         try:
102             if item['DRIVER'] == 'usb-storage':
103                 usbstorage_list.append(item['PRODUCT'])
104         except: pass
105
106     for item1 in usbstorage_list:
107         for item2 in devices_list:
108             try:
109                 if item2['PRODUCT'] == item1 and item2['DRIVER'] == 'usb':
110                     all_script += make_script(item2)
111             except: pass
112     return all_script
113
114 class DeviceEventListener:
115         notifyCallbackFunctionList = []
116         def __init__(self):
117                 self.sock = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, 15)
118                 try:            
119                         self.sock.bind((os.getpid(), 1))
120                         self.notifier = eSocketNotifier(self.sock.fileno(), POLLIN|POLLPRI)
121                         self.notifier.callback.append(self.cbEventHandler)
122                 except Exception, msg:
123                         print "[ModemManager Plugin] Error >>", msg
124                         self.sock.close()
125
126         def cbEventHandler(self, sockfd):
127                 recv = self.sock.recv(65536)
128                 #printDebugModemMgr(str(recv.splitlines()))
129                 if recv.startswith("add@/block") or recv.startswith("remove@/block"):
130                         for x in self.notifyCallbackFunctionList:
131                                 try:    x(recv)
132                                 except: self.notifyCallbackFunctionList.remove(x)
133
134         def addCallback(self, func):
135                 if func is not None:
136                         self.notifyCallbackFunctionList.append(func)
137
138         def delCallback(self, func):
139                 if func is not None:
140                         self.notifyCallbackFunctionList.remove(func)
141
142         def close(self):
143                 try:
144                         self.notifier.callback.remove(self.cbEventHandler)
145                         self.sock.close()
146                 except: pass
147
148 class TaskManager:
149         def __init__(self):
150                 self.taskIdx = 0
151                 self.taskList = []
152                 self.gTaskInstance = None
153                 self.occurError = False
154                 self.cbSetStatusCB = None
155
156         def append(self, command, cbDataFunc, cbCloseFunc):
157                 self.taskList.append([command+'\n', cbDataFunc, cbCloseFunc])
158
159         def dump(self):
160                 print "############### TASK ###############"
161                 print "Current Task Index :", self.taskIdx
162                 print "Current Task Instance :", self.gTaskInstance
163                 print "Occur Error :", self.occurError
164                 print "Task List:\n", self.taskList
165                 print "####################################"
166
167         def error(self):
168                 printInfoModemMgr("set task error!!")
169                 self.occurError = True
170
171         def reset(self):
172                 self.taskIdx = 0
173                 self.gTaskInstance = None
174                 self.occurError = False
175
176         def clean(self):
177                 self.reset()
178                 self.taskList = []
179                 self.cbSetStatusCB = None
180                 print "clear task!!"
181
182         def index(self):
183                 self.taskIdx
184
185         def setStatusCB(self, cbfunc):
186                 self.cbSetStatusCB = cbfunc
187                 
188         def next(self):
189                 if self.taskIdx >= len(self.taskList) or self.occurError:
190                         printInfoModemMgr("can't run task!!")
191                         return False
192                 command     = self.taskList[self.taskIdx][0]
193                 cbDataFunc  = self.taskList[self.taskIdx][1]
194                 cbCloseFunc = self.taskList[self.taskIdx][2]
195
196                 self.gTaskInstance = eConsoleAppContainer()
197                 if cbDataFunc is not None:
198                         self.gTaskInstance.dataAvail.append(cbDataFunc)
199                 if cbCloseFunc is not None:
200                         self.gTaskInstance.appClosed.append(cbCloseFunc)
201                 if self.cbSetStatusCB is not None:
202                         self.cbSetStatusCB(self.taskIdx)
203
204                 printInfoModemMgr("prepared command :%s"%(command))
205                 self.gTaskInstance.execute(command)
206                 self.taskIdx += 1
207                 return True
208
209 class ParserHandler(handler.ContentHandler):
210         nodeList = []
211         def __init__(self):
212                 self.nodeList = []
213         def startDocument(self):
214                 pass
215         def endDocument(self):  
216                 pass
217         def startElement(self, name, attrs):
218                 if name == 'apn':
219                         node = {}
220                         for attr in attrs.getNames():
221                                 node[attr] = str(attrs.getValue(attr))
222                         self.nodeList.append(node)
223         def endElement(self, name):
224                 pass
225         def characters(self, content):
226                 pass
227         def setDocumentLocator(self, locator):
228                 pass
229         def getNodeList(self):
230                 return self.nodeList
231
232 class EditModemManual(ConfigListScreen, Screen):
233         param = int(getDesktop(0).size().height()) >= 720 and (450,360) or (160,300)
234         skin =  """
235                 <screen position="center,center" size="600,360" title="3G Modem Manager Config Edit">
236                         <widget name="config" zPosition="2" position="0,0" size="600,300" scrollbarMode="showOnDemand" transparent="1" />
237
238                         <ePixmap pixmap="skin_default/buttons/red.png" position="5,320" size="140,40" alphatest="on" />
239                         <ePixmap pixmap="skin_default/buttons/green.png" position="155,320" size="140,40" alphatest="on" />
240                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,320" size="140,40" alphatest="on" />
241                         <ePixmap pixmap="skin_default/buttons/blue.png" position="455,320" size="140,40" alphatest="on" />
242
243                         <widget source="key_red" render="Label" position="5,320" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
244                         <widget source="key_green" render="Label" position="155,320" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
245                         <widget source="key_blue" render="Label" position="455,320" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b"  foregroundColor="#ffffff" transparent="1" />
246
247                         <widget name="VKeyIcon" pixmap="skin_default/buttons/key_text.png" position="50,200" zPosition="10" size="35,25" transparent="1" alphatest="on" />
248                         <widget name="HelpWindow" pixmap="skin_default/vkey_icon.png" position="%d,%d" zPosition="1" size="1,1" transparent="1" alphatest="on" />
249                 </screen>
250                 """ % param
251
252         def __init__(self, session, cbFuncClose, uid=None, pwd=None, pin=None, apn=None, phone='*99#', isAdd=False):
253                 Screen.__init__(self, session)
254                 self.cbFuncClose, self.isAdd = cbFuncClose, isAdd
255
256                 if isAdd:
257                         self.uid,self.pwd,self.pin,self.apn,self.phone = "","","","",""
258                 else:
259                         self.uid,self.pwd,self.pin,self.apn,self.phone = uid,pwd,pin,apn,phone
260                         if self.uid is None: self.uid = ""
261                         if self.pwd is None: self.pwd = ""
262                         if self.pin is None: self.pin = ""
263                         if self.apn is None: self.apn = ""
264                         if self.phone is None: self.phone = ""
265
266                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions",],
267                 {
268                         "ok":     self.keyOK,
269                         "cancel": self.keyExit,
270                         "red":    self.keyExit,
271                         "green":  self.keyOK,
272                         "blue":   self.keyRemove,
273                 }, -2)
274
275                 self["VirtualKB"] = ActionMap(["VirtualKeyboardActions" ],
276                 {
277                         "showVirtualKeyboard": self.KeyText,
278                 }, -1)
279
280                 self.configList = []
281                 ConfigListScreen.__init__(self, self.configList, session=session)
282                 self.createConfigList()
283
284                 self["key_red"]    = StaticText(_("Cancel"))
285                 self["key_green"]  = StaticText(_("Save"))
286                 self["key_blue"]   = StaticText(_(self.isAdd and " " or "Remove"))
287                 self["VKeyIcon"]   = Pixmap()
288                 self["HelpWindow"] = Pixmap()
289                 self["VirtualKB"].setEnabled(False)
290                 if self.isAdd:
291                         self.setTitle("3G Modem Manager Config Add")
292
293         def createConfigList(self):
294                 self.configName     = ConfigText(default="", visible_width=50, fixed_size=False)
295                 self.configUserName = ConfigText(default=str(self.uid), visible_width=50, fixed_size=False)
296                 self.configPassword = ConfigText(default=str(self.pwd), visible_width=50, fixed_size=False)
297                 self.configAPN      = ConfigText(default=str(self.apn), visible_width=50, fixed_size=False)
298                 self.configPIN      = ConfigText(default=str(self.pin), visible_width=50, fixed_size=False)
299                 self.configPhone    = ConfigText(default=str(self.phone), visible_width=50, fixed_size=False)
300
301                 self.configEntryName     = getConfigListEntry(_("Name :"),     self.configName)
302                 self.configEntryUserName = getConfigListEntry(_("User :"),     self.configUserName)
303                 self.configEntryPassword = getConfigListEntry(_("Password :"), self.configPassword)
304                 self.configEntryAPN      = getConfigListEntry(_("APN :"),      self.configAPN)
305                 self.configEntryPIN      = getConfigListEntry(_("PIN :"),      self.configPIN)
306                 self.configEntryPhone    = getConfigListEntry(_("Phone :"),    self.configPhone)
307
308                 if self.isAdd:
309                         self.configList.append(self.configEntryName)
310                 self.configList.append(self.configEntryUserName)
311                 self.configList.append(self.configEntryPassword)
312                 self.configList.append(self.configEntryAPN)
313                 self.configList.append(self.configEntryPIN)
314                 self.configList.append(self.configEntryPhone)
315
316                 self["config"].list = self.configList
317                 self["config"].l.setList(self.configList)
318
319         def getCurrentItem(self):
320                 currentPosition = self["config"].getCurrent()
321                 if currentPosition == self.configEntryName:
322                         return self.configName
323                 if currentPosition == self.configEntryUserName:
324                         return self.configUserName
325                 elif currentPosition == self.configEntryPassword:
326                         return self.configPassword
327                 elif currentPosition == self.configEntryAPN:
328                         return self.configAPN
329                 elif currentPosition == self.configEntryPIN:
330                         return self.configPIN
331                 elif currentPosition == self.configEntryPhone:
332                         return self.configPhone
333                 return None
334
335         def KeyText(self):
336                 currentItemValue = ""
337                 currentItem = self.getCurrentItem()
338                 if currentItem is not None:
339                         currentItemValue = currentItem.value
340                         if isEmpty(currentItemValue):
341                                 currentItemValue = ""
342                 self.session.openWithCallback(self.cbKeyText, VirtualKeyBoard, title=("Please input here"), text=currentItemValue)
343
344         def cbKeyText(self, data=None):
345                 if data is not None:
346                         currentItem = self.getCurrentItem()
347                         if currentItem is not None:
348                                 currentItem.setValue(data)
349
350         def keyExit(self):
351                 self.close()
352
353         def keyRemove(self):
354                 if self.isAdd:
355                         return
356                 if self.cbFuncClose is not None:
357                         self.cbFuncClose(isRemove = True)
358                 self.close()
359
360         def showKeyboard(self, ret=None):
361                 self["VKeyIcon"].show()
362                 current = self["config"].getCurrent()
363                 if hasattr(current[1], 'help_window'):
364                         if current[1].help_window.instance is not None:
365                                 current[1].help_window.instance.show()
366
367         def hideKeyboard(self):
368                 self["VKeyIcon"].hide()
369                 current = self["config"].getCurrent()
370                 if hasattr(current[1], 'help_window'):
371                         if current[1].help_window.instance is not None:
372                                 current[1].help_window.instance.hide()
373
374         def keyOK(self):
375                 message = '%s field is empty!!'
376                 if isEmpty(self.configName.value) and self.isAdd:
377                         self.hideKeyboard()
378                         self.session.openWithCallback(self.showKeyboard, MessageBox, message%('Name'), MessageBox.TYPE_INFO)
379                         return
380                 if isEmpty(self.configAPN.value):
381                         self.hideKeyboard()
382                         self.session.openWithCallback(self.showKeyboard, MessageBox, message%('APN'), MessageBox.TYPE_INFO)
383                         return
384
385                 if self.cbFuncClose is not None:
386                         self.uid   = self.configUserName.value
387                         self.pwd   = self.configPassword.value
388                         self.pin   = self.configPIN.value
389                         self.apn   = self.configAPN.value
390                         self.phone = self.configPhone.value
391                         self.name  = self.isAdd and self.configName.value or None
392                         self.cbFuncClose(self.uid,self.pwd,self.pin,self.apn,self.phone,self.name)
393                 self.close()
394
395 class ModemManual(Screen):
396         skin =  """
397                 <screen position="center,center" size="600,360" title="3G Modem Manager Config">
398                         <widget name="menulist" position="0,0" size="300,300" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
399                         <widget name="apnInfo" position="310,0" size="290,300" font="Regular;20" halign="left" backgroundColor="#a08500" transparent="1" />
400
401                         <ePixmap pixmap="skin_default/buttons/red.png" position="5,320" size="140,40" alphatest="on" />
402                         <ePixmap pixmap="skin_default/buttons/green.png" position="155,320" size="140,40" alphatest="on" />
403                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,320" size="140,40" alphatest="on" />
404                         <ePixmap pixmap="skin_default/buttons/blue.png" position="455,320" size="140,40" alphatest="on" />
405
406                         <widget source="key_red" render="Label" position="5,320" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
407                         <widget source="key_green" render="Label" position="155,320" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
408                         <widget source="key_yellow" render="Label" position="305,320" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500"  foregroundColor="#ffffff" transparent="1" />
409                         <widget source="key_blue" render="Label" position="455,320" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b"  foregroundColor="#ffffff" transparent="1" />
410                 </screen>
411                 """
412
413         def __init__(self, session, cbFuncClose, uid=None, pwd=None, pin=None, apn=None, phone='*99#'):
414                 Screen.__init__(self, session)
415                 self.cbFuncClose,self.uid,self.pwd,self.pin,self.apn,self.phone = cbFuncClose,uid,pwd,pin,apn,phone
416                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions"],
417                 {
418                         "ok":     self.keyOK,
419                         "cancel": self.keyExit,
420                         "red":    self.keyExit,
421                         "green":  self.keyOK,
422                         "yellow": self.keyEdit,
423                         "blue":   self.keyAdd,
424                         "left":   self.keyLeft,
425                         "right":  self.keyRight,
426                         "up":     self.keyUp,
427                         "down":   self.keyDown,
428                 }, -2)
429
430                 self.apnItems = self.setListOnView()
431                 self["menulist"]   = MenuList(self.apnItems)
432                 self["key_red"]    = StaticText(_("Cancel"))
433                 self["key_green"]  = StaticText(_("OK"))
434                 self["key_yellow"] = StaticText(_("Edit"))
435                 self["key_blue"]   = StaticText(_("Add"))
436                 self["apnInfo"]    = Label(' ')
437
438                 self.keyUp()
439         
440         def keyAdd(self):
441                 self.session.open(EditModemManual, self.cb3GManualSetting, isAdd=True)
442
443         def keyEdit(self):
444                 self.session.open(EditModemManual, self.cb3GManualSetting, self.uid,self.pwd,self.pin,self.apn,self.phone)
445
446         def cb3GManualSetting(self, uid=None, pwd=None, pin=None, apn=None, phone='*99#', name=None, isRemove=False):
447                 if not isRemove:
448                         self.uid = isEmpty(uid) and "" or uid
449                         self.pwd = isEmpty(pwd) and "" or pwd
450                         self.pin = isEmpty(pin) and "" or pin
451                         self.apn = isEmpty(apn) and "" or apn
452                         self.phone = isEmpty(phone) and "" or phone
453                         
454                 if name is not None:
455                         self["menulist"].list.append((name, {'carrier':name, 'apn':self.apn, 'user':self.uid, 'password':self.pwd, 'pin':self.pin, 'phone':self.phone}))
456                         self["menulist"].setList(self["menulist"].list)
457                         self["menulist"].moveToIndex(len(self["menulist"].list)-1)
458                 if isRemove:
459                         index = 0
460                         newList = []
461                         selectedIndex = self["menulist"].getSelectionIndex()
462                         for x in self["menulist"].list:
463                                 if index == selectedIndex:
464                                         index += 1
465                                         continue
466                                 newList.append(x)
467                                 index += 1
468                         self["menulist"].setList(newList)
469                         self["menulist"].moveToIndex(0)
470                         self.setAPNInfo(True)
471                         name = ' '
472                 if not isRemove and isEmpty(name):
473                         self.updateAPNList()
474                 self.updateAPNInfo()
475                 self.saveAPNList(name)
476
477         def updateAPNList(self):
478                 selectedIndex = self["menulist"].getSelectionIndex()
479                 apnList = self["menulist"].list
480                 currentListItem = apnList[selectedIndex][1]
481
482                 currentListItem['user'] = self.uid
483                 currentListItem['apn'] = self.apn
484                 currentListItem['password'] = self.pwd
485                 currentListItem['pin'] = self.pin
486                 currentListItem['phone'] = self.phone
487
488                 self["menulist"].setList(apnList)
489
490         def saveAPNList(self, name=None):
491                 apnList = self["menulist"].list
492                 selectedIndex = self["menulist"].getSelectionIndex()
493
494                 def makeItem(carrier, apn, user, password, pin, phone):
495                         printDebugModemMgr("%s, %s, %s, %s, %s, %s"%(carrier, apn, user, password, pin, phone))
496                         tempStr  = '    <apn'
497                         tempStr += ' carrier="%s"'%(carrier)
498                         tempStr += ' apn="%s"'%(apn)
499                         if not isEmpty(user):     tempStr += ' user="%s"'%(user)
500                         if not isEmpty(password): tempStr += ' password="%s"'%(password)
501                         if not isEmpty(pin):      tempStr += ' pin="%s"'%(pin)
502                         if not isEmpty(phone) :   tempStr += ' phone="%s"'%(phone)
503                         tempStr += ' />\n'
504                         return tempStr
505
506                 tempIndex = 0
507                 apnString = '<apns version="1">\n'
508                 for x in apnList:
509                         try:
510                                 if selectedIndex == tempIndex and name is None:
511                                         apnString += makeItem(x[0], self.apn, self.uid, self.pwd, self.pin, self.phone)
512                                         continue
513                                 apnString += makeItem(x[1].get('carrier'), x[1].get('apn'), x[1].get('user'), x[1].get('password'), x[1].get('pin'), x[1].get('phone'))
514                         finally: tempIndex += 1
515                 apnString += '</apns>\n'
516                 printDebugModemMgr(apnString)
517                 apnListFile = file(resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/3GModemManager/apnlist.xml"), 'w')
518                 apnListFile.write(apnString)
519                 apnListFile.close()
520
521         def keyLeft(self):
522                 self['menulist'].pageUp()
523                 self.setAPNInfo()
524
525         def keyRight(self):
526                 self['menulist'].pageDown()
527                 self.setAPNInfo()
528
529         def keyUp(self):
530                 self['menulist'].up()
531                 self.setAPNInfo()
532
533         def keyDown(self):
534                 self['menulist'].down()
535                 self.setAPNInfo()
536
537         def keyOK(self):
538                 if self.cbFuncClose is not None:
539                         self.cbFuncClose(self.uid,self.pwd,self.pin,self.apn,self.phone)
540                 self.close()
541
542         def keyExit(self):
543                 self.close()
544
545         def setAPNInfo(self, noUpdate=False):
546                 try:
547                         x = self["menulist"].getCurrent()[1]
548                         self.apn, self.uid, self.pwd, self.pin, self.phone = x.get("apn"), x.get("user"), x.get("password"), x.get('pin'), x.get('phone')
549                 except Exception, err: pass
550                 if noUpdate: return
551                 self.updateAPNInfo()
552
553         def updateAPNInfo(self):
554                 apn,uid,pwd,pin,phone = self.apn,self.uid,self.pwd,self.pin,self.phone
555                 if apn is None:   apn = ""
556                 if uid is None:   uid = ""
557                 if pwd is None:   pwd = ""
558                 if pin is None:   pin = ""
559                 if phone is None: phone = ""
560                 info = 'APN : %s\nUSER : %s\nPASSWD : %s\nPIN : %s\nPHONE : %s\n' % (apn, uid, pwd, pin, phone)
561                 self["apnInfo"].setText(info)
562
563         def setListOnView(self):
564                 lvApnItems = []
565                 def uppercaseCompare(a,b):
566                         aa = a.get("carrier")
567                         bb = b.get("carrier")
568                         if isEmpty(aa): aa = ""
569                         if isEmpty(bb): bb = ""
570                         return cmp(aa.upper(),bb.upper())
571                 def isExistAPN(name):
572                         for x in lvApnItems:
573                                 if x[0] == name:
574                                         return True
575                         return False
576                 try:
577                         handle = ParserHandler()
578                         parser = make_parser()
579                         parser.setContentHandler(handle)
580                         parser.parse(resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/3GModemManager/apnlist.xml"))
581
582                         apnList = handle.getNodeList()
583                         apnList.sort(uppercaseCompare)
584                         for x in apnList:
585                                 name = str(x.get('carrier'))
586                                 if isEmpty(name):
587                                         continue
588                                 if isExistAPN(name):
589                                         continue
590                                 d = {}
591                                 d['carrier']  = name
592                                 d['apn']      = x.get('apn')
593                                 d['user']     = x.get('user')
594                                 d['password'] = x.get('password')
595                                 d['pin']      = x.get('pin')
596                                 d['phone']    = x.get('phone')
597                                 lvApnItems.append((name,d))
598                 except Exception, err: pass
599                 finally: del handle
600                 return lvApnItems
601
602 class ModemManager(Screen):
603         skin =  """
604                 <screen position="center,center" size="600,360" title="3G Modem Manager">
605                         <widget name="menulist" position="0,0" size="300,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
606                         <widget name="usbinfo" position="310,0" size="290,150" font="Regular;18" halign="left" />
607
608                         <widget name="statusTitle" position="0,160" size="600,120" font="Regular;20" halign="center" backgroundColor="#a08500" transparent="1" />
609                         <widget name="statusInfo" position="0,185" size="600,120" font="Regular;20" halign="left" backgroundColor="#a08500" transparent="1" />
610
611                         <ePixmap pixmap="skin_default/buttons/red.png" position="5,320" size="140,40" alphatest="on" />
612                         <ePixmap pixmap="skin_default/buttons/green.png" position="155,320" size="140,40" alphatest="on" />
613                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,320" size="140,40" alphatest="on" />
614                         <ePixmap pixmap="skin_default/buttons/blue.png" position="455,320" size="140,40" alphatest="on" />
615
616                         <widget source="key_red" render="Label" position="5,320" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
617                         <widget source="key_green" render="Label" position="155,320" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
618                         <widget source="key_yellow" render="Label" position="305,320" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500"  foregroundColor="#ffffff" transparent="1" />
619                         <widget source="key_blue" render="Label" position="455,320" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b"  foregroundColor="#ffffff" transparent="1" />
620                 </screen>
621                 """
622         uid,pwd,pin,apn,phone = None,None,None,None,'*99#'
623         connectionStatus = 0
624         def __init__(self, session): 
625                 Screen.__init__(self, session)
626                 self.usb_lv_items = self.setListOnView()
627
628                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", "NumberActions"],
629                 {
630                         "ok":     self.keyOK,
631                         "cancel": self.keyExit,
632                         "red":    self.keyExit,
633                         "green":  self.keyOK,
634                         "yellow": self.keyManual,
635                         "blue":   self.keyReset,
636                         "up":     self.keyUp,
637                         "down":   self.keyDown,
638                         "left":   self.keyLeft,
639                         "right":  self.keyRight,
640                         "0":      self.keyNumber,
641                 }, -2)
642                 self["menulist"] = MenuList(self.usb_lv_items)
643                 self['usbinfo'] = Label(' ')
644                 self['statusTitle'] = Label('[ Status ]')
645                 self['statusInfo'] = Label(' ')
646                 self["key_red"] = StaticText(_("Exit"))
647                 if self.isConnected():
648                         self["key_green"] = StaticText("Disconnect")
649                         self.setDisconnectStatus(0)
650                 else:
651                         self["key_green"] = StaticText("Connect")
652                         self.setConnectStatus(0)
653                 self["key_yellow"] = StaticText(_("Manual"))
654                 self["key_blue"] = StaticText(_("Reset"))
655
656                 self.updateUSBInfo()
657
658                 self.udevListener = DeviceEventListener()
659                 self.udevListener.addCallback(self.cbUdevListener)
660
661                 self.taskManager = TaskManager()
662
663                 self.refreshStatusTimer = eTimer()
664                 self.refreshStatusTimer.callback.append(self.cbRefreshStatus)
665
666                 #self.restartAppTimer = eTimer()
667                 #self.restartAppTimer.callback.append(self.cbRestartAppTimer)
668                 self.commandBin = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/3GModemManager/3gcommand")
669                 self.forceStop = False
670
671         def cbRestartAppTimer(self):
672                 self.restartAppTimer.stop()
673                 model = file('/proc/stb/info/vumodel').read().strip()
674                 if model is not None:
675                         if model == 'solo' or model == 'bm750':
676                                 self.session.open(TryQuitMainloop, 3)
677
678         def cbRefreshStatus(self):
679                 self.refreshStatusTimer.stop()
680                 if self["key_green"].getText() == 'Connect':
681                         self.setConnectStatus(0)
682                 elif self["key_green"].getText() == 'Disconnect': 
683                         self.setDisconnectStatus(0)
684
685         def cbUdevListener(self, data):
686                 printDebugModemMgr('Udev Listener Refresh!!')
687                 time.sleep(2)
688                 self["menulist"].setList(self.setListOnView())
689                 self.updateUSBInfo()
690
691         def isAttemptConnect(self):
692                 if self.connectionStatus == 0 or self.forceStop:
693                         return False
694                 maxIdx = 4
695                 if self["key_green"].getText() == 'Disconnect':
696                         maxIdx = 2
697                 if self.connectionStatus < maxIdx:
698                         printInfoModemMgr("can't excute a command during connecting...")
699                         return True
700                 return False
701
702         def keyManual(self):
703                 if self.isAttemptConnect():
704                         return
705                 self.session.open(ModemManual, self.cb3GManualSetting, self.uid,self.pwd,self.pin,self.apn,self.phone)
706                 #self.session.open(ModemManual, self.cb3GManualSetting)
707
708         def keyReset(self):
709                 if self.isAttemptConnect():
710                         return
711                 self.cb3GManualSetting()
712
713         def cb3GManualSetting(self, uid=None, pwd=None, pin=None, apn=None, phone='*99#'):
714                 self.uid,self.pwd,self.pin,self.apn,self.phone = uid,pwd,pin,apn,phone
715                 self.updateUSBInfo()
716
717         def keyNumber(self, num=None):
718                 global debug_mode_modem_mgr
719                 debug_mode_modem_mgr = not debug_mode_modem_mgr
720                 printInfoModemMgr('changed log mode, debug %s'%(debug_mode_modem_mgr and 'on' or 'off'))
721
722         def keyExit(self):
723                 if self.isAttemptConnect():
724                         message = "Can't disconnect doring connecting..\nDo you want to forcibly exit?"
725                         self.session.openWithCallback(self.cbForciblyExit, MessageBox, _(message), default = False)
726                         return
727                 self.udevListener.close()
728                 self.close()
729
730         def cbForciblyExit(self, result):
731                 if result:
732                         os.system('%s -s 6' % self.commandBin)
733                         self.udevListener.close()
734                         self.close()
735
736         def keyLeft(self):
737                 self["menulist"].pageUp()
738                 self.updateUSBInfo()
739
740         def keyRight(self):
741                 self["menulist"].pageDown()
742                 self.updateUSBInfo()
743
744         def keyUp(self):
745                 self["menulist"].up()
746                 self.updateUSBInfo()
747
748         def keyDown(self):
749                 self["menulist"].down()
750                 self.updateUSBInfo()
751
752         def keyOK(self):
753                 self.forceStop = False
754                 if self.isAttemptConnect():
755                         return
756
757                 def areadyExistAnotherAdapter():
758                         networkAdapters = iNetwork.getConfiguredAdapters()
759                         for x in networkAdapters:
760                                 if x[:3] != 'ppp':
761                                         return True
762                         return False
763
764                 if self["key_green"].getText() == 'Disconnect':
765                         message = "Do you want to disconnect?"
766                         self.session.openWithCallback(self.cbConfirmDone, MessageBox, _(message), default = False)
767                         return
768
769                 if areadyExistAnotherAdapter():
770                         message = "Another adapter connected has been found.\n\nA connection is attempted after disconnect all of other device. Do you want to?"
771                         self.session.openWithCallback(self.cbConfirmDone, MessageBox, _(message), default = True)
772                 else:   self.cbConfirmDone(True)
773
774         def cbConfirmDone(self, ret):
775                 if not ret: return
776                 if self["key_green"].getText() == 'Connect':
777                         networkAdapters = iNetwork.getConfiguredAdapters()
778                         for x in networkAdapters:
779                                 if x[:3] == 'ppp': continue
780                                 iNetwork.setAdapterAttribute(x, "up", False)
781                                 iNetwork.deactivateInterface(x)
782
783                 x = {}
784                 try: x = self["menulist"].getCurrent()[1]
785                 except:
786                         printInfoModemMgr('no selected device..')
787                         return
788
789                 devFile = '/usr/share/usb_modeswitch/%s:%s' % (x.get("Vendor"), x.get("ProdID"))
790                 if not os.path.exists(devFile) :
791                         message = "Can't found device file!! [%s]" % (devFile)
792                         printInfoModemMgr(message)
793                         self.session.open(MessageBox, _(message), MessageBox.TYPE_INFO)
794                         return
795
796                 if self["key_green"].getText() == 'Disconnect':
797                         cmd = "%s -s 0" % (self.commandBin)
798                         self.taskManager.append(cmd, self.cbPrintAvail, self.cbPrintClose)
799
800                         cmd = "%s -s 1" % (self.commandBin)
801                         self.taskManager.append(cmd, self.cbPrintAvail, self.cbUnloadClose)
802                         self.taskManager.setStatusCB(self.setDisconnectStatus)
803                 else:
804                         cmd = "%s -s 2 -e vendor=0x%s -e product=0x%s" % (self.commandBin, x.get("Vendor"), x.get("ProdID"))
805                         self.taskManager.append(cmd, self.cbStep1PrintAvail, self.cbPrintClose)
806
807                         cmd = "%s -s 3 -e %s:%s" % (self.commandBin, x.get("Vendor"), x.get("ProdID"))
808                         self.taskManager.append(cmd, self.cbPrintAvail, self.cbPrintClose)
809
810                         cmd = "%s -s 4" % (self.commandBin)
811                         self.taskManager.append(cmd, self.cbStep3PrintAvail, self.cbMakeWvDialClose)
812
813                         cmd = "%s -s 5" % (self.commandBin)
814                         self.taskManager.append(cmd, self.cbRunWvDialAvail, self.cbPrintClose)
815                         self.taskManager.setStatusCB(self.setConnectStatus)
816                 
817                 self.taskManager.next()
818
819         def printStatus(self, idx, STATUS):
820                 message = ''
821                 self.connectionStatus = idx
822                 for x in range(0,len(STATUS)):
823                         if idx == x:
824                                 message += '  > '
825                         else:   message += '      '
826                         message += STATUS[x]
827                         message += '\n'
828                 self['statusInfo'].setText(message)
829
830         def setConnectStatus(self, idx):
831                 STATUS = {
832                  0:'1. Load a Mobile Broadband Device'
833                 ,1:'2. Set up a Mobile Broadband Device'
834                 ,2:'3. Generate a WvDial profile'
835                 ,3:'4. Attempt to connect'
836                 ,4:'5. Done'
837                 }
838                 self.printStatus(idx, STATUS)
839
840         def setDisconnectStatus(self, idx):
841                 STATUS = {
842                  0:'1. Drop WvDial'
843                 ,1:'2. Unload a Mobile Broadband Device'
844                 ,2:'3. Done'
845                 }
846                 self.printStatus(idx, STATUS)
847
848         def cbStep1PrintAvail(self, data):
849                 print data
850                 if data.find('modules.dep') > -1:
851                         self.forceStop = True
852
853         def cbStep3PrintAvail(self, data):
854                 print data
855                 if data.find('no modem was detected') > -1:
856                         self.forceStop = True
857
858         def cbPrintAvail(self, data):
859                 print data
860
861         def cbPrintClose(self, ret):
862                 if self.forceStop:
863                         self.taskManager.clean()
864                         time.sleep(2)
865                         message = "Occur error during connection...\nPlease, Check your setting!!"
866                         self.session.open(MessageBox, _(message), MessageBox.TYPE_INFO)
867                         return
868                 self.taskManager.next()
869
870         def cbUnloadClose(self, ret):
871                 self.taskManager.clean()
872                 time.sleep(2)
873                 self["key_green"].setText('Connect')
874                 self.setDisconnectStatus(2)
875                 self.refreshStatusTimer.start(1000)
876
877         def cbRunWvDialAvail(self, data):
878                 print data
879                 if data.find('Bad init') > -1 or data.find('Invalid dial') > -1 or data.find('No Carrier') > -1:
880                         self.forceStop = True
881                         return
882                 if data.find('Pid of pppd:') > -1:
883                         self.taskManager.clean()
884                         time.sleep(2)
885                         self["key_green"].setText('Disconnect')
886                         self.setConnectStatus(4)
887                         self.refreshStatusTimer.start(1000)
888                         #self.restartAppTimer.start(3000)
889
890         def cbMakeWvDialClose(self, ret):
891                 if self.forceStop:
892                         self.taskManager.clean()
893                         time.sleep(2)
894                         message = "Occur error during connection...\nPlease, Check your setting!!"
895                         self.session.open(MessageBox, _(message), MessageBox.TYPE_INFO)
896                         return
897
898                 info = {}
899                 try:
900         
901                         datalist = file('/etc/wvdial.conf').read().splitlines()
902                         for x in datalist:
903                                 if x.startswith('Modem ='):
904                                         print x
905                                         info['Modem'] = x[7:].strip()
906                                 elif x.startswith('Init2 ='):
907                                         print x
908                                         info['Init'] = x[7:].strip()
909                                 elif x.startswith('Baud ='):
910                                         print x
911                                         info['Baud'] = x[6:].strip()
912                 except Exception, err: 
913                         printDebugModemMgr("getModemInfo Error : [%s]" % (str(err)))
914                         # TODO : occur error!!
915                         return
916
917                 if not isEmpty(self.apn):   info['apn']   = self.apn
918                 if not isEmpty(self.uid):   info['uid']   = self.uid
919                 if not isEmpty(self.pwd):   info['pwd']   = self.pwd
920                 if not isEmpty(self.pin):   info['pin']   = self.pin
921                 if not isEmpty(self.phone): info['phone'] = self.phone
922                 #info['phone'] = '*99#'
923                 self.makeWvDialConf(info)
924                 self.taskManager.next()
925
926         def writeConf(self, data, oper='>>'):
927                 confFile = '/etc/wvdial.conf'
928                 if oper == '>':
929                         os.system('mv %s %s.bak' % (confFile, confFile))
930                 cmd = "echo '%s' %s %s" % (data, oper, confFile)
931                 os.system(cmd)
932
933         def makeWvDialConf(self, params):
934                 baud  = params.get('Baud')
935                 init  = params.get('Init')
936                 modem = params.get('Modem')
937                 phone = params.get('phone')
938                 apn = params.get('apn')
939                 uid = params.get('uid')
940                 pwd = params.get('pwd')
941                 pin = params.get('pin')
942                 idxInit = 1
943
944                 if isEmpty(phone): phone = '*99#'
945                 if isEmpty(uid):   uid = 'USER'
946                 if isEmpty(pwd):   pwd = 'PASSWORD'
947
948                 self.writeConf('','>')
949
950                 self.writeConf('[Dialer Defaults]')
951                 if isEmpty(modem) or isEmpty(init) or isEmpty(baud):
952                         return False
953                 self.writeConf('Modem = %s' % (modem))
954                 self.writeConf('Baud = %s' % (baud))
955                 self.writeConf('Dial Command = ATDT')
956                 self.writeConf('Init%d = ATZ' % (idxInit))
957                 idxInit = idxInit + 1
958                 if not isEmpty(pin):
959                         self.writeConf('Init%d = AT+CPIN=%s' % (idxInit, pin))
960                         idxInit = idxInit + 1
961                 self.writeConf('Init%d = %s' % (idxInit, init))
962                 idxInit = idxInit + 1
963                 if isEmpty(apn) and isEmpty(uid) and isEmpty(pwd) and isEmpty(pin):
964                         self.writeConf('Init%d = AT&F' % (idxInit))
965                         idxInit = idxInit + 1
966                 if not isEmpty(apn):
967                         self.writeConf('Init%d = AT+CGDCONT=1,"IP","%s"' % (idxInit, apn))
968                         idxInit = idxInit + 1
969                 self.writeConf('Init%d = AT+CFUN = 1' % (idxInit))
970                 self.writeConf('Username = %s' % (uid))
971                 self.writeConf('Password = %s' % (pwd))
972                 self.writeConf('Phone = %s' % (phone)) #*99#
973                 self.writeConf('Modem Type = Analog Modem')
974                 self.writeConf('ISDN = 0')
975                 self.writeConf('Carrier Check = 0')
976                 self.writeConf('Abort on No Dialtone = 0')
977                 self.writeConf('Stupid Mode = 1')
978                 self.writeConf('Check DNS = 1')
979                 self.writeConf('Check Def Route = 1')
980                 self.writeConf('Auto DNS = 1')
981                 if debug_mode_modem_mgr:
982                         printDebugModemMgr(file('/etc/wvdial.conf').read())
983
984         def isConnected(self):
985                 return len(os.popen('ifconfig -a | grep ppp').read().strip()) > 0
986
987         def updateUSBInfo(self):
988                 info = ' '
989                 try:
990                         apn,uid,pwd,pin,phone = self.apn,self.uid,self.pwd,self.pin,self.phone
991                         if apn is None:   apn = ""
992                         if uid is None:   uid = ""
993                         if pwd is None:   pwd = ""
994                         if pin is None:   pin = ""
995                         if phone is None: phone = ""
996                         x = self["menulist"].getCurrent()[1]
997                         info = 'Vendor : %s/%s\nAPN : %s\nUser : %s\nPassword : %s\nPin : %s\nPhone : %s' % (
998                                         x.get("Vendor"), 
999                                         x.get("ProdID"), 
1000                                         apn,
1001                                         uid,
1002                                         pwd,
1003                                         pin,
1004                                         phone
1005                                 )
1006                 except: pass
1007                 self['usbinfo'].setText(info)
1008
1009         def setListOnView(self):
1010                 lv_usb_items = []
1011                 try:
1012                         for x in self.getUSBList():
1013                                 lv_usb_items.append((x.get("Product"),x))
1014                 except: pass
1015                 printDebugModemMgr(str(lv_usb_items))
1016                 return lv_usb_items
1017
1018         def getUSBList(self):
1019                 parsed_usb_list = []
1020                 usb_devices = lsusb_devices()
1021                 tmp_device = {}
1022                 for x in usb_devices.splitlines():
1023                         if x is None or len(x) == 0:
1024                                 printDebugModemMgr("TMP DEVICE : [%s]" % (tmp_device))
1025                                 if len(tmp_device):
1026                                         parsed_usb_list.append(tmp_device)
1027                                 tmp_device = {}
1028                                 continue
1029                         try:
1030                                 if x[0] in ('P', 'S', 'I', 'T'):
1031                                         tmp = x[2:].strip()
1032                                         printDebugModemMgr("TMP : [%s]" % (tmp))
1033                                         if tmp.startswith('Bus='):
1034                                                 #printDebugModemMgr("TMP SPLIT for BUS : [%s]" % (str(tmp.split())))
1035                                                 for xx in tmp.split():
1036                                                         if xx.startswith('Bus='):
1037                                                                 tmp_device['Bus'] = xx[4:]
1038                                                                 break
1039                                         if tmp.startswith('Manufacturer='):
1040                                                 tmp_device['Manufacturer'] = tmp[13:]
1041                                         if tmp.startswith('Product='):
1042                                                 tmp_device['Product'] = tmp[8:]
1043                                         elif tmp.startswith('SerialNumber='):
1044                                                 tmp_device['SerialNumber'] = tmp[13:]
1045                                         elif tmp.startswith('Vendor='):
1046                                                 #printDebugModemMgr("TMP SPLIT for BUS : [%s]" % (str(tmp.split())))
1047                                                 for xx in tmp.split():
1048                                                         if xx.startswith('Vendor='):
1049                                                                 tmp_device['Vendor'] = xx[7:]
1050                                                         elif xx.startswith('ProdID='):
1051                                                                 tmp_device['ProdID'] = xx[7:]
1052                                                 #tmp_device['Vendor'] = tmp
1053                                         elif tmp.find('Driver=') > 0:
1054                                                 d = tmp[tmp.find('Driver=')+7:]
1055                                                 if d != '(none)':
1056                                                         tmp_device['Interface'] = d
1057                         except Exception, errmsg:
1058                                 print errmsg
1059                 if len(tmp_device):
1060                         parsed_usb_list.append(tmp_device)
1061                 printDebugModemMgr("PARSED DEVICE LIST : " + str(parsed_usb_list))
1062                 rt_usb_list = []
1063                 for x in parsed_usb_list:
1064                         printDebugModemMgr('Looking >> ' + str(x))
1065                         try:
1066                                 xx = x.get("Interface")
1067                                 if xx.startswith('usb'):
1068                                         rt_usb_list.append(x)
1069                         except: pass
1070                 printInfoModemMgr("USB DEVICE LIST : " + str(rt_usb_list))
1071                 return rt_usb_list
1072
1073 def main(session, **kwargs):
1074         session.open(ModemManager)
1075                                                            
1076 def Plugins(**kwargs):            
1077         return PluginDescriptor(name=_("Modem Manager"), description="management 3g modem", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
1078