7834f06edd7d63c3e0ca5ed85ff53c4d20619d57
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / FirmwareUpgrade / plugin.py
1 import os, urllib
2 from urllib import urlretrieve
3
4 from Plugins.Plugin import PluginDescriptor
5
6 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigText, ConfigSelection, ConfigYesNo,ConfigText
7 from Components.ConfigList import ConfigListScreen
8 from Components.ActionMap import ActionMap
9 from Components.Sources.StaticText import StaticText
10 from Components.Pixmap import Pixmap
11 from Components.Label import Label
12
13 from Components.FileList import FileList 
14 from Components.Slider import Slider
15
16 from Screens.Screen import Screen
17 from Screens.MessageBox import MessageBox
18
19 from enigma import ePoint, eConsoleAppContainer, eTimer, getDesktop
20 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
21
22 fwlist = None
23 fwdata = None
24 if os.path.exists("/proc/stb/info/vumodel"):
25         vumodel = open("/proc/stb/info/vumodel")
26         info = vumodel.read().strip()
27         vumodel.close()
28
29         if info == "ultimo":
30                 fwlist= [
31                          ("fpga", _("FPGA"))
32                         ,("fp", _("Front Processor"))
33                         ]
34                 fwdata= { 
35                          "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
36                         ,"fp"   : ["http://archive.vuplus.com/download/fp", "fp.files", "/dev/bcm_mu;"]
37                         }
38         elif info == "uno":
39                 fwlist= [
40                         ("fpga", _("FPGA"))
41                         ]
42                 fwdata= { 
43                         "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.file", "/dev/fpga_dp;/dev/misc/dp;"]
44                         }
45
46 import os, fcntl, thread
47 STATUS_READY            = 0
48 STATUS_DONE             = 1
49 STATUS_ERROR            = 2
50 STATUS_PREPARED         = 3
51 STATUS_PROGRAMMING      = 4
52 STATUS_RETRY_UPGRADE    = 5
53
54 class FPUpgradeCore() :
55         status = STATUS_READY
56         errmsg = ''
57         MAX_CALL_COUNT = 120
58         def __init__(self, firmwarefile, devicefile):
59                 self.devicefile = devicefile
60                 self.firmwarefile = firmwarefile
61
62         def doUpgrade(self):
63                 firmware,device = None,None
64                 def closefpga(fp, fd):
65                         if fd is not None: os.close(fd)
66                         if fp is not None: fp.close()
67                 try:
68                         size = os.path.getsize(self.firmwarefile)
69                         if size == 0: raise Exception, 'data_size is zero'
70                         #print '[FPUpgradeCore] data_size :',size
71
72                         for xx in range(3):
73                                 self.callcount = 0
74                                 self.status = STATUS_READY
75
76                                 firmware = open(self.firmwarefile, 'rb')
77                                 device = os.open(self.devicefile, os.O_RDWR)
78                                 #print '[FPUpgradeCore] open >> [ok]'
79
80                                 rc = fcntl.ioctl(device, 0, size)
81                                 if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
82                                 #print '[FPUpgradeCore] set size >> [ok]'
83                                 self.status = STATUS_PREPARED
84
85                                 while True:
86                                         data = firmware.read(1024)
87                                         if data == '': break
88                                         os.write(device, data)
89                                 #print '[FPUpgradeCore] write data >> [ok]'
90
91                                 self.status = STATUS_PROGRAMMING
92                                 rc = fcntl.ioctl(device, 1, 0)
93                                 if rc == 0: break
94                                 if xx == 2: raise Exception, 'fail to upgrade : %d'%(rc)
95                                 self.errmsg = 'fail to upgrade, retry..'
96                                 self.status = STATUS_RETRY_UPGRADE
97                                 closefpga(firmware, device)
98                         #print '[FPUpgradeCore] upgrade done.'
99                         if self.callcount < 20: raise Exception, 'wrong fpga file.'
100                 except Exception, msg:
101                         self.errmsg = msg
102                         print '[FPUpgradeCore] ERROR >>',msg
103                         closefpga(firmware, device)
104                         return STATUS_ERROR
105                 return STATUS_DONE
106
107         def upgradeMain(self):
108                 self.status = STATUS_READY
109                 self.status = self.doUpgrade()
110                 if self.status == STATUS_DONE:
111                         print 'upgrade done.'
112                 elif self.status == STATUS_ERROR:
113                         print 'error!!'
114                 else:   print 'unknown.'
115
116 class FPGAUpgradeCore() :
117         status = STATUS_READY
118         errmsg = ''
119         callcount       = 0
120         MAX_CALL_COUNT  = 1500
121         def __init__(self, firmwarefile, devicefile):
122                 print '[FPGAUpgrade]'
123                 self.devicefile = devicefile
124                 self.firmwarefile = firmwarefile
125
126         def doUpgrade(self):
127                 firmware,device = None,None
128                 def closefpga(fp, fd):
129                         if fd is not None: os.close(fd)
130                         if fp is not None: fp.close()
131                 try:
132                         size = os.path.getsize(self.firmwarefile)
133                         if size == 0: raise Exception, 'data_size is zero'
134                         #print '[FPGAUpgradeCore] data_size :',size
135
136                         firmware = open(self.firmwarefile, 'rb')
137                         device = os.open(self.devicefile, os.O_RDWR)
138                         #print '[FPGAUpgradeCore] open >> [ok]'
139
140                         rc = fcntl.ioctl(device, 0, size)
141                         if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
142                         #print '[FPGAUpgradeCore] set size >> [ok]'
143
144                         rc = fcntl.ioctl(device, 2, 5)
145                         if rc < 0: raise Exception, 'fail to set programming mode : %d'%(rc)
146                         #print '[FPGAUpgradeCore] programming mode >> [ok]'
147                         self.status = STATUS_PREPARED
148
149                         while True:
150                                 data = firmware.read(1024)
151                                 if data == '': break
152                                 os.write(device, data)
153                         #print '[FPGAUpgradeCore] write data >> [ok]'
154
155                         self.status = STATUS_PROGRAMMING
156                         rc = fcntl.ioctl(device, 1, 0)
157                         if rc < 0: raise Exception, 'fail to programming : %d'%(rc)
158                         #print '[FPGAUpgradeCore] upgrade done.'
159                         if self.callcount < 20: raise Exception, 'wrong fpga file.'
160                 except Exception, msg:
161                         self.errmsg = msg
162                         print '[FPGAUpgradeCore] ERROR >>',msg
163                         closefpga(firmware, device)
164                         return STATUS_ERROR
165                 closefpga(firmware, device)
166                 return STATUS_DONE
167
168         def upgradeMain(self):
169                 self.status = STATUS_READY
170                 self.status = self.doUpgrade()
171                 if self.status == STATUS_DONE:
172                         print '[FPGAUpgrade] upgrade done.'
173                 elif self.status == STATUS_ERROR:
174                         print '[FPGAUpgrade] occur error.'
175                 else:   print '[FPGAUpgrade] occur unknown error.'
176
177 class FirmwareUpgradeManager:
178         fu = None
179         def getInterval(self):
180                 return 200
181
182         def startUpgrade(self, datafile, device, firmware):
183                 if firmware == 'fpga':
184                         self.fu = FPGAUpgradeCore(firmwarefile=datafile, devicefile=device)
185                 elif firmware == 'fp':
186                         self.fu = FPUpgradeCore(firmwarefile=datafile, devicefile=device)
187                 thread.start_new_thread(self.fu.upgradeMain, ())
188
189         def checkError(self):
190                 if self.fu.status == STATUS_ERROR:
191                         self.fu.callcount = 0
192                         return True
193                 return False
194
195         def getStatus(self):
196                 if self.fu.status in (STATUS_READY, STATUS_ERROR):
197                         return 0
198                 elif self.fu.status == STATUS_PREPARED:
199                         return 2
200                 elif self.fu.status == STATUS_PROGRAMMING:
201                         self.fu.callcount += 1
202                         ret = (self.fu.callcount * 100) / self.fu.MAX_CALL_COUNT + 2
203                         if ret >= 100: ret = 99
204                         #print "callcount : [%d]"%(self.fu.callcount);
205                         return ret
206                 elif self.fu.status == STATUS_DONE:
207                         return 100
208
209         def getErrorMessage(self, errno, errmsg):
210                 return str(self.fu.errmsg)
211
212 class UpgradeStatus(Screen):
213         skin =  """
214                 <screen position="center,center" size="450,130" title=" ">
215                         <widget name="name" position="10,0" size="430,20" font="Regular;18" halign="left" valign="bottom"/>
216                         <widget name="slider" position="10,25" size="430,30" borderWidth="2" borderColor="#cccccc"/>
217                         <widget name="status" position="10,25" zPosition="1" size="430,30" font="Regular;18" halign="center" valign="center" foregroundColor="#9f1313" transparent="1"/>
218                         <widget source="info" render="Label" position="10,70" zPosition="1" size="430,60" font="Regular;22" halign="center" valign="center" transparent="1"/>
219                 </screen>
220                 """
221
222         def __init__(self, session, parent, firmware, datafile, device):
223                 Screen.__init__(self,session)
224                 self.session = session
225
226                 self["actions"] = ActionMap(["OkCancelActions"],
227                 {
228                         "ok": self.keyExit,
229                 }, -1)
230
231                 self.firmware = firmware
232                 self.datafile = datafile
233                 #print "[FirmwareUpgrade] - [%s][%s][%s]" % (self.datafile, firmware, device)
234
235                 self["name"] = Label(_(" "))
236                 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
237
238                 self["status"] = Label(_("Status : 0%"))
239
240                 self.slider = Slider(0, 100)
241                 self["slider"] = self.slider
242
243                 self.callback = None
244
245                 self.setTitle(firmware.upper() + " Upgrade Status")
246
247                 self.FU = FirmwareUpgradeManager()
248
249                 self.old_status   = 0
250                 self.status_exit  = None
251                 self.check_status = eTimer()
252                 self.check_status.callback.append(self.cbCheckStatus)
253                 self.check_status.start(self.FU.getInterval())
254
255                 self.exitTimerCallCount = 0;
256                 self.upgradeLock = True
257                 self.FU.startUpgrade(self.datafile, device, firmware)
258
259         def cbCheckStatus(self):
260                 errmsg = ""
261                 errno  = self.FU.checkError()
262                 if errno:
263                         self.check_status.stop()
264                         errmsg = self.FU.getErrorMessage(errno, errmsg)
265                         print "[FirmwareUpgrade] - ERROR : [%d][%s]" % (errno, errmsg)
266                         self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
267                         self.cbConfirmExit(False)
268                         return
269                 status = self.FU.getStatus()
270                 if self.old_status > status and status != -1:
271                         self.session.open(MessageBox, _("Fail to upgrade!! Retry!!"), MessageBox.TYPE_INFO, timeout = 10)
272                 self.slider.setValue(status)
273                 self["status"].setText(_("%d / 100" % (status)))
274                 if status == 100:
275                         self.check_status.stop()
276                         self["status"].setText(_("Success. Press OK to exit."))
277                         self.status_exit = eTimer()
278                         self.status_exit.callback.append(self.cbTimerExit)
279                         self.status_exit.start(1000)
280                         self.upgradeLock = False
281                 self.old_status = status
282
283         def setCallback(self, cb):
284                 self.callback = cb
285
286         def cbTimerExit(self):
287                 if self.exitTimerCallCount < 10: # exit after 10 sec.
288                         self.exitTimerCallCount = self.exitTimerCallCount + 1
289                         self.setTitle("%s Upgrade Status (%d)" % (self.firmware.upper(), 10-self.exitTimerCallCount))
290                         return
291                 if self.status_exit is not None:
292                         self.status_exit.stop()
293                 self.keyExit()
294
295         def cbConfirmExit(self, ret):
296                 if ret:
297                         os.system("rm -f %s %s.md5" % (self.datafile, self.datafile))
298                 self.close()
299
300         def keyExit(self):
301                 if self.upgradeLock:
302                         return
303                 if self.callback is not None:
304                         self.callback("Reboot now for a successful upgrade.", True)
305                 self.session.openWithCallback(self.cbConfirmExit, MessageBox, _("Do you want to remove binary data?"), MessageBox.TYPE_YESNO, timeout = 10, default = False)
306
307 class FUFilebrowser(Screen):
308         skin =  """
309                 <screen position="center,center" size="500,290" title="File Browser" >
310                         <ePixmap pixmap="skin_default/buttons/blue.png" position="5,10" size="140,40" alphatest="blend" />
311
312                         <widget source="key_blue" render="Label" position="5,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1"/>
313
314                         <widget name="file_list" position="0,70" size="495,160" scrollbarMode="showOnDemand" />
315                         <widget source="status" render="Label" position="0,230" zPosition="1" size="495,70" font="Regular;18" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
316                 </screen>
317                 """
318
319         def __init__(self, session, parent, firmware):
320                 Screen.__init__(self, session)
321                 self.session = session 
322                 
323                 self["key_blue"] = StaticText(_("Download"))
324
325                 self["status"]    = StaticText(_(" "))
326                 self["file_list"] = FileList("/", matchingPattern = "^.*")
327
328                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
329                 {
330                         "ok":     self.onClickOk,
331                         "cancel": self.onClickCancel,
332                         "blue":   self.onClickBlue,
333                         "up":     self.onClickUp,
334                         "down":   self.onClickDown,
335                         "left":   self.onClickLeft,
336                         "right":  self.onClickRight,
337                 }, -1) 
338
339                 self.resetGUI()
340                 self.firmware = firmware
341
342                 self.callback = None
343                 self.timer_downloading = None
344
345                 self.downloadLock = False
346                 self.setTitle(firmware.upper() + " File Browser")
347
348         def resetGUI(self):
349                 self["status"].setText("Select to press OK, Exit to press Cancel.\nPress the BLUE button to download the latest firmware.")
350
351         def setCallback(self, func):
352                 self.callback = func
353
354         def onClickOk(self):
355                 if self.downloadLock:
356                         return
357
358                 if self["file_list"].canDescent() : # isDir
359                         self["file_list"].descent()
360                         return
361
362                 # verify data
363                 self.gbin = self["file_list"].getCurrentDirectory() + self["file_list"].getFilename()
364                 if not os.path.exists(self.gbin):
365                         self.session.open(MessageBox, _("Can't found binary file."), MessageBox.TYPE_INFO, timeout = 10)
366                         return
367                 if not os.path.exists(self.gbin+".md5"):
368                         self.session.open(MessageBox, _("Can't found MD5 file."), MessageBox.TYPE_INFO, timeout = 10)
369                         return
370                 try:
371                         def checkExt(ext):
372                                 name_ext = os.path.splitext(self["file_list"].getFilename())
373                                 return len(name_ext)==2 and ext.startswith(name_ext[1])
374                         self.check_ext = False
375                         if (self.firmware == "fp" and checkExt(".bin")) or (self.firmware == "fpga" and checkExt(".dat")):
376                                 self.check_ext = True
377                         if self.check_ext == False:
378                                 self.session.open(MessageBox, _("You chose the incorrect file."), MessageBox.TYPE_INFO)
379                                 return
380                 except:
381                         self.session.open(MessageBox, _("You chose the incorrect file."), MessageBox.TYPE_INFO)
382                         return
383
384                 if os.path.exists("/usr/bin/md5sum") == False:
385                         self.session.open(MessageBox, _("Can't find /usr/bin/md5sum"), MessageBox.TYPE_INFO, timeout = 10)
386                         return
387                 md5sum_A = os.popen("md5sum %s | awk \'{print $1}\'"%(self.gbin)).readline().strip()
388                 md5sum_B = os.popen("cat %s.md5 | awk \'{print $1}\'"%(self.gbin)).readline().strip()
389                 #print "[FirmwareUpgrade] - Verify : file[%s], md5[%s]"%(md5sum_A,md5sum_B)
390
391                 if md5sum_A != md5sum_B:
392                         self.session.open(MessageBox, _("Fail to verify data file. \nfile[%s]\nmd5[%s]"%(md5sum_A,md5sum_B)), MessageBox.TYPE_INFO, timeout = 10)
393                         return 
394
395                 if self.callback is not None:
396                         self.callback(_(self.gbin))
397                 self.close()
398
399         def onClickCancel(self):
400                 self.close()
401
402         # uri : source file url(string)
403         # tf  : target file name(string)
404         # bd  : target base directory(string)
405         # cbfunc(string) : callback function(function)
406         def doDownload(self, uri, tf, bd='/tmp', cbfunc=None, errmsg="Fail to download."):
407                 tar = bd + "/" + tf
408                 #print "[FirmwareUpgrade] - Download Info : [%s][%s]" % (uri, tar)
409                 def doHook(blockNumber, blockSize, totalSize) :
410                         if blockNumber*blockSize > totalSize and cbfunc is not None:
411                                 cbfunc(tar)
412                 opener = urllib.URLopener()
413                 try:
414                         opener.open(uri)
415                 except:
416                         #self.session.open(MessageBox, _("File not found in this URL:\n%s"%(uri)), MessageBox.TYPE_INFO, timeout = 10)
417                         print "[FirmwareUpgrade] - Fail to download. URL :",uri
418                         self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
419                         del opener
420                         return False
421                 try :
422                         f, h = urlretrieve(uri, tar, doHook)
423                 except IOError, msg:
424                         #self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 10)
425                         print "[FirmwareUpgrade] - Fail to download. ERR_MSG :",str(msg)
426                         self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
427                         del opener
428                         return False
429                 del opener
430                 return True
431
432         def runDownloading(self) :
433                 self.timer_downloading.stop()
434                 machine = str(open("/proc/stb/info/vumodel").read().strip())
435
436                 def cbDownloadDone(tar):
437                         try:
438                                 if os.path.splitext(tar)[1] != ".files":
439                                         self["status"].setText("Downloaded : %s\nSelect to press OK, Exit to press Cancel."%(tar))
440                         except:
441                                 pass
442                 # target
443                 global fwdata
444                 root_uri  = fwdata[self.firmware][0]
445                 root_file = fwdata[self.firmware][1]
446                 if not self.doDownload("%s/%s"%(root_uri, root_file), root_file, cbfunc=cbDownloadDone):
447                         self.resetGUI()
448                         self.downloadLock = False
449                         return
450
451                 target_path = ""
452                 for l in file("/tmp/"+root_file).readlines():
453                         if l.startswith(machine):
454                                 try:
455                                         target_path = l.split("=")[1].strip()
456                                 except:
457                                         target_path = ""
458                                         pass
459                 if target_path == "":
460                         self.session.open(MessageBox, _("Firmware does not exist."), MessageBox.TYPE_INFO)
461                         self.resetGUI()
462                         self.downloadLock = False
463                         return
464
465                 self.guri = "%s/vu%s/%s"%(root_uri, machine, target_path)
466                 self.gbin = os.path.basename(target_path)
467                 #print "[FirmwareUpgrade] - uri[%s], data[%s], data_path[%s]" % (self.gbin, self.guri, target_path)
468                 os.system("rm -f /tmp/" + root_file)
469
470                 # md5
471                 if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone, errmsg="Can't download the checksum file."):
472                         self.resetGUI()
473                         self.downloadLock = False
474                         return
475                 # data
476                 if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone, errmsg="Can't download the firmware file."):
477                         self.resetGUI()
478                         self.downloadLock = False
479                         return
480
481                 t = ''
482                 self["file_list"].changeDir("/tmp/")
483                 self["file_list"].moveToIndex(0)
484                 while cmp(self["file_list"].getFilename(), self.gbin) != 0 :
485                         self["file_list"].down()
486                         if cmp(t, self["file_list"].getFilename()) == 0:
487                                 break
488                         t = self["file_list"].getFilename()
489
490                 del self.timer_downloading
491                 self.timer_downloading = None
492                 self.downloadLock = False
493
494         def onClickBlue(self):
495                 if self.downloadLock:
496                         return
497                 self.downloadLock = True
498                 if not os.path.exists("/proc/stb/info/vumodel"):
499                         self.session.open(MessageBox, _("Can't found model name."), MessageBox.TYPE_INFO, timeout = 10)
500                         self.downloadLock = False
501                         return
502                 self["status"].setText("Please wait during download.")
503                 self.timer_downloading = eTimer()
504                 self.timer_downloading.callback.append(self.runDownloading)
505                 self.timer_downloading.start(1000)
506
507         def onClickUp(self):
508                 if self.downloadLock:
509                         return
510                 self.resetGUI()
511                 self["file_list"].up()
512
513         def onClickDown(self):
514                 if self.downloadLock:
515                         return
516                 self.resetGUI()
517                 self["file_list"].down()
518
519         def onClickLeft(self):
520                 if self.downloadLock:
521                         return
522                 self.resetGUI()
523                 self["file_list"].pageUp()
524
525         def onClickRight(self):
526                 if self.downloadLock:
527                         return
528                 self.resetGUI()
529                 self["file_list"].pageDown()
530
531         def keyNone(self):
532                 None
533
534 class FirmwareUpgrade(Screen, ConfigListScreen):
535         skin =  """
536                 <screen position="center,center" size="560,175" title="Firmware Upgrade" >
537                         <ePixmap pixmap="skin_default/buttons/red.png" position="110,10" size="140,40" alphatest="blend" />
538                         <ePixmap pixmap="skin_default/buttons/green.png" position="310,10" size="140,40" alphatest="blend" />
539
540                         <widget source="key_red" render="Label" position="110,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
541                         <widget source="key_green" render="Label" position="310,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
542
543                         <widget name="config" zPosition="2" position="0,70" itemHeight="36" size="540,40" scrollbarMode="showOnDemand" transparent="1" />
544                         <widget source="status" render="Label" position="0,100" zPosition="1" size="540,75" font="Regular;20" halign="center" valign="center" />
545                 </screen>
546                 """
547
548         def __init__(self, session): 
549                 Screen.__init__(self, session)
550                 self.session = session 
551
552                 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
553                 {
554                         "ok":      self.keyGreen,
555                         "cancel":  self.keyRed,
556                         "red":     self.keyRed,
557                         "green":   self.keyGreen,
558                         "blue":    self.keyBlue,
559                 }, -2)
560
561                 self.list = []
562                 self.updateFilePath = ""
563
564                 self.finishedExit = False
565
566                 self.rebootLock = False
567                 self.rebootMessage = ""
568                 self.cbRebootCallCount = 0;
569
570                 ConfigListScreen.__init__(self, self.list, session=self.session)
571                 self["key_red"] = StaticText(_("Close"))
572
573                 self.logmode = None
574                 self.old_blue_clicked = 0
575                 self.fileopenmode = False
576                 self.upgrade_auto_run_timer = eTimer()
577                 self.upgrade_auto_run_timer.callback.append(self.keyGreen)
578
579                 global fwlist
580                 if fwlist is None:
581                         self["key_green"] = StaticText(_(" "))
582                         self["status"] = StaticText(_("This plugin is supported only the Ultimo/Uno."))
583                 else:
584                         self["key_green"] = StaticText(_("Upgrade"))
585                         self["status"] = StaticText(_(" "))
586                         self.setupUI()
587
588         def setupUI(self):
589                 global fwlist
590                 self.list = []
591                 self._item_firmware  = ConfigSelection(default=fwlist[0][0],  choices=fwlist)
592                 self._entry_firmware = getConfigListEntry(_("Firmware"), self._item_firmware)
593                 self.list.append(self._entry_firmware)
594                 self["config"].list = self.list
595                 self["config"].l.setList(self.list)
596                 self.setupStatus()
597
598         def setupStatus(self,message=None,reboot=False):
599                 self.updateFilePath = ""
600                 if message is not None:
601                         self.rebootLock = reboot
602                         self["status"].setText(message)
603                         if reboot:
604                                 self.rebootMessage = message
605                                 self.reboot_timer = eTimer()
606                                 self.reboot_timer.callback.append(self.cbReboot)
607                                 self.reboot_timer.start(1000)
608                         return
609                 if not self.rebootLock:
610                         self["status"].setText("Press the Green/OK button")
611
612         def doReboot(self):
613                 from Screens.Standby import TryQuitMainloop
614                 self.session.open(TryQuitMainloop, 2)
615
616         def cbReboot(self):
617                 max_call_count = 20
618                 self.finishedExit = True
619                 if self.cbRebootCallCount < max_call_count:
620                         self.cbRebootCallCount = self.cbRebootCallCount + 1
621                         #self["status"].setText("%s (%d)"%(self.rebootMessage, max_call_count-self.cbRebootCallCount))
622                         self["status"].setText("Reboot after %d seconds. Press the OK to reboot now."%(max_call_count-self.cbRebootCallCount))
623                         return
624                 self.doReboot()
625
626         # filebrowser window callback function
627         def cbSetStatus(self, data=None):
628                 if data is not None:
629                         self["status"].setText("Press the Green/OK button, if you want to upgrade to this file:\n%s\n" % (data))
630                         self.updateFilePath = data
631                         if self.fileopenmode == False:
632                                 self.upgrade_auto_run_timer.start(1000)
633
634         # upgrade window callback function
635         def cbFinishedUpgrade(self,message=None,reboot=False):
636                 self.setupStatus(message=message,reboot=reboot)
637
638         def cbRunUpgrade(self, ret):
639                 if ret == False:
640                         return
641
642                 if self.updateFilePath == "":
643                         self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO, timeout = 10)
644                         return
645                 device = None
646                 for d in fwdata[self._item_firmware.value][2].split(';'):
647                         if os.path.exists(d):
648                                 device = d                      
649                 if device is None:
650                         self.session.open(MessageBox, _("Can't found device file!!"), MessageBox.TYPE_INFO, timeout = 10)
651                         return
652                 fbs = self.session.open(UpgradeStatus, self, self._item_firmware.value, self.updateFilePath, device)
653                 fbs.setCallback(self.cbFinishedUpgrade)
654         
655         def doFileOpen(self):
656                 fbs = self.session.open(FUFilebrowser, self, self._item_firmware.value)
657                 fbs.setCallback(self.cbSetStatus)
658
659         def keyLeft(self):
660                 if self.rebootLock:
661                         return
662                 global fwlist
663                 if fwlist is None:
664                         return
665                 ConfigListScreen.keyLeft(self)
666                 self.setupStatus()
667
668         def keyRight(self):
669                 if self.rebootLock:
670                         return
671                 global fwlist
672                 if fwlist is None:
673                         return
674                 ConfigListScreen.keyRight(self)
675                 self.setupStatus()
676
677         def keyGreen(self):
678                 if self.finishedExit:
679                         self.doReboot()
680                         return
681                 self.upgrade_auto_run_timer.stop()
682                 if self.rebootLock:
683                         return
684                 global fwlist
685                 if fwlist is None:
686                         return
687                 if self.updateFilePath == "":
688                         #self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO)
689                         self.doFileOpen()
690                         return
691                 msg = "You should not be stop during the upgrade.\nDo you want to upgrade?"
692                 self.session.openWithCallback(self.cbRunUpgrade, MessageBox, _(msg), MessageBox.TYPE_YESNO, timeout = 15, default = True)
693                 self.fileopenmode = False
694
695         def keyYellow(self):
696                 if self.rebootLock:
697                         return
698                 global fwlist
699                 if fwlist is None:
700                         return
701                 self.fileopenmode = True
702                 self.doFileOpen()
703
704         def keyRed(self):
705                 if self.rebootLock:
706                         return
707                 self.close()
708
709         def cbLogMode(self):
710                 if self.old_blue_clicked:
711                         return
712                 self.logmode.stop()
713                 if os.path.exists("/tmp/onlogmode"):
714                         return
715                 os.system("touch /tmp/onlogmode")
716
717         def keyBlue(self):
718                 if self.rebootLock:
719                         return
720                 if self.logmode is not None and self.old_blue_clicked == 0:
721                         return
722                 if self.old_blue_clicked:
723                         self.old_blue_clicked = 0
724                         return
725                 self.old_blue_clicked = 1
726                 self.logmode = eTimer()
727                 self.logmode.callback.append(self.cbLogMode)
728                 self.logmode.start(1000)
729                 
730         def keyNone(self):
731                 None
732
733 def main(session, **kwargs):
734         session.open(FirmwareUpgrade)
735                                                            
736 def Plugins(**kwargs):            
737         return PluginDescriptor(name=_("Firmware Upgrade"), description="Upgrade Firmware..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
738