use defined hexdump istead of rfid_hexdump
[librfid] / win32 / openpcd.c
1 /*************************************************************************/
2 /*                                                                       */
3 /* Mifare support for accessing RFID cards with OpenPCD RFID reader      */
4 /* in WIN32 - see http://www.openpcd.org                                 */
5 /*                                                                       */
6 /* Copyright (C) 2007 Milosch Meriac <meriac@bitmanufaktur.de>           */
7 /*                                                                       */
8 /* Redistribution and use in source and binary forms, with or without    */
9 /* modification, are permitted provided that the following conditions are*/
10 /* met:                                                                  */
11 /*                                                                       */
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.  */
17 /*                                                                       */
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. */
20 /*                                                                       */
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.                                           */
32 /*                                                                       */
33 /*************************************************************************/
34
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <windows.h>
41
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>
47
48 #define BUILD_DLL
49 #include "openpcd.h"
50
51 #define LIBMIFARE_MAGIC 0xDEADBEEF
52
53 struct openpcd_state
54 {
55     unsigned int magic;    
56     unsigned int cl_auth;
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];
61     unsigned int uid;
62 } openpcd_state;
63
64 int openpcd_cl_auth(struct openpcd_state* state ,int page)
65 {
66     int rc;
67
68     if(!state || page<=0 || page>MIFARE_CL_PAGE_MAX )
69         return PCDERROR_INVALID_PARAMETER;
70         
71     if(!state->ph)
72         return PCDERROR_CLOSED;
73
74     rc = mfcl_set_key(state->ph, state->key);
75     if (rc < 0)
76         return PCDERROR_KEY_FORMAT;
77         
78     rc = mfcl_auth(state->ph, state->cl_auth, page);
79
80     return rc<0 ? PCDERROR_KEY_AUTH : PCDERROR_NONE;
81 }
82
83 EXPORT int EXPORT_CONVENTION openpcd_set_key(MIFARE_HANDLE handle,unsigned int key_id,const void* key)
84 {
85     struct openpcd_state *state;
86
87     if(!handle)
88         return PCDERROR_INVALID_PARAMETER;
89     state=(struct openpcd_state*)handle;
90     
91     switch(key_id)
92     {
93         case PCDAUTH_KEYID_1A:
94             state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
95             break;
96         case PCDAUTH_KEYID_1B:
97             state->cl_auth=RFID_CMD_MIFARE_AUTH1B;
98             break;
99         default:
100             return PCDERROR_INVALID_PARAMETER;
101     }
102     
103     memcpy(state->key,key,MIFARE_CL_KEY_LEN);
104     
105     return PCDERROR_NONE;
106 }
107
108 EXPORT int EXPORT_CONVENTION openpcd_select_card(MIFARE_HANDLE handle)
109 {
110     int res;
111     struct openpcd_state *state;
112         
113     if(!handle)
114         return PCDERROR_INVALID_PARAMETER;
115     state=(struct openpcd_state*)handle;
116     
117     state->l2h = rfid_layer2_init(state->rh,RFID_LAYER2_ISO14443A);
118     if(!state->l2h)
119         res=PCDERROR_LAYER2_INIT;
120     else
121     {        
122         if( rfid_layer2_open(state->l2h)>=0 ) 
123         {
124             state->ph = rfid_protocol_init(state->l2h,RFID_PROTOCOL_MIFARE_CLASSIC);
125         
126             if(state->ph)
127             {
128                 if(rfid_protocol_open(state->ph)>=0)
129                     return PCDERROR_NONE;
130                 
131                 rfid_protocol_fini(state->ph);
132                 state->ph=NULL;
133         
134                 res=PCDERROR_LAYER3_OPEN;
135             }
136             else
137                 res=PCDERROR_LAYER3_INIT;
138
139             rfid_layer2_close(state->l2h);      
140         }
141         else
142             res=PCDERROR_LAYER2_OPEN;
143     }
144     
145     rfid_layer2_fini(state->l2h);
146     state->l2h=NULL;
147     
148     return res; 
149 }
150
151 EXPORT int EXPORT_CONVENTION openpcd_deselect_card(MIFARE_HANDLE handle)
152 {
153     struct openpcd_state *state;
154         
155     if(!handle)
156         return PCDERROR_INVALID_PARAMETER;
157     state=(struct openpcd_state*)handle;
158     
159     if(state->ph)
160     {
161         rfid_protocol_close(state->ph);
162         rfid_protocol_fini(state->ph);
163         rfid_layer2_close(state->l2h);
164         rfid_layer2_fini(state->l2h);
165
166         state->ph=NULL;
167         state->l2h=NULL;
168         state->uid=0;
169         
170         return PCDERROR_NONE;
171     }    
172     else
173         return PCDERROR_CLOSED;
174 }
175
176 EXPORT int EXPORT_CONVENTION openpcd_get_card_id(MIFARE_HANDLE handle,unsigned int *uid)
177 {
178     unsigned int uid_len;
179     struct openpcd_state *state;
180         
181     if(!handle || !uid)
182         return PCDERROR_INVALID_PARAMETER;
183     state=(struct openpcd_state*)handle;
184     
185     if(state->ph)
186     {
187         uid_len=sizeof(*uid);
188         if(rfid_layer2_getopt(state->l2h,RFID_OPT_LAYER2_UID,uid,&uid_len))
189             return PCDERROR_INVALID_PARAMETER;
190         else
191             return uid_len==4 ? PCDERROR_NONE:PCDERROR_READ_FAILED;
192     }
193     else
194         return PCDERROR_CLOSED;    
195 }
196
197 EXPORT int EXPORT_CONVENTION openpcd_open_reader(MIFARE_HANDLE *handle)
198 {
199     struct rfid_reader_handle *rh;
200     struct openpcd_state *state;
201     
202     if(!handle)
203         return PCDERROR_INVALID_PARAMETER;
204         
205     rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
206     if(!rh)
207         return PCDERROR_NO_READER;
208     
209     state=(struct openpcd_state*)malloc(sizeof(*state));
210     if(state)
211     {
212         memset(state,0,sizeof(*state));
213         state->magic=LIBMIFARE_MAGIC;
214         state->rh=rh;
215         state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
216         memset(state->key,0xFF,sizeof(state->key));
217         
218         // do initial reset
219         openpcd_reset_reader((MIFARE_HANDLE)state);
220         Sleep(1500);
221         // reopen
222         state->rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
223         
224         *handle=(MIFARE_HANDLE)state;
225         
226         return PCDERROR_NONE;
227     }
228     else
229     {   
230         rfid_reader_close(rh);
231         return PCDERROR_OUT_OF_MEMORY;
232     }
233 }
234
235 EXPORT int EXPORT_CONVENTION openpcd_close_reader(MIFARE_HANDLE handle)
236 {
237     struct openpcd_state *state;
238     
239     if(!handle)
240         return PCDERROR_INVALID_PARAMETER;
241     state=(struct openpcd_state*)handle;
242
243     openpcd_deselect_card(handle);
244
245     openpcd_reset_reader(handle);
246     Sleep(500);
247
248     state->magic=0;
249     rfid_reader_close(state->rh);
250     free(state);    
251     
252     return PCDERROR_NONE;
253 }
254
255 EXPORT int EXPORT_CONVENTION openpcd_read(MIFARE_HANDLE handle,int page, void* data, int len)
256 {
257     int res;
258     unsigned int count;
259     unsigned char buf[MIFARE_CL_PAGE_SIZE];
260     struct openpcd_state *state;        
261     
262     if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
263         return PCDERROR_INVALID_PARAMETER;
264         
265     state=(struct openpcd_state*)handle;
266     if ( (res=openpcd_cl_auth(state,page)) < 0)
267         return res;
268         
269     count = sizeof(buf);
270     res = rfid_protocol_read(state->ph, page, buf, &count);    
271     if(res>=0)
272         memcpy(data,buf,len);
273
274     if ( res<0 )
275         return PCDERROR_READ_FAILED;
276     else
277         return count;
278 }
279
280 EXPORT int EXPORT_CONVENTION openpcd_write(MIFARE_HANDLE handle,int page,const void *data,int len)
281 {
282     int res;
283     unsigned char buf[16];
284     struct openpcd_state *state;
285
286     if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
287         return PCDERROR_INVALID_PARAMETER;
288         
289     state=(struct openpcd_state*)handle;
290     if ( (res=openpcd_cl_auth(state,page)) < 0)
291         return res;
292
293     memcpy(buf,data,len);
294     memset(&buf[len],0,sizeof(buf)-len);
295     
296     res = rfid_protocol_write(state->ph, page, buf, sizeof(buf));
297     
298     return (res<0 && res!=-101) ? PCDERROR_WRITE_FAILED : len;
299 }
300
301 EXPORT int EXPORT_CONVENTION openpcd_get_api_version(MIFARE_HANDLE handle, unsigned int *version)
302 {
303     unsigned char b;
304     struct openpcd_state *state;
305
306     if( !handle || !version )
307         return PCDERROR_INVALID_PARAMETER;
308     state=(struct openpcd_state*)handle;
309     
310     b=0;
311         
312     if(state->rh->reader->get_api_version(state->rh,&b)<0)
313         return PCDERROR_READER_VERSION;
314     else
315     {
316         *version=b;
317         return PCDERROR_NONE;
318     }
319 }
320
321 EXPORT int EXPORT_CONVENTION openpcd_reset_reader(MIFARE_HANDLE handle)
322 {
323     struct openpcd_state *state;
324
325     if( !handle )
326         return PCDERROR_INVALID_PARAMETER;
327     state=(struct openpcd_state*)handle;
328         
329     return (state->rh->reader->reset(state->rh)<0) ? PCDERROR_WRITE_FAILED : PCDERROR_NONE;
330 }
331
332 EXPORT int EXPORT_CONVENTION openpcd_get_environment(
333     MIFARE_HANDLE handle,
334     unsigned char count,
335     unsigned char* data
336     )
337 {
338     struct openpcd_state *state;
339
340     if( !handle )
341         return PCDERROR_INVALID_PARAMETER;
342     state=(struct openpcd_state*)handle;
343         
344     return (state->rh->reader->get_environment(state->rh,count,data)<0) ? PCDERROR_READ_FAILED : PCDERROR_NONE;
345 }
346
347 EXPORT int EXPORT_CONVENTION openpcd_set_environment(
348     MIFARE_HANDLE handle,
349     unsigned char count,
350     const unsigned char* data)
351 {
352     struct openpcd_state *state;
353
354     if( !handle )
355         return PCDERROR_INVALID_PARAMETER;
356     state=(struct openpcd_state*)handle;
357         
358     return (state->rh->reader->set_environment(state->rh,count,data)<0) ? PCDERROR_WRITE_FAILED : PCDERROR_NONE;
359 }
360
361 EXPORT char* EXPORT_CONVENTION openpcd_get_error_text(int error)
362 {
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
380     };
381     const int count=sizeof(msg)/sizeof(msg[0]);
382     
383     if(error>0)
384         error=0;
385     else
386         error=-error;
387                 
388     return (error>=count) ? "PCDERROR_UNKNOWN" : (char*)msg[error];
389 }