2 from urllib import urlretrieve
4 from Plugins.Plugin import PluginDescriptor
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
13 from Components.FileList import FileList
14 from Components.Slider import Slider
16 from Screens.Screen import Screen
17 from Screens.MessageBox import MessageBox
19 from enigma import ePoint, eConsoleAppContainer, eTimer, getDesktop
20 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
24 if os.path.exists("/proc/stb/info/vumodel"):
25 vumodel = open("/proc/stb/info/vumodel")
26 info = vumodel.read().strip()
32 ,("fp", _("Front Processor"))
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;"]
43 "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
50 "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
57 "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
60 import os, fcntl, thread
65 STATUS_PROGRAMMING = 4
66 STATUS_RETRY_UPGRADE = 5
68 class FPUpgradeCore() :
72 def __init__(self, firmwarefile, devicefile):
73 self.devicefile = devicefile
74 self.firmwarefile = firmwarefile
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()
82 size = os.path.getsize(self.firmwarefile)
83 if size == 0: raise Exception, 'data_size is zero'
84 #print '[FPUpgradeCore] data_size :',size
88 self.status = STATUS_READY
90 firmware = open(self.firmwarefile, 'rb')
91 device = os.open(self.devicefile, os.O_RDWR)
92 #print '[FPUpgradeCore] open >> [ok]'
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
100 data = firmware.read(1024)
102 os.write(device, data)
103 #print '[FPUpgradeCore] write data >> [ok]'
105 self.status = STATUS_PROGRAMMING
106 rc = fcntl.ioctl(device, 1, 0)
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:
116 print '[FPUpgradeCore] ERROR >>',msg
117 closefpga(firmware, device)
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:
128 else: print 'unknown.'
130 class FPGAUpgradeCore() :
131 status = STATUS_READY
134 MAX_CALL_COUNT = 1500
135 def __init__(self, firmwarefile, devicefile):
136 print '[FPGAUpgrade]'
137 self.devicefile = devicefile
138 self.firmwarefile = firmwarefile
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()
146 size = os.path.getsize(self.firmwarefile)
147 if size == 0: raise Exception, 'data_size is zero'
148 #print '[FPGAUpgradeCore] data_size :',size
150 firmware = open(self.firmwarefile, 'rb')
151 device = os.open(self.devicefile, os.O_RDWR)
152 #print '[FPGAUpgradeCore] open >> [ok]'
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]'
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
164 data = firmware.read(1024)
166 os.write(device, data)
167 #print '[FPGAUpgradeCore] write data >> [ok]'
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:
176 print '[FPGAUpgradeCore] ERROR >>',msg
177 closefpga(firmware, device)
179 closefpga(firmware, device)
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.'
191 class FirmwareUpgradeManager:
193 def getInterval(self):
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, ())
203 def checkError(self):
204 if self.fu.status == STATUS_ERROR:
205 self.fu.callcount = 0
210 if self.fu.status in (STATUS_READY, STATUS_ERROR):
212 elif self.fu.status == STATUS_PREPARED:
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);
220 elif self.fu.status == STATUS_DONE:
223 def getErrorMessage(self, errno, errmsg):
224 return str(self.fu.errmsg)
226 class UpgradeStatus(Screen):
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"/>
236 def __init__(self, session, parent, firmware, datafile, device):
237 Screen.__init__(self,session)
238 self.session = session
240 self["actions"] = ActionMap(["OkCancelActions"],
245 self.firmware = firmware
246 self.datafile = datafile
247 #print "[FirmwareUpgrade] - [%s][%s][%s]" % (self.datafile, firmware, device)
249 self["name"] = Label(_(" "))
250 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
252 self["status"] = Label(_("Status : 0%"))
254 self.slider = Slider(0, 100)
255 self["slider"] = self.slider
259 self.setTitle(firmware.upper() + " Upgrade Status")
261 self.FU = FirmwareUpgradeManager()
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())
269 self.exitTimerCallCount = 0;
270 self.upgradeLock = True
271 self.FU.startUpgrade(self.datafile, device, firmware)
273 def cbCheckStatus(self):
275 errno = self.FU.checkError()
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)
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)))
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
297 def setCallback(self, cb):
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))
305 if self.status_exit is not None:
306 self.status_exit.stop()
309 def cbConfirmExit(self, ret):
311 os.system("rm -f %s %s.md5" % (self.datafile, self.datafile))
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)
321 class FUFilebrowser(Screen):
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" />
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"/>
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" />
333 def __init__(self, session, parent, firmware):
334 Screen.__init__(self, session)
335 self.session = session
337 self["key_blue"] = StaticText(_("Download"))
339 self["status"] = StaticText(_(" "))
340 self["file_list"] = FileList("/", matchingPattern = "^.*")
342 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
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,
354 self.firmware = firmware
357 self.timer_downloading = None
359 self.downloadLock = False
360 self.setTitle(firmware.upper() + " File Browser")
363 self["status"].setText("Select to press OK, Exit to press Cancel.\nPress the BLUE button to download the latest firmware.")
365 def setCallback(self, func):
369 if self.downloadLock:
372 if self["file_list"].canDescent() : # isDir
373 self["file_list"].descent()
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)
381 if not os.path.exists(self.gbin+".md5"):
382 self.session.open(MessageBox, _("Can't found MD5 file."), MessageBox.TYPE_INFO, timeout = 10)
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)
395 self.session.open(MessageBox, _("You chose the incorrect file."), MessageBox.TYPE_INFO)
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)
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)
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)
409 if self.callback is not None:
410 self.callback(_(self.gbin))
413 def onClickCancel(self):
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."):
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:
426 opener = urllib.URLopener()
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)
436 f, h = urlretrieve(uri, tar, doHook)
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)
446 def runDownloading(self) :
447 self.timer_downloading.stop()
448 machine = str(open("/proc/stb/info/vumodel").read().strip())
450 def cbDownloadDone(tar):
452 if os.path.splitext(tar)[1] != ".files":
453 self["status"].setText("Downloaded : %s\nSelect to press OK, Exit to press Cancel."%(tar))
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):
462 self.downloadLock = False
466 for l in file("/tmp/"+root_file).readlines():
467 if l.startswith(machine):
469 target_path = l.split("=")[1].strip()
473 if target_path == "":
474 self.session.open(MessageBox, _("Firmware does not exist."), MessageBox.TYPE_INFO)
476 self.downloadLock = False
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)
485 if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone, errmsg="Can't download the checksum file."):
487 self.downloadLock = False
490 if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone, errmsg="Can't download the firmware file."):
492 self.downloadLock = False
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:
502 t = self["file_list"].getFilename()
504 del self.timer_downloading
505 self.timer_downloading = None
506 self.downloadLock = False
508 def onClickBlue(self):
509 if self.downloadLock:
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
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)
522 if self.downloadLock:
525 self["file_list"].up()
527 def onClickDown(self):
528 if self.downloadLock:
531 self["file_list"].down()
533 def onClickLeft(self):
534 if self.downloadLock:
537 self["file_list"].pageUp()
539 def onClickRight(self):
540 if self.downloadLock:
543 self["file_list"].pageDown()
548 class FirmwareUpgrade(Screen, ConfigListScreen):
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" />
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" />
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" />
562 def __init__(self, session):
563 Screen.__init__(self, session)
564 self.session = session
566 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
569 "cancel": self.keyRed,
571 "green": self.keyGreen,
572 "blue": self.keyBlue,
576 self.updateFilePath = ""
578 self.finishedExit = False
580 self.rebootLock = False
581 self.rebootMessage = ""
582 self.cbRebootCallCount = 0;
584 ConfigListScreen.__init__(self, self.list, session=self.session)
585 self["key_red"] = StaticText(_("Close"))
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)
595 self["key_green"] = StaticText(_(" "))
596 self["status"] = StaticText(_("This plugin is supported only the Ultimo/Uno."))
598 self["key_green"] = StaticText(_("Upgrade"))
599 self["status"] = StaticText(_(" "))
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)
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)
618 self.rebootMessage = message
619 self.reboot_timer = eTimer()
620 self.reboot_timer.callback.append(self.cbReboot)
621 self.reboot_timer.start(1000)
623 if not self.rebootLock:
624 self["status"].setText("Press the Green/OK button")
627 from Screens.Standby import TryQuitMainloop
628 self.session.open(TryQuitMainloop, 2)
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))
640 # filebrowser window callback function
641 def cbSetStatus(self, data=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)
648 # upgrade window callback function
649 def cbFinishedUpgrade(self,message=None,reboot=False):
650 self.setupStatus(message=message,reboot=reboot)
652 def cbRunUpgrade(self, ret):
656 if self.updateFilePath == "":
657 self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO, timeout = 10)
660 for d in fwdata[self._item_firmware.value][2].split(';'):
661 if os.path.exists(d):
664 self.session.open(MessageBox, _("Can't found device file!!"), MessageBox.TYPE_INFO, timeout = 10)
666 fbs = self.session.open(UpgradeStatus, self, self._item_firmware.value, self.updateFilePath, device)
667 fbs.setCallback(self.cbFinishedUpgrade)
669 def doFileOpen(self):
670 fbs = self.session.open(FUFilebrowser, self, self._item_firmware.value)
671 fbs.setCallback(self.cbSetStatus)
679 ConfigListScreen.keyLeft(self)
688 ConfigListScreen.keyRight(self)
692 if self.finishedExit:
695 self.upgrade_auto_run_timer.stop()
701 if self.updateFilePath == "":
702 #self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO)
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
715 self.fileopenmode = True
724 if self.old_blue_clicked:
727 if os.path.exists("/tmp/onlogmode"):
729 os.system("touch /tmp/onlogmode")
734 if self.logmode is not None and self.old_blue_clicked == 0:
736 if self.old_blue_clicked:
737 self.old_blue_clicked = 0
739 self.old_blue_clicked = 1
740 self.logmode = eTimer()
741 self.logmode.callback.append(self.cbLogMode)
742 self.logmode.start(1000)
747 def main(session, **kwargs):
748 session.open(FirmwareUpgrade)
750 def Plugins(**kwargs):
751 return PluginDescriptor(name=_("Firmware Upgrade"), description="Upgrade Firmware..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)