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