1 """ Copyright (C) 2010-2011 ST-Ericsson SA """ 2 3 """ Author: Szymon Janc <szymon.janc (a] 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 """gracefull""" 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 944