tizen 2.3.1 release
[framework/connectivity/bluez.git] / test / sap_client.py
1 """ Copyright (C) 2010-2011 ST-Ericsson SA """
2
3 """ Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson. """
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """
18
19 from array import array
20 from bluetooth import *
21 import time
22 import re
23
24 class SAPParam:
25     """ SAP Parameter Class """
26
27     MaxMsgSize = 0x00
28     ConnectionStatus = 0x01
29     ResultCode = 0x02
30     DisconnectionType = 0x03
31     CommandAPDU = 0x04
32     ResponseAPDU = 0x05
33     ATR = 0x06
34     CardReaderStatus = 0x07
35     StatusChange = 0x08
36     TransportProtocol = 0x09
37     CommandAPDU7816 = 0x10
38
39     def __init__(self, name, id, value = None):
40         self.name = name
41         self.id = id
42         self.value = value
43
44     def _padding(self,  buf):
45         pad = array('B')
46         while ( (len(buf) + len(pad)) % 4 ) != 0:
47             pad.append(0)
48         return pad
49
50     def _basicCheck(self,  buf):
51         if len(buf) < 4 or (len(buf) % 4) != 0 or buf[1] != 0:
52                 return (-1,  -1)
53         if buf[0] != self.id:
54             return (-1,  -1)
55         plen = buf[2] * 256 + buf[3] + 4
56         if plen > len(buf):
57             return (-1,  -1)
58         pad = plen
59         while (pad % 4) != 0:
60             if buf[pad] != 0:
61                 return (-1,  -1)
62             pad+=1
63         return (plen,  pad)
64
65     def getID(self):
66         return self.id
67
68     def getValue(self):
69         return self.value
70
71     def getContent(self):
72         return "%s(id=0x%.2X), value=%s \n" %  (self.name,  self.id, self.value)
73
74     def serialize(self):
75         a = array('B', '\00\00\00\00')
76         a[0] = self.id
77         a[1] = 0        # reserved
78         a[2] = 0        # length
79         a[3] = 1        # length
80         a.append(self.value)
81         a.extend(self._padding(a))
82         return a
83
84     def deserialize(self,  buf):
85         p = self._basicCheck(buf)
86         if p[0] == -1:
87             return -1
88         self.id = buf[0]
89         self.value = buf[4]
90         return p[1]
91
92
93 class SAPParam_MaxMsgSize(SAPParam):
94     """MaxMsgSize Param """
95
96     def __init__(self,  value = None):
97         SAPParam.__init__(self,"MaxMsgSize",  SAPParam.MaxMsgSize, value)
98         self.__validate()
99
100     def __validate(self):
101         if self.value > 0xFFFF:
102              self.value = 0xFFFF
103
104     def serialize(self):
105         a = array('B', '\00\00\00\00')
106         a[0] = self.id
107         a[3] = 2
108         a.append(self.value / 256)
109         a.append(self.value % 256)
110         a.extend(self._padding(a))
111         return a
112
113     def deserialize(self,  buf):
114         p = self._basicCheck(buf)
115         if p[0] == -1 :
116             return -1
117         self.value = buf[4] * 256 + buf[5]
118         return p[1]
119
120 class SAPParam_CommandAPDU(SAPParam):
121     def __init__(self,  value = None):
122         if value is None:
123             SAPParam.__init__(self, "CommandAPDU",  SAPParam.CommandAPDU, array('B'))
124         else:
125             SAPParam.__init__(self, "CommandAPDU",  SAPParam.CommandAPDU, array('B', value))
126
127     def serialize(self):
128         a = array('B', '\00\00\00\00')
129         a[0] = self.id
130         plen = len(self.value)
131         a[2] = plen / 256
132         a[3] = plen % 256
133         a.extend(self.value)
134         a.extend(self._padding(a))
135         return a
136
137     def deserialize(self,  buf):
138         p = self._basicCheck(buf)
139         if p[0] == -1:
140             return -1
141         self.value = buf[4:p[0]]
142         return p[1]
143
144 class SAPParam_ResponseAPDU(SAPParam_CommandAPDU):
145     """ResponseAPDU Param """
146
147     def __init__(self,  value = None):
148         if value is None:
149             SAPParam.__init__(self, "ResponseAPDU",  SAPParam.ResponseAPDU, array('B'))
150         else:
151             SAPParam.__init__(self, "ResponseAPDU",  SAPParam.ResponseAPDU, array('B', value))
152
153 class SAPParam_ATR(SAPParam_CommandAPDU):
154     """ATR Param """
155
156     def __init__(self,  value = None):
157         if value is None:
158             SAPParam.__init__(self, "ATR",  SAPParam.ATR, array('B'))
159         else:
160             SAPParam.__init__(self, "ATR",  SAPParam.ATR, array('B', value))
161
162 class SAPParam_CommandAPDU7816(SAPParam_CommandAPDU):
163     """Command APDU7816 Param."""
164
165     def __init__(self,  value = None):
166         if value is None:
167             SAPParam.__init__(self, "CommandAPDU7816",  SAPParam.CommandAPDU7816, array('B'))
168         else:
169             SAPParam.__init__(self, "CommandAPDU7816",  SAPParam.CommandAPDU7816, array('B', value))
170
171
172 class SAPParam_ConnectionStatus(SAPParam):
173     """Connection status Param."""
174
175     def __init__(self,  value = None):
176         SAPParam.__init__(self,"ConnectionStatus",  SAPParam.ConnectionStatus, value)
177         self.__validate()
178
179     def __validate(self):
180         if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04):
181             print "Warning. ConnectionStatus value in reserved range (0x%x)" % self.value
182
183     def deserialize(self,  buf):
184         ret = SAPParam.deserialize(self, buf)
185         if ret == -1:
186             return -1
187         self.__validate()
188         return ret
189
190 class SAPParam_ResultCode(SAPParam):
191     """ Result Code Param """
192
193     def __init__(self,  value = None):
194         SAPParam.__init__(self,"ResultCode",  SAPParam.ResultCode, value)
195         self.__validate()
196
197     def __validate(self):
198         if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07):
199             print "Warning. ResultCode value in reserved range (0x%x)" % self.value
200
201     def deserialize(self,  buf):
202         ret = SAPParam.deserialize(self, buf)
203         if ret == -1:
204             return -1
205         self.__validate()
206         return ret
207
208 class SAPParam_DisconnectionType(SAPParam):
209     """Disconnection Type Param."""
210
211     def __init__(self,  value = None):
212         SAPParam.__init__(self,"DisconnectionType",  SAPParam.DisconnectionType, value)
213         self.__validate()
214
215     def __validate(self):
216         if self.value is not None and self.value not in (0x00,  0x01):
217             print "Warning. DisconnectionType value in reserved range (0x%x)" % self.value
218
219     def deserialize(self,  buf):
220         ret = SAPParam.deserialize(self, buf)
221         if ret == -1:
222             return -1
223         self.__validate()
224         return ret
225
226 class SAPParam_CardReaderStatus(SAPParam_CommandAPDU):
227     """Card reader Status Param."""
228
229     def __init__(self,  value = None):
230         if value is None:
231             SAPParam.__init__(self, "CardReaderStatus",  SAPParam.CardReaderStatus, array('B'))
232         else:
233             SAPParam.__init__(self, "CardReaderStatus",  SAPParam.CardReaderStatus, array('B', value))
234
235 class SAPParam_StatusChange(SAPParam):
236     """Status Change Param """
237
238     def __init__(self,  value = None):
239         SAPParam.__init__(self,"StatusChange",  SAPParam.StatusChange, value)
240
241     def __validate(self):
242         if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04,  0x05):
243             print "Warning. StatusChange value in reserved range (0x%x)" % self.value
244
245     def deserialize(self,  buf):
246         ret = SAPParam.deserialize(self, buf)
247         if ret == -1:
248             return -1
249         self.__validate()
250         return ret
251
252 class SAPParam_TransportProtocol(SAPParam):
253     """Transport Protocol Param """
254
255     def __init__(self,  value = None):
256         SAPParam.__init__(self,"TransportProtocol",  SAPParam.TransportProtocol, value)
257         self.__validate()
258
259     def __validate(self):
260         if self.value is not None and self.value not in (0x00,  0x01):
261             print "Warning. TransportProtoco value in reserved range (0x%x)" % self.value
262
263     def deserialize(self,  buf):
264         ret = SAPParam.deserialize(self, buf)
265         if ret == -1:
266             return -1
267         self.__validate()
268         return ret
269
270 class SAPMessage:
271
272     CONNECT_REQ = 0x00
273     CONNECT_RESP = 0x01
274     DISCONNECT_REQ = 0x02
275     DISCONNECT_RESP =0x03
276     DISCONNECT_IND = 0x04
277     TRANSFER_APDU_REQ = 0x05
278     TRANSFER_APDU_RESP = 0x06
279     TRANSFER_ATR_REQ = 0x07
280     TRANSFER_ATR_RESP = 0x08
281     POWER_SIM_OFF_REQ = 0x09
282     POWER_SIM_OFF_RESP = 0x0A
283     POWER_SIM_ON_REQ = 0x0B
284     POWER_SIM_ON_RESP = 0x0C
285     RESET_SIM_REQ = 0x0D
286     RESET_SIM_RESP = 0x0E
287     TRANSFER_CARD_READER_STATUS_REQ = 0x0F
288     TRANSFER_CARD_READER_STATUS_RESP = 0x10
289     STATUS_IND = 0x11
290     ERROR_RESP = 0x12
291     SET_TRANSPORT_PROTOCOL_REQ = 0x13
292     SET_TRANSPORT_PROTOCOL_RESP = 0x14
293
294     def __init__(self,  name,  id):
295         self.name = name
296         self.id = id
297         self.params = []
298         self.buf = array('B')
299
300     def _basicCheck(self,  buf):
301         if len(buf) < 4 or (len(buf) % 4) != 0 :
302             return False
303
304         if buf[0] != self.id:
305             return False
306
307         return True
308
309     def getID(self):
310         return self.id
311
312     def getContent(self):
313         s = "%s(id=0x%.2X) " % (self.name,  self.id)
314         if len( self.buf): s = s + "[%s]" % re.sub("(.{2})", "0x\\1 " , self.buf.tostring().encode("hex").upper(), re.DOTALL)
315         s = s + "\n\t"
316         for p in self.params:
317             s = s + "\t" + p.getContent()
318         return s
319
320     def getParams(self):
321         return self.params
322
323     def addParam(self,  param):
324         self.params.append(param)
325
326     def serialize(self):
327         ret = array('B', '\00\00\00\00')
328         ret[0] = self.id
329         ret[1] = len(self.params)
330         ret[2] = 0      # reserved
331         ret[3] = 0      # reserved
332         for p in self.params:
333             ret.extend(p.serialize())
334
335         self.buf = ret
336         return ret
337
338     def deserialize(self,  buf):
339         self.buf = buf
340         return len(buf) == 4 and buf[1] == 0 and self._basicCheck(buf)
341
342
343 class SAPMessage_CONNECT_REQ(SAPMessage):
344     def __init__(self,  MaxMsgSize = None):
345         SAPMessage.__init__(self,"CONNECT_REQ",  SAPMessage.CONNECT_REQ)
346         if MaxMsgSize is not None:
347             self.addParam(SAPParam_MaxMsgSize(MaxMsgSize))
348
349     def _validate(self):
350         if len(self.params) == 1:
351             if self.params[0].getID() == SAPParam.MaxMsgSize:
352                 return True
353         return False
354
355     def deserialize(self,  buf):
356         self.buf = buf
357         self.params[:] = []
358         if SAPMessage._basicCheck(self,  buf):
359             p = SAPParam_MaxMsgSize()
360             if p.deserialize(buf[4:]) == len(buf[4:]):
361                 self.addParam(p)
362                 return self._validate()
363
364         return False
365
366 class SAPMessage_CONNECT_RESP(SAPMessage):
367     def __init__(self,  ConnectionStatus = None,  MaxMsgSize = None):
368         SAPMessage.__init__(self,"CONNECT_RESP",  SAPMessage.CONNECT_RESP)
369         if ConnectionStatus is not None:
370             self.addParam(SAPParam_ConnectionStatus(ConnectionStatus))
371             if MaxMsgSize is not None:
372                 self.addParam(SAPParam_MaxMsgSize(MaxMsgSize))
373
374     def _validate(self):
375         if len(self.params) > 0:
376             if self.params[0] .getID() == SAPParam.ConnectionStatus:
377                 if self.params[0].getValue() ==  0x02:
378                     if len(self.params) == 2:
379                         return True
380                 else:
381                     if len(self.params) == 1:
382                         return True
383         return False
384
385     def deserialize(self,  buf):
386         self.buf = buf
387         self.params[:] = []
388
389         if SAPMessage._basicCheck(self,  buf):
390             p = SAPParam_ConnectionStatus()
391             r = p.deserialize(buf[4:])
392             if  r != -1:
393                 self.addParam(p)
394                 if buf[1] == 2:
395                     p = SAPParam_MaxMsgSize()
396                     r = p.deserialize(buf[4+r:])
397                     if r != -1:
398                         self.addParam(p)
399
400                 return self._validate()
401
402         return False
403
404 class SAPMessage_DISCONNECT_REQ(SAPMessage):
405     def __init__(self):
406         SAPMessage.__init__(self,"DISCONNECT_REQ",  SAPMessage.DISCONNECT_REQ)
407
408 class SAPMessage_DISCONNECT_RESP(SAPMessage):
409     def __init__(self):
410         SAPMessage.__init__(self,"DISCONNECT_RESP",  SAPMessage.DISCONNECT_RESP)
411
412 class SAPMessage_DISCONNECT_IND(SAPMessage):
413     def __init__(self,  Type = None):
414         SAPMessage.__init__(self,"DISCONNECT_IND",  SAPMessage.DISCONNECT_IND)
415         if Type is not None:
416             self.addParam(SAPParam_DisconnectionType(Type))
417
418     def _validate(self):
419         if len(self.params) == 1:
420             if self.params[0].getID() == SAPParam.DisconnectionType:
421                 return True
422         return False
423
424     def deserialize(self,  buf):
425         self.buf = buf
426         self.params[:] = []
427         if SAPMessage._basicCheck(self,  buf):
428             p = SAPParam_DisconnectionType()
429             if p.deserialize(buf[4:]) == len(buf[4:]):
430                 self.addParam(p)
431                 return self._validate()
432
433         return False
434
435
436 class SAPMessage_TRANSFER_APDU_REQ(SAPMessage):
437     def __init__(self,  APDU = None,  T = False):
438         SAPMessage.__init__(self,"TRANSFER_APDU_REQ",  SAPMessage.TRANSFER_APDU_REQ)
439         if APDU is not None:
440             if T :
441                 self.addParam(SAPParam_CommandAPDU(APDU))
442             else:
443                 self.addParam(SAPParam_CommandAPDU7816(APDU))
444
445     def _validate(self):
446         if len(self.params) == 1:
447             if self.params[0].getID() == SAPParam.CommandAPDU or self.params[0].getID() == SAPParam.CommandAPDU7816:
448                 return True
449         return False
450
451     def deserialize(self,  buf):
452         self.buf = buf
453         self.params[:] = []
454         if SAPMessage._basicCheck(self,  buf):
455
456             p = SAPParam_CommandAPDU()
457             p2 = SAPParam_CommandAPDU7816()
458             if p.deserialize(buf[4:]) == len(buf[4:]):
459                 self.addParam(p)
460                 return self._validate()
461             elif p2.deserialize(buf[4:]) == len(buf[4:]):
462                 self.addParam(p2)
463                 return self._validate()
464
465         return False
466
467 class SAPMessage_TRANSFER_APDU_RESP(SAPMessage):
468     def __init__(self,  ResultCode = None,  Response = None):
469         SAPMessage.__init__(self,"TRANSFER_APDU_RESP",  SAPMessage.TRANSFER_APDU_RESP)
470         if ResultCode is not None:
471             self.addParam(SAPParam_ResultCode(ResultCode))
472             if Response is not None:
473                 self.addParam(SAPParam_ResponseAPDU(Response))
474
475     def _validate(self):
476         if len(self.params) > 0:
477             if self.params[0] .getID() == SAPParam.ResultCode:
478                 if self.params[0].getValue() == 0x00:
479                     if len(self.params) == 2:
480                         return True
481                 else:
482                     if len(self.params) == 1:
483                         return True
484         return False
485
486     def deserialize(self,  buf):
487         self.buf = buf
488         self.params[:] = []
489
490         if SAPMessage._basicCheck(self,  buf):
491             p = SAPParam_ResultCode()
492             r = p.deserialize(buf[4:])
493             if  r != -1:
494                 self.addParam(p)
495                 if buf[1] == 2:
496                     p = SAPParam_ResponseAPDU()
497                     r = p.deserialize(buf[4+r:])
498                     if r != -1:
499                         self.addParam(p)
500
501                 return self._validate()
502
503         return False
504
505 class SAPMessage_TRANSFER_ATR_REQ(SAPMessage):
506     def __init__(self):
507         SAPMessage.__init__(self,"TRANSFER_ATR_REQ",  SAPMessage.TRANSFER_ATR_REQ)
508
509 class SAPMessage_TRANSFER_ATR_RESP(SAPMessage):
510     def __init__(self,  ResultCode = None,  ATR = None):
511         SAPMessage.__init__(self,"TRANSFER_ATR_RESP",  SAPMessage.TRANSFER_ATR_RESP)
512         if ResultCode is not None:
513             self.addParam(SAPParam_ResultCode(ResultCode))
514             if ATR is not None:
515                 self.addParam(SAPParam_ATR(ATR))
516
517     def _validate(self):
518         if len(self.params) > 0:
519             if self.params[0] .getID() == SAPParam.ResultCode:
520                 if self.params[0].getValue() == 0x00:
521                     if len(self.params) == 2:
522                         return True
523                 else:
524                     if len(self.params) == 1:
525                         return True
526         return False
527
528     def deserialize(self,  buf):
529         self.buf = buf
530         self.params[:] = []
531
532         if SAPMessage._basicCheck(self,  buf):
533
534             p = SAPParam_ResultCode()
535             r = p.deserialize(buf[4:])
536
537             if  r != -1:
538
539                 self.addParam(p)
540                 if buf[1] == 2:
541
542                     p = SAPParam_ATR()
543                     r = p.deserialize(buf[4+r:])
544                     if r != -1:
545                         self.addParam(p)
546
547                 return self._validate()
548
549         return False
550
551 class SAPMessage_POWER_SIM_OFF_REQ(SAPMessage):
552     def __init__(self):
553         SAPMessage.__init__(self,"POWER_SIM_OFF_REQ",  SAPMessage.POWER_SIM_OFF_REQ)
554
555 class SAPMessage_POWER_SIM_OFF_RESP(SAPMessage):
556     def __init__(self,  ResultCode = None):
557         SAPMessage.__init__(self,"POWER_SIM_OFF_RESP",  SAPMessage.POWER_SIM_OFF_RESP)
558         if ResultCode is not None:
559             self.addParam(SAPParam_ResultCode(ResultCode))
560
561     def _validate(self):
562         if len(self.params) == 1:
563             if self.params[0].getID() == SAPParam.ResultCode:
564                 return True
565         return False
566
567     def deserialize(self,  buf):
568         self.buf = buf
569         self.params[:] = []
570         if SAPMessage._basicCheck(self,  buf):
571             p = SAPParam_ResultCode()
572             if p.deserialize(buf[4:]) == len(buf[4:]):
573                 self.addParam(p)
574                 return self._validate()
575
576         return False
577
578 class SAPMessage_POWER_SIM_ON_REQ(SAPMessage):
579     def __init__(self):
580         SAPMessage.__init__(self,"POWER_SIM_ON_REQ",  SAPMessage.POWER_SIM_ON_REQ)
581
582 class SAPMessage_POWER_SIM_ON_RESP(SAPMessage_POWER_SIM_OFF_RESP):
583     def __init__(self,  ResultCode = None):
584         SAPMessage.__init__(self,"POWER_SIM_ON_RESP",  SAPMessage.POWER_SIM_ON_RESP)
585         if ResultCode is not None:
586             self.addParam(SAPParam_ResultCode(ResultCode))
587
588 class SAPMessage_RESET_SIM_REQ(SAPMessage):
589     def __init__(self):
590         SAPMessage.__init__(self,"RESET_SIM_REQ",  SAPMessage.RESET_SIM_REQ)
591
592 class SAPMessage_RESET_SIM_RESP(SAPMessage_POWER_SIM_OFF_RESP):
593     def __init__(self,  ResultCode = None):
594         SAPMessage.__init__(self,"RESET_SIM_RESP",  SAPMessage.RESET_SIM_RESP)
595         if ResultCode is not None:
596             self.addParam(SAPParam_ResultCode(ResultCode))
597
598 class SAPMessage_STATUS_IND(SAPMessage):
599     def __init__(self,  StatusChange = None):
600         SAPMessage.__init__(self,"STATUS_IND",  SAPMessage.STATUS_IND)
601         if StatusChange is not None:
602             self.addParam(SAPParam_StatusChange(StatusChange))
603
604     def _validate(self):
605         if len(self.params) == 1:
606             if self.params[0].getID() == SAPParam.StatusChange:
607                 return True
608         return False
609
610     def deserialize(self,  buf):
611         self.buf = buf
612         self.params[:] = []
613         if SAPMessage._basicCheck(self,  buf):
614             p = SAPParam_StatusChange()
615             if p.deserialize(buf[4:]) == len(buf[4:]):
616                 self.addParam(p)
617                 return self._validate()
618
619         return False
620
621 class SAPMessage_TRANSFER_CARD_READER_STATUS_REQ(SAPMessage):
622     def __init__(self):
623         SAPMessage.__init__(self,"TRANSFER_CARD_READER_STATUS_REQ",  SAPMessage.TRANSFER_CARD_READER_STATUS_REQ)
624
625 class SAPMessage_TRANSFER_CARD_READER_STATUS_RESP(SAPMessage):
626     def __init__(self,  ResultCode = None,  Status = None):
627         SAPMessage.__init__(self,"TRANSFER_CARD_READER_STATUS_RESP",  SAPMessage.TRANSFER_CARD_READER_STATUS_RESP)
628         if ResultCode is not None:
629             self.addParam(SAPParam_ResultCode(ResultCode))
630             if Status is not None:
631                 self.addParam(SAPParam_CardReaderStatus(Status))
632
633     def _validate(self):
634         if len(self.params) > 0:
635             if self.params[0] .getID() == SAPParam.ResultCode:
636                 if self.params[0].getValue() == 0x00:
637                     if len(self.params) == 2:
638                         return True
639                 else:
640                     if len(self.params) == 1:
641                         return True
642         return False
643
644     def deserialize(self,  buf):
645         self.buf = buf
646         self.params[:] = []
647
648         if SAPMessage._basicCheck(self,  buf):
649             p = SAPParam_ResultCode()
650             r = p.deserialize(buf[4:])
651             if  r != -1:
652                 self.addParam(p)
653                 if buf[1] == 2:
654                     p = SAPParam_CardReaderStatus()
655                     r = p.deserialize(buf[4+r:])
656                     if r != -1:
657                         self.addParam(p)
658
659                 return self._validate()
660
661         return False
662
663 class SAPMessage_ERROR_RESP(SAPMessage):
664     def __init__(self):
665         SAPMessage.__init__(self,"ERROR_RESP",  SAPMessage.ERROR_RESP)
666
667
668 class SAPMessage_SET_TRANSPORT_PROTOCOL_REQ(SAPMessage):
669     def __init__(self,  protocol = None):
670         SAPMessage.__init__(self,"SET_TRANSPORT_PROTOCOL_REQ",  SAPMessage.SET_TRANSPORT_PROTOCOL_REQ)
671         if protocol is not None:
672             self.addParam(SAPParam_TransportProtocol(protocol))
673
674     def _validate(self):
675         if len(self.params) == 1:
676             if self.params[0].getID() == SAPParam.TransportProtocol:
677                 return True
678         return False
679
680     def deserialize(self,  buf):
681         self.buf = buf
682         self.params[:] = []
683         if SAPMessage._basicCheck(self,  buf):
684             p = SAPParam_TransportProtocol()
685             if p.deserialize(buf[4:]) == len(buf[4:]):
686                 self.addParam(p)
687                 return self._validate()
688
689         return False
690
691 class SAPMessage_SET_TRANSPORT_PROTOCOL_RESP(SAPMessage_POWER_SIM_OFF_RESP):
692     def __init__(self,  ResultCode = None):
693         SAPMessage.__init__(self,"SET_TRANSPORT_PROTOCOL_RESP",  SAPMessage.SET_TRANSPORT_PROTOCOL_RESP)
694         if ResultCode is not None:
695             self.addParam(SAPParam_ResultCode(ResultCode))
696
697
698 class SAPClient:
699
700     CONNECTED = 1
701     DISCONNECTED = 0
702
703     uuid = "0000112D-0000-1000-8000-00805F9B34FB"
704     bufsize = 1024
705     timeout = 20
706     state = DISCONNECTED
707
708     def __init__(self,  host = None,  port = None):
709         self.sock = None
710
711         if host is None or is_valid_address(host):
712             self.host = host
713         else:
714             raise BluetoothError ("%s is not a valid BT address." % host)
715             self.host = None
716             return
717
718         if port is None:
719             self.__discover()
720         else:
721             self.port = port
722
723         self.__connectRFCOMM()
724
725     def __del__(self):
726         self.__disconnectRFCOMM()
727
728     def __disconnectRFCOMM(self):
729         if self.sock is not None:
730             self.sock.close()
731             self.state = self.DISCONNECTED
732
733     def __discover(self):
734         service_matches = find_service(self.uuid, self.host)
735
736         if len(service_matches) == 0:
737             raise BluetoothError ("No SAP service found")
738             return
739
740         first_match = service_matches[0]
741         self.port = first_match["port"]
742         self.host = first_match["host"]
743
744         print "SAP Service found on %s(%s)" % first_match["name"] % self.host
745
746     def __connectRFCOMM(self):
747         self.sock=BluetoothSocket( RFCOMM )
748         self.sock.connect((self.host, self.port))
749         self.sock.settimeout(self.timeout)
750         self.state = self.CONNECTED
751
752     def __sendMsg(self, msg):
753         if isinstance(msg,  SAPMessage):
754             s = msg.serialize()
755             print "\tTX: " + msg.getContent()
756             return self.sock.send(s.tostring())
757
758     def __rcvMsg(self,  msg):
759         if isinstance(msg,  SAPMessage):
760             print "\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id)
761             data = self.sock.recv(self.bufsize)
762             if data:
763                 if msg.deserialize(array('B',data)):
764                     print "\tRX: len(%d) %s" % (len(data), msg.getContent())
765                     return msg
766                 else:
767                     print "msg: %s" % array('B',data)
768                     raise BluetoothError ("Message deserialization failed.")
769             else:
770                 raise BluetoothError ("Timeout. No data received.")
771
772     def connect(self):
773         self.__connectRFCOMM()
774
775     def disconnect(self):
776         self.__disconnectRFCOMM()
777
778     def isConnected(self):
779         return self.state
780
781     def proc_connect(self):
782         try:
783             self.__sendMsg(SAPMessage_CONNECT_REQ(self.bufsize))
784             params = self.__rcvMsg(SAPMessage_CONNECT_RESP()).getParams()
785
786             if params[0].getValue() in (0x00,  0x04):
787                 pass
788             elif params[0].getValue() == 0x02:
789                 self.bufsize = params[1].getValue()
790
791                 self.__sendMsg(SAPMessage_CONNECT_REQ(self.bufsize))
792                 params = self.__rcvMsg(SAPMessage_CONNECT_RESP()).getParams()
793
794                 if params[0].getValue() not in (0x00,  0x04):
795                     return False
796             else:
797                 return False
798
799             params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
800             if params[0].getValue() == 0x00:
801                 return False
802             elif params[0].getValue() == 0x01:
803                 """OK, Card reset"""
804                 return self.proc_transferATR()
805             elif params[0].getValue() == 0x02:
806                 """T0 not supported"""
807                 if self.proc_transferATR():
808                     return self.proc_setTransportProtocol(1)
809                 else:
810                     return False
811             else:
812                 return False
813         except BluetoothError , e:
814             print "Error. " +str(e)
815             return False
816
817     def proc_disconnectByClient(self, timeout=0):
818         try:
819             self.__sendMsg(SAPMessage_DISCONNECT_REQ())
820             self.__rcvMsg(SAPMessage_DISCONNECT_RESP())
821             time.sleep(timeout) # let srv to close rfcomm
822             self.__disconnectRFCOMM()
823             return True
824         except BluetoothError , e:
825             print "Error. " +str(e)
826             return False
827
828     def proc_disconnectByServer(self, timeout=0):
829         try:
830             params = self.__rcvMsg(SAPMessage_DISCONNECT_IND()).getParams()
831
832             """graceful"""
833             if params[0].getValue() == 0x00:
834                 if not self.proc_transferAPDU():
835                     return False
836
837             return self.proc_disconnectByClient(timeout)
838
839         except BluetoothError , e:
840             print "Error. " +str(e)
841             return False
842
843     def proc_transferAPDU(self,  apdu = "Sample APDU command"):
844         try:
845             self.__sendMsg(SAPMessage_TRANSFER_APDU_REQ(apdu))
846             params = self.__rcvMsg(SAPMessage_TRANSFER_APDU_RESP()).getParams()
847             return True
848         except BluetoothError , e:
849             print "Error. " +str(e)
850             return False
851
852     def proc_transferATR(self):
853         try:
854             self.__sendMsg(SAPMessage_TRANSFER_ATR_REQ())
855             params = self.__rcvMsg(SAPMessage_TRANSFER_ATR_RESP()).getParams()
856             return True
857         except BluetoothError , e:
858             print "Error. " +str(e)
859             return False
860
861     def proc_powerSimOff(self):
862         try:
863             self.__sendMsg(SAPMessage_POWER_SIM_OFF_REQ())
864             params = self.__rcvMsg(SAPMessage_POWER_SIM_OFF_RESP()).getParams()
865             return True
866         except BluetoothError , e:
867             print "Error. " +str(e)
868             return False
869
870     def proc_powerSimOn(self):
871         try:
872             self.__sendMsg(SAPMessage_POWER_SIM_ON_REQ())
873             params = self.__rcvMsg(SAPMessage_POWER_SIM_ON_RESP()).getParams()
874             if params[0].getValue() == 0x00:
875                 return self.proc_transferATR()
876
877             return True
878         except BluetoothError , e:
879             print "Error. " +str(e)
880             return False
881
882     def proc_resetSim(self):
883         try:
884             self.__sendMsg(SAPMessage_RESET_SIM_REQ())
885             params = self.__rcvMsg(SAPMessage_RESET_SIM_RESP()).getParams()
886             if params[0].getValue() == 0x00:
887                 return self.proc_transferATR()
888
889             return True
890         except BluetoothError , e:
891             print "Error. " +str(e)
892             return False
893
894     def proc_reportStatus(self):
895         try:
896             params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
897         except BluetoothError , e:
898             print "Error. " +str(e)
899             return False
900
901     def proc_transferCardReaderStatus(self):
902         try:
903             self.__sendMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_REQ())
904             params = self.__rcvMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_RESP()).getParams()
905         except BluetoothError , e:
906             print "Error. " +str(e)
907             return False
908
909     def proc_errorResponse(self):
910         try:
911             """ send malformed message, no mandatory maxmsgsize parameter"""
912             self.__sendMsg(SAPMessage_CONNECT_REQ())
913
914             params = self.__rcvMsg(SAPMessage_ERROR_RESP()).getParams()
915         except BluetoothError , e:
916             print "Error. " +str(e)
917             return False
918
919     def proc_setTransportProtocol(self,  protocol = 0):
920         try:
921             self.__sendMsg(SAPMessage_SET_TRANSPORT_PROTOCOL_REQ(protocol))
922             params = self.__rcvMsg(SAPMessage_SET_TRANSPORT_PROTOCOL_RESP()).getParams()
923
924             if params[0].getValue() == 0x00:
925                 params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
926                 if params[0].getValue() in (0x01,  0x02):
927                     return self.proc_transferATR()
928                 else:
929                     return True
930                     """return False ???"""
931             elif params[0].getValue == 0x07:
932                 """not supported"""
933                 return True
934                 """return False ???"""
935             else:
936                 return False
937
938         except BluetoothError , e:
939             print "Error. " +str(e)
940             return False
941
942 if __name__ == "__main__":
943     pass