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
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):
214 <screen position="center,center" size="450,100" title=" ">
215 <widget name="name" position="10,0" size="430,20" font="Regular;18" halign="left" valign="bottom"/>
216 <widget name="slider" position="10,25" size="430,30" backgroundColor="white"/>
217 <widget name="status" position="10,25" zPosition="1" size="430,30" font="Regular;18" halign="center" valign="center" foregroundColor="black" backgroundColor="black" transparent="1"/>
218 <widget source="info" render="Label" position="10,70" zPosition="1" size="430,30" font="Regular;22" halign="center" valign="center" backgroundColor="#a08500" transparent="1"/>
222 def __init__(self, session, parent, firmware, datafile, device):
223 Screen.__init__(self,session)
224 self.session = session
226 self["actions"] = ActionMap(["OkCancelActions"],
231 self.firmware = firmware
232 self.datafile = datafile
233 #print "[FirmwareUpgrade] - [%s][%s][%s]" % (self.datafile, firmware, device)
235 self["name"] = Label(_(" "))
236 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
238 self["status"] = Label(_("Status : 0%"))
240 self.slider = Slider(0, 100)
241 self["slider"] = self.slider
245 self.setTitle(firmware.upper() + " Upgrade Status")
247 self.FU = FirmwareUpgradeManager()
250 self.status_exit = None
251 self.check_status = eTimer()
252 self.check_status.callback.append(self.cbCheckStatus)
253 self.check_status.start(self.FU.getInterval())
255 self.exitTimerCallCount = 0;
256 self.upgradeLock = True
257 self.FU.startUpgrade(self.datafile, device, firmware)
259 def cbCheckStatus(self):
261 errno = self.FU.checkError()
263 self.check_status.stop()
264 errmsg = self.FU.getErrorMessage(errno, errmsg)
265 print "[FirmwareUpgrade] - ERROR : [%d][%s]" % (errno, errmsg)
266 self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
267 self.cbConfirmExit(False)
269 status = self.FU.getStatus()
270 if self.old_status > status and status != -1:
271 self.session.open(MessageBox, _("Fail to upgrade!! Retry!!"), MessageBox.TYPE_INFO, timeout = 10)
272 self.slider.setValue(status)
273 self["status"].setText(_("%d / 100" % (status)))
275 self.check_status.stop()
276 self["status"].setText(_("Success. Press OK to exit."))
277 self.status_exit = eTimer()
278 self.status_exit.callback.append(self.cbTimerExit)
279 self.status_exit.start(1000)
280 self.upgradeLock = False
281 self.old_status = status
283 def setCallback(self, cb):
286 def cbTimerExit(self):
287 if self.exitTimerCallCount < 10: # exit after 10 sec.
288 self.exitTimerCallCount = self.exitTimerCallCount + 1
289 self.setTitle("%s Upgrade Status (%d)" % (self.firmware.upper(), 10-self.exitTimerCallCount))
291 if self.status_exit is not None:
292 self.status_exit.stop()
295 def cbConfirmExit(self, ret):
297 os.system("rm -f %s %s.md5" % (self.datafile, self.datafile))
303 if self.callback is not None:
304 self.callback("Reboot now for a successful upgrade.", True)
305 self.session.openWithCallback(self.cbConfirmExit, MessageBox, _("Do you want to remove binary data?"), MessageBox.TYPE_YESNO, timeout = 10, default = False)
307 class Filebrowser(Screen):
309 <screen position="center,center" size="500,260" title="File Browser" >
310 <ePixmap pixmap="Vu_HD/buttons/blue.png" position="5,7" size="80,40" alphatest="blend" />
311 <widget source="key_blue" render="Label" position="40,0" zPosition="1" size="300,40" font="Regular;20" halign="left" valign="center" transparent="1"/>
312 <widget name="file_list" position="0,50" size="500,160" scrollbarMode="showOnDemand" />
314 <widget source="status" render="Label" position="0,220" zPosition="1" size="500,40" font="Regular;18" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
318 def __init__(self, session, parent, firmware):
319 Screen.__init__(self, session)
320 self.session = session
322 self["key_blue"] = StaticText(_("Download the firmware (latest)"))
324 self["status"] = StaticText(_(" "))
325 self["file_list"] = FileList("/", matchingPattern = "^.*")
327 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
329 "ok": self.onClickOk,
330 "cancel": self.onClickCancel,
331 "blue": self.onClickBlue,
332 "up": self.onClickUp,
333 "down": self.onClickDown,
334 "left": self.onClickLeft,
335 "right": self.onClickRight,
339 self.firmware = firmware
342 self.timer_downloading = None
344 self.downloadLock = False
345 self.setTitle(firmware.upper() + " File Browser")
348 self["status"].setText("Select to press OK, Exit to press Cancel.")
350 def setCallback(self, func):
354 if self.downloadLock:
357 if self["file_list"].canDescent() : # isDir
358 self["file_list"].descent()
362 self.gbin = self["file_list"].getCurrentDirectory() + self["file_list"].getFilename()
363 if not os.path.exists(self.gbin):
364 self.session.open(MessageBox, _("Can't found binary file."), MessageBox.TYPE_INFO, timeout = 10)
366 if not os.path.exists(self.gbin+".md5"):
367 self.session.open(MessageBox, _("Can't found MD5 file."), MessageBox.TYPE_INFO, timeout = 10)
371 name_ext = os.path.splitext(self["file_list"].getFilename())
372 return len(name_ext)==2 and ext.startswith(name_ext[1])
373 self.check_ext = False
374 if (self.firmware == "fp" and checkExt(".bin")) or (self.firmware == "fpga" and checkExt(".dat")):
375 self.check_ext = True
376 if self.check_ext == False:
377 self.session.open(MessageBox, _("You chose the incorrect file."), MessageBox.TYPE_INFO)
380 self.session.open(MessageBox, _("You chose the incorrect file."), MessageBox.TYPE_INFO)
383 if os.path.exists("/usr/bin/md5sum") == False:
384 self.session.open(MessageBox, _("Can't find /usr/bin/md5sum"), MessageBox.TYPE_INFO, timeout = 10)
386 md5sum_A = os.popen("md5sum %s | awk \'{print $1}\'"%(self.gbin)).readline().strip()
387 md5sum_B = os.popen("cat %s.md5 | awk \'{print $1}\'"%(self.gbin)).readline().strip()
388 #print "[FirmwareUpgrade] - Verify : file[%s], md5[%s]"%(md5sum_A,md5sum_B)
390 if md5sum_A != md5sum_B:
391 self.session.open(MessageBox, _("Fail to verify data file. \nfile[%s]\nmd5[%s]"%(md5sum_A,md5sum_B)), MessageBox.TYPE_INFO, timeout = 10)
394 if self.callback is not None:
395 self.callback(_(self.gbin))
398 def onClickCancel(self):
401 # uri : source file url(string)
402 # tf : target file name(string)
403 # bd : target base directory(string)
404 # cbfunc(string) : callback function(function)
405 def doDownload(self, uri, tf, bd='/tmp', cbfunc=None, errmsg="Fail to download."):
407 #print "[FirmwareUpgrade] - Download Info : [%s][%s]" % (uri, tar)
408 def doHook(blockNumber, blockSize, totalSize) :
409 if blockNumber*blockSize > totalSize and cbfunc is not None:
411 opener = urllib.URLopener()
415 #self.session.open(MessageBox, _("File not found in this URL:\n%s"%(uri)), MessageBox.TYPE_INFO, timeout = 10)
416 print "[FirmwareUpgrade] - Fail to download. URL :",uri
417 self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
421 f, h = urlretrieve(uri, tar, doHook)
423 #self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 10)
424 print "[FirmwareUpgrade] - Fail to download. ERR_MSG :",str(msg)
425 self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
431 def runDownloading(self) :
432 self.timer_downloading.stop()
433 machine = str(open("/proc/stb/info/vumodel").read().strip())
435 def cbDownloadDone(tar):
437 if os.path.splitext(tar)[1] != ".files":
438 self["status"].setText("Downloaded : %s\nSelect to press OK, Exit to press Cancel."%(tar))
443 root_uri = fwdata[self.firmware][0]
444 root_file = fwdata[self.firmware][1]
445 if not self.doDownload("%s/%s"%(root_uri, root_file), root_file, cbfunc=cbDownloadDone):
447 self.downloadLock = False
451 for l in file("/tmp/"+root_file).readlines():
452 if l.startswith(machine):
454 target_path = l.split("=")[1].strip()
458 if target_path == "":
459 self.session.open(MessageBox, _("Firmware does not exist."), MessageBox.TYPE_INFO)
461 self.downloadLock = False
464 self.guri = "%s/vu%s/%s"%(root_uri, machine, target_path)
465 self.gbin = os.path.basename(target_path)
466 #print "[FirmwareUpgrade] - uri[%s], data[%s], data_path[%s]" % (self.gbin, self.guri, target_path)
467 os.system("rm -f /tmp/" + root_file)
470 if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone, errmsg="Can't download the checksum file."):
472 self.downloadLock = False
475 if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone, errmsg="Can't download the firmware file."):
477 self.downloadLock = False
481 self["file_list"].changeDir("/tmp/")
482 self["file_list"].moveToIndex(0)
483 while cmp(self["file_list"].getFilename(), self.gbin) != 0 :
484 self["file_list"].down()
485 if cmp(t, self["file_list"].getFilename()) == 0:
487 t = self["file_list"].getFilename()
489 del self.timer_downloading
490 self.timer_downloading = None
491 self.downloadLock = False
493 def onClickBlue(self):
494 if self.downloadLock:
496 self.downloadLock = True
497 if not os.path.exists("/proc/stb/info/vumodel"):
498 self.session.open(MessageBox, _("Can't found model name."), MessageBox.TYPE_INFO, timeout = 10)
499 self.downloadLock = False
501 self["status"].setText("Please wait during download.")
502 self.timer_downloading = eTimer()
503 self.timer_downloading.callback.append(self.runDownloading)
504 self.timer_downloading.start(1000)
507 if self.downloadLock:
510 self["file_list"].up()
512 def onClickDown(self):
513 if self.downloadLock:
516 self["file_list"].down()
518 def onClickLeft(self):
519 if self.downloadLock:
522 self["file_list"].pageUp()
524 def onClickRight(self):
525 if self.downloadLock:
528 self["file_list"].pageDown()
533 class FirmwareUpgrade(Screen, ConfigListScreen):
535 <screen position="center,center" size="560,175" title="Firmware Upgrade" >
536 <ePixmap pixmap="Vu_HD/buttons/red.png" position="125,7" size="80,40" alphatest="blend" />
537 <ePixmap pixmap="Vu_HD/buttons/green.png" position="330,7" size="80,40" alphatest="blend" />
539 <widget source="key_red" render="Label" position="160,0" zPosition="1" size="155,40" font="Regular;20" halign="left" valign="center" transparent="1" />
540 <widget source="key_green" render="Label" position="365,0" zPosition="1" size="155,40" font="Regular;20" halign="left" valign="center" transparent="1" />
542 <widget name="config" zPosition="2" position="0,50" itemHeight="36" size="540,40" scrollbarMode="showOnDemand" transparent="1" />
543 <widget source="status" render="Label" position="0,100" zPosition="1" size="540,75" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
547 def __init__(self, session):
548 Screen.__init__(self, session)
549 self.session = session
551 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
554 "cancel": self.keyRed,
556 "green": self.keyGreen,
557 "blue": self.keyBlue,
561 self.updateFilePath = ""
563 self.finishedExit = False
565 self.rebootLock = False
566 self.rebootMessage = ""
567 self.cbRebootCallCount = 0;
569 ConfigListScreen.__init__(self, self.list, session=self.session)
570 self["key_red"] = StaticText(_("Close"))
573 self.old_blue_clicked = 0
574 self.fileopenmode = False
575 self.upgrade_auto_run_timer = eTimer()
576 self.upgrade_auto_run_timer.callback.append(self.keyGreen)
580 self["key_green"] = StaticText(_(" "))
581 self["status"] = StaticText(_("This plugin is supported only the Ultimo/Uno."))
583 self["key_green"] = StaticText(_("Upgrade"))
584 self["status"] = StaticText(_(" "))
590 self._item_firmware = ConfigSelection(default=fwlist[0][0], choices=fwlist)
591 self._entry_firmware = getConfigListEntry(_("Firmware"), self._item_firmware)
592 self.list.append(self._entry_firmware)
593 self["config"].list = self.list
594 self["config"].l.setList(self.list)
597 def setupStatus(self,message=None,reboot=False):
598 self.updateFilePath = ""
599 if message is not None:
600 self.rebootLock = reboot
601 self["status"].setText(message)
603 self.rebootMessage = message
604 self.reboot_timer = eTimer()
605 self.reboot_timer.callback.append(self.cbReboot)
606 self.reboot_timer.start(1000)
608 if not self.rebootLock:
609 self["status"].setText("Press the Green/OK button")
612 from Screens.Standby import TryQuitMainloop
613 self.session.open(TryQuitMainloop, 2)
617 self.finishedExit = True
618 if self.cbRebootCallCount < max_call_count:
619 self.cbRebootCallCount = self.cbRebootCallCount + 1
620 #self["status"].setText("%s (%d)"%(self.rebootMessage, max_call_count-self.cbRebootCallCount))
621 self["status"].setText("Reboot after %d seconds. Press the OK to reboot now."%(max_call_count-self.cbRebootCallCount))
625 # filebrowser window callback function
626 def cbSetStatus(self, data=None):
628 self["status"].setText("Press the Green/OK button, if you want to upgrade to this file:\n%s\n" % (data))
629 self.updateFilePath = data
630 if self.fileopenmode == False:
631 self.upgrade_auto_run_timer.start(1000)
633 # upgrade window callback function
634 def cbFinishedUpgrade(self,message=None,reboot=False):
635 self.setupStatus(message=message,reboot=reboot)
637 def cbRunUpgrade(self, ret):
641 if self.updateFilePath == "":
642 self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO, timeout = 10)
645 for d in fwdata[self._item_firmware.value][2].split(';'):
646 if os.path.exists(d):
649 self.session.open(MessageBox, _("Can't found device file!!"), MessageBox.TYPE_INFO, timeout = 10)
651 fbs = self.session.open(UpgradeStatus, self, self._item_firmware.value, self.updateFilePath, device)
652 fbs.setCallback(self.cbFinishedUpgrade)
654 def doFileOpen(self):
655 fbs = self.session.open(Filebrowser, self, self._item_firmware.value)
656 fbs.setCallback(self.cbSetStatus)
664 ConfigListScreen.keyLeft(self)
671 ConfigListScreen.keyRight(self)
675 if self.finishedExit:
678 self.upgrade_auto_run_timer.stop()
684 if self.updateFilePath == "":
685 #self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO)
688 msg = "You should not be stop during the upgrade.\nDo you want to upgrade?"
689 self.session.openWithCallback(self.cbRunUpgrade, MessageBox, _(msg), MessageBox.TYPE_YESNO, timeout = 15, default = True)
690 self.fileopenmode = False
698 self.fileopenmode = True
707 if self.old_blue_clicked:
710 if os.path.exists("/tmp/onlogmode"):
712 os.system("touch /tmp/onlogmode")
717 if self.logmode is not None and self.old_blue_clicked == 0:
719 if self.old_blue_clicked:
720 self.old_blue_clicked = 0
722 self.old_blue_clicked = 1
723 self.logmode = eTimer()
724 self.logmode.callback.append(self.cbLogMode)
725 self.logmode.start(1000)
730 def main(session, **kwargs):
731 session.open(FirmwareUpgrade)
733 def Plugins(**kwargs):
734 return PluginDescriptor(name=_("Firmware Upgrade"), description="Upgrade Firmware..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)