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