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 /*************************************************************************/
42 #include <librfid/rfid.h>
43 #include <librfid/rfid_scan.h>
44 #include <librfid/rfid_reader.h>
45 #include <librfid/rfid_protocol.h>
46 #include <librfid/rfid_protocol_mifare_classic.h>
51 #define LIBMIFARE_MAGIC 0xDEADBEEF
57 struct rfid_reader_handle *rh;
58 struct rfid_layer2_handle *l2h;
59 struct rfid_protocol_handle *ph;
60 unsigned char key[MIFARE_CL_KEY_LEN];
64 int openpcd_cl_auth(struct openpcd_state* state ,int page)
68 if(!state || page<=0 || page>MIFARE_CL_PAGE_MAX )
69 return PCDERROR_INVALID_PARAMETER;
72 return PCDERROR_CLOSED;
74 rc = mfcl_set_key(state->ph, state->key);
76 return PCDERROR_KEY_FORMAT;
78 rc = mfcl_auth(state->ph, state->cl_auth, page);
80 return rc<0 ? PCDERROR_KEY_AUTH : PCDERROR_NONE;
83 EXPORT int EXPORT_CONVENTION openpcd_set_key(MIFARE_HANDLE handle,unsigned int key_id,const void* key)
85 struct openpcd_state *state;
88 return PCDERROR_INVALID_PARAMETER;
89 state=(struct openpcd_state*)handle;
93 case PCDAUTH_KEYID_1A:
94 state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
96 case PCDAUTH_KEYID_1B:
97 state->cl_auth=RFID_CMD_MIFARE_AUTH1B;
100 return PCDERROR_INVALID_PARAMETER;
103 memcpy(state->key,key,MIFARE_CL_KEY_LEN);
105 return PCDERROR_NONE;
108 EXPORT int EXPORT_CONVENTION openpcd_select_card(MIFARE_HANDLE handle)
111 struct openpcd_state *state;
114 return PCDERROR_INVALID_PARAMETER;
115 state=(struct openpcd_state*)handle;
117 state->l2h = rfid_layer2_init(state->rh,RFID_LAYER2_ISO14443A);
119 res=PCDERROR_LAYER2_INIT;
122 if( rfid_layer2_open(state->l2h)>=0 )
124 state->ph = rfid_protocol_init(state->l2h,RFID_PROTOCOL_MIFARE_CLASSIC);
128 if(rfid_protocol_open(state->ph)>=0)
129 return PCDERROR_NONE;
131 rfid_protocol_fini(state->ph);
134 res=PCDERROR_LAYER3_OPEN;
137 res=PCDERROR_LAYER3_INIT;
139 rfid_layer2_close(state->l2h);
142 res=PCDERROR_LAYER2_OPEN;
145 rfid_layer2_fini(state->l2h);
151 EXPORT int EXPORT_CONVENTION openpcd_deselect_card(MIFARE_HANDLE handle)
153 struct openpcd_state *state;
156 return PCDERROR_INVALID_PARAMETER;
157 state=(struct openpcd_state*)handle;
161 rfid_protocol_close(state->ph);
162 rfid_protocol_fini(state->ph);
163 rfid_layer2_close(state->l2h);
164 rfid_layer2_fini(state->l2h);
170 return PCDERROR_NONE;
173 return PCDERROR_CLOSED;
176 EXPORT int EXPORT_CONVENTION openpcd_get_card_id(MIFARE_HANDLE handle,unsigned int *uid)
178 unsigned int uid_len;
179 struct openpcd_state *state;
182 return PCDERROR_INVALID_PARAMETER;
183 state=(struct openpcd_state*)handle;
187 uid_len=sizeof(*uid);
188 if(rfid_layer2_getopt(state->l2h,RFID_OPT_LAYER2_UID,uid,&uid_len))
189 return PCDERROR_INVALID_PARAMETER;
191 return uid_len==4 ? PCDERROR_NONE:PCDERROR_READ_FAILED;
194 return PCDERROR_CLOSED;
197 EXPORT int EXPORT_CONVENTION openpcd_open_reader(MIFARE_HANDLE *handle)
199 struct rfid_reader_handle *rh;
200 struct openpcd_state *state;
203 return PCDERROR_INVALID_PARAMETER;
205 rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
207 return PCDERROR_NO_READER;
209 state=(struct openpcd_state*)malloc(sizeof(*state));
212 memset(state,0,sizeof(*state));
213 state->magic=LIBMIFARE_MAGIC;
215 state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
216 memset(state->key,0xFF,sizeof(state->key));
219 openpcd_reset_reader((MIFARE_HANDLE)state);
222 state->rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
224 *handle=(MIFARE_HANDLE)state;
226 return PCDERROR_NONE;
230 rfid_reader_close(rh);
231 return PCDERROR_OUT_OF_MEMORY;
235 EXPORT int EXPORT_CONVENTION openpcd_close_reader(MIFARE_HANDLE handle)
237 struct openpcd_state *state;
240 return PCDERROR_INVALID_PARAMETER;
241 state=(struct openpcd_state*)handle;
243 openpcd_deselect_card(handle);
245 openpcd_reset_reader(handle);
249 rfid_reader_close(state->rh);
252 return PCDERROR_NONE;
255 EXPORT int EXPORT_CONVENTION openpcd_read(MIFARE_HANDLE handle,int page, void* data, int len)
259 unsigned char buf[MIFARE_CL_PAGE_SIZE];
260 struct openpcd_state *state;
262 if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
263 return PCDERROR_INVALID_PARAMETER;
265 state=(struct openpcd_state*)handle;
266 if ( (res=openpcd_cl_auth(state,page)) < 0)
270 res = rfid_protocol_read(state->ph, page, buf, &count);
272 memcpy(data,buf,len);
275 return PCDERROR_READ_FAILED;
280 EXPORT int EXPORT_CONVENTION openpcd_write(MIFARE_HANDLE handle,int page,const void *data,int len)
283 unsigned char buf[16];
284 struct openpcd_state *state;
286 if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
287 return PCDERROR_INVALID_PARAMETER;
289 state=(struct openpcd_state*)handle;
290 if ( (res=openpcd_cl_auth(state,page)) < 0)
293 memcpy(buf,data,len);
294 memset(&buf[len],0,sizeof(buf)-len);
296 res = rfid_protocol_write(state->ph, page, buf, sizeof(buf));
298 return (res<0 && res!=-101) ? PCDERROR_WRITE_FAILED : len;
301 EXPORT int EXPORT_CONVENTION openpcd_get_api_version(MIFARE_HANDLE handle, unsigned int *version)
304 struct openpcd_state *state;
306 if( !handle || !version )
307 return PCDERROR_INVALID_PARAMETER;
308 state=(struct openpcd_state*)handle;
312 if(state->rh->reader->get_api_version(state->rh,&b)<0)
313 return PCDERROR_READER_VERSION;
317 return PCDERROR_NONE;
321 EXPORT int EXPORT_CONVENTION openpcd_reset_reader(MIFARE_HANDLE handle)
323 struct openpcd_state *state;
326 return PCDERROR_INVALID_PARAMETER;
327 state=(struct openpcd_state*)handle;
329 return (state->rh->reader->reset(state->rh)<0) ? PCDERROR_WRITE_FAILED : PCDERROR_NONE;
332 EXPORT int EXPORT_CONVENTION openpcd_get_environment(
333 MIFARE_HANDLE handle,
338 struct openpcd_state *state;
341 return PCDERROR_INVALID_PARAMETER;
342 state=(struct openpcd_state*)handle;
344 return (state->rh->reader->get_environment(state->rh,count,data)<0) ? PCDERROR_READ_FAILED : PCDERROR_NONE;
347 EXPORT int EXPORT_CONVENTION openpcd_set_environment(
348 MIFARE_HANDLE handle,
350 const unsigned char* data)
352 struct openpcd_state *state;
355 return PCDERROR_INVALID_PARAMETER;
356 state=(struct openpcd_state*)handle;
358 return (state->rh->reader->set_environment(state->rh,count,data)<0) ? PCDERROR_WRITE_FAILED : PCDERROR_NONE;
361 EXPORT char* EXPORT_CONVENTION openpcd_get_error_text(int error)
363 const static char* msg[]={
364 "PCDERROR_NONE", // 0
365 "PCDERROR_INVALID_PARAMETER", // -1
366 "PCDERROR_KEY_FORMAT", // -2
367 "PCDERROR_KEY_AUTH", // -3
368 "PCDERROR_NO_CARD_FOUND", // -4
369 "PCDERROR_LAYER2_INIT", // -5
370 "PCDERROR_LAYER2_OPEN", // -6
371 "PCDERROR_LAYER3_INIT", // -7
372 "PCDERROR_LAYER3_OPEN", // -8
373 "PCDERROR_SELECT", // -9
374 "PCDERROR_READ_FAILED", // -10
375 "PCDERROR_WRITE_FAILED", // -11
376 "PCDERROR_CLOSED", // -12
377 "PCDERROR_NO_READER", // -13
378 "PCDERROR_OUT_OF_MEMORY", // -14
379 "PCDERROR_READER_VERSION" // -15
381 const int count=sizeof(msg)/sizeof(msg[0]);
388 return (error>=count) ? "PCDERROR_UNKNOWN" : (char*)msg[error];