| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- # SPDX-License-Identifier: LGPL-2.1-or-later
- """ Copyright (C) 2010-2011 ST-Ericsson SA """
- """ Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson. """
- from array import array
- from bluetooth import *
- import time
- import re
- class SAPParam:
- """ SAP Parameter Class """
- MaxMsgSize = 0x00
- ConnectionStatus = 0x01
- ResultCode = 0x02
- DisconnectionType = 0x03
- CommandAPDU = 0x04
- ResponseAPDU = 0x05
- ATR = 0x06
- CardReaderStatus = 0x07
- StatusChange = 0x08
- TransportProtocol = 0x09
- CommandAPDU7816 = 0x10
- def __init__(self, name, id, value = None):
- self.name = name
- self.id = id
- self.value = value
- def _padding(self, buf):
- pad = array('B')
- while ( (len(buf) + len(pad)) % 4 ) != 0:
- pad.append(0)
- return pad
- def _basicCheck(self, buf):
- if len(buf) < 4 or (len(buf) % 4) != 0 or buf[1] != 0:
- return (-1, -1)
- if buf[0] != self.id:
- return (-1, -1)
- plen = buf[2] * 256 + buf[3] + 4
- if plen > len(buf):
- return (-1, -1)
- pad = plen
- while (pad % 4) != 0:
- if buf[pad] != 0:
- return (-1, -1)
- pad+=1
- return (plen, pad)
- def getID(self):
- return self.id
- def getValue(self):
- return self.value
- def getContent(self):
- return "%s(id=0x%.2X), value=%s \n" % (self.name, self.id, self.value)
- def serialize(self):
- a = array('B', '\00\00\00\00')
- a[0] = self.id
- a[1] = 0 # reserved
- a[2] = 0 # length
- a[3] = 1 # length
- a.append(self.value)
- a.extend(self._padding(a))
- return a
- def deserialize(self, buf):
- p = self._basicCheck(buf)
- if p[0] == -1:
- return -1
- self.id = buf[0]
- self.value = buf[4]
- return p[1]
- class SAPParam_MaxMsgSize(SAPParam):
- """MaxMsgSize Param """
- def __init__(self, value = None):
- SAPParam.__init__(self,"MaxMsgSize", SAPParam.MaxMsgSize, value)
- self.__validate()
- def __validate(self):
- if self.value > 0xFFFF:
- self.value = 0xFFFF
- def serialize(self):
- a = array('B', '\00\00\00\00')
- a[0] = self.id
- a[3] = 2
- a.append(self.value / 256)
- a.append(self.value % 256)
- a.extend(self._padding(a))
- return a
- def deserialize(self, buf):
- p = self._basicCheck(buf)
- if p[0] == -1 :
- return -1
- self.value = buf[4] * 256 + buf[5]
- return p[1]
- class SAPParam_CommandAPDU(SAPParam):
- def __init__(self, value = None):
- if value is None:
- SAPParam.__init__(self, "CommandAPDU", SAPParam.CommandAPDU, array('B'))
- else:
- SAPParam.__init__(self, "CommandAPDU", SAPParam.CommandAPDU, array('B', value))
- def serialize(self):
- a = array('B', '\00\00\00\00')
- a[0] = self.id
- plen = len(self.value)
- a[2] = plen / 256
- a[3] = plen % 256
- a.extend(self.value)
- a.extend(self._padding(a))
- return a
- def deserialize(self, buf):
- p = self._basicCheck(buf)
- if p[0] == -1:
- return -1
- self.value = buf[4:p[0]]
- return p[1]
- class SAPParam_ResponseAPDU(SAPParam_CommandAPDU):
- """ResponseAPDU Param """
- def __init__(self, value = None):
- if value is None:
- SAPParam.__init__(self, "ResponseAPDU", SAPParam.ResponseAPDU, array('B'))
- else:
- SAPParam.__init__(self, "ResponseAPDU", SAPParam.ResponseAPDU, array('B', value))
- class SAPParam_ATR(SAPParam_CommandAPDU):
- """ATR Param """
- def __init__(self, value = None):
- if value is None:
- SAPParam.__init__(self, "ATR", SAPParam.ATR, array('B'))
- else:
- SAPParam.__init__(self, "ATR", SAPParam.ATR, array('B', value))
- class SAPParam_CommandAPDU7816(SAPParam_CommandAPDU):
- """Command APDU7816 Param."""
- def __init__(self, value = None):
- if value is None:
- SAPParam.__init__(self, "CommandAPDU7816", SAPParam.CommandAPDU7816, array('B'))
- else:
- SAPParam.__init__(self, "CommandAPDU7816", SAPParam.CommandAPDU7816, array('B', value))
- class SAPParam_ConnectionStatus(SAPParam):
- """Connection status Param."""
- def __init__(self, value = None):
- SAPParam.__init__(self,"ConnectionStatus", SAPParam.ConnectionStatus, value)
- self.__validate()
- def __validate(self):
- if self.value is not None and self.value not in (0x00, 0x01, 0x02, 0x03, 0x04):
- print "Warning. ConnectionStatus value in reserved range (0x%x)" % self.value
- def deserialize(self, buf):
- ret = SAPParam.deserialize(self, buf)
- if ret == -1:
- return -1
- self.__validate()
- return ret
- class SAPParam_ResultCode(SAPParam):
- """ Result Code Param """
- def __init__(self, value = None):
- SAPParam.__init__(self,"ResultCode", SAPParam.ResultCode, value)
- self.__validate()
- def __validate(self):
- if self.value is not None and self.value not in (0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07):
- print "Warning. ResultCode value in reserved range (0x%x)" % self.value
- def deserialize(self, buf):
- ret = SAPParam.deserialize(self, buf)
- if ret == -1:
- return -1
- self.__validate()
- return ret
- class SAPParam_DisconnectionType(SAPParam):
- """Disconnection Type Param."""
- def __init__(self, value = None):
- SAPParam.__init__(self,"DisconnectionType", SAPParam.DisconnectionType, value)
- self.__validate()
- def __validate(self):
- if self.value is not None and self.value not in (0x00, 0x01):
- print "Warning. DisconnectionType value in reserved range (0x%x)" % self.value
- def deserialize(self, buf):
- ret = SAPParam.deserialize(self, buf)
- if ret == -1:
- return -1
- self.__validate()
- return ret
- class SAPParam_CardReaderStatus(SAPParam_CommandAPDU):
- """Card reader Status Param."""
- def __init__(self, value = None):
- if value is None:
- SAPParam.__init__(self, "CardReaderStatus", SAPParam.CardReaderStatus, array('B'))
- else:
- SAPParam.__init__(self, "CardReaderStatus", SAPParam.CardReaderStatus, array('B', value))
- class SAPParam_StatusChange(SAPParam):
- """Status Change Param """
- def __init__(self, value = None):
- SAPParam.__init__(self,"StatusChange", SAPParam.StatusChange, value)
- def __validate(self):
- if self.value is not None and self.value not in (0x00, 0x01, 0x02, 0x03, 0x04, 0x05):
- print "Warning. StatusChange value in reserved range (0x%x)" % self.value
- def deserialize(self, buf):
- ret = SAPParam.deserialize(self, buf)
- if ret == -1:
- return -1
- self.__validate()
- return ret
- class SAPParam_TransportProtocol(SAPParam):
- """Transport Protocol Param """
- def __init__(self, value = None):
- SAPParam.__init__(self,"TransportProtocol", SAPParam.TransportProtocol, value)
- self.__validate()
- def __validate(self):
- if self.value is not None and self.value not in (0x00, 0x01):
- print "Warning. TransportProtoco value in reserved range (0x%x)" % self.value
- def deserialize(self, buf):
- ret = SAPParam.deserialize(self, buf)
- if ret == -1:
- return -1
- self.__validate()
- return ret
- class SAPMessage:
- CONNECT_REQ = 0x00
- CONNECT_RESP = 0x01
- DISCONNECT_REQ = 0x02
- DISCONNECT_RESP =0x03
- DISCONNECT_IND = 0x04
- TRANSFER_APDU_REQ = 0x05
- TRANSFER_APDU_RESP = 0x06
- TRANSFER_ATR_REQ = 0x07
- TRANSFER_ATR_RESP = 0x08
- POWER_SIM_OFF_REQ = 0x09
- POWER_SIM_OFF_RESP = 0x0A
- POWER_SIM_ON_REQ = 0x0B
- POWER_SIM_ON_RESP = 0x0C
- RESET_SIM_REQ = 0x0D
- RESET_SIM_RESP = 0x0E
- TRANSFER_CARD_READER_STATUS_REQ = 0x0F
- TRANSFER_CARD_READER_STATUS_RESP = 0x10
- STATUS_IND = 0x11
- ERROR_RESP = 0x12
- SET_TRANSPORT_PROTOCOL_REQ = 0x13
- SET_TRANSPORT_PROTOCOL_RESP = 0x14
- def __init__(self, name, id):
- self.name = name
- self.id = id
- self.params = []
- self.buf = array('B')
- def _basicCheck(self, buf):
- if len(buf) < 4 or (len(buf) % 4) != 0 :
- return False
- if buf[0] != self.id:
- return False
- return True
- def getID(self):
- return self.id
- def getContent(self):
- s = "%s(id=0x%.2X) " % (self.name, self.id)
- if len( self.buf): s = s + "[%s]" % re.sub("(.{2})", "0x\\1 " , self.buf.tostring().encode("hex").upper(), re.DOTALL)
- s = s + "\n\t"
- for p in self.params:
- s = s + "\t" + p.getContent()
- return s
- def getParams(self):
- return self.params
- def addParam(self, param):
- self.params.append(param)
- def serialize(self):
- ret = array('B', '\00\00\00\00')
- ret[0] = self.id
- ret[1] = len(self.params)
- ret[2] = 0 # reserved
- ret[3] = 0 # reserved
- for p in self.params:
- ret.extend(p.serialize())
- self.buf = ret
- return ret
- def deserialize(self, buf):
- self.buf = buf
- return len(buf) == 4 and buf[1] == 0 and self._basicCheck(buf)
- class SAPMessage_CONNECT_REQ(SAPMessage):
- def __init__(self, MaxMsgSize = None):
- SAPMessage.__init__(self,"CONNECT_REQ", SAPMessage.CONNECT_REQ)
- if MaxMsgSize is not None:
- self.addParam(SAPParam_MaxMsgSize(MaxMsgSize))
- def _validate(self):
- if len(self.params) == 1:
- if self.params[0].getID() == SAPParam.MaxMsgSize:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_MaxMsgSize()
- if p.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_CONNECT_RESP(SAPMessage):
- def __init__(self, ConnectionStatus = None, MaxMsgSize = None):
- SAPMessage.__init__(self,"CONNECT_RESP", SAPMessage.CONNECT_RESP)
- if ConnectionStatus is not None:
- self.addParam(SAPParam_ConnectionStatus(ConnectionStatus))
- if MaxMsgSize is not None:
- self.addParam(SAPParam_MaxMsgSize(MaxMsgSize))
- def _validate(self):
- if len(self.params) > 0:
- if self.params[0] .getID() == SAPParam.ConnectionStatus:
- if self.params[0].getValue() == 0x02:
- if len(self.params) == 2:
- return True
- else:
- if len(self.params) == 1:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_ConnectionStatus()
- r = p.deserialize(buf[4:])
- if r != -1:
- self.addParam(p)
- if buf[1] == 2:
- p = SAPParam_MaxMsgSize()
- r = p.deserialize(buf[4+r:])
- if r != -1:
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_DISCONNECT_REQ(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"DISCONNECT_REQ", SAPMessage.DISCONNECT_REQ)
- class SAPMessage_DISCONNECT_RESP(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"DISCONNECT_RESP", SAPMessage.DISCONNECT_RESP)
- class SAPMessage_DISCONNECT_IND(SAPMessage):
- def __init__(self, Type = None):
- SAPMessage.__init__(self,"DISCONNECT_IND", SAPMessage.DISCONNECT_IND)
- if Type is not None:
- self.addParam(SAPParam_DisconnectionType(Type))
- def _validate(self):
- if len(self.params) == 1:
- if self.params[0].getID() == SAPParam.DisconnectionType:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_DisconnectionType()
- if p.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_TRANSFER_APDU_REQ(SAPMessage):
- def __init__(self, APDU = None, T = False):
- SAPMessage.__init__(self,"TRANSFER_APDU_REQ", SAPMessage.TRANSFER_APDU_REQ)
- if APDU is not None:
- if T :
- self.addParam(SAPParam_CommandAPDU(APDU))
- else:
- self.addParam(SAPParam_CommandAPDU7816(APDU))
- def _validate(self):
- if len(self.params) == 1:
- if self.params[0].getID() == SAPParam.CommandAPDU or self.params[0].getID() == SAPParam.CommandAPDU7816:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_CommandAPDU()
- p2 = SAPParam_CommandAPDU7816()
- if p.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p)
- return self._validate()
- elif p2.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p2)
- return self._validate()
- return False
- class SAPMessage_TRANSFER_APDU_RESP(SAPMessage):
- def __init__(self, ResultCode = None, Response = None):
- SAPMessage.__init__(self,"TRANSFER_APDU_RESP", SAPMessage.TRANSFER_APDU_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- if Response is not None:
- self.addParam(SAPParam_ResponseAPDU(Response))
- def _validate(self):
- if len(self.params) > 0:
- if self.params[0] .getID() == SAPParam.ResultCode:
- if self.params[0].getValue() == 0x00:
- if len(self.params) == 2:
- return True
- else:
- if len(self.params) == 1:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_ResultCode()
- r = p.deserialize(buf[4:])
- if r != -1:
- self.addParam(p)
- if buf[1] == 2:
- p = SAPParam_ResponseAPDU()
- r = p.deserialize(buf[4+r:])
- if r != -1:
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_TRANSFER_ATR_REQ(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"TRANSFER_ATR_REQ", SAPMessage.TRANSFER_ATR_REQ)
- class SAPMessage_TRANSFER_ATR_RESP(SAPMessage):
- def __init__(self, ResultCode = None, ATR = None):
- SAPMessage.__init__(self,"TRANSFER_ATR_RESP", SAPMessage.TRANSFER_ATR_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- if ATR is not None:
- self.addParam(SAPParam_ATR(ATR))
- def _validate(self):
- if len(self.params) > 0:
- if self.params[0] .getID() == SAPParam.ResultCode:
- if self.params[0].getValue() == 0x00:
- if len(self.params) == 2:
- return True
- else:
- if len(self.params) == 1:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_ResultCode()
- r = p.deserialize(buf[4:])
- if r != -1:
- self.addParam(p)
- if buf[1] == 2:
- p = SAPParam_ATR()
- r = p.deserialize(buf[4+r:])
- if r != -1:
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_POWER_SIM_OFF_REQ(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"POWER_SIM_OFF_REQ", SAPMessage.POWER_SIM_OFF_REQ)
- class SAPMessage_POWER_SIM_OFF_RESP(SAPMessage):
- def __init__(self, ResultCode = None):
- SAPMessage.__init__(self,"POWER_SIM_OFF_RESP", SAPMessage.POWER_SIM_OFF_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- def _validate(self):
- if len(self.params) == 1:
- if self.params[0].getID() == SAPParam.ResultCode:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_ResultCode()
- if p.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_POWER_SIM_ON_REQ(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"POWER_SIM_ON_REQ", SAPMessage.POWER_SIM_ON_REQ)
- class SAPMessage_POWER_SIM_ON_RESP(SAPMessage_POWER_SIM_OFF_RESP):
- def __init__(self, ResultCode = None):
- SAPMessage.__init__(self,"POWER_SIM_ON_RESP", SAPMessage.POWER_SIM_ON_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- class SAPMessage_RESET_SIM_REQ(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"RESET_SIM_REQ", SAPMessage.RESET_SIM_REQ)
- class SAPMessage_RESET_SIM_RESP(SAPMessage_POWER_SIM_OFF_RESP):
- def __init__(self, ResultCode = None):
- SAPMessage.__init__(self,"RESET_SIM_RESP", SAPMessage.RESET_SIM_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- class SAPMessage_STATUS_IND(SAPMessage):
- def __init__(self, StatusChange = None):
- SAPMessage.__init__(self,"STATUS_IND", SAPMessage.STATUS_IND)
- if StatusChange is not None:
- self.addParam(SAPParam_StatusChange(StatusChange))
- def _validate(self):
- if len(self.params) == 1:
- if self.params[0].getID() == SAPParam.StatusChange:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_StatusChange()
- if p.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_TRANSFER_CARD_READER_STATUS_REQ(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"TRANSFER_CARD_READER_STATUS_REQ", SAPMessage.TRANSFER_CARD_READER_STATUS_REQ)
- class SAPMessage_TRANSFER_CARD_READER_STATUS_RESP(SAPMessage):
- def __init__(self, ResultCode = None, Status = None):
- SAPMessage.__init__(self,"TRANSFER_CARD_READER_STATUS_RESP", SAPMessage.TRANSFER_CARD_READER_STATUS_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- if Status is not None:
- self.addParam(SAPParam_CardReaderStatus(Status))
- def _validate(self):
- if len(self.params) > 0:
- if self.params[0] .getID() == SAPParam.ResultCode:
- if self.params[0].getValue() == 0x00:
- if len(self.params) == 2:
- return True
- else:
- if len(self.params) == 1:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_ResultCode()
- r = p.deserialize(buf[4:])
- if r != -1:
- self.addParam(p)
- if buf[1] == 2:
- p = SAPParam_CardReaderStatus()
- r = p.deserialize(buf[4+r:])
- if r != -1:
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_ERROR_RESP(SAPMessage):
- def __init__(self):
- SAPMessage.__init__(self,"ERROR_RESP", SAPMessage.ERROR_RESP)
- class SAPMessage_SET_TRANSPORT_PROTOCOL_REQ(SAPMessage):
- def __init__(self, protocol = None):
- SAPMessage.__init__(self,"SET_TRANSPORT_PROTOCOL_REQ", SAPMessage.SET_TRANSPORT_PROTOCOL_REQ)
- if protocol is not None:
- self.addParam(SAPParam_TransportProtocol(protocol))
- def _validate(self):
- if len(self.params) == 1:
- if self.params[0].getID() == SAPParam.TransportProtocol:
- return True
- return False
- def deserialize(self, buf):
- self.buf = buf
- self.params[:] = []
- if SAPMessage._basicCheck(self, buf):
- p = SAPParam_TransportProtocol()
- if p.deserialize(buf[4:]) == len(buf[4:]):
- self.addParam(p)
- return self._validate()
- return False
- class SAPMessage_SET_TRANSPORT_PROTOCOL_RESP(SAPMessage_POWER_SIM_OFF_RESP):
- def __init__(self, ResultCode = None):
- SAPMessage.__init__(self,"SET_TRANSPORT_PROTOCOL_RESP", SAPMessage.SET_TRANSPORT_PROTOCOL_RESP)
- if ResultCode is not None:
- self.addParam(SAPParam_ResultCode(ResultCode))
- class SAPClient:
- CONNECTED = 1
- DISCONNECTED = 0
- uuid = "0000112D-0000-1000-8000-00805F9B34FB"
- bufsize = 1024
- timeout = 20
- state = DISCONNECTED
- def __init__(self, host = None, port = None):
- self.sock = None
- if host is None or is_valid_address(host):
- self.host = host
- else:
- raise BluetoothError ("%s is not a valid BT address." % host)
- self.host = None
- return
- if port is None:
- self.__discover()
- else:
- self.port = port
- self.__connectRFCOMM()
- def __del__(self):
- self.__disconnectRFCOMM()
- def __disconnectRFCOMM(self):
- if self.sock is not None:
- self.sock.close()
- self.state = self.DISCONNECTED
- def __discover(self):
- service_matches = find_service(self.uuid, self.host)
- if len(service_matches) == 0:
- raise BluetoothError ("No SAP service found")
- return
- first_match = service_matches[0]
- self.port = first_match["port"]
- self.host = first_match["host"]
- print "SAP Service found on %s(%s)" % first_match["name"] % self.host
- def __connectRFCOMM(self):
- self.sock=BluetoothSocket( RFCOMM )
- self.sock.connect((self.host, self.port))
- self.sock.settimeout(self.timeout)
- self.state = self.CONNECTED
- def __sendMsg(self, msg):
- if isinstance(msg, SAPMessage):
- s = msg.serialize()
- print "\tTX: " + msg.getContent()
- return self.sock.send(s.tostring())
- def __rcvMsg(self, msg):
- if isinstance(msg, SAPMessage):
- print "\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id)
- data = self.sock.recv(self.bufsize)
- if data:
- if msg.deserialize(array('B',data)):
- print "\tRX: len(%d) %s" % (len(data), msg.getContent())
- return msg
- else:
- print "msg: %s" % array('B',data)
- raise BluetoothError ("Message deserialization failed.")
- else:
- raise BluetoothError ("Timeout. No data received.")
- def connect(self):
- self.__connectRFCOMM()
- def disconnect(self):
- self.__disconnectRFCOMM()
- def isConnected(self):
- return self.state
- def proc_connect(self):
- try:
- self.__sendMsg(SAPMessage_CONNECT_REQ(self.bufsize))
- params = self.__rcvMsg(SAPMessage_CONNECT_RESP()).getParams()
- if params[0].getValue() in (0x00, 0x04):
- pass
- elif params[0].getValue() == 0x02:
- self.bufsize = params[1].getValue()
- self.__sendMsg(SAPMessage_CONNECT_REQ(self.bufsize))
- params = self.__rcvMsg(SAPMessage_CONNECT_RESP()).getParams()
- if params[0].getValue() not in (0x00, 0x04):
- return False
- else:
- return False
- params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
- if params[0].getValue() == 0x00:
- return False
- elif params[0].getValue() == 0x01:
- """OK, Card reset"""
- return self.proc_transferATR()
- elif params[0].getValue() == 0x02:
- """T0 not supported"""
- if self.proc_transferATR():
- return self.proc_setTransportProtocol(1)
- else:
- return False
- else:
- return False
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_disconnectByClient(self, timeout=0):
- try:
- self.__sendMsg(SAPMessage_DISCONNECT_REQ())
- self.__rcvMsg(SAPMessage_DISCONNECT_RESP())
- time.sleep(timeout) # let srv to close rfcomm
- self.__disconnectRFCOMM()
- return True
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_disconnectByServer(self, timeout=0):
- try:
- params = self.__rcvMsg(SAPMessage_DISCONNECT_IND()).getParams()
- """graceful"""
- if params[0].getValue() == 0x00:
- if not self.proc_transferAPDU():
- return False
- return self.proc_disconnectByClient(timeout)
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_transferAPDU(self, apdu = "Sample APDU command"):
- try:
- self.__sendMsg(SAPMessage_TRANSFER_APDU_REQ(apdu))
- params = self.__rcvMsg(SAPMessage_TRANSFER_APDU_RESP()).getParams()
- return True
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_transferATR(self):
- try:
- self.__sendMsg(SAPMessage_TRANSFER_ATR_REQ())
- params = self.__rcvMsg(SAPMessage_TRANSFER_ATR_RESP()).getParams()
- return True
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_powerSimOff(self):
- try:
- self.__sendMsg(SAPMessage_POWER_SIM_OFF_REQ())
- params = self.__rcvMsg(SAPMessage_POWER_SIM_OFF_RESP()).getParams()
- return True
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_powerSimOn(self):
- try:
- self.__sendMsg(SAPMessage_POWER_SIM_ON_REQ())
- params = self.__rcvMsg(SAPMessage_POWER_SIM_ON_RESP()).getParams()
- if params[0].getValue() == 0x00:
- return self.proc_transferATR()
- return True
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_resetSim(self):
- try:
- self.__sendMsg(SAPMessage_RESET_SIM_REQ())
- params = self.__rcvMsg(SAPMessage_RESET_SIM_RESP()).getParams()
- if params[0].getValue() == 0x00:
- return self.proc_transferATR()
- return True
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_reportStatus(self):
- try:
- params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_transferCardReaderStatus(self):
- try:
- self.__sendMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_REQ())
- params = self.__rcvMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_RESP()).getParams()
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_errorResponse(self):
- try:
- """ send malformed message, no mandatory maxmsgsize parameter"""
- self.__sendMsg(SAPMessage_CONNECT_REQ())
- params = self.__rcvMsg(SAPMessage_ERROR_RESP()).getParams()
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- def proc_setTransportProtocol(self, protocol = 0):
- try:
- self.__sendMsg(SAPMessage_SET_TRANSPORT_PROTOCOL_REQ(protocol))
- params = self.__rcvMsg(SAPMessage_SET_TRANSPORT_PROTOCOL_RESP()).getParams()
- if params[0].getValue() == 0x00:
- params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
- if params[0].getValue() in (0x01, 0x02):
- return self.proc_transferATR()
- else:
- return True
- """return False ???"""
- elif params[0].getValue == 0x07:
- """not supported"""
- return True
- """return False ???"""
- else:
- return False
- except BluetoothError , e:
- print "Error. " +str(e)
- return False
- if __name__ == "__main__":
- pass
|