1 /*************************************************************************/
3 /* Mifare support for accessing RFID cards with OpenPCD RFID reader */
4 /* in WIN32 - see http://www.openpcd.org */
6 /* Copyright (C) 2007 Milosch Meriac <meriac@bitmanufaktur.de> */
8 /* Redistribution and use in source and binary forms, with or without */
9 /* modification, are permitted provided that the following conditions are*/
12 /* Redistributions of source code must retain the above copyright notice,*/
13 /* this list of conditions and the following disclaimer. */
14 /* Redistributions in binary form must reproduce the above copyright */
15 /* notice, this list of conditions and the following disclaimer in the */
16 /* documentation and/or other materials provided with the distribution. */
18 /* The name of the author may not be used to endorse or promote products */
19 /* derived from this software without specific prior written permission. */
21 /* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR */
22 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
23 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE*/
24 /* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, */
25 /* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
26 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR */
27 /* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
28 /* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */
29 /* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING */
30 /* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
31 /* POSSIBILITY OF SUCH DAMAGE. */
33 /*************************************************************************/
41 #include <librfid/rfid.h>
42 #include <librfid/rfid_scan.h>
43 #include <librfid/rfid_reader.h>
44 #include <librfid/rfid_protocol.h>
45 #include <librfid/rfid_protocol_mifare_classic.h>
50 #define LIBMIFARE_MAGIC 0xDEADBEEF
56 struct rfid_reader_handle *rh;
57 struct rfid_layer2_handle *l2h;
58 struct rfid_protocol_handle *ph;
59 unsigned char key[MIFARE_CL_KEY_LEN];
63 int openpcd_cl_auth(struct openpcd_state* state ,int page)
67 if(!state || page<=0 || page>MIFARE_CL_PAGE_MAX )
68 return PCDERROR_INVALID_PARAMETER;
71 return PCDERROR_CLOSED;
73 rc = mfcl_set_key(state->ph, state->key);
75 return PCDERROR_KEY_FORMAT;
77 rc = mfcl_auth(state->ph, state->cl_auth, page);
79 return rc<0 ? PCDERROR_KEY_AUTH : PCDERROR_NONE;
82 void Sleep(unsigned int ms ) {
86 EXPORT int EXPORT_CONVENTION openpcd_set_key(MIFARE_HANDLE handle,unsigned int key_id,const void* key)
88 struct openpcd_state *state;
91 return PCDERROR_INVALID_PARAMETER;
92 state=(struct openpcd_state*)handle;
96 case PCDAUTH_KEYID_1A:
97 state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
99 case PCDAUTH_KEYID_1B:
100 state->cl_auth=RFID_CMD_MIFARE_AUTH1B;
103 return PCDERROR_INVALID_PARAMETER;
106 memcpy(state->key,key,MIFARE_CL_KEY_LEN);
108 return PCDERROR_NONE;
111 EXPORT int EXPORT_CONVENTION openpcd_select_card(MIFARE_HANDLE handle)
114 struct openpcd_state *state;
117 return PCDERROR_INVALID_PARAMETER;
118 state=(struct openpcd_state*)handle;
120 state->l2h = rfid_layer2_init(state->rh,RFID_LAYER2_ISO14443A);
122 res=PCDERROR_LAYER2_INIT;
125 if( rfid_layer2_open(state->l2h)>=0 )
127 state->ph = rfid_protocol_init(state->l2h,RFID_PROTOCOL_MIFARE_CLASSIC);
131 if(rfid_protocol_open(state->ph)>=0)
132 return PCDERROR_NONE;
134 rfid_protocol_fini(state->ph);
137 res=PCDERROR_LAYER3_OPEN;
140 res=PCDERROR_LAYER3_INIT;
142 rfid_layer2_close(state->l2h);
145 res=PCDERROR_LAYER2_OPEN;
148 rfid_layer2_fini(state->l2h);
154 EXPORT int EXPORT_CONVENTION openpcd_deselect_card(MIFARE_HANDLE handle)
156 struct openpcd_state *state;
159 return PCDERROR_INVALID_PARAMETER;
160 state=(struct openpcd_state*)handle;
164 rfid_protocol_close(state->ph);
165 rfid_protocol_fini(state->ph);
166 rfid_layer2_close(state->l2h);
167 rfid_layer2_fini(state->l2h);
173 return PCDERROR_NONE;
176 return PCDERROR_CLOSED;
179 EXPORT int EXPORT_CONVENTION openpcd_get_card_id(MIFARE_HANDLE handle,unsigned int *uid)
181 unsigned int uid_len;
182 struct openpcd_state *state;
185 return PCDERROR_INVALID_PARAMETER;
186 state=(struct openpcd_state*)handle;
190 uid_len=sizeof(*uid);
191 if(rfid_layer2_getopt(state->l2h,RFID_OPT_LAYER2_UID,uid,&uid_len))
192 return PCDERROR_INVALID_PARAMETER;
194 return uid_len==4 ? PCDERROR_NONE:PCDERROR_READ_FAILED;
197 return PCDERROR_CLOSED;
200 EXPORT int EXPORT_CONVENTION openpcd_open_reader(MIFARE_HANDLE *handle)
202 struct rfid_reader_handle *rh;
203 struct openpcd_state *state;
206 return PCDERROR_INVALID_PARAMETER;
208 rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
210 return PCDERROR_NO_READER;
212 state=(struct openpcd_state*)malloc(sizeof(*state));
215 memset(state,0,sizeof(*state));
216 state->magic=LIBMIFARE_MAGIC;
218 state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
219 memset(state->key,0xFF,sizeof(state->key));
222 openpcd_reset_reader((MIFARE_HANDLE)state);
225 state->rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
227 *handle=(MIFARE_HANDLE)state;
229 return PCDERROR_NONE;
233 rfid_reader_close(rh);
234 return PCDERROR_OUT_OF_MEMORY;
238 EXPORT int EXPORT_CONVENTION openpcd_close_reader(MIFARE_HANDLE handle)
240 struct openpcd_state *state;
243 return PCDERROR_INVALID_PARAMETER;
244 state=(struct openpcd_state*)handle;
246 openpcd_deselect_card(handle);
248 openpcd_reset_reader(handle);
252 rfid_reader_close(state->rh);
255 return PCDERROR_NONE;
258 EXPORT int EXPORT_CONVENTION openpcd_read(MIFARE_HANDLE handle,int page, void* data, int len)
262 unsigned char buf[MIFARE_CL_PAGE_SIZE];
263 struct openpcd_state *state;
265 if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
266 return PCDERROR_INVALID_PARAMETER;
268 state=(struct openpcd_state*)handle;
269 if ( (res=openpcd_cl_auth(state,page)) < 0)
273 res = rfid_protocol_read(state->ph, page, buf, &count);
275 memcpy(data,buf,len);
278 return PCDERROR_READ_FAILED;
283 EXPORT int EXPORT_CONVENTION openpcd_write(MIFARE_HANDLE handle,int page,const void *data,int len)
286 unsigned char buf[16];
287 struct openpcd_state *state;
289 if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
290 return PCDERROR_INVALID_PARAMETER;
292 state=(struct openpcd_state*)handle;
293 if ( (res=openpcd_cl_auth(state,page)) < 0)
296 memcpy(buf,data,len);
297 memset(&buf[len],0,sizeof(buf)-len);
299 res = rfid_protocol_write(state->ph, page, buf, sizeof(buf));
301 return (res<0 && res!=-101) ? PCDERROR_WRITE_FAILED : len;
305 EXPORT int EXPORT_CONVENTION openpcd_reset_reader(MIFARE_HANDLE handle)
307 struct openpcd_state *state;
310 return PCDERROR_INVALID_PARAMETER;
311 state=(struct openpcd_state*)handle;
313 return (state->rh->reader->reset(state->rh)<0) ? PCDERROR_WRITE_FAILED : PCDERROR_NONE;
317 EXPORT char* EXPORT_CONVENTION openpcd_get_error_text(int error)
319 const static char* msg[]={
320 "PCDERROR_NONE", // 0
321 "PCDERROR_INVALID_PARAMETER", // -1
322 "PCDERROR_KEY_FORMAT", // -2
323 "PCDERROR_KEY_AUTH", // -3
324 "PCDERROR_NO_CARD_FOUND", // -4
325 "PCDERROR_LAYER2_INIT", // -5
326 "PCDERROR_LAYER2_OPEN", // -6
327 "PCDERROR_LAYER3_INIT", // -7
328 "PCDERROR_LAYER3_OPEN", // -8
329 "PCDERROR_SELECT", // -9
330 "PCDERROR_READ_FAILED", // -10
331 "PCDERROR_WRITE_FAILED", // -11
332 "PCDERROR_CLOSED", // -12
333 "PCDERROR_NO_READER", // -13
334 "PCDERROR_OUT_OF_MEMORY", // -14
335 "PCDERROR_READER_VERSION" // -15
337 const int count=sizeof(msg)/sizeof(msg[0]);
344 return (error>=count) ? "PCDERROR_UNKNOWN" : (char*)msg[error];