blob: 55774e65dfd6be1c1981c71eab2a1b45f2ffe588 [file] [log] [blame]
Tang Cheng396e8252012-07-03 13:21:11 +08001# -*- coding: utf-8 -*-
2'''
3Created on 2011-9-29
Tang Chenge90e9bb2012-07-03 13:38:01 +08004读卡库程序
Tang Cheng396e8252012-07-03 13:21:11 +08005@author: cheng.tang
6'''
7from ctypes import *
8import codecs
9
Tang Cheng1aa15ee2012-09-06 10:12:23 +080010
11def _b(v):
12 if isinstance(v, unicode):
13 return v.encode('latin_1')
14 else:
15 return v
16
17
Tang Cheng396e8252012-07-03 13:21:11 +080018class CardOperatorError(Exception):
Tang Cheng1aa15ee2012-09-06 10:12:23 +080019 def __init__(self, msg):
20 Exception.__init__(self, msg)
21 self.msg = msg
22
23
24class py_decard(object):
25 # M1 卡密钥
26 KEY_A = 1
27 KEY_B = 2
28 # 寻卡模式
Tang Cheng396e8252012-07-03 13:21:11 +080029 MODE_ALL = 1
30 MODE_IDLE = 0
Tang Cheng1aa15ee2012-09-06 10:12:23 +080031 #
Tang Cheng396e8252012-07-03 13:21:11 +080032 ERROR_RET_NONE = 0
33 ERROR_RAISE_EXP = 1
34 dll_handle = None
35 dll_name = 'dcrf32.dll'
36 device_handle = None
37 error_method = ERROR_RET_NONE
38
39 @staticmethod
40 def _do_load_dll():
Tang Cheng1aa15ee2012-09-06 10:12:23 +080041 if py_decard.dll_handle != None:
Tang Cheng396e8252012-07-03 13:21:11 +080042 return
43 py_decard.dll_handle = windll.LoadLibrary(py_decard.dll_name)
44
45 @staticmethod
46 def setup(**kwdargs):
Tang Cheng1aa15ee2012-09-06 10:12:23 +080047 if 'error_method' in kwdargs:
Tang Cheng396e8252012-07-03 13:21:11 +080048 py_decard.error_method = kwdargs["error_method"]
49
Tang Cheng1aa15ee2012-09-06 10:12:23 +080050####################################################################
Tang Cheng396e8252012-07-03 13:21:11 +080051 def __init__(self):
52 py_decard._do_load_dll()
53 self.card_mode = 'contactless'
54 self.ic_port = 0
Tang Cheng1aa15ee2012-09-06 10:12:23 +080055
56 def set_card_mode(self, mode='cotactless', icport=-1):
Tang Cheng396e8252012-07-03 13:21:11 +080057 self.card_mode = mode
Tang Cheng1aa15ee2012-09-06 10:12:23 +080058 if self.card_mode != 'contactless':
Tang Cheng396e8252012-07-03 13:21:11 +080059 self.ic_port = icport
Tang Cheng1aa15ee2012-09-06 10:12:23 +080060
61 def setsamport(self, port):
Tang Cheng396e8252012-07-03 13:21:11 +080062 self.sam_port = self._get_sam_port(port)
63 ats_buffer = create_string_buffer('\000' * 256)
64 ats_len = c_char('\000')
Tang Cheng1aa15ee2012-09-06 10:12:23 +080065
66 py_decard.dll_handle.dc_setcpu(py_decard.device_handle, self.sam_port)
67 ret = py_decard.dll_handle.dc_cpureset(py_decard.device_handle,
68 byref(ats_len), ats_buffer)
69 if ret != 0:
Tang Cheng396e8252012-07-03 13:21:11 +080070 return self.error('CPUCard ats error')
71 l = ord(ats_len.value)
72 r = ats_buffer.raw[:l]
73 #print codecs.encode(r,'hex')
74 return r
Tang Cheng1aa15ee2012-09-06 10:12:23 +080075
76 def error(self, error):
Tang Cheng396e8252012-07-03 13:21:11 +080077 if py_decard.error_method == py_decard.ERROR_RET_NONE:
78 return None
79 raise CardOperatorError(error)
Tang Cheng1aa15ee2012-09-06 10:12:23 +080080
81 def open_port(self, port, baud):
Tang Cheng396e8252012-07-03 13:21:11 +080082 if py_decard.dll_handle == None:
Tang Cheng1aa15ee2012-09-06 10:12:23 +080083 raise RuntimeError(py_decard.dll_name + ' not load ')
84 if py_decard.device_handle != None:
Tang Cheng396e8252012-07-03 13:21:11 +080085 return True
Tang Cheng1aa15ee2012-09-06 10:12:23 +080086
87 dev_handle = py_decard.dll_handle.dc_init(port, baud)
Tang Cheng396e8252012-07-03 13:21:11 +080088 if dev_handle <= 0:
89 return False
90 py_decard.device_handle = dev_handle
91 return True
Tang Cheng1aa15ee2012-09-06 10:12:23 +080092
Tang Cheng396e8252012-07-03 13:21:11 +080093 def close_port(self):
94 if py_decard.device_handle == None:
95 return
96 py_decard.dll_handle.dc_exit(py_decard.device_handle)
97 py_decard.device_handle = None
Tang Cheng1aa15ee2012-09-06 10:12:23 +080098
Tang Cheng396e8252012-07-03 13:21:11 +080099 def request_card(self):
100 if self.card_mode == 'contactless':
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800101 py_decard.dll_handle.dc_reset(py_decard.device_handle, 1)
Tang Cheng396e8252012-07-03 13:21:11 +0800102 cardphyno = create_string_buffer('\000' * 64)
103 ret = py_decard.dll_handle.dc_card_hex(py_decard.device_handle,
104 py_decard.MODE_ALL,
105 cardphyno)
106 if ret == 0:
107 return cardphyno.value
108 return self.error('Request Card Error')
109 else:
110 return ''
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800111
Tang Cheng396e8252012-07-03 13:21:11 +0800112 def cpucard_ats(self):
113 ats_buffer = create_string_buffer('\000' * 256)
114 ats_len = c_char('\000')
115 if self.card_mode == 'contactless':
116 py_decard.dll_handle.dc_pro_reset.restype = c_short
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800117 ret = py_decard.dll_handle.dc_pro_reset(py_decard.device_handle,
118 byref(ats_len), ats_buffer)
119 if ret != 0:
Tang Cheng396e8252012-07-03 13:21:11 +0800120 return self.error('CPUCard ats error')
121 l = ord(ats_len.value)
122 r = ats_buffer.raw[:l]
123 #print codecs.encode(r,'hex')
124 return r
125 else:
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800126 py_decard.dll_handle.dc_setcpu(py_decard.device_handle,
127 self._get_sam_port(self.ic_port))
128 ret = py_decard.dll_handle.dc_cpureset(py_decard.device_handle,
129 byref(ats_len), ats_buffer)
130 if ret != 0:
Tang Cheng396e8252012-07-03 13:21:11 +0800131 return self.error('CPUCard ats error')
132 l = ord(ats_len.value)
133 r = ats_buffer.raw[:l]
134 #print codecs.encode(r,'hex')
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800135 return r
136
137 def _get_sam_port(self, port):
Tang Cheng396e8252012-07-03 13:21:11 +0800138 if port == 1:
139 return 0x0c
140 elif port == 2:
141 return 0x0d
142 elif port == 3:
143 return 0x0e
144 elif port == 4:
145 return 0x0f
146 else:
147 self.error('samport error')
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800148
149 def _do_apdu(self, command):
Tang Cheng396e8252012-07-03 13:21:11 +0800150 response = create_string_buffer('\000' * 256)
151 resplen = c_char('\000')
152 if self.card_mode == 'contactless':
153 py_decard.dll_handle.dc_pro_commandlink.restype = c_short
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800154 ret = py_decard.dll_handle.dc_pro_commandlink(py_decard.device_handle, len(command),
155 command, byref(resplen), response, 7, 56)
Tang Cheng396e8252012-07-03 13:21:11 +0800156 else:
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800157 ret = py_decard.dll_handle.dc_cpuapdu(py_decard.device_handle, len(command),
158 command, byref(resplen), response)
159
160 if ret != 0:
161 command_header = codecs.encode(command, 'hex')
162 return self.error('CPUCard apdu command : %s ,ret=%d' % (command_header, ret))
Tang Cheng396e8252012-07-03 13:21:11 +0800163 return response.raw[:ord(resplen.value)]
164
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800165 def cpucard_apdu(self, command):
Tang Cheng396e8252012-07-03 13:21:11 +0800166 current_resp = self._do_apdu(command)
167 if ord(current_resp[-2]) == 0x61 and ord(current_resp[-1]) > 0x00:
168 cmd = '\x00\xC0\x00\x00' + current_resp[-1]
169 #print "get response : %s" % codecs.encode(cmd,'hex')
170 return self._do_apdu(cmd)
171 else:
172 return current_resp
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800173
174 def cpucard_apdu_hex(self, command):
175 cmd_result = command.replace(' ', '')
176 resp = self.cpucard_apdu(codecs.decode(cmd_result, 'hex'))
Tang Cheng396e8252012-07-03 13:21:11 +0800177 if resp == None:
178 return None
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800179 return codecs.encode(resp, 'hex').upper()
180
181 def _do_sam_apdu(self, command):
Tang Cheng396e8252012-07-03 13:21:11 +0800182 response = create_string_buffer('\000' * 256)
183 resplen = c_char('\000')
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800184 ret = py_decard.dll_handle.dc_cpuapdu(py_decard.device_handle, len(command),
185 command, byref(resplen), response)
186
187 if ret != 0:
188 command_header = codecs.encode(command, 'hex')
189 return self.error('CPUCard apdu command : %s ,ret=%d' % (command_header, ret))
Tang Cheng396e8252012-07-03 13:21:11 +0800190 return response.raw[:ord(resplen.value)]
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800191
192 def sam_apdu(self, command):
Tang Cheng396e8252012-07-03 13:21:11 +0800193 current_resp = self._do_sam_apdu(command)
194 if ord(current_resp[-2]) == 0x61 and ord(current_resp[-1]) > 0x00:
195 cmd = '\x00\xC0\x00\x00' + current_resp[-1]
196 #print "get response : %s" % codecs.encode(cmd,'hex')
197 return self._do_sam_apdu(cmd)
198 else:
199 return current_resp
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800200
201 def sam_apdu_hex(self, command):
202 cmd_result = command.replace(' ', '')
203 resp = self.sam_apdu(codecs.decode(cmd_result, 'hex'))
Tang Cheng396e8252012-07-03 13:21:11 +0800204 if resp == None:
205 return None
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800206 return codecs.encode(resp, 'hex').upper()
207
Tang Cheng396e8252012-07-03 13:21:11 +0800208 def beep(self):
Tang Cheng1aa15ee2012-09-06 10:12:23 +0800209 py_decard.dll_handle.dc_beep(py_decard.device_handle, 10)
210
211 def auth_card(self, sectno, key, key_type):
212 assert key_type in (py_decard.KEY_A, py_decard.KEY_B), u"密钥类型错误"
213 if key_type == py_decard.KEY_A:
214 key_type = 0
215 else:
216 key_type = 4
217
218 r = py_decard.dll_handle.dc_authentication_pass(py_decard.device_handle,
219 key_type, sectno, key)
220 if r != 0:
221 return False
222 return True
223
224 def read_block(self, block_no):
225 data = create_string_buffer('\000' * 16)
226 r = py_decard.dll_handle.dc_read(py_decard.device_handle,
227 block_no, data)
228 if r != 0:
229 return None
230 return data.raw[:16]
231
232 def write_block(self, block_no, data):
233 data = _b(data)
234 r = py_decard.dll_handle.dc_write(py_decard.device_handle,
235 block_no, data)
236 if r != 0:
237 return False
238 return True