sap_client.py 29 KB

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