modify skin of plugins.
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / FPGAUpgrade / plugin.py
1 import os, fcntl, thread
2
3 from enigma import eTimer, getDesktop
4
5 from urllib import urlretrieve
6 import urllib
7
8 from Screens.Screen import Screen
9 from Screens.MessageBox import MessageBox
10
11 from Plugins.Plugin import PluginDescriptor
12
13 from Tools.Directories import fileExists
14
15 from Components.Label import Label
16 from Components.Slider import Slider
17 from Components.Pixmap import Pixmap
18 from Components.FileList import FileList 
19 from Components.ActionMap import ActionMap
20 from Components.PluginComponent import plugins
21 from Components.Sources.StaticText import StaticText
22
23 STATUS_READY            = 0
24 STATUS_DONE             = 1
25 STATUS_ERROR            = 2
26 STATUS_PREPARED         = 3
27 STATUS_PROGRAMMING      = 4
28
29 class FPGAUpgradeCore() :
30         status = STATUS_READY
31         errmsg = ''
32         callcount       = 0
33         MAX_CALL_COUNT  = 1500
34         def __init__(self, firmwarefile, devicefile):
35                 print '[FPGAUpgrade]'
36                 self.devicefile = devicefile
37                 self.firmwarefile = firmwarefile
38
39         def doUpgrade(self):
40                 firmware,device = None,None
41                 def closefpga(fp, fd):
42                         if fd is not None: os.close(fd)
43                         if fp is not None: fp.close()
44                 try:
45                         size = os.path.getsize(self.firmwarefile)
46                         if size == 0: raise Exception, 'data_size is zero'
47                         #print '[FPGAUpgradeCore] data_size :',size
48
49                         firmware = open(self.firmwarefile, 'rb')
50                         device = os.open(self.devicefile, os.O_RDWR)
51                         #print '[FPGAUpgradeCore] open >> [ok]'
52
53                         rc = fcntl.ioctl(device, 0, size)
54                         if rc < 0: raise Exception, 'fail to set size : %d'%(rc)
55                         #print '[FPGAUpgradeCore] set size >> [ok]'
56
57                         rc = fcntl.ioctl(device, 2, 5)
58                         if rc < 0: raise Exception, 'fail to set programming mode : %d'%(rc)
59                         #print '[FPGAUpgradeCore] programming mode >> [ok]'
60                         self.status = STATUS_PREPARED
61
62                         while True:
63                                 data = firmware.read(1024)
64                                 if data == '': break
65                                 os.write(device, data)
66                         #print '[FPGAUpgradeCore] write data >> [ok]'
67
68                         self.status = STATUS_PROGRAMMING
69                         rc = fcntl.ioctl(device, 1, 0)
70                         if rc < 0: raise Exception, 'fail to programming : %d'%(rc)
71                         #print '[FPGAUpgradeCore] upgrade done.'
72                         if self.callcount < 100: raise Exception, 'wrong fpga file.'
73                 except Exception, msg:
74                         self.errmsg = msg
75                         print '[FPGAUpgradeCore] ERROR >>',msg
76                         closefpga(firmware, device)
77                         return STATUS_ERROR
78                 closefpga(firmware, device)
79                 return STATUS_DONE
80
81         def upgradeMain(self):
82                 self.status = STATUS_READY
83                 self.status = self.doUpgrade()
84                 if self.status == STATUS_DONE:
85                         print '[FPGAUpgrade] upgrade done.'
86                 elif self.status == STATUS_ERROR:
87                         print '[FPGAUpgrade] occur error.'
88                 else:   print '[FPGAUpgrade] occur unknown error.'
89
90 class FPGAUpgradeManager:
91         fu = None
92         def get_interval(self):
93                 return 200
94
95         def fpga_upgrade(self, datafile, device):
96                 self.fu = FPGAUpgradeCore(firmwarefile=datafile, devicefile=device)
97                 thread.start_new_thread(self.fu.upgradeMain, ())
98
99         def checkError(self):
100                 if self.fu.status == STATUS_ERROR:
101                         self.fu.callcount = 0
102                         return True
103                 return False
104
105         def get_status(self):
106                 if self.fu.status == STATUS_READY:
107                         return 0
108                 elif self.fu.status == STATUS_ERROR:
109                         return -1
110                 elif self.fu.status == STATUS_PREPARED:
111                         return 2
112                 elif self.fu.status == STATUS_PROGRAMMING:
113                         self.fu.callcount += 1
114                         ret = (self.fu.callcount * 100) / self.fu.MAX_CALL_COUNT + 2
115                         if ret >= 100: ret = 99
116                         #print "callcount : [%d]"%(self.fu.callcount);
117                         return ret
118                 elif self.fu.status == STATUS_DONE:
119                         return 100
120
121         def get_error_msg(self, errno, errmsg):
122                 return str(self.fu.errmsg)
123
124 class UpgradeStatus(Screen):
125         skin =  """
126                 <screen position="center,center" size="450,130" title=" ">
127                         <widget name="name" position="10,0" size="430,20" font="Regular;18" halign="left" valign="bottom"/>
128                         <widget name="slider" position="10,25" size="430,30" borderWidth="2" borderColor="#cccccc"/>
129                         <widget name="status" position="10,25" zPosition="1" size="430,30" font="Regular;18" halign="center" valign="center" foregroundColor="#9f1313" transparent="1"/>
130                         <widget source="info" render="Label" position="10,70" zPosition="1" size="430,60" font="Regular;22" halign="center" valign="center" transparent="1"/>
131                 </screen>
132                 """
133
134         def __init__(self, session, parent, timeout = 20):
135                 Screen.__init__(self,session)
136                 self.session = session
137
138                 self["actions"] = ActionMap(["OkCancelActions"],
139                 {
140                         "ok": self.keyExit,
141                 }, -2)
142
143                 self.is_done = 0
144                 self.exit_count = 0
145                 self.timeout = 20
146                 self.title_str = "FPGA Upgrade"
147
148                 #self["name"] = Label(_("Upgrade status"))
149                 self["name"] = Label(_(" "))
150                 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
151
152                 self["status"] = Label(_("Status : 0%"))
153                 self.status_bar = self["status"] 
154
155                 self.slider = Slider(0, 100)
156                 self["slider"] = self.slider
157                 
158                 self.setTitle("FPGA Upgrade Status")
159
160                 self.parent = parent
161                 self.timer_check_progress = eTimer()
162                 self.timer_check_progress.callback.append(self.callbackDoCheckProgress)
163                 interval = self.parent.FPGA.get_interval()
164                 self.timer_check_progress.start(interval)
165                 self.need_restart = False
166
167         def callbackDoCheckProgress(self):
168                 self.status = self.parent.FPGA.get_status()
169
170                 if self.status > 0:
171                         self.slider.setValue(self.status)
172
173                 if self.status == 100:
174                         #print "fpga-upgrade done!!"
175                         self.status_bar.setText(_("Succeed"))
176                         #self.status_bar.setText(_("%d / 100" % (self.status)))
177                         self.timer_check_progress.stop()
178                         self.is_done = 1
179                         self.timer_exit = eTimer()
180                         self.timer_exit.callback.append(self.callbackExit)
181                         self.timer_exit.start(1000)
182
183                 elif self.status < 0:#elif self.status == -1 or self.status == -2:
184                         #print "fpga-upgrade error >> errno : [%d]" % (self.status)
185                         ERROR_MSG = ''
186                         ERROR_CODE = int(self.status) * -1
187                         ERROR_MSG = self.parent.FPGA.get_error_msg(ERROR_CODE, ERROR_MSG)
188                         self.status_bar.setText("Fail to update!!")
189                         self["info"].setText(_("Error[%d] : %s.\nPress OK to exit." % (self.status, ERROR_MSG)))
190                         self.timer_check_progress.stop()
191                         self.is_done = 1
192
193                 else:
194                         #print "fpga-upgrade status : %d" % self.status
195                         self.status_bar.setText(_("%d / 100" % (self.status)))
196
197         def callbackExit(self):
198                 self.need_restart = True
199                 if self.exit_count == self.timeout:
200                         self.timer_exit.stop()
201                         self.keyExit()
202                 self.exit_count = self.exit_count + 1
203                 #self.instance.setTitle("%s (%d)" % (self.title_str, (self.timeout-self.exit_count)))
204                 self["info"].setText("Reboot after %d seconds.\nPress the OK to reboot now." %(self.timeout-self.exit_count)) 
205
206         def keyExit(self):
207                 if self.need_restart:
208                         from Screens.Standby import TryQuitMainloop
209                         self.session.open(TryQuitMainloop, 2)
210                 if self.is_done :
211                         self.close()
212                 
213 class FPGAUpgrade(Screen):
214         skin =  """
215                 <screen position="center,center" size="560,430" title="FPGA Upgrade" >
216                         <ePixmap pixmap="skin_default/buttons/red.png" position="40,10" size="140,40" alphatest="blend" />
217                         <ePixmap pixmap="skin_default/buttons/green.png" position="210,10" size="140,40" alphatest="blend" />
218                         <ePixmap pixmap="skin_default/buttons/blue.png" position="380,10" size="140,40" alphatest="blend" />
219
220                         <widget source="key_red" render="Label" position="40,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1"/>
221                         <widget source="key_green" render="Label" position="210,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1"/>
222                         <widget source="key_blue" render="Label" position="380,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1"/>
223
224                         <widget source="status" render="Label" position="15,60" zPosition="1" size="540,40" font="Regular;18" halign="left" valign="center" transparent="1" />
225                         <widget name="file_list" position="0,100" size="555,320" scrollbarMode="showOnDemand" />
226                 </screen>
227                 """
228
229         def __init__(self, session): 
230                 Screen.__init__(self, session)
231                 self.session = session 
232
233                 self["key_red"] = StaticText(_("Close"))
234                 self["key_green"] = StaticText(_("Upgrade"))
235                 self["key_blue"] = StaticText(_("Download"))
236
237                 self["status"] = StaticText(_(" "))
238                 self["file_list"] = FileList("/", matchingPattern = "^.*")
239
240                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
241                 {
242                         "red": self.onClickRed,
243                         "green": self.onClickGreen,
244                         "blue": self.onClickBlue,
245                         "back": self.onClickRed,
246                         "ok": self.onClickOk,
247                         "up": self.onClickUp,
248                         "down": self.onClickDown,
249                         "left": self.onClickLeft,
250                         "right": self.onClickRight,
251                 }, -1) 
252                 self.onLayoutFinish.append(self.doLayoutFinish)
253         
254                 self.ERROR_MSG = ''                                                                                          
255                 self.ERROR_CODE = 0                                                                                          
256                 self.SOURCELIST = self["file_list"]                                                                          
257                 self.STATUS_BAR = self["status"]                                                                             
258                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
259
260                 self.DEVICE_LIST = '/dev/fpga_dp;/dev/misc/dp;'
261                 self.DOWNLOAD_TAR_PATH = '/tmp/'                                                                             
262                 self.DOWNLOAD_FILE_NAME = 'TS_PRO.dat'                                                                       
263                 self.DOWNLOAD_URL = ''
264                 self.doLoadConf()
265                 self.FPGA = FPGAUpgradeManager()
266                 print self.DEVICE_LIST
267                 print self.DOWNLOAD_TAR_PATH
268                 print self.DOWNLOAD_FILE_NAME
269                 print self.DOWNLOAD_URL
270
271         def doLayoutFinish(self):
272                 return  
273
274         def doExit(self):
275                 if fileExists(self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME):
276                         os.remove(self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME)
277                 self.close()
278
279         def doLoadConf(self):
280                 if fileExists("/proc/stb/info/vumodel"):
281                         model = open("/proc/stb/info/vumodel").read().strip()
282                         download_uri_header = open('/usr/lib/enigma2/python/Plugins/SystemPlugins/FPGAUpgrade/fpga.conf').readline().strip()
283                         self.DOWNLOAD_URL = str(download_uri_header) + "vu" + str(model) + "/" + self.DOWNLOAD_FILE_NAME
284
285         def doHook(self, blockNumber, blockSize, totalSize) :
286                 if blockNumber*blockSize > totalSize :
287                         self.STATUS_BAR.setText(_("Downloaded " + self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME))
288                 else :
289                         self.STATUS_BAR.setText(_("Downloading..."))
290                 
291         def onCallbackHandler(self, confirmed):                                                                                                                
292                 if confirmed:                                                                                                                    
293                         self.doExit()   
294
295         def doUpgradeHandler(self, confirmed):
296                 if confirmed == False:
297                         return
298                 
299                 path = ''
300                 try:
301                         path = self.SOURCELIST.getCurrentDirectory() + self.SOURCELIST.getFilename() 
302                 except:
303                         #self.session.open(MessageBox, _("Can't select directory."), MessageBox.TYPE_INFO, timeout = 5)
304                         return
305
306                 device = ""
307                 device_list = self.DEVICE_LIST.split(";")
308
309                 for d in device_list:
310                         if os.path.exists(d):
311                                 device = d
312                                 break
313
314                 if device == None or len(device) == 0:
315                         message = "Fail to upgrade.\nCause : Can't found device.\nDo you want to exit?"
316                         self.session.openWithCallback(self.onCallbackHandler, MessageBox, _(message), MessageBox.TYPE_YESNO, timeout = 10, default = True)
317                         print "DEVICE_LIST : ", device_list
318
319                 print "DEVICE : ", device
320                 self.ERROR_CODE = self.FPGA.fpga_upgrade(path, device)
321                 if self.ERROR_CODE > 0:
322                         self.ERROR_MSG = self.FPGA.get_error_msg(self.ERROR_CODE, self.ERROR_MSG)
323                         message = "Fail to upgrade.\nCause : " + self.ERROR_MSG + "\nDo you want to exit?"
324                         self.session.openWithCallback(self.onCallbackHandler, MessageBox, _(message), MessageBox.TYPE_YESNO, timeout = 10, default = True)
325                         print "DEVICE : ", device
326                         print "FILE : ", path
327                 else:
328                         #self.session.open(MessageBox, _("Success!!"), MessageBox.TYPE_INFO, timeout = 5)
329                         self.session.open(UpgradeStatus, self, timeout = 20)                    
330
331         def onClickRed(self):
332                 self.doExit()
333
334         # run upgrade!!
335         def onClickGreen(self):
336                 #self.session.open(MessageBox, _("Upgrade will take about 5 minutes to finish."), MessageBox.TYPE_INFO, timeout = 10)
337                 message = "Upgrade will take about 5 minutes to finish.\nDo you want to upgrade?"
338                 self.session.openWithCallback(self.doUpgradeHandler, MessageBox, _(message), MessageBox.TYPE_YESNO, timeout = 10, default = True)
339
340         def onClickBlue(self):
341                 fname = ''
342                 header = ''
343                 test_opener = urllib.URLopener()
344                 try:
345                         test_opener.open(self.DOWNLOAD_URL)
346                 except:
347                         self.session.open(MessageBox, _('File not found'), MessageBox.TYPE_INFO, timeout = 5)
348                         del test_opener
349                         return
350                 try :
351                         fname, header = urlretrieve(self.DOWNLOAD_URL, self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME, self.doHook)
352                 except IOError, msg:
353                         self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 5)
354                         del test_opener
355                         return
356                 del test_opener
357
358                 before_name = ''
359                 self.SOURCELIST.changeDir(self.DOWNLOAD_TAR_PATH)
360                 self.SOURCELIST.moveToIndex(0)
361                 while cmp(self.SOURCELIST.getFilename(), self.DOWNLOAD_FILE_NAME) != 0 :
362                         self.SOURCELIST.down()
363                         if cmp(before_name, self.SOURCELIST.getFilename()) == 0:
364                                 break
365                         before_name = self.SOURCELIST.getFilename()
366
367         def onClickOk(self):
368                 if self.SOURCELIST.canDescent() : # isDir                                                                   
369                         self.SOURCELIST.descent()                                                                              
370                         if self.SOURCELIST.getCurrentDirectory():
371                                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
372                 else:                                                                                                      
373                         self.onClickGreen()
374
375         def onClickUp(self):
376                 self.SOURCELIST.up()
377                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
378
379         def onClickDown(self):
380                 self.SOURCELIST.down()
381                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
382
383         def onClickLeft(self):
384                 self.SOURCELIST.pageUp()
385                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
386
387         def onClickRight(self):
388                 self.SOURCELIST.pageDown()
389                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
390
391 def main(session, **kwargs):
392         session.open(FPGAUpgrade)
393                                                            
394 def Plugins(**kwargs):            
395         return PluginDescriptor(name=_("FPGA Upgrade"), description="Upgrade FPGA..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
396