change plugins code.
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / FirmwareUpgrade / plugin.py
index ff593de..0181fac 100644 (file)
@@ -28,12 +28,12 @@ if os.path.exists("/proc/stb/info/vumodel"):
 
        if info == "ultimo":
                fwlist= [
-                        ("fp", _("Front Processor"))
-                       ,("fpga", _("FPGA"))
+                        ("fpga", _("FPGA"))
+                       ,("fp", _("Front Processor"))
                        ]
                fwdata= { 
-                        "fp"   : ["http://archive.vuplus.com/download/fp", "fp.files", "/dev/bcm_mu;"]
-                       ,"fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
+                        "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
+                       ,"fp"   : ["http://archive.vuplus.com/download/fp", "fp.files", "/dev/bcm_mu;"]
                        }
        elif info == "uno":
                fwlist= [
@@ -43,6 +43,172 @@ if os.path.exists("/proc/stb/info/vumodel"):
                        "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.file", "/dev/fpga_dp;/dev/misc/dp;"]
                        }
 
+import os, fcntl, thread
+STATUS_READY           = 0
+STATUS_DONE            = 1
+STATUS_ERROR           = 2
+STATUS_PREPARED                = 3
+STATUS_PROGRAMMING     = 4
+STATUS_RETRY_UPGRADE   = 5
+
+class FPUpgradeCore() :
+       status = STATUS_READY
+       errmsg = ''
+       MAX_CALL_COUNT = 120
+       def __init__(self, firmwarefile, devicefile):
+               self.devicefile = devicefile
+               self.firmwarefile = firmwarefile
+
+       def doUpgrade(self):
+               firmware,device = None,None
+               def closefpga(fp, fd):
+                       if fd is not None: os.close(fd)
+                       if fp is not None: fp.close()
+               try:
+                       size = os.path.getsize(self.firmwarefile)
+                       if size == 0: raise Exception, 'data_size is zero'
+                       #print '[FPUpgradeCore] data_size :',size
+
+                       for xx in range(3):
+                               self.callcount = 0
+                               self.status = STATUS_READY
+
+                               firmware = open(self.firmwarefile, 'rb')
+                               device = os.open(self.devicefile, os.O_RDWR)
+                               #print '[FPUpgradeCore] open >> [ok]'
+
+                               rc = fcntl.ioctl(device, 0, size)
+                               if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
+                               #print '[FPUpgradeCore] set size >> [ok]'
+                               self.status = STATUS_PREPARED
+
+                               while True:
+                                       data = firmware.read(1024)
+                                       if data == '': break
+                                       os.write(device, data)
+                               #print '[FPUpgradeCore] write data >> [ok]'
+
+                               self.status = STATUS_PROGRAMMING
+                               rc = fcntl.ioctl(device, 1, 0)
+                               if rc == 0: break
+                               if xx == 2: raise Exception, 'fail to upgrade : %d'%(rc)
+                               self.errmsg = 'fail to upgrade, retry..'
+                               self.status = STATUS_RETRY_UPGRADE
+                               closefpga(firmware, device)
+                       #print '[FPUpgradeCore] upgrade done.'
+                       if self.callcount < 20: raise Exception, 'wrong fpga file.'
+               except Exception, msg:
+                       self.errmsg = msg
+                       print '[FPUpgradeCore] ERROR >>',msg
+                       closefpga(firmware, device)
+                       return STATUS_ERROR
+               return STATUS_DONE
+
+       def upgradeMain(self):
+               self.status = STATUS_READY
+               self.status = self.doUpgrade()
+               if self.status == STATUS_DONE:
+                       print 'upgrade done.'
+               elif self.status == STATUS_ERROR:
+                       print 'error!!'
+               else:   print 'unknown.'
+
+class FPGAUpgradeCore() :
+       status = STATUS_READY
+       errmsg = ''
+       callcount       = 0
+       MAX_CALL_COUNT  = 1500
+       def __init__(self, firmwarefile, devicefile):
+               print '[FPGAUpgrade]'
+               self.devicefile = devicefile
+               self.firmwarefile = firmwarefile
+
+       def doUpgrade(self):
+               firmware,device = None,None
+               def closefpga(fp, fd):
+                       if fd is not None: os.close(fd)
+                       if fp is not None: fp.close()
+               try:
+                       size = os.path.getsize(self.firmwarefile)
+                       if size == 0: raise Exception, 'data_size is zero'
+                       #print '[FPGAUpgradeCore] data_size :',size
+
+                       firmware = open(self.firmwarefile, 'rb')
+                       device = os.open(self.devicefile, os.O_RDWR)
+                       #print '[FPGAUpgradeCore] open >> [ok]'
+
+                       rc = fcntl.ioctl(device, 0, size)
+                       if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
+                       #print '[FPGAUpgradeCore] set size >> [ok]'
+
+                       rc = fcntl.ioctl(device, 2, 5)
+                       if rc < 0: raise Exception, 'fail to set programming mode : %d'%(rc)
+                       #print '[FPGAUpgradeCore] programming mode >> [ok]'
+                       self.status = STATUS_PREPARED
+
+                       while True:
+                               data = firmware.read(1024)
+                               if data == '': break
+                               os.write(device, data)
+                       #print '[FPGAUpgradeCore] write data >> [ok]'
+
+                       self.status = STATUS_PROGRAMMING
+                       rc = fcntl.ioctl(device, 1, 0)
+                       if rc < 0: raise Exception, 'fail to programming : %d'%(rc)
+                       #print '[FPGAUpgradeCore] upgrade done.'
+                       if self.callcount < 20: raise Exception, 'wrong fpga file.'
+               except Exception, msg:
+                       self.errmsg = msg
+                       print '[FPGAUpgradeCore] ERROR >>',msg
+                       closefpga(firmware, device)
+                       return STATUS_ERROR
+               closefpga(firmware, device)
+               return STATUS_DONE
+
+       def upgradeMain(self):
+               self.status = STATUS_READY
+               self.status = self.doUpgrade()
+               if self.status == STATUS_DONE:
+                       print '[FPGAUpgrade] upgrade done.'
+               elif self.status == STATUS_ERROR:
+                       print '[FPGAUpgrade] occur error.'
+               else:   print '[FPGAUpgrade] occur unknown error.'
+
+class FirmwareUpgradeManager:
+       fu = None
+       def getInterval(self):
+               return 200
+
+       def startUpgrade(self, datafile, device, firmware):
+               if firmware == 'fpga':
+                       self.fu = FPGAUpgradeCore(firmwarefile=datafile, devicefile=device)
+               elif firmware == 'fp':
+                       self.fu = FPUpgradeCore(firmwarefile=datafile, devicefile=device)
+               thread.start_new_thread(self.fu.upgradeMain, ())
+
+       def checkError(self):
+               if self.fu.status == STATUS_ERROR:
+                       self.fu.callcount = 0
+                       return True
+               return False
+
+       def getStatus(self):
+               if self.fu.status in (STATUS_READY, STATUS_ERROR):
+                       return 0
+               elif self.fu.status == STATUS_PREPARED:
+                       return 2
+               elif self.fu.status == STATUS_PROGRAMMING:
+                       self.fu.callcount += 1
+                       ret = (self.fu.callcount * 100) / self.fu.MAX_CALL_COUNT + 2
+                       if ret >= 100: ret = 99
+                       #print "callcount : [%d]"%(self.fu.callcount);
+                       return ret
+               elif self.fu.status == STATUS_DONE:
+                       return 100
+
+       def getErrorMessage(self, errno, errmsg):
+               return str(self.fu.errmsg)
+
 class UpgradeStatus(Screen):
        skin =  """
                <screen position="center,center" size="450,100" title=" ">
@@ -78,8 +244,7 @@ class UpgradeStatus(Screen):
 
                self.setTitle(firmware.upper() + " Upgrade Status")
 
-               import fu
-               self.FU = fu.FU()
+               self.FU = FirmwareUpgradeManager()
 
                self.old_status   = 0
                self.status_exit  = None
@@ -102,7 +267,7 @@ class UpgradeStatus(Screen):
                        self.cbConfirmExit(False)
                        return
                status = self.FU.getStatus()
-               if self.old_status > status:
+               if self.old_status > status and status != -1:
                        self.session.open(MessageBox, _("Fail to upgrade!! Retry!!"), MessageBox.TYPE_INFO, timeout = 10)
                self.slider.setValue(status)
                self["status"].setText(_("%d / 100" % (status)))
@@ -143,7 +308,7 @@ class Filebrowser(Screen):
        skin =  """
                <screen position="center,center" size="500,260" title="File Browser" >
                        <ePixmap pixmap="Vu_HD/buttons/blue.png" position="5,7" size="80,40" alphatest="blend" />
