fix compiler warnings
[librfid] / python / 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
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>
46
47 #define BUILD_DLL
48 #include "openpcd.h"
49
50 #define LIBMIFARE_MAGIC 0xDEADBEEF
51
52 struct openpcd_state
53 {
54     unsigned int magic;    
55     unsigned int cl_auth;
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];
60     unsigned int uid;
61 } openpcd_state;
62
63 int openpcd_cl_auth(struct openpcd_state* state ,int page)
64 {
65     int rc;
66
67     if(!state || page<=0 || page>MIFARE_CL_PAGE_MAX )
68         return PCDERROR_INVALID_PARAMETER;
69         
70     if(!state->ph)
71         return PCDERROR_CLOSED;
72
73     rc = mfcl_set_key(state->ph, state->key);
74     if (rc < 0)
75         return PCDERROR_KEY_FORMAT;
76         
77     rc = mfcl_auth(state->ph, state->cl_auth, page);
78
79     return rc<0 ? PCDERROR_KEY_AUTH : PCDERROR_NONE;
80 }
81
82 void Sleep(unsigned int ms ) {
83     usleep(ms*1000);
84 }
85
86 EXPORT int EXPORT_CONVENTION openpcd_set_key(MIFARE_HANDLE handle,unsigned int key_id,const void* key)
87 {
88     struct openpcd_state *state;
89
90     if(!handle)
91         return PCDERROR_INVALID_PARAMETER;
92     state=(struct openpcd_state*)handle;
93     
94     switch(key_id)
95     {
96         case PCDAUTH_KEYID_1A:
97             state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
98             break;
99         case PCDAUTH_KEYID_1B:
100             state->cl_auth=RFID_CMD_MIFARE_AUTH1B;
101             break;
102         default:
103             return PCDERROR_INVALID_PARAMETER;
104     }
105     
106     memcpy(state->key,key,MIFARE_CL_KEY_LEN);
107     
108     return PCDERROR_NONE;
109 }
110
111 EXPORT int EXPORT_CONVENTION openpcd_select_card(MIFARE_HANDLE handle)
112 {
113     int res;
114     struct openpcd_state *state;
115         
116     if(!handle)
117         return PCDERROR_INVALID_PARAMETER;
118     state=(struct openpcd_state*)handle;
119     
120     state->l2h = rfid_layer2_init(state->rh,RFID_LAYER2_ISO14443A);
121     if(!state->l2h)
122         res=PCDERROR_LAYER2_INIT;
123     else
124     {        
125         if( rfid_layer2_open(state->l2h)>=0 ) 
126         {
127             state->ph = rfid_protocol_init(state->l2h,RFID_PROTOCOL_MIFARE_CLASSIC);
128         
129             if(state->ph)
130             {
131                 if(rfid_protocol_open(state->ph)>=0)
132                     return PCDERROR_NONE;
133                 
134                 rfid_protocol_fini(state->ph);
135                 state->ph=NULL;
136         
137                 res=PCDERROR_LAYER3_OPEN;
138             }
139             else
140                 res=PCDERROR_LAYER3_INIT;
141
142             rfid_layer2_close(state->l2h);      
143         }
144         else
145             res=PCDERROR_LAYER2_OPEN;
146     }
147     
148     rfid_layer2_fini(state->l2h);
149     state->l2h=NULL;
150     
151     return res; 
152 }
153
154 EXPORT int EXPORT_CONVENTION openpcd_deselect_card(MIFARE_HANDLE handle)
155 {
156     struct openpcd_state *state;
157         
158     if(!handle)
159         return PCDERROR_INVALID_PARAMETER;
160     state=(struct openpcd_state*)handle;
161     
162     if(state->ph)
163     {
164         rfid_protocol_close(state->ph);
165         rfid_protocol_fini(state->ph);
166         rfid_layer2_close(state->l2h);
167         rfid_layer2_fini(state->l2h);
168
169         state->ph=NULL;
170         state->l2h=NULL;
171         state->uid=0;
172         
173         return PCDERROR_NONE;
174     }    
175     else
176         return PCDERROR_CLOSED;
177 }
178
179 EXPORT int EXPORT_CONVENTION openpcd_get_card_id(MIFARE_HANDLE handle,unsigned int *uid)
180 {
181     unsigned int uid_len;
182     struct openpcd_state *state;
183         
184     if(!handle || !uid)
185         return PCDERROR_INVALID_PARAMETER;
186     state=(struct openpcd_state*)handle;
187     
188     if(state->ph)
189     {
190         uid_len=sizeof(*uid);
191         if(rfid_layer2_getopt(state->l2h,RFID_OPT_LAYER2_UID,uid,&uid_len))
192             return PCDERROR_INVALID_PARAMETER;
193         else
194             return uid_len==4 ? PCDERROR_NONE:PCDERROR_READ_FAILED;
195     }
196     else
197         return PCDERROR_CLOSED;    
198 }
199
200 EXPORT int EXPORT_CONVENTION openpcd_open_reader(MIFARE_HANDLE *handle)
201 {
202     struct rfid_reader_handle *rh;
203     struct openpcd_state *state;
204     
205     if(!handle)
206         return PCDERROR_INVALID_PARAMETER;
207         
208     rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
209     if(!rh)
210         return PCDERROR_NO_READER;
211     
212     state=(struct openpcd_state*)malloc(sizeof(*state));
213     if(state)
214     {
215         memset(state,0,sizeof(*state));
216         state->magic=LIBMIFARE_MAGIC;
217         state->rh=rh;
218         state->cl_auth=RFID_CMD_MIFARE_AUTH1A;
219         memset(state->key,0xFF,sizeof(state->key));
220         
221         // do initial reset
222         openpcd_reset_reader((MIFARE_HANDLE)state);
223         Sleep(1500);
224         // reopen
225         state->rh = rfid_reader_open(NULL, RFID_READER_OPENPCD);
226         
227         *handle=(MIFARE_HANDLE)state;
228         
229         return PCDERROR_NONE;
230     }
231     else
232     {   
233         rfid_reader_close(rh);
234         return PCDERROR_OUT_OF_MEMORY;
235     }
236 }
237
238 EXPORT int EXPORT_CONVENTION openpcd_close_reader(MIFARE_HANDLE handle)
239 {
240     struct openpcd_state *state;
241     
242     if(!handle)
243         return PCDERROR_INVALID_PARAMETER;
244     state=(struct openpcd_state*)handle;
245
246     openpcd_deselect_card(handle);
247
248     openpcd_reset_reader(handle);
249     Sleep(500);
250
251     state->magic=0;
252     rfid_reader_close(state->rh);
253     free(state);    
254     
255     return PCDERROR_NONE;
256 }
257
258 EXPORT int EXPORT_CONVENTION openpcd_read(MIFARE_HANDLE handle,int page, void* data, int len)
259 {
260     int res;
261     unsigned int count;
262     unsigned char buf[MIFARE_CL_PAGE_SIZE];
263     struct openpcd_state *state;        
264     
265     if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
266         return PCDERROR_INVALID_PARAMETER;
267         
268     state=(struct openpcd_state*)handle;
269     if ( (res=openpcd_cl_auth(state,page)) < 0)
270         return res;
271         
272     count = sizeof(buf);
273     res = rfid_protocol_read(state->ph, page, buf, &count);    
274     if(res>=0)
275         memcpy(data,buf,len);
276
277     if ( res<0 )
278         return PCDERROR_READ_FAILED;
279     else
280         return count;
281 }
282
283 EXPORT int EXPORT_CONVENTION openpcd_write(MIFARE_HANDLE handle,int page,const void *data,int len)
284 {
285     int res;
286     unsigned char buf[16];
287     struct openpcd_state *state;
288
289     if( !handle || !buf || page<0 || page>MIFARE_CL_PAGE_MAX || len<=0 || len>sizeof(buf))
290         return PCDERROR_INVALID_PARAMETER;
291         
292     state=(struct openpcd_state*)handle;
293     if ( (res=openpcd_cl_auth(state,page)) < 0)
294         return res;
295
296     memcpy(buf,data,len);
297     memset(&buf[len],0,sizeof(buf)-len);
298     
299     res = rfid_protocol_write(state->ph, page, buf, sizeof(buf));
300     
301     return (res<0 && res!=-101) ? PCDERROR_WRITE_FAILED : len;
302 }
303
304
305 EXPORT int EXPORT_CONVENTION openpcd_reset_reader(MIFARE_HANDLE handle)
306 {
307     struct openpcd_state *state;
308
309     if( !handle )
310         return PCDERROR_INVALID_PARAMETER;
311     state=(struct openpcd_state*)handle;
312         
313     return (state->rh->reader->reset(state->rh)<0) ? PCDERROR_WRITE_FAILED : PCDERROR_NONE;
314 }
315
316
317 EXPORT char* EXPORT_CONVENTION openpcd_get_error_text(int error)
318 {
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
336     };
337     const int count=sizeof(msg)/sizeof(msg[0]);
338     
339     if(error>0)
340         error=0;
341     else
342         error=-error;
343                 
344     return (error>=count) ? "PCDERROR_UNKNOWN" : (char*)msg[error];
345 }