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