-                       <widget source="key_blue" render="Label" position="40,0" zPosition="1" size="180,40" font="Regular;20" halign="left" valign="center" transparent="1"/>
+                       <widget source="key_blue" render="Label" position="40,0" zPosition="1" size="300,40" font="Regular;20" halign="left" valign="center" transparent="1"/>
                        <widget name="file_list" position="0,50" size="500,160" scrollbarMode="showOnDemand" />
 
                        <widget source="status" render="Label" position="0,220" zPosition="1" size="500,40" font="Regular;18" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
@@ -154,7 +319,7 @@ class Filebrowser(Screen):
                Screen.__init__(self, session)
                 self.session = session 
                
-               self["key_blue"] = StaticText(_("Download"))
+               self["key_blue"] = StaticText(_("Download  the  firmware (latest)"))
 
                self["status"]    = StaticText(_(" "))
                self["file_list"] = FileList("/", matchingPattern = "^.*")
@@ -237,7 +402,7 @@ class Filebrowser(Screen):
        # tf  : target file name(string)
        # bd  : target base directory(string)
        # cbfunc(string) : callback function(function)
-       def doDownload(self, uri, tf, bd='/tmp', cbfunc=None):
+       def doDownload(self, uri, tf, bd='/tmp', cbfunc=None, errmsg="Fail to download."):
                tar = bd + "/" + tf
                #print "[FirmwareUpgrade] - Download Info : [%s][%s]" % (uri, tar)
                def doHook(blockNumber, blockSize, totalSize) :
