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