Replace 'tap' to 'spaces' to make gbs build succeed
[platform/upstream/hplip.git] / base / LedmWifi.py
1 # -*- coding: utf-8 -*-
2 #
3 # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # Author: Shunmugaraj.K
20 #
21
22 # StdLib
23 import time
24 import cStringIO
25 import xml.parsers.expat
26 from string import *
27
28 # Local
29 from base.g import *
30 from base import device, utils
31
32 http_result_pat = re.compile("""HTTP/\d.\d\s(\d+)""", re.I)
33 HTTP_OK = 200
34 HTTP_ACCEPTED = 202
35 HTTP_NOCONTENT = 204
36 HTTP_ERROR = 500
37
38 MAX_RETRIES = 2
39
40 LEDM_WIFI_BASE_URI = "/IoMgmt/Adapters/"
41
42 adapterPowerXml = """<io:Adapters xmlns:io=\"http://www.hp.com/schemas/imaging/con/ledm/iomgmt/2008/11/30\" xmlns:dd=\"http://www.hp.com/schemas/imaging/con/dictionaries/1.0/\"><io:Adapter><io:HardwareConfig><dd:Power>%s</dd:Power></io:HardwareConfig></io:Adapter></io:Adapters>"""
43
44 passPhraseXml="""<io:Profile xmlns:io="http://www.hp.com/schemas/imaging/con/ledm/iomgmt/2008/11/30" xmlns:dd="http://www.hp.com/schemas/imaging/con/dictionaries/1.0/" xmlns:wifi="http://www.hp.com/schemas/imaging/con/wifi/2009/06/26" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.hp.com/schemas/imaging/con/ledm/iomgmt/2008/11/30 ../../schemas/IoMgmt.xsd http://www.hp.com/schemas/imaging/con/dictionaries/1.0/ ../../schemas/dd/DataDictionaryMasterLEDM.xsd"><io:AdapterProfile><io:WifiProfile><wifi:SSID>%s</wifi:SSID><wifi:CommunicationMode>%s</wifi:CommunicationMode><wifi:EncryptionType>%s</wifi:EncryptionType><wifi:AuthenticationMode>%s</wifi:AuthenticationMode></io:WifiProfile></io:AdapterProfile></io:Profile>"""
45
46 keyInfoXml = """<io:KeyInfo><io:WpaPassPhraseInfo><wifi:RsnEncryption>AESOrTKIP</wifi:RsnEncryption><wifi:RsnAuthorization>autoWPA</wifi:RsnAuthorization><wifi:PassPhrase>%s</wifi:PassPhrase></io:WpaPassPhraseInfo></io:KeyInfo>"""
47
48 def getAdaptorList(dev):
49     ret,params,elementCount,code ={},{},0,HTTP_ERROR         
50     max_tries = 0
51     while max_tries < MAX_RETRIES:
52         max_tries +=1
53         URI = LEDM_WIFI_BASE_URI[0:len(LEDM_WIFI_BASE_URI)-1]# to remove "\" from the string
54         params,code,elementCount = readXmlDataFromURI(dev,URI,'<io:Adapters', '<io:Adapter>')
55         if code == HTTP_OK:
56             break
57
58     if code != HTTP_OK:
59         log.error("Request Failed With Response Code %d"%code)
60         return ret
61
62     ret['adaptorlistlength'] = elementCount
63     if params is not None:        
64         if elementCount == 1:
65             try:
66                 ret['adaptorid-0' % a] = params['io:adapters-io:adapter-map:resourcenode-map:resourcelink-dd:resourceuri']
67                 ret['adaptorname-0' % a] = params['io:adapters-io:adapter-io:hardwareconfig-dd:name']
68                 ret['adaptorpresence-0' % a] = ''
69                 ret['adaptorstate-0' % a] = ''
70                 ret['adaptortype-0' % a] = params['io:adapters-io:adapter-io:hardwareconfig-dd:deviceconnectivityporttype']                
71             except KeyError, e:
72                 log.error("Missing response key: %s" % e) 
73         else:
74             for a in xrange(elementCount):
75                 try:
76                     ret['adaptorid-%d' % a] = params['io:adapters-io:adapter-map:resourcenode-map:resourcelink-dd:resourceuri-%d' % a]
77                     ret['adaptorname-%d' % a] = params['io:adapters-io:adapter-io:hardwareconfig-dd:name-%d' % a]
78                     ret['adaptorpresence-%d' % a] = ''
79                     ret['adaptorstate-%d' % a] = ''
80                     ret['adaptortype-%d' % a] = params['io:adapters-io:adapter-io:hardwareconfig-dd:deviceconnectivityporttype-%d' % a]                     
81                 except KeyError, e:
82                     log.error("Missing response key: %s" % e)
83     return ret   
84
85
86 def getWifiAdaptorID(dev):
87     ret = {}
88
89     ret = getAdaptorList(dev)
90     try:
91         num_adaptors = ret['adaptorlistlength']
92     except KeyError:
93         num_adaptors = 0
94
95     for n in xrange(num_adaptors):
96         try:
97             name = ret['adaptortype-%d' % n]
98         except KeyError:
99             name = ''
100
101         if name.lower() in ('wifiembedded', 'wifiaccessory'):            
102             params = ['adaptorid', 'adaptorname', 'adaptorstate', 'adaptorpresence']            
103             r = []
104             for p in params:
105                 try:
106                     x = ret[''.join([p, '-', str(n)])]
107                 except KeyError:
108                     if p == 'adaptorid':
109                         x = -1
110                     else:
111                         x = 'Unknown'
112
113                 r.append(x)
114
115             return r
116
117     return -1, 'Unknown', 'Unknown', 'Unknown'
118                          
119 def setAdaptorPower(dev, adapterName, adaptor_id=0, power_state='on'):
120     ret,powerXml,URI,code = {},'','',HTTP_ERROR
121     URI = LEDM_WIFI_BASE_URI + adapterName
122     powerXml = adapterPowerXml %(power_state)  
123   
124     ret['errorreturn'] = writeXmlDataToURI(dev,URI,powerXml,10)    
125     if not(ret['errorreturn'] == HTTP_OK or HTTP_NOCONTENT):
126         log.error("Request Failed With Response Code %d" %code)
127     
128     return ret
129
130 def performScan(dev, adapterName, ssid=None):
131     ret ={}
132
133     if ssid is None:
134         URI = LEDM_WIFI_BASE_URI + adapterName + "/WifiNetworks"
135     else:
136         URI = LEDM_WIFI_BASE_URI + adapterName + "/WifiNetworks/SSID="+ssid 
137
138     while True:            
139         params,code,elementCount = readXmlDataFromURI(dev,URI,'<io:WifiNetworks', '<io:WifiNetwork>',10)        
140         if code == HTTP_ACCEPTED:
141             continue
142         else:
143             break  
144
145     ret['numberofscanentries'] = elementCount 
146     if code != HTTP_OK:
147         log.error("Request Failed With Response Code %d"%code)
148         return ret
149        
150     if params is not None:              
151         if elementCount == 1:
152             try:
153                 ssid = str(params['io:wifinetworks-io:wifinetwork-wifi:ssid']).decode("hex")
154                 if not ssid:
155                     ret['ssid-0'] = u'(unknown)'
156                 else:
157                     ret['ssid-0'] = ssid
158                 ret['bssid-0'] = str(params['io:wifinetworks-io:wifinetwork-wifi:bssid']).decode("hex")
159                 ret['channel-0'] = params['io:wifinetworks-io:wifinetwork-wifi:channel']
160                 ret['communicationmode-0'] = params['io:wifinetworks-io:wifinetwork-wifi:communicationmode']
161                 ret['dbm-0'] = params['io:wifinetworks-io:wifinetwork-io:signalinfo-wifi:dbm']
162                 ret['encryptiontype-0'] = params['io:wifinetworks-io:wifinetwork-wifi:encryptiontype']
163                 ret['signalstrength-0'] = params['io:wifinetworks-io:wifinetwork-io:signalinfo-wifi:signalstrength']                
164             except KeyError, e:
165                 log.error("Missing response key: %s" % e)  
166         else:
167             for a in xrange(elementCount):
168                 try:                
169                     ssid = str(params['io:wifinetworks-io:wifinetwork-wifi:ssid-%d' % a]).decode("hex")
170                     if not ssid:
171                         ret['ssid-%d' % a] = u'(unknown)'
172                     else:
173                         ret['ssid-%d' % a] = ssid
174                     ret['bssid-%d' % a] = str(params['io:wifinetworks-io:wifinetwork-wifi:bssid-%d' % a]).decode("hex")
175                     ret['channel-%d' % a] = params['io:wifinetworks-io:wifinetwork-wifi:channel-%d' % a]
176                     ret['communicationmode-%d' % a] = params['io:wifinetworks-io:wifinetwork-wifi:communicationmode-%d' % a]
177                     ret['dbm-%d' % a] = params['io:wifinetworks-io:wifinetwork-io:signalinfo-wifi:dbm-%d' % a]
178                     ret['encryptiontype-%d' % a] = params['io:wifinetworks-io:wifinetwork-wifi:encryptiontype-%d' % a]
179                     ret['signalstrength-%d' % a] = params['io:wifinetworks-io:wifinetwork-io:signalinfo-wifi:signalstrength-%d' % a]                        
180                 
181                 except KeyError, e:
182                     log.error("Missing response key: %s" % e)  
183                 try:                    
184                     ret['signalstrengthmax'] = 5
185                     ret['signalstrengthmin'] = 0
186                 except KeyError, e:
187                     log.debug("Missing response key: %s" % e)       
188     return ret    
189
190 def getIPConfiguration(dev, adapterName):
191     ip, hostname, addressmode, subnetmask, gateway, pridns, sec_dns = \
192         '0.0.0.0', 'Unknown', 'Unknown', '0.0.0.0', '0.0.0.0', '0.0.0.0', '0.0.0.0'
193     
194     URI = LEDM_WIFI_BASE_URI + adapterName + "/Protocols"
195     params,code,elementCount = {},HTTP_ERROR,0  
196     max_tries = 0
197
198     while max_tries < MAX_RETRIES:
199         max_tries +=1
200         params,code,elementCount = readXmlDataFromURI(dev,URI,'<io:Protocol', '<io:Protocol')
201         if code == HTTP_OK:
202             break 
203      
204     if code != HTTP_OK:
205         log.error("Request Failed With Response Code %d" %code)
206         return ip, hostname, addressmode, subnetmask, gateway, pridns, sec_dns
207   
208     if params is not None and code == HTTP_OK:
209         try:
210             ip = params['io:protocols-io:protocol-io:addresses-io:ipv4addresses-io:ipv4address-dd:ipv4address']            
211             subnetmask = params['io:protocols-io:protocol-io:addresses-io:ipv4addresses-io:ipv4address-dd:subnetmask']
212             gateway = params['io:protocols-io:protocol-io:addresses-io:ipv4addresses-io:ipv4address-dd:defaultgateway']
213             
214             if 'DHCP' in params['io:protocols-io:protocol-io:addresses-io:ipv4addresses-io:ipv4address-dd:configmethod']:
215                 addressmode = 'dhcp'
216             else:
217                 addressmode = 'autoip'    
218             if elementCount ==1:
219                 pridns = params['io:protocols-io:protocol-dd:dnsserveripaddress']
220                 sec_dns = params['io:protocols-io:protocol-dd:secondarydnsserveripaddress']          
221             for a in xrange(elementCount):
222                 if params['io:protocols-io:protocol-dd:dnsserveripaddress-%d' %a] !="::":
223                     pridns = params['io:protocols-io:protocol-dd:dnsserveripaddress-%d' %a]
224                     sec_dns = params['io:protocols-io:protocol-dd:secondarydnsserveripaddress-%d' %a]
225                     break
226         except KeyError, e:
227             log.error("Missing response key: %s" % str(e))        
228
229     return ip, hostname, addressmode, subnetmask, gateway, pridns, sec_dns  
230
231
232 def getCryptoSuite(dev, adapterName):
233     alg, mode, secretid = '', '', ''
234     parms,code,elementCount ={},HTTP_ERROR,0
235     URI = LEDM_WIFI_BASE_URI + adapterName + "/Profiles/Active"
236     max_tries = 0
237     
238     while max_tries < MAX_RETRIES:
239         max_tries +=1
240         parms,code,elementCount = readXmlDataFromURI(dev,URI,'<io:Profile', '<io:Profile')
241         if code == HTTP_OK:
242             break 
243     
244     if code !=HTTP_OK:
245         log.error("Request Failed With Response Code %d" %code)
246         return  alg, mode, secretid
247
248     if parms is not None:        
249         try:
250             mode = parms['io:profile-io:adapterprofile-io:wifiprofile-wifi:communicationmode']
251             alg = parms['io:profile-io:adapterprofile-io:wifiprofile-wifi:encryptiontype']
252             secretid = parms['io:profile-io:adapterprofile-io:wifiprofile-wifi:bssid']    
253         except KeyError, e:
254             log.error("Missing response key: %s" % str(e))
255     
256     return  alg, mode, secretid
257
258
259 def associate(dev, adapterName, ssid, communication_mode, encryption_type, key):
260     ret,code = {},HTTP_ERROR    
261     URI = LEDM_WIFI_BASE_URI + adapterName + "/Profiles/Active"
262
263     if encryption_type == 'none':
264         authMode = 'open'
265         ppXml = passPhraseXml%(ssid.encode('hex'),communication_mode,encryption_type,authMode)
266     else:
267         authMode = encryption_type
268         pos = passPhraseXml.find("</io:WifiProfile>",0,len(passPhraseXml))
269         ppXml = (passPhraseXml[:pos] + keyInfoXml + passPhraseXml[pos:])%(ssid.encode('hex'),communication_mode,encryption_type,\
270         authMode,key.encode('hex'))        
271
272     code = writeXmlDataToURI(dev,URI,ppXml,10)    
273     ret['errorreturn'] = code
274     if not(code == HTTP_OK or HTTP_NOCONTENT):
275         log.error("Request Failed With Response Code %d" % ret['errorreturn'])
276     
277     return ret
278
279
280 def getVSACodes(dev, adapterName):
281     ret,params,code,elementCount = [],{},HTTP_ERROR,0
282     severity,rule ='',''
283     URI = LEDM_WIFI_BASE_URI + adapterName + "/VsaCodes.xml"
284     max_tries = 0
285     
286     while max_tries < MAX_RETRIES:
287         max_tries +=1
288         params,code,elementCount = readXmlDataFromURI(dev,URI,"<io:VsaCodes","<io:VsaCodes",10)
289         if code == HTTP_OK:
290             break
291     
292     if code != HTTP_OK:
293         log.error("Request Failed With Response Code %d"%code)
294         return ret
295  
296     if params is not None:
297         try:
298             severity= params['io:vsacodes-wifi:vsacode-dd:severity']
299         except:
300             severity = ""
301         try:
302             rule = params['io:vsacodes-wifi:vsacode-wifi:rulenumber']            
303        # except KeyError, e:
304            # log.error("Missing response key: %s" % str(e))
305         except:
306             rule = ""
307         ret.append((rule, severity))       
308     return ret  
309
310
311 def getHostname(dev):
312     hostName = ''
313     URI = "/IoMgmt/IoConfig.xml"
314     max_tries = 0
315     
316     while max_tries < MAX_RETRIES:
317         max_tries +=1
318         params,code,elementCount = readXmlDataFromURI(dev,URI,'<io:IoConfig', '<io:IoConfig')        
319         if code == HTTP_OK:
320             break    
321     
322     if code != HTTP_OK:
323         log.error("Request failed with Response code %d"%code)
324         return hostName
325        
326     if params is not None:        
327         try:               
328             hostName = params['io:ioconfig-io:iodeviceconfig-dd3:hostname']            
329         except KeyError, e:
330             log.error("Missing response key: %s" % e)
331
332     return  hostName
333
334 def getSignalStrength(dev, adapterName, ssid, adaptor_id=0):
335     ss_max, ss_min, ss_val, ss_dbm = 5, 0, 0, -200
336     params,code,elementCount = {},HTTP_ERROR,0
337
338     if ssid is not None:      
339         URI = LEDM_WIFI_BASE_URI + adapterName + "/WifiNetworks/SSID="+ssid 
340     else:
341         return ss_max, ss_min, ss_val, ss_dbm
342
343     while True:            
344         params,code,elementCount = readXmlDataFromURI(dev,URI,'<io:WifiNetworks', '<io:WifiNetwork>',10)        
345         if code == HTTP_ACCEPTED:
346             log.info("Got Response as HTTP_ACCEPTED, so retrying to get the actual result")
347             continue
348         else:
349             break  
350
351     if code != HTTP_OK:
352         log.error("Request Failed With Response Code %d"%code)
353         return ss_max, ss_min, ss_val, ss_dbm
354        
355     if params is not None:        
356         if elementCount == 1:
357             try:                
358                 ss_dbm = params['io:wifinetworks-io:wifinetwork-io:signalinfo-wifi:dbm']                
359                 ss_val = params['io:wifinetworks-io:wifinetwork-io:signalinfo-wifi:signalstrength']                
360             except KeyError, e:
361                 log.error("Missing response key: %s" % e)
362
363     return  ss_max, ss_min, ss_val, ss_dbm
364
365
366 def readXmlDataFromURI(dev,URI,xmlRootNode,xmlChildNode,timeout=5):
367     params,code,elementCount ={},HTTP_ERROR,0 
368     
369     data = format_http_get(URI,0,"")
370     log.info(data)
371     response = cStringIO.StringIO()
372     if dev.openLEDM() == -1:
373         dev.openEWS_LEDM()
374         dev.writeEWS_LEDM(data)
375         try:
376             while dev.readEWS_LEDM(1024, response, timeout):
377                 pass
378         except Error:
379             dev.closeEWS_LEDM()
380             log.error("Unable to read EWS_LEDM Channel")
381     else:
382         dev.writeLEDM(data)
383
384     #response = cStringIO.StringIO()
385         try:
386             while dev.readLEDM(1024, response, timeout):
387                 pass
388         except Error:
389             dev.closeLEDM()
390             log.error("Unable to read LEDM Channel") 
391     #dev.closeEWS_LEDM()    
392     strResp = str(response.getvalue())
393     #log.error(strResp)
394     if strResp is not None:                             
395         code = get_error_code(strResp)        
396         pos = strResp.find(xmlRootNode,0,len(strResp))    
397         repstr = strResp[pos:].strip()
398         repstr = filter(lambda c: c not in "\r\t\n", repstr) # To remove formating characters from the received xml
399         repstr = repstr.rstrip('0')   # To remove trailing zero from the received xml
400         elementCount = repstr.count(xmlChildNode)                       
401         try:
402             params = utils.XMLToDictParser().parseXML(repstr)            
403         except xml.parsers.expat.ExpatError, e:
404             log.error("XML parser failed: %s" % e) 
405
406     return params,code,elementCount
407
408
409 def writeXmlDataToURI(dev,URI,xml,timeout=5):
410     code = HTTP_ERROR
411
412     data = format_http_put(URI,len(xml),xml)
413     response = cStringIO.StringIO()
414
415     if dev.openLEDM() == -1:
416         dev.openEWS_LEDM()
417         dev.writeEWS_LEDM(data)
418         try:
419             while dev.readEWS_LEDM(1000, response, timeout):
420                 pass
421         except Error:
422                 dev.closeEWS_LEDM()
423                 log.error("Unable to read EWS_LEDM Channel")
424             
425     else:
426         dev.writeLEDM(data)
427     #response = cStringIO.StringIO()
428         try:
429             while dev.readLEDM(1000, response, timeout):
430                 pass
431         except Error:
432             dev.closeLEDM()
433             log.error("Unable to read LEDM Channel") 
434         
435
436     strResp = str(response.getvalue())    
437     if strResp is not None:
438         code = get_error_code(strResp)           
439     return code
440
441
442 def get_error_code(ret):
443     if not ret: return HTTP_ERROR
444     match = http_result_pat.match(ret)
445     if match is None: return HTTP_ERROR
446     try:
447         code = int(match.group(1))
448     except (ValueError, TypeError):
449         code = HTTP_ERROR
450     return code
451
452
453 def format_http_get(requst, ledmlen, xmldata, content_type="text/xml; charset=utf-8"):
454     host = 'localhost'
455     return  utils.cat(
456 """GET $requst HTTP/1.1\r
457 Host: $host\r
458 User-Agent: hplip/3.0\r
459 Content-Type: $content_type\r
460 Content-Length: $ledmlen\r
461 \r
462 $xmldata""")
463
464
465 def format_http_put(requst, ledmlen, xmldata, content_type="text/xml; charset=utf-8"):
466     host = 'localhost'
467     return  utils.cat(
468 """PUT $requst HTTP/1.1\r
469 Host: $host\r
470 User-Agent: hplip/3.0\r
471 Content-Type: $content_type\r
472 Content-Length: $ledmlen\r
473 \r
474 $xmldata""")    
475