@@ -247,13 +412,17 @@ class Filebrowser(Screen):
                try:
                        opener.open(uri)
                except:
-                       self.session.open(MessageBox, _("File not found in this URL:\n%s"%(uri)), MessageBox.TYPE_INFO, timeout = 10)
+                       #self.session.open(MessageBox, _("File not found in this URL:\n%s"%(uri)), MessageBox.TYPE_INFO, timeout = 10)
+                       print "[FirmwareUpgrade] - Fail to download. URL :",uri
+                       self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
                        del opener
                        return False
                try :
                        f, h = urlretrieve(uri, tar, doHook)
                except IOError, msg:
-                       self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 10)
+                       #self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 10)
+                       print "[FirmwareUpgrade] - Fail to download. ERR_MSG :",str(msg)
+                       self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
                        del opener
                        return False
                del opener
@@ -298,12 +467,12 @@ class Filebrowser(Screen):
                os.system("rm -f /tmp/" + root_file)
 
                # md5
-               if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone):
+               if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone, errmsg="Can't download the checksum file."):
                        self.resetGUI()
                        self.downloadLock = False
                        return
                # data
-               if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone):
+               if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone, errmsg="Can't download the firmware file."):
                        self.resetGUI()
                        self.downloadLock = False
                        return
@@ -391,6 +560,8 @@ class FirmwareUpgrade(Screen, ConfigListScreen):
                self.list = []
                self.updateFilePath = ""
 
+               self.finishedExit = False
+
                self.rebootLock = False
                self.rebootMessage = ""
                self.cbRebootCallCount = 0;
@@ -432,18 +603,24 @@ class FirmwareUpgrade(Screen, ConfigListScreen):
                                self.rebootMessage = message
                                self.reboot_timer = eTimer()
                                self.reboot_timer.callback.append(self.cbReboot)
-                               self.reboot_timer.start(500)
+                               self.reboot_timer.start(1000)
                        return
                if not self.rebootLock:
                        self["status"].setText("Press the Green/OK button")
 
+       def doReboot(self):
+               from Screens.Standby import TryQuitMainloop
+               self.session.open(TryQuitMainloop, 2)
+
        def cbReboot(self):
-               if self.cbRebootCallCount < 6:
+               max_call_count = 20
+               self.finishedExit = True
+               if self.cbRebootCallCount < max_call_count:
                        self.cbRebootCallCount = self.cbRebootCallCount + 1
-                       self["status"].setText("%s (%d)"%(self.rebootMessage, 6-self.cbRebootCallCount))
+                       #self["status"].setText("%s (%d)"%(self.rebootMessage, max_call_count-self.cbRebootCallCount))
+                       self["status"].setText("Reboot after %d seconds. Press the OK to reboot now."%(max_call_count-self.cbRebootCallCount))
                        return
-               from Screens.Standby import TryQuitMainloop
-               self.session.open(TryQuitMainloop, 2)
+               self.doReboot()
 
        # filebrowser window callback function
        def cbSetStatus(self, data=None):
@@ -495,6 +672,9 @@ class FirmwareUpgrade(Screen, ConfigListScreen):
                self.setupStatus()
 
        def keyGreen(self):
+               if self.finishedExit:
+                       self.doReboot()
+                       return
                self.upgrade_auto_run_timer.stop()
                if self.rebootLock:
                        return