[firmware upgrade] add firmware type(vfd).
[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.files", "/dev/fpga_dp;/dev/misc/dp;"]
44                         }
45         elif info == "solo2":
46                 fwlist= [
47                          ("fpga", _("FPGA"))
48                         ,("fp", _("Front Processor"))
49                         ]
50                 fwdata= { 
51                          "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
52                         ,"fp"   : ["http://archive.vuplus.com/download/fp", "fp.files", "/dev/bcm_mu;"]
53                         }
54         elif info == "duo2":
55                 fwlist= [
56                          ("fpga", _("FPGA"))
57                         ,("fp", _("Front Processor"))
58                         ,("vfd", _("VFD Controller"))
59                         ]
60                 fwdata= {
61                          "fpga" : ["http://archive.vuplus.com/download/fpga", "fpga.files", "/dev/fpga_dp;/dev/misc/dp;"]
62                         ,"fp"   : ["http://archive.vuplus.com/download/fp", "fp.files", "/dev/bcm_mu;"]
63                         ,"vfd"  : ["http://archive.vuplus.com/download/vfd", "vfd.files", "/dev/bcm_vfd_ctrl;"]
64                         }
65
66 import os, fcntl, thread
67 STATUS_READY            = 0
68 STATUS_DONE             = 1
69 STATUS_ERROR            = 2
70 STATUS_PREPARED         = 3
71 STATUS_PROGRAMMING      = 4
72 STATUS_RETRY_UPGRADE    = 5
73
74 class FPUpgradeCore() :
75         status = STATUS_READY
76         errmsg = ''
77         MAX_CALL_COUNT = 120
78         def __init__(self, firmwarefile, devicefile):
79                 self.devicefile = devicefile
80                 self.firmwarefile = firmwarefile
81
82         def doUpgrade(self):
83                 firmware,device = None,None
84                 def closefp(fp, fd):
85                         if fd is not None: os.close(fd)
86                         if fp is not None: fp.close()
87                 try:
88                         size = os.path.getsize(self.firmwarefile)
89                         if size == 0: raise Exception, 'data_size is zero'
90                         #print '[FPUpgradeCore] data_size :',size
91
92                         for xx in range(3):
93                                 self.callcount = 0
94                                 self.status = STATUS_READY
95
96                                 firmware = open(self.firmwarefile, 'rb')
97                                 device = os.open(self.devicefile, os.O_RDWR)
98                                 #print '[FPUpgradeCore] open >> [ok]'
99
100                                 rc = fcntl.ioctl(device, 0, size)
101                                 if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
102                                 #print '[FPUpgradeCore] set size >> [ok]'
103                                 self.status = STATUS_PREPARED
104
105                                 while True:
106                                         data = firmware.read(1024)
107                                         if data == '': break
108                                         os.write(device, data)
109                                 #print '[FPUpgradeCore] write data >> [ok]'
110
111                                 self.status = STATUS_PROGRAMMING
112                                 rc = fcntl.ioctl(device, 1, 0)
113                                 if rc == 0: break
114                                 if xx == 2: raise Exception, 'fail to upgrade : %d'%(rc)
115                                 self.errmsg = 'fail to upgrade, retry..'
116                                 self.status = STATUS_RETRY_UPGRADE
117                                 closefp(firmware, device)
118                         #print '[FPUpgradeCore] upgrade done.'
119                         if self.callcount < 20: raise Exception, 'wrong fpga file.'
120                 except Exception, msg:
121                         self.errmsg = msg
122                         print '[FPUpgradeCore] ERROR >>',msg
123                         closefp(firmware, device)
124                         return STATUS_ERROR
125                 return STATUS_DONE
126
127         def upgradeMain(self):
128                 self.status = STATUS_READY
129                 self.status = self.doUpgrade()
130                 if self.status == STATUS_DONE:
131                         print 'upgrade done.'
132                 elif self.status == STATUS_ERROR:
133                         print 'error!!'
134                 else:   print 'unknown.'
135
136 class FPGAUpgradeCore() :
137         status = STATUS_READY
138         errmsg = ''
139         callcount       = 0
140         MAX_CALL_COUNT  = 1500
141         def __init__(self, firmwarefile, devicefile):
142                 print '[FPGAUpgrade]'
143                 self.devicefile = devicefile
144                 self.firmwarefile = firmwarefile
145
146         def doUpgrade(self):
147                 firmware,device = None,None
148                 def closefpga(fp, fd):
149                         if fd is not None: os.close(fd)
150                         if fp is not None: fp.close()
151                 try:
152                         size = os.path.getsize(self.firmwarefile)
153                         if size == 0: raise Exception, 'data_size is zero'
154                         #print '[FPGAUpgradeCore] data_size :',size
155
156                         firmware = open(self.firmwarefile, 'rb')
157                         device = os.open(self.devicefile, os.O_RDWR)
158                         #print '[FPGAUpgradeCore] open >> [ok]'
159
160                         rc = fcntl.ioctl(device, 0, size)
161                         if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
162                         #print '[FPGAUpgradeCore] set size >> [ok]'
163
164                         rc = fcntl.ioctl(device, 2, 5)
165                         if rc < 0: raise Exception, 'fail to set programming mode : %d'%(rc)
166                         #print '[FPGAUpgradeCore] programming mode >> [ok]'
167                         self.status = STATUS_PREPARED
168
169                         while True:
170                                 data = firmware.read(1024)
171                                 if data == '': break
172                                 os.write(device, data)
173                         #print '[FPGAUpgradeCore] write data >> [ok]'
174
175                         self.status = STATUS_PROGRAMMING
176                         rc = fcntl.ioctl(device, 1, 0)
177                         if rc < 0: raise Exception, 'fail to programming : %d'%(rc)
178                         #print '[FPGAUpgradeCore] upgrade done.'
179                         if self.callcount < 20: raise Exception, 'wrong fpga file.'
180                 except Exception, msg:
181                         self.errmsg = msg
182                         print '[FPGAUpgradeCore] ERROR >>',msg
183                         closefpga(firmware, device)
184                         return STATUS_ERROR
185                 closefpga(firmware, device)
186                 return STATUS_DONE
187
188         def upgradeMain(self):
189                 self.status = STATUS_READY
190                 self.status = self.doUpgrade()
191                 if self.status == STATUS_DONE:
192                         print '[FPGAUpgrade] upgrade done.'
193                 elif self.status == STATUS_ERROR:
194                         print '[FPGAUpgrade] occur error.'
195                 else:   print '[FPGAUpgrade] occur unknown error.'
196
197
198 class VFDCtrlUpgradeCore() :
199         status = STATUS_READY
200         errmsg = ''
201         MAX_CALL_COUNT = 120
202         def __init__(self, firmwarefile, devicefile):
203                 #print '[VFDCtrlUpgradeCore]'
204                 self.devicefile = devicefile
205                 self.firmwarefile = firmwarefile
206                 #print '[VFDCtrlUpgradeCore] devicefile :', self.devicefile
207                 #print '[VFDCtrlUpgradeCore] firmwarefile :', self.firmwarefile
208
209         def doUpgrade(self):
210                 firmware,device,firmwarename = None,None,None
211                 print '[VFDCtrlUpgradeCore] checkvfd..'
212                 cmd_t = "/usr/lib/enigma2/python/Plugins/SystemPlugins/FirmwareUpgrade/checkvfd %s" 
213                 ret_d = os.popen(cmd_t % (self.firmwarefile)).read()
214
215                 if ret_d is not None and len(ret_d) > 0:
216                         print '[VFDCtrlUpgradeCore] fail to checkvfd.. [' + ret_d + ']'
217                         return STATUS_ERROR
218
219                 def closevfd(fp, fd, filename):
220                         if fd is not None: os.close(fd)
221                         if fp is not None: fp.close()
222                         if filename is not None: os.system('rm -f %s' % (filename))
223                 try:
224                         max_size = 1024 * 16
225                         size = max_size #os.path.getsize(self.firmwarefile)
226                         if size == 0: raise Exception, 'data_size is zero'
227                         #print '[VFDCtrlUpgradeCore] data_size :',size
228
229                         for xx in range(3):
230                                 self.callcount = 0
231                                 self.status = STATUS_READY
232                                 firmwarename = os.path.splitext(self.firmwarefile)[0]
233                                 firmware = open(firmwarename, 'rb')
234                                 device = os.open(self.devicefile, os.O_RDWR)
235                                 #print '[VFDCtrlUpgradeCore] open >> [ok]'
236
237                                 rc = fcntl.ioctl(device, 0, size)
238                                 if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
239                                 #print '[VFDCtrlUpgradeCore] set size >> [ok]'
240                                 self.status = STATUS_PREPARED
241
242                                 total_write_size = 0
243                                 while True:
244                                         data = firmware.read(1024)
245                                         if data == '' or total_write_size == max_size:
246                                                 break
247                                         os.write(device, data)
248                                         total_write_size = total_write_size + 1024
249                                 #print '[VFDCtrlUpgradeCore] write data >> [ok]'
250
251                                 self.status = STATUS_PROGRAMMING
252                                 rc = fcntl.ioctl(device, 1, 0)
253                                 if rc == 0: break
254                                 if rc < 0 or xx == 2: raise Exception, 'fail to upgrade : %d'%(rc)
255                                 self.errmsg = 'fail to upgrade, retry..'
256                                 self.status = STATUS_RETRY_UPGRADE
257                         #print '[VFDCtrlUpgradeCore] upgrade done.'
258                         if self.callcount < 20: raise Exception, 'wrong fpga file.'
259                 except Exception, msg:
260                         self.errmsg = msg
261                         print '[VFDCtrlUpgradeCore] ERROR >>',msg
262                         closevfd(firmware, device, firmwarename)
263                         return STATUS_ERROR
264                 closevfd(firmware, device, firmwarename)
265                 return STATUS_DONE
266
267         def upgradeMain(self):
268                 self.status = STATUS_READY
269                 self.status = self.doUpgrade()
270                 if self.status == STATUS_DONE:
271                         print '[VFDCtrlUpgradeCore] upgrade done.'
272                 elif self.status == STATUS_ERROR:
273                         print '[VFDCtrlUpgradeCore] error.'
274                 else:   print '[VFDCtrlUpgradeCore] unknown error.'
275
276 class FirmwareUpgradeManager:
277         fu = None
278         def getInterval(self):
279                 return 200
280
281         def startUpgrade(self, datafile, device, firmware):
282                 if firmware == 'fpga':
283                         self.fu = FPGAUpgradeCore(firmwarefile=datafile, devicefile=device)
284                 elif firmware == 'fp':
285                         self.fu = FPUpgradeCore(firmwarefile=datafile, devicefile=device)
286                 elif firmware == 'vfd':
287                         self.fu = VFDCtrlUpgradeCore(firmwarefile=datafile, devicefile=device)
288                 thread.start_new_thread(self.fu.upgradeMain, ())
289
290         def checkError(self):
291                 if self.fu.status == STATUS_ERROR:
292                         self.fu.callcount = 0
293                         return True
294                 return False
295
296         def getStatus(self):
297                 if self.fu.status in (STATUS_READY, STATUS_ERROR):
298                         return 0
299                 elif self.fu.status == STATUS_PREPARED:
300                         return 2
301                 elif self.fu.status == STATUS_PROGRAMMING:
302                         self.fu.callcount += 1
303                         ret = (self.fu.callcount * 100) / self.fu.MAX_CALL_COUNT + 2
304                         if ret >= 100: ret = 99
305                         #print "callcount : [%d]"%(self.fu.callcount);
306                         return ret
307                 elif self.fu.status == STATUS_DONE:
308                         return 100
309
310         def getErrorMessage(self, errno, errmsg):
311                 return str(self.fu.errmsg)
312
313 class UpgradeStatus(Screen):
314         skin =  """
315                 <screen position="center,center" size="450,130" title=" ">
316                         <widget name="name" position="10,0" size="430,20" font="Regular;18" halign="left" valign="bottom"/>
317                         <widget name="slider" position="10,25" size="430,30" borderWidth="2" borderColor="#cccccc"/>
318                         <widget name="status" position="10,25" zPosition="1" size="430,30" font="Regular;18" halign="center" valign="center" foregroundColor="#9f1313" transparent="1"/>
319                         <widget source="info" render="Label" position="10,70" zPosition="1" size="430,60" font="Regular;22" halign="center" valign="center" transparent="1"/>
320                 </screen>
321                 """
322
323         def __init__(self, session, parent, firmware, datafile, device):
324                 Screen.__init__(self,session)
325                 self.session = session
326
327                 self["actions"] = ActionMap(["OkCancelActions"],
328                 {
329                         "ok": self.keyExit,
330                 }, -1)
331
332                 self.firmware = firmware
333                 self.datafile = datafile
334                 #print "[FirmwareUpgrade] - [%s][%s][%s]" % (self.datafile, firmware, device)
335
336                 self["name"] = Label(_(" "))
337                 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
338
339                 self["status"] = Label(_("Status : 0%"))
340
341                 self.slider = Slider(0, 100)
342                 self["slider"] = self.slider
343
344                 self.callback = None
345
346                 self.setTitle(firmware.upper() + " Upgrade Status")
347
348                 self.FU = FirmwareUpgradeManager()
349
350                 self.old_status   = 0
351                 self.status_exit  = None
352                 self.check_status = eTimer()
353                 self.check_status.callback.append(self.cbCheckStatus)
354                 self.check_status.start(self.FU.getInterval())
355
356                 self.exitTimerCallCount = 0;
357                 self.upgradeLock = True
358                 self.FU.startUpgrade(self.datafile, device, firmware)
359
360         def cbCheckStatus(self):
361                 errmsg = ""
362                 errno  = self.FU.checkError()
363                 if errno:
364                         self.check_status.stop()
365                         errmsg = self.FU.getErrorMessage(errno, errmsg)
366                         print "[FirmwareUpgrade] - ERROR : [%d][%s]" % (errno, errmsg)
367                         self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
368                         self.cbConfirmExit(False)
369                         return
370                 status = self.FU.getStatus()
371                 if self.old_status > status and status != -1:
372                         self.session.open(MessageBox, _("Fail to upgrade!! Retry!!"), MessageBox.TYPE_INFO, timeout = 10)
373                 self.slider.setValue(status)
374                 self["status"].setText(_("%d / 100" % (status)))
375                 if status == 100:
376                         self.check_status.stop()
377                         self["status"].setText(_("Success. Press OK to exit."))
378                         self.status_exit = eTimer()
379                         self.status_exit.callback.append(self.cbTimerExit)
380                         self.status_exit.start(1000)
381                         self.upgradeLock = False
382                 self.old_status = status
383
384         def setCallback(self, cb):
385                 self.callback = cb
386
387         def cbTimerExit(self):
388                 if self.exitTimerCallCount < 10: # exit after 10 sec.
389                         self.exitTimerCallCount = self.exitTimerCallCount + 1
390                         self.setTitle("%s Upgrade Status (%d)" % (self.firmware.upper(), 10-self.exitTimerCallCount))
391                         return
392                 if self.status_exit is not None:
393                         self.status_exit.stop()
394                 self.keyExit()
395
396         def cbConfirmExit(self, ret):
397                 if ret:
398                         os.system("rm -f %s %s.md5" % (self.datafile, self.datafile))
399                 self.close()
400
401         def keyExit(self):
402                 if self.upgradeLock:
403                         return
404                 if self.callback is not None:
405                         self.callback("Reboot now for a successful upgrade.", True)
406                 self.session.openWithCallback(self.cbConfirmExit, MessageBox, _("Do you want to remove binary data?"), MessageBox.TYPE_YESNO, timeout = 10, default = False)
407
408 class FUFilebrowser(Screen):
409         skin =  """
410                 <screen position="center,center" size="500,290" title="File Browser" >
411                         <ePixmap pixmap="skin_default/buttons/blue.png" position="5,10" size="140,40" alphatest="blend" />
412
413                         <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"/>
414
415                         <widget name="file_list" position="0,70" size="495,160" scrollbarMode="showOnDemand" />
416                         <widget source="status" render="Label" position="0,230" zPosition="1" size="495,70" font="Regular;18" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
417                 </screen>
418                 """
419
420         def __init__(self, session, parent, firmware):
421                 Screen.__init__(self, session)
422                 self.session = session 
423                 
424                 self["key_blue"] = StaticText(_("Download"))
425
426                 self["status"]    = StaticText(_(" "))
427                 self["file_list"] = FileList("/", matchingPattern = "^.*")
428
429                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
430                 {
431                         "ok":     self.onClickOk,
432                         "cancel": self.onClickCancel,
433                         "blue":   self.onClickBlue,
434                         "up":     self.onClickUp,
435                         "down":   self.onClickDown,
436                         "left":   self.onClickLeft,
437                         "right":  self.onClickRight,
438                 }, -1) 
439
440                 self.resetGUI()
441                 self.firmware = firmware
442
443                 self.callback = None
444                 self.timer_downloading = None
445
446                 self.downloadLock = False
447                 self.setTitle(firmware.upper() + " File Browser")
448
449         def resetGUI(self):
450                 self["status"].setText("Press OK to select, Press Cancel to exit.\nPress BLUE to download the latest firmware.")
451
452         def setCallback(self, func):
453                 self.callback = func
454
455         def onClickOk(self):
456                 if self.downloadLock:
457                         return
458
459                 if self["file_list"].canDescent() : # isDir
460                         self["file_list"].descent()
461                         return
462
463                 # verify data
464                 self.gbin = self["file_list"].getCurrentDirectory() + self["file_list"].getFilename()
465                 if not os.path.exists(self.gbin):
466                         self.session.open(MessageBox, _("Can't found binary file."), MessageBox.TYPE_INFO, timeout = 10)
467                         return
468                 if not os.path.exists(self.gbin+".md5"):
469                         self.session.open(MessageBox, _("Can't found MD5 file."), MessageBox.TYPE_INFO, timeout = 10)
470                         return
471                 try:
472                         def checkExt(ext):
473                                 name_ext = os.path.splitext(self["file_list"].getFilename())
474                                 return len(name_ext)==2 and ext.startswith(name_ext[1])
475                         self.check_ext = False
476                         if (self.firmware == "fp" and checkExt(".bin")) or (self.firmware == "fpga" and checkExt(".dat")) or (self.firmware == "vfd" and checkExt(".vfd")):
477                                 self.check_ext = True
478                         if self.check_ext == False:
479                                 print self.firmware,",",self["file_list"].getFilename()
480                                 self.session.open(MessageBox, _("You choose the incorrect file. "), MessageBox.TYPE_INFO)
481                                 return
482                 except:
483                         print self.firmware,",",self["file_list"].getFilename()
484                         self.session.open(MessageBox, _("You choose the incorrect file. "), MessageBox.TYPE_INFO)
485                         return
486
487                 if os.path.exists("/usr/bin/md5sum") == False:
488                         self.session.open(MessageBox, _("Can't find /usr/bin/md5sum"), MessageBox.TYPE_INFO, timeout = 10)
489                         return
490                 md5sum_A = os.popen("md5sum %s | awk \'{print $1}\'"%(self.gbin)).readline().strip()
491                 md5sum_B = os.popen("cat %s.md5 | awk \'{print $1}\'"%(self.gbin)).readline().strip()
492                 #print "[FirmwareUpgrade] - Verify : file[%s], md5[%s]"%(md5sum_A,md5sum_B)
493
494                 if md5sum_A != md5sum_B:
495                         self.session.open(MessageBox, _("Fail to verify data file. \nfile[%s]\nmd5[%s]"%(md5sum_A,md5sum_B)), MessageBox.TYPE_INFO, timeout = 10)
496                         return 
497
498                 if self.callback is not None:
499                         self.callback(_(self.gbin))
500                 self.close()
501
502         def onClickCancel(self):
503                 self.close()
504
505         # uri : source file url(string)
506         # tf  : target file name(string)
507         # bd  : target base directory(string)
508         # cbfunc(string) : callback function(function)
509         def doDownload(self, uri, tf, bd='/tmp', cbfunc=None, errmsg="Fail to download."):
510                 tar = bd + "/" + tf
511                 #print "[FirmwareUpgrade] - Download Info : [%s][%s]" % (uri, tar)
512                 def doHook(blockNumber, blockSize, totalSize) :
513                         if blockNumber*blockSize > totalSize and cbfunc is not None:
514                                 cbfunc(tar)
515                 opener = urllib.URLopener()
516                 try:
517                         opener.open(uri)
518                 except:
519                         #self.session.open(MessageBox, _("File not found in this URL:\n%s"%(uri)), MessageBox.TYPE_INFO, timeout = 10)
520                         print "[FirmwareUpgrade] - Fail to download. URL :",uri
521                         self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
522                         del opener
523                         return False
524                 try :
525                         f, h = urlretrieve(uri, tar, doHook)
526                 except IOError, msg:
527                         #self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 10)
528                         print "[FirmwareUpgrade] - Fail to download. ERR_MSG :",str(msg)
529                         self.session.open(MessageBox, _(errmsg), MessageBox.TYPE_INFO, timeout = 10)
530                         del opener
531                         return False
532                 del opener
533                 return True
534
535         def runDownloading(self) :
536                 self.timer_downloading.stop()
537                 machine = str(open("/proc/stb/info/vumodel").read().strip())
538
539                 def cbDownloadDone(tar):
540                         try:
541                                 if os.path.splitext(tar)[1] != ".files":
542                                         self["status"].setText("Downloaded : %s\nPress OK to select, Press Cancel to exit."%(tar))
543                         except:
544                                 pass
545                 # target
546                 global fwdata
547                 root_uri  = fwdata[self.firmware][0]
548                 root_file = fwdata[self.firmware][1]
549                 if not self.doDownload("%s/%s"%(root_uri, root_file), root_file, cbfunc=cbDownloadDone):
550                         self.resetGUI()
551                         self.downloadLock = False
552                         return
553
554                 target_path = ""
555                 for l in file("/tmp/"+root_file).readlines():
556                         if l.startswith(machine):
557                                 try:
558                                         target_path = l.split("=")[1].strip()
559                                 except:
560                                         target_path = ""
561                                         pass
562                 if target_path == "":
563                         self.session.open(MessageBox, _("Firmware does not exist."), MessageBox.TYPE_INFO)
564                         self.resetGUI()
565                         self.downloadLock = False
566                         return
567
568                 self.guri = "%s/vu%s/%s"%(root_uri, machine, target_path)
569                 self.gbin = os.path.basename(target_path)
570                 #print "[FirmwareUpgrade] - uri[%s], data[%s], data_path[%s]" % (self.gbin, self.guri, target_path)
571                 os.system("rm -f /tmp/" + root_file)
572
573                 # md5
574                 if not self.doDownload(self.guri+".md5", self.gbin+".md5", cbfunc=cbDownloadDone, errmsg="Can't download the checksum file."):
575                         self.resetGUI()
576                         self.downloadLock = False
577                         return
578                 # data
579                 if not self.doDownload(self.guri, self.gbin, cbfunc=cbDownloadDone, errmsg="Can't download the firmware file."):
580                         self.resetGUI()
581                         self.downloadLock = False
582                         return
583
584                 t = ''
585                 self["file_list"].changeDir("/tmp/")
586                 self["file_list"].moveToIndex(0)
587                 while cmp(self["file_list"].getFilename(), self.gbin) != 0 :
588                         self["file_list"].down()
589                         if cmp(t, self["file_list"].getFilename()) == 0:
590                                 break
591                         t = self["file_list"].getFilename()
592
593                 del self.timer_downloading
594                 self.timer_downloading = None
595                 self.downloadLock = False
596
597         def onClickBlue(self):
598                 if self.downloadLock:
599                         return
600                 self.downloadLock = True
601                 if not os.path.exists("/proc/stb/info/vumodel"):
602                         self.session.open(MessageBox, _("Can't found model name."), MessageBox.TYPE_INFO, timeout = 10)
603                         self.downloadLock = False
604                         return
605                 self["status"].setText("Please wait during download.")
606                 self.timer_downloading = eTimer()
607                 self.timer_downloading.callback.append(self.runDownloading)
608                 self.timer_downloading.start(1000)
609
610         def onClickUp(self):
611                 if self.downloadLock:
612                         return
613                 self.resetGUI()
614                 self["file_list"].up()
615
616         def onClickDown(self):
617                 if self.downloadLock:
618                         return
619                 self.resetGUI()
620                 self["file_list"].down()
621
622         def onClickLeft(self):
623                 if self.downloadLock:
624                         return
625                 self.resetGUI()
626                 self["file_list"].pageUp()
627
628         def onClickRight(self):
629                 if self.downloadLock:
630                         return
631                 self.resetGUI()
632                 self["file_list"].pageDown()
633
634         def keyNone(self):
635                 None
636
637 class FirmwareUpgrade(Screen, ConfigListScreen):
638         skin =  """
639                 <screen position="center,center" size="560,175" title="Firmware Upgrade" >
640                         <ePixmap pixmap="skin_default/buttons/red.png" position="110,10" size="140,40" alphatest="blend" />
641                         <ePixmap pixmap="skin_default/buttons/green.png" position="310,10" size="140,40" alphatest="blend" />
642
643                         <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" />
644                         <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" />
645
646                         <widget name="config" zPosition="2" position="0,70" itemHeight="36" size="540,40" scrollbarMode="showOnDemand" transparent="1" />
647                         <widget source="status" render="Label" position="0,100" zPosition="1" size="540,75" font="Regular;20" halign="center" valign="center" />
648                 </screen>
649                 """
650
651         def __init__(self, session): 
652                 Screen.__init__(self, session)
653                 self.session = session 
654
655                 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
656                 {
657                         "ok":      self.keyGreen,
658                         "cancel":  self.keyRed,
659                         "red":     self.keyRed,
660                         "green":   self.keyGreen,
661                         "blue":    self.keyBlue,
662                 }, -2)
663
664                 self.list = []
665                 self.updateFilePath = ""
666
667                 self.finishedExit = False
668
669                 self.rebootLock = False
670                 self.rebootMessage = ""
671                 self.cbRebootCallCount = 0;
672
673                 ConfigListScreen.__init__(self, self.list, session=self.session)
674                 self["key_red"] = StaticText(_("Close"))
675
676                 self.logmode = None
677                 self.old_blue_clicked = 0
678                 self.fileopenmode = False
679                 self.upgrade_auto_run_timer = eTimer()
680                 self.upgrade_auto_run_timer.callback.append(self.keyGreen)
681
682                 global fwlist
683                 if fwlist is None:
684                         self["key_green"] = StaticText(_(" "))
685                         self["status"] = StaticText(_("Duo/Solo was not support."))
686                 else:
687                         self["key_green"] = StaticText(_("Upgrade"))
688                         self["status"] = StaticText(_(" "))
689                         self.setupUI()
690
691         def setupUI(self):
692                 global fwlist
693                 self.list = []
694                 self._item_firmware  = ConfigSelection(default=fwlist[0][0],  choices=fwlist)
695                 self._entry_firmware = getConfigListEntry(_("Firmware"), self._item_firmware)
696                 self.list.append(self._entry_firmware)
697                 self["config"].list = self.list
698                 self["config"].l.setList(self.list)
699                 self.setupStatus()
700
701         def setupStatus(self,message=None,reboot=False):
702                 self.updateFilePath = ""
703                 if message is not None:
704                         self.rebootLock = reboot
705                         self["status"].setText(message)
706                         if reboot:
707                                 self.rebootMessage = message
708                                 self.reboot_timer = eTimer()
709                                 self.reboot_timer.callback.append(self.cbReboot)
710                                 self.reboot_timer.start(1000)
711                         return
712                 if not self.rebootLock:
713                         self["status"].setText(" ")
714
715         def doReboot(self):
716                 from Screens.Standby import TryQuitMainloop
717                 self.session.open(TryQuitMainloop, 2)
718
719         def cbReboot(self):
720                 max_call_count = 20
721                 self.finishedExit = True
722                 if self.cbRebootCallCount < max_call_count:
723                         self.cbRebootCallCount = self.cbRebootCallCount + 1
724                         #self["status"].setText("%s (%d)"%(self.rebootMessage, max_call_count-self.cbRebootCallCount))
725                         self["status"].setText("Reboot in %d seconds. Press OK to reboot now."%(max_call_count-self.cbRebootCallCount))
726                         return
727                 self.doReboot()
728
729         # filebrowser window callback function
730         def cbSetStatus(self, data=None):
731                 if data is not None:
732                         self["status"].setText(" ")
733                         self.updateFilePath = data
734                         if self.fileopenmode == False:
735                                 self.upgrade_auto_run_timer.start(1000)
736
737         # upgrade window callback function
738         def cbFinishedUpgrade(self,message=None,reboot=False):
739                 self.setupStatus(message=message,reboot=reboot)
740
741         def cbRunUpgrade(self, ret):
742                 if ret == False:
743                         return
744
745                 if self.updateFilePath == "":
746                         self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO, timeout = 10)
747                         return
748                 device = None
749                 for d in fwdata[self._item_firmware.value][2].split(';'):
750                         if os.path.exists(d):
751                                 device = d                      
752                 if device is None:
753                         self.session.open(MessageBox, _("Can't found device file!!"), MessageBox.TYPE_INFO, timeout = 10)
754                         return
755                 fbs = self.session.open(UpgradeStatus, self, self._item_firmware.value, self.updateFilePath, device)
756                 fbs.setCallback(self.cbFinishedUpgrade)
757         
758         def doFileOpen(self):
759                 fbs = self.session.open(FUFilebrowser, self, self._item_firmware.value)
760                 fbs.setCallback(self.cbSetStatus)
761
762         def keyLeft(self):
763                 if self.rebootLock:
764                         return
765                 global fwlist
766                 if fwlist is None:
767                         return
768                 ConfigListScreen.keyLeft(self)
769                 self.setupStatus()
770
771         def keyRight(self):
772                 if self.rebootLock:
773                         return
774                 global fwlist
775                 if fwlist is None:
776                         return
777                 ConfigListScreen.keyRight(self)
778                 self.setupStatus()
779
780         def keyGreen(self):
781                 if self.finishedExit:
782                         self.doReboot()
783                         return
784                 self.upgrade_auto_run_timer.stop()
785                 if self.rebootLock:
786                         return
787                 global fwlist
788                 if fwlist is None:
789                         return
790                 if self.updateFilePath == "":
791                         #self.session.open(MessageBox, _("No selected binary data!!"), MessageBox.TYPE_INFO)
792                         self.doFileOpen()
793                         return
794                 msg = "You can't cancel during upgrade.\nDo you want to continue?"
795                 self.session.openWithCallback(self.cbRunUpgrade, MessageBox, _(msg), MessageBox.TYPE_YESNO, timeout = 15, default = True)
796                 self.fileopenmode = False
797
798         def keyYellow(self):
799                 if self.rebootLock:
800                         return
801                 global fwlist
802                 if fwlist is None:
803                         return
804                 self.fileopenmode = True
805                 self.doFileOpen()
806
807         def keyRed(self):
808                 if self.rebootLock:
809                         return
810                 self.close()
811
812         def cbLogMode(self):
813                 if self.old_blue_clicked:
814                         return
815                 self.logmode.stop()
816                 if os.path.exists("/tmp/onlogmode"):
817                         return
818                 os.system("touch /tmp/onlogmode")
819
820         def keyBlue(self):
821                 if self.rebootLock:
822                         return
823                 if self.logmode is not None and self.old_blue_clicked == 0:
824                         return
825                 if self.old_blue_clicked:
826                         self.old_blue_clicked = 0
827                         return
828                 self.old_blue_clicked = 1
829                 self.logmode = eTimer()
830                 self.logmode.callback.append(self.cbLogMode)
831                 self.logmode.start(1000)
832                 
833         def keyNone(self):
834                 None
835
836 def main(session, **kwargs):
837         session.open(FirmwareUpgrade)
838                                                            
839 def Plugins(**kwargs):            
840         return PluginDescriptor(name=_("Firmware Upgrade"), description="Upgrade Firmware..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
841