fix ui of plugins on 750s.
[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         size = getDesktop(0).size()
126         position_params = size.width() > 750 and (' ') or ('backgroundColor=\"blue\"')
127         skin =  """
128                 <screen position="center,center" size="450,130" title="FPGA Upgrade">
129                         <widget name="name" position="10,0" size="430,20" font="Regular;18" halign="left" valign="bottom"/>
130                         <widget name="slider" position="10,25" size="430,30" borderWidth="2" borderColor="#cccccc"/>
131                         <widget name="status" position="10,25" zPosition="1" size="430,30" font="Regular;18" halign="center" valign="center" foregroundColor="blue" %s transparent="1"/>
132                         <widget source="info" render="Label" position="10,70" zPosition="1" size="430,60" font="Regular;22" halign="center" valign="center" backgroundColor="#a08500" transparent="1"/>
133                 </screen>
134                 """ % position_params
135
136         def __init__(self, session, parent, timeout = 20):
137                 Screen.__init__(self,session)
138                 self.session = session
139
140                 self["actions"] = ActionMap(["OkCancelActions"],
141                 {
142                         "ok": self.keyExit,
143                 }, -2)
144
145                 self.is_done = 0
146                 self.exit_count = 0
147                 self.timeout = 20
148                 self.title_str = "FPGA Upgrade"
149
150                 #self["name"] = Label(_("Upgrade status"))
151                 self["name"] = Label(_(" "))
152                 self["info"] = StaticText(_("Can't cancel during upgrade!!"))
153
154                 self["status"] = Label(_("Status : 0%"))
155                 self.status_bar = self["status"] 
156
157                 self.slider = Slider(0, 100)
158                 self["slider"] = self.slider
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         size = getDesktop(0).size()
215         position_params = size.width() > 750 and ('center', 440) or ('120', 420)
216         skin =  """
217                 <screen position="center,%s" size="560,%d" title="FPGA Upgrade" >
218                         <ePixmap pixmap="Vu_HD/buttons/red.png" position="0,7" size="80,40" alphatest="blend" />
219                         <ePixmap pixmap="Vu_HD/buttons/green.png" position="186,7" size="80,40" alphatest="blend" />
220                         <ePixmap pixmap="Vu_HD/buttons/blue.png" position="372,7" size="80,40" alphatest="blend" />
221
222                         <widget source="key_red" render="Label" position="28,0" zPosition="1" size="160,40" font="Regular;20" halign="center" valign="center" transparent="1"/>
223                         <widget source="key_green" render="Label" position="213,0" zPosition="1" size="160,40" font="Regular;20" halign="center" valign="center" transparent="1"/>
224                         <widget source="key_blue" render="Label" position="400,0" zPosition="1" size="160,40" font="Regular;20" halign="center" valign="center" transparent="1"/>
225
226                         <widget source="status" render="Label" position="15,45" zPosition="1" size="540,40" font="Regular;18" halign="left" valign="center" backgroundColor="#a08500" transparent="1" />
227                         <widget name="file_list" position="0,100" size="555,325" scrollbarMode="showOnDemand" />
228                 </screen>
229                 """ % position_params 
230
231         def __init__(self, session): 
232                 Screen.__init__(self, session)
233                 self.session = session 
234
235                 self["key_red"] = StaticText(_("Close"))
236                 self["key_green"] = StaticText(_("Upgrade"))
237                 self["key_blue"] = StaticText(_("Download"))
238
239                 self["status"] = StaticText(_(" "))
240                 self["file_list"] = FileList("/", matchingPattern = "^.*")
241
242                 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", ],
243                 {
244                         "red": self.onClickRed,
245                         "green": self.onClickGreen,
246                         "blue": self.onClickBlue,
247                         "back": self.onClickRed,
248                         "ok": self.onClickOk,
249                         "up": self.onClickUp,
250                         "down": self.onClickDown,
251                         "left": self.onClickLeft,
252                         "right": self.onClickRight,
253                 }, -1) 
254                 self.onLayoutFinish.append(self.doLayoutFinish)
255         
256                 self.ERROR_MSG = ''                                                                                          
257                 self.ERROR_CODE = 0                                                                                          
258                 self.SOURCELIST = self["file_list"]                                                                          
259                 self.STATUS_BAR = self["status"]                                                                             
260                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
261
262                 self.DEVICE_LIST = '/dev/fpga_dp;/dev/misc/dp;'
263                 self.DOWNLOAD_TAR_PATH = '/tmp/'                                                                             
264                 self.DOWNLOAD_FILE_NAME = 'TS_PRO.dat'                                                                       
265                 self.DOWNLOAD_URL = ''
266                 self.doLoadConf()
267                 self.FPGA = FPGAUpgradeManager()
268                 print self.DEVICE_LIST
269                 print self.DOWNLOAD_TAR_PATH
270                 print self.DOWNLOAD_FILE_NAME
271                 print self.DOWNLOAD_URL
272
273         def doLayoutFinish(self):
274                 return  
275
276         def doExit(self):
277                 if fileExists(self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME):
278                         os.remove(self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME)
279                 self.close()
280
281         def doLoadConf(self):
282                 if fileExists("/proc/stb/info/vumodel"):
283                         model = open("/proc/stb/info/vumodel").read().strip()
284                         download_uri_header = open('/usr/lib/enigma2/python/Plugins/SystemPlugins/FPGAUpgrade/fpga.conf').readline().strip()
285                         self.DOWNLOAD_URL = str(download_uri_header) + "vu" + str(model) + "/" + self.DOWNLOAD_FILE_NAME
286
287         def doHook(self, blockNumber, blockSize, totalSize) :
288                 if blockNumber*blockSize > totalSize :
289                         self.STATUS_BAR.setText(_("Downloaded " + self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME))
290                 else :
291                         self.STATUS_BAR.setText(_("Downloading..."))
292                 
293         def onCallbackHandler(self, confirmed):                                                                                                                
294                 if confirmed:                                                                                                                    
295                         self.doExit()   
296
297         def doUpgradeHandler(self, confirmed):
298                 if confirmed == False:
299                         return
300                 
301                 path = ''
302                 try:
303                         path = self.SOURCELIST.getCurrentDirectory() + self.SOURCELIST.getFilename() 
304                 except:
305                         #self.session.open(MessageBox, _("Can't select directory."), MessageBox.TYPE_INFO, timeout = 5)
306                         return
307
308                 device = ""
309                 device_list = self.DEVICE_LIST.split(";")
310
311                 for d in device_list:
312                         if os.path.exists(d):
313                                 device = d
314                                 break
315
316                 if device == None or len(device) == 0:
317                         message = "Fail to upgrade.\nCause : Can't found device.\nDo you want to exit?"
318                         self.session.openWithCallback(self.onCallbackHandler, MessageBox, _(message), MessageBox.TYPE_YESNO, timeout = 10, default = True)
319                         print "DEVICE_LIST : ", device_list
320
321                 print "DEVICE : ", device
322                 self.ERROR_CODE = self.FPGA.fpga_upgrade(path, device)
323                 if self.ERROR_CODE > 0:
324                         self.ERROR_MSG = self.FPGA.get_error_msg(self.ERROR_CODE, self.ERROR_MSG)
325                         message = "Fail to upgrade.\nCause : " + self.ERROR_MSG + "\nDo you want to exit?"
326                         self.session.openWithCallback(self.onCallbackHandler, MessageBox, _(message), MessageBox.TYPE_YESNO, timeout = 10, default = True)
327                         print "DEVICE : ", device
328                         print "FILE : ", path
329                 else:
330                         #self.session.open(MessageBox, _("Success!!"), MessageBox.TYPE_INFO, timeout = 5)
331                         self.session.open(UpgradeStatus, self, timeout = 20)                    
332
333         def onClickRed(self):
334                 self.doExit()
335
336         # run upgrade!!
337         def onClickGreen(self):
338                 #self.session.open(MessageBox, _("Upgrade will take about 5 minutes to finish."), MessageBox.TYPE_INFO, timeout = 10)
339                 message = "Upgrade will take about 5 minutes to finish.\nDo you want to upgrade?"
340                 self.session.openWithCallback(self.doUpgradeHandler, MessageBox, _(message), MessageBox.TYPE_YESNO, timeout = 10, default = True)
341
342         def onClickBlue(self):
343                 fname = ''
344                 header = ''
345                 test_opener = urllib.URLopener()
346                 try:
347                         test_opener.open(self.DOWNLOAD_URL)
348                 except:
349                         self.session.open(MessageBox, _('File not found'), MessageBox.TYPE_INFO, timeout = 5)
350                         del test_opener
351                         return
352                 try :
353                         fname, header = urlretrieve(self.DOWNLOAD_URL, self.DOWNLOAD_TAR_PATH + self.DOWNLOAD_FILE_NAME, self.doHook)
354                 except IOError, msg:
355                         self.session.open(MessageBox, _(str(msg)), MessageBox.TYPE_INFO, timeout = 5)
356                         del test_opener
357                         return
358                 del test_opener
359
360                 before_name = ''
361                 self.SOURCELIST.changeDir(self.DOWNLOAD_TAR_PATH)
362                 self.SOURCELIST.moveToIndex(0)
363                 while cmp(self.SOURCELIST.getFilename(), self.DOWNLOAD_FILE_NAME) != 0 :
364                         self.SOURCELIST.down()
365                         if cmp(before_name, self.SOURCELIST.getFilename()) == 0:
366                                 break
367                         before_name = self.SOURCELIST.getFilename()
368
369         def onClickOk(self):
370                 if self.SOURCELIST.canDescent() : # isDir                                                                   
371                         self.SOURCELIST.descent()                                                                              
372                         if self.SOURCELIST.getCurrentDirectory():
373                                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
374                 else:                                                                                                      
375                         self.onClickGreen()
376
377         def onClickUp(self):
378                 self.SOURCELIST.up()
379                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
380
381         def onClickDown(self):
382                 self.SOURCELIST.down()
383                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
384
385         def onClickLeft(self):
386                 self.SOURCELIST.pageUp()
387                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
388
389         def onClickRight(self):
390                 self.SOURCELIST.pageDown()
391                 self.STATUS_BAR.setText(_(self.SOURCELIST.getCurrentDirectory()))
392
393 def main(session, **kwargs):
394         session.open(FPGAUpgrade)
395                                                            
396 def Plugins(**kwargs):            
397         return PluginDescriptor(name=_("FPGA Upgrade"), description="Upgrade FPGA..", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
398