# -*- coding: utf-8 -*- | |
''' | |
Created on 2011-9-29 | |
读卡库程序 | |
@author: cheng.tang | |
''' | |
from ctypes import * | |
import codecs | |
class CardOperatorError(Exception): | |
def __init__(self,msg): | |
Exception.__init__(self,msg) | |
class py_decard: | |
MODE_ALL = 1 | |
MODE_IDLE = 0 | |
ERROR_RET_NONE = 0 | |
ERROR_RAISE_EXP = 1 | |
dll_handle = None | |
dll_name = 'dcrf32.dll' | |
device_handle = None | |
error_method = ERROR_RET_NONE | |
@staticmethod | |
def _do_load_dll(): | |
if py_decard.dll_handle <> None: | |
return | |
py_decard.dll_handle = windll.LoadLibrary(py_decard.dll_name) | |
@staticmethod | |
def setup(**kwdargs): | |
if kwdargs.has_key("error_method"): | |
py_decard.error_method = kwdargs["error_method"] | |
#################################################################### | |
def __init__(self): | |
py_decard._do_load_dll() | |
self.card_mode = 'contactless' | |
self.ic_port = 0 | |
def set_card_mode(self,mode='cotactless',icport=-1): | |
self.card_mode = mode | |
if self.card_mode <> 'contactless': | |
self.ic_port = icport | |
def setsamport(self,port): | |
self.sam_port = self._get_sam_port(port) | |
ats_buffer = create_string_buffer('\000' * 256) | |
ats_len = c_char('\000') | |
py_decard.dll_handle.dc_setcpu(py_decard.device_handle,self.sam_port) | |
ret = py_decard.dll_handle.dc_cpureset(py_decard.device_handle,byref(ats_len),ats_buffer) | |
if ret <> 0: | |
return self.error('CPUCard ats error') | |
l = ord(ats_len.value) | |
r = ats_buffer.raw[:l] | |
#print codecs.encode(r,'hex') | |
return r | |
def error(self,error): | |
if py_decard.error_method == py_decard.ERROR_RET_NONE: | |
return None | |
raise CardOperatorError(error) | |
def open_port(self,port,baud): | |
if py_decard.dll_handle == None: | |
raise RuntimeError( py_decard.dll_name + ' not load ') | |
if py_decard.device_handle <> None: | |
return True | |
dev_handle = py_decard.dll_handle.dc_init(port,baud) | |
if dev_handle <= 0: | |
return False | |
py_decard.device_handle = dev_handle | |
return True | |
def close_port(self): | |
if py_decard.device_handle == None: | |
return | |
py_decard.dll_handle.dc_exit(py_decard.device_handle) | |
py_decard.device_handle = None | |
def request_card(self): | |
if self.card_mode == 'contactless': | |
py_decard.dll_handle.dc_reset(py_decard.device_handle,1) | |
cardphyno = create_string_buffer('\000' * 64) | |
ret = py_decard.dll_handle.dc_card_hex(py_decard.device_handle, | |
py_decard.MODE_ALL, | |
cardphyno) | |
if ret == 0: | |
return cardphyno.value | |
return self.error('Request Card Error') | |
else: | |
return '' | |
def cpucard_ats(self): | |
ats_buffer = create_string_buffer('\000' * 256) | |
ats_len = c_char('\000') | |
if self.card_mode == 'contactless': | |
py_decard.dll_handle.dc_pro_reset.restype = c_short | |
ret = py_decard.dll_handle.dc_pro_reset(py_decard.device_handle,byref(ats_len),ats_buffer) | |
if ret <> 0: | |
return self.error('CPUCard ats error') | |
l = ord(ats_len.value) | |
r = ats_buffer.raw[:l] | |
#print codecs.encode(r,'hex') | |
return r | |
else: | |
py_decard.dll_handle.dc_setcpu(py_decard.device_handle,self._get_sam_port(self.ic_port)) | |
ret = py_decard.dll_handle.dc_cpureset(py_decard.device_handle,byref(ats_len),ats_buffer) | |
if ret <> 0: | |
return self.error('CPUCard ats error') | |
l = ord(ats_len.value) | |
r = ats_buffer.raw[:l] | |
#print codecs.encode(r,'hex') | |
return r | |
def _get_sam_port(self,port): | |
if port == 1: | |
return 0x0c | |
elif port == 2: | |
return 0x0d | |
elif port == 3: | |
return 0x0e | |
elif port == 4: | |
return 0x0f | |
else: | |
self.error('samport error') | |
def _do_apdu(self,command): | |
response = create_string_buffer('\000' * 256) | |
resplen = c_char('\000') | |
if self.card_mode == 'contactless': | |
py_decard.dll_handle.dc_pro_commandlink.restype = c_short | |
ret = py_decard.dll_handle.dc_pro_commandlink(py_decard.device_handle,len(command), | |
command,byref(resplen),response,7,56) | |
else: | |
ret = py_decard.dll_handle.dc_cpuapdu(py_decard.device_handle,len(command), | |
command,byref(resplen),response) | |
if ret <> 0: | |
command_header = codecs.encode(command,'hex') | |
return self.error('CPUCard apdu command : %s ,ret=%d' % (command_header,ret)) | |
return response.raw[:ord(resplen.value)] | |
def cpucard_apdu(self,command): | |
current_resp = self._do_apdu(command) | |
if ord(current_resp[-2]) == 0x61 and ord(current_resp[-1]) > 0x00: | |
cmd = '\x00\xC0\x00\x00' + current_resp[-1] | |
#print "get response : %s" % codecs.encode(cmd,'hex') | |
return self._do_apdu(cmd) | |
else: | |
return current_resp | |
def cpucard_apdu_hex(self,command): | |
cmd_result = command.replace(' ','') | |
resp = self.cpucard_apdu(codecs.decode(cmd_result,'hex')) | |
if resp == None: | |
return None | |
return codecs.encode(resp,'hex').upper() | |
def _do_sam_apdu(self,command): | |
response = create_string_buffer('\000' * 256) | |
resplen = c_char('\000') | |
ret = py_decard.dll_handle.dc_cpuapdu(py_decard.device_handle,len(command), | |
command,byref(resplen),response) | |
if ret <> 0: | |
command_header = codecs.encode(command,'hex') | |
return self.error('CPUCard apdu command : %s ,ret=%d' % (command_header,ret)) | |
return response.raw[:ord(resplen.value)] | |
def sam_apdu(self,command): | |
current_resp = self._do_sam_apdu(command) | |
if ord(current_resp[-2]) == 0x61 and ord(current_resp[-1]) > 0x00: | |
cmd = '\x00\xC0\x00\x00' + current_resp[-1] | |
#print "get response : %s" % codecs.encode(cmd,'hex') | |
return self._do_sam_apdu(cmd) | |
else: | |
return current_resp | |
def sam_apdu_hex(self,command): | |
cmd_result = command.replace(' ','') | |
resp = self.sam_apdu(codecs.decode(cmd_result,'hex')) | |
if resp == None: | |
return None | |
return codecs.encode(resp,'hex').upper() | |
def beep(self): | |
py_decard.dll_handle.dc_beep(py_decard.device_handle,10) | |