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.file", "/dev/fpga_dp;/dev/misc/dp;"]
46 import os, fcntl, thread
51 STATUS_PROGRAMMING = 4
52 STATUS_RETRY_UPGRADE = 5
54 class FPUpgradeCore() :
58 def __init__(self, firmwarefile, devicefile):
59 self.devicefile = devicefile
60 self.firmwarefile = firmwarefile
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()
68 size = os.path.getsize(self.firmwarefile)
69 if size == 0: raise Exception, 'data_size is zero'
70 #print '[FPUpgradeCore] data_size :',size
74 self.status = STATUS_READY
76 firmware = open(self.firmwarefile, 'rb')
77 device = os.open(self.devicefile, os.O_RDWR)
78 #print '[FPUpgradeCore] open >> [ok]'
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
86 data = firmware.read(1024)
88 os.write(device, data)
89 #print '[FPUpgradeCore] write data >> [ok]'
91 self.status = STATUS_PROGRAMMING
92 rc = fcntl.ioctl(device, 1, 0)
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:
102 print '[FPUpgradeCore] ERROR >>',msg
103 closefpga(firmware, device)
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:
114 else: print 'unknown.'
116 class FPGAUpgradeCore() :
117 status = STATUS_READY
120 MAX_CALL_COUNT = 1500
121 def __init__(self, firmwarefile, devicefile):
122 print '[FPGAUpgrade]'
123 self.devicefile = devicefile
124 self.firmwarefile = firmwarefile
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()
132 size = os.path.getsize(self.firmwarefile)
133 if size == 0: raise Exception, 'data_size is zero'
134 #print '[FPGAUpgradeCore] data_size :',size
136 firmware = open(self.firmwarefile, 'rb')
137 device = os.open(self.devicefile, os.O_RDWR)
138 #print '[FPGAUpgradeCore] open >> [ok]'
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]'
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
150 data = firmware.read(1024)
152 os.write(device, data)
153 #print '[FPGAUpgradeCore] write data >> [ok]'
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:
162 print '[FPGAUpgradeCore] ERROR >>',msg
163 closefpga(firmware, device)
165 closefpga(firmware, device)
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.'
177 class FirmwareUpgradeManager:
179 def getInterval(self):
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, ())
189 def checkError(self):
190 if self.fu.status == STATUS_ERROR:
191 self.fu.callcount = 0
196 if self.fu.status in (STATUS_READY, STATUS_ERROR):
198 elif self.fu.status == STATUS_PREPARED:
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);
206 elif self.fu.status == STATUS_DONE:
209 def getErrorMessage(self, errno, errmsg):
210 return str(self.fu.errmsg)
212 class UpgradeStatus(Screen):
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"/>
223 size = getDesktop(0).size()
224 position_params = size.width() > 750 and (' ') or ('backgroundColor=\"blue\"')
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"/>
232 """ % position_params
234 def __init__(self, session, parent, firmware, datafile, device):
235 Screen.__init__(self,session)
236 self.session = session
238 self["actions"] = ActionMap(["OkCancelActions"],
243 self.firmware = firmware
244 self.datafile = datafile
245 #print "[FirmwareUpgrade] - [%s][%s][%s]" % (self.datafile, firmware, device)
247 self["name"] = Label(_(" "))
248 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
250 self["status"] = Label(_("Status : 0%"))
252 self.slider = Slider(0, 100)
253 self["slider"] = self.slider
257 self.setTitle(firmware.upper() + " Upgrade Status")
259 self.FU = FirmwareUpgradeManager()
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())
267 self.exitTimerCallCount = 0;
268 self.upgradeLock = True
269 self.FU.startUpgrade(self.datafile, device, firmware)
271 def cbCheckStatus(self):
273 errno = self.FU.checkError()
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)
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)))
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
295 def setCallback(self, cb):
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))
303 if self.status_exit is not None:
304 self.status_exit.stop()
307 def cbConfirmExit(self, ret):
309 os.system("rm -f %s %s.md5" % (self.datafile, self.datafile))
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)
319 class Filebrowser(Screen):
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" />
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" />
330 def __init__(self, session, parent, firmware):
331 Screen.__init__(self, session)
332 self.session = session
334 self["key_blue"] = StaticText(_("Download the firmware (latest)"))
336 self["status"] = StaticText(_(" "))
337 self["file_list"] = FileList("/", matchingPattern = "^.*")
339 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
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,
351 self.firmware = firmware
354 self.timer_downloading = None
356 self.downloadLock = False
357 self.setTitle(firmware.upper() + " File Browser")
360 self["status"].setText("Select to press OK, Exit to press Cancel.")
362 def setCallback(self, func):
366 if self.downloadLock:
369 if self["file_list"].canDescent() : # isDir
370 self["file_list"].descent()
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)
378 if not os.path.exists(self.gbin+".md5"):
379 self.session.open(MessageBox, _("Can't found MD5 file."), MessageBox.TYPE_INFO, timeout = 10)
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)
392 self.session.open(MessageBox, _("You chose the incorrect file."), MessageBox.TYPE_INFO)
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)
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)
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)
406 if self.callback is not None:
407 self.callback(_(self.gbin))
410 def onClickCancel(self):
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."):
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:
423 opener = urllib.URLopener()
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)
433 f, h = urlretrieve(uri, tar, doHook)
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)
443 def runDownloading(self) :
444 self.timer_downloading.stop()
445 machine = str(open("/proc/stb/info/vumodel").read().strip())
447 def cbDownloadDone(tar):
449 if os.path.splitext(tar)[1] != ".files":
450 self["status"].setText("Downloaded : %s\nSelect to press OK, Exit to press Cancel."%(tar))
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):
459 self.downloadLock = False
463 for l in file("/tmp/"+root_file).readlines():
464 if l.startswith(machine):
466 target_path = l.split("=")[1].strip()
470 if target_path == "":
471 self.session.open(MessageBox, _("Firmware does not exist."), MessageBox.TYPE_INFO)
473 self.downloadLock = False
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)
482 if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone, errmsg="Can't download the checksum file."):
484 self.downloadLock = False
487 if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone, errmsg="Can't download the firmware file."):
489 self.downloadLock = False
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:
499 t = self["file_list"].getFilename()
501 del self.timer_downloading
502 self.timer_downloading = None
503 self.downloadLock = False
505 def onClickBlue(self):
506 if self.downloadLock:
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
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)
519 if self.downloadLock:
522 self["file_list"].up()
524 def onClickDown(self):
525 if self.downloadLock:
528 self["file_list"].down()
530 def onClickLeft(self):
531 if self.downloadLock:
534 self["file_list"].pageUp()
536 def onClickRight(self):
537 if self.downloadLock:
540 self["file_list"].pageDown()
545 class FirmwareUpgrade(Screen, ConfigListScreen):
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" />
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" />
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" />
559 def __init__(self, session):
560 Screen.__init__(self, session)
561 self.session = session
563 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
566 "cancel": self.keyRed,
568 "green": self.keyGreen,
569 "blue": self.keyBlue,
573 self.updateFilePath = ""
575 self.finishedExit = False
577 self.rebootLock = False
578 self.rebootMessage = ""
579 self.cbRebootCallCount = 0;
581 ConfigListScreen.__init__(self, self.list, session=self.session)
582 self["key_red"] = StaticText(_("Close"))
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)
592 self["key_green"] = StaticText(_(" "))
593 self["status"] = StaticText(_("This plugin is supported only the Ultimo/Uno."))
595 self["key_green"] = StaticText(_("Upgrade"))
596 self["status"] = StaticText(_(" "))
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)
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)
615 self.rebootMessage = message
616 self.reboot_timer = eTimer()
617 self.reboot_timer.callback.append(self.cbReboot)
618 self.reboot_timer.start(1000)
620 if not self.rebootLock:
621 self["status"].setText("Press the Green/OK button")
624 from Screens.Standby import TryQuitMainloop
625 self.session.open(TryQuitMainloop, 2)
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))
637 # filebrowser window callback function
638 def cbSetStatus(self, data=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)
645 # upgrade window callback function
646 def cbFinishedUpgrade(self,message=None,reboot=False):
647 self.setupStatus(message=message,reboot=reboot)
649 def cbRunUpgrade(self, ret):
653 if self.updateFilePath == "":
654 self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO, timeout = 10)
657 for d in fwdata[self._item_firmware.value][2].split(';'):
658 if os.path.exists(d):
661 self.session.open(MessageBox, _("Can't found device file!!"), MessageBox.TYPE_INFO, timeout = 10)
663 fbs = self.session.open(UpgradeStatus, self, self._item_firmware.value, self.updateFilePath, device)
664 fbs.setCallback(self.cbFinishedUpgrade)
666 def doFileOpen(self):
667 fbs = self.session.open(Filebrowser, self, self._item_firmware.value)
668 fbs.setCallback(self.cbSetStatus)
676 ConfigListScreen.keyLeft(self)
683 ConfigListScreen.keyRight(self)
687 if self.finishedExit:
690 self.upgrade_auto_run_timer.stop()
696 if self.updateFilePath == "":
697 #self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO)
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
710 self.fileopenmode = True
719 if self.old_blue_clicked:
722 if os.path.exists("/tmp/onlogmode"):
724 os.system("touch /tmp/onlogmode")
729 if self.logmode is not None and self.old_blue_clicked == 0:
731 if self.old_blue_clicked:
732 self.old_blue_clicked = 0
734 self.old_blue_clicked = 1
735 self.logmode = eTimer()
736 self.logmode.callback.append(self.cbLogMode)
737 self.logmode.start(1000)
742 def main(session, **kwargs):
743 session.open(FirmwareUpgrade)
745 def Plugins(**kwargs):
746 return PluginDescriptor(name=_("Firmware Upgrade"), description="Upgrade Firmware..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)