500428d90f2871d1d7e5dddbb7db75a254b48263
[librfid] / src / rfid_reader_openpcd.c
1 /* OpenPC specific RC632 transport layer 
2  *
3  * (C) 2006 by Harald Welte <laforge@gnumonks.org>
4  *
5  * The OpenPCD is an Atmel AT91SAM7Sxx based USB RFID reader.
6  * It's CL RC632 is connected via SPI.
7  *
8  * TODO:
9  * - put hdl from static variable into asic transport or reader handle 
10  */
11
12 /*
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License version 2 
15  *  as published by the Free Software Foundation
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #include <usb.h>
33
34 #include <librfid/rfid.h>
35 #include <librfid/rfid_reader.h>
36 #include <librfid/rfid_asic.h>
37 #include <librfid/rfid_asic_rc632.h>
38 #include <librfid/rfid_reader_openpcd.h>
39
40 /* FIXME */
41 #include "rc632.h"
42
43
44 #define SENDBUF_LEN     (256+7+10) /* 256bytes max FSD/FSC, plus 7 bytes header,
45                                     plus 10 bytes reserve */
46 #define RECVBUF_LEN     SENDBUF_LEN
47
48 static char snd_buf[SENDBUF_LEN];
49 static char rcv_buf[RECVBUF_LEN];
50 static struct openpcd_hdr *snd_hdr;
51 static struct openpcd_hdr *rcv_hdr;
52
53
54 static struct usb_device *dev;
55 static struct usb_dev_handle *hdl;
56
57 static int openpcd_send_command(u_int8_t cmd, u_int8_t reg, u_int8_t val,
58                                 u_int16_t len, const unsigned char *data)
59 {
60         int ret;
61         u_int16_t cur;
62
63         snd_hdr->cmd = cmd;
64         snd_hdr->reg = reg;
65         snd_hdr->val = val;
66         snd_hdr->len = len;
67         if (data && len)
68                 memcpy(snd_hdr->data, data, len);
69
70         cur = sizeof(*snd_hdr) + len;
71
72         return usb_bulk_write(hdl, OPENPCD_OUT_EP, snd_hdr, cur, 0);
73 }
74
75 static int openpcd_recv_reply(void)
76 {
77         int ret;
78
79         ret = usb_bulk_read(hdl, OPENPCD_IN_EP, rcv_buf, sizeof(rcv_buf), 1000);
80
81         return ret;
82 }
83         
84 static struct usb_device *find_opcd_device(void)
85 {
86         struct usb_bus *bus;
87
88         for (bus = usb_busses; bus; bus = bus->next) {
89                 struct usb_device *dev;
90                 for (dev = bus->devices; dev; dev = dev->next) {
91                         if (dev->descriptor.idVendor == OPENPCD_VENDOR_ID
92                             && dev->descriptor.idProduct == OPENPCD_PRODUCT_ID
93                             && dev->descriptor.iManufacturer == 0
94                             && dev->descriptor.iProduct == 0
95                             && dev->descriptor.bNumConfigurations == 1
96                             && dev->config->bNumInterfaces == 1
97                             && dev->config->iConfiguration == 0)
98                                 return dev;
99                 }
100         }
101         return NULL;
102 }
103
104 static int openpcd_reg_write(struct rfid_asic_transport_handle *rath,
105                              unsigned char reg, unsigned char value)
106 {
107         int ret;
108
109         DEBUGP("reg=0x%02x, val=%02x: ", reg, value);
110
111         ret = openpcd_send_command(OPENPCD_CMD_WRITE_REG, reg, value, 0, NULL);
112         if (ret < 0)
113                 DEBUGPC("ERROR\n");
114         else
115                 DEBUGPC("OK\n");
116
117         ret = openpcd_recv_reply();
118         if (ret < 0)
119                 DEBUGPC("ERROR\n");
120         else
121                 DEBUGPC("OK\n");
122
123         return ret;
124 }
125
126 static int openpcd_reg_read(struct rfid_asic_transport_handle *rath,
127                             unsigned char reg,
128                             unsigned char *value)
129 {
130         int ret;        
131
132         DEBUGP("reg=0x%02x, ", reg);
133
134         ret = openpcd_send_command(OPENPCD_CMD_READ_REG, reg, 0, 0, NULL);
135         if (ret < 0) {
136                 DEBUGPC("ERROR\n");
137                 return ret;
138         }
139
140         ret = openpcd_recv_reply();
141         if (ret < 0) {
142                 DEBUGPC("ERROR\n");
143                 return ret;
144         }
145
146         *value = rcv_hdr->val;
147         DEBUGPC("val=%02x: OK\n", *value);
148
149         return ret;
150 }
151
152 static int openpcd_fifo_read(struct rfid_asic_transport_handle *rath,
153                              unsigned char num_bytes,
154                              unsigned char *buf)
155 {
156         int ret;
157
158         DEBUGP(" ");
159
160         ret = openpcd_send_command(OPENPCD_CMD_READ_FIFO, 0x00, num_bytes, 0, NULL);
161         if (ret < 0) {
162                 DEBUGPC("ERROR\n");
163                 return ret;
164         }
165
166         ret = openpcd_recv_reply();
167         if (ret < 0) {
168                 DEBUGPC("ERROR\n");
169                 return ret;
170         }
171
172         memcpy(buf, rcv_hdr->data, rcv_hdr->len);
173
174         return ret;
175 }
176
177 static int openpcd_fifo_write(struct rfid_asic_transport_handle *rath,
178                              unsigned char len,
179                              const unsigned char *bytes,
180                              unsigned char flags)
181 {
182         int ret;
183
184         ret = openpcd_send_command(OPENPCD_CMD_WRITE_FIFO, 0, 0, len, bytes);
185
186         return ret;
187 }
188
189 static int openpcd_transceive(struct rfid_reader_handle *rh,
190                              enum rfid_frametype frametype,
191                              const unsigned char *tx_data, unsigned int tx_len,
192                              unsigned char *rx_data, unsigned int *rx_len,
193                              u_int64_t timeout, unsigned int flags)
194 {
195         return rh->ah->asic->priv.rc632.fn.transceive(rh->ah, frametype,
196                                                 tx_data, tx_len, rx_data,
197                                                 rx_len, timeout, flags);
198 }
199
200 static int openpcd_transceive_sf(struct rfid_reader_handle *rh,
201                                unsigned char cmd, struct iso14443a_atqa *atqa)
202 {
203         return rh->ah->asic->priv.rc632.fn.iso14443a.transceive_sf(rh->ah,
204                                                                    cmd,
205                                                                    atqa);
206 }
207
208 static int
209 openpcd_transceive_acf(struct rfid_reader_handle *rh,
210                       struct iso14443a_anticol_cmd *cmd,
211                       unsigned int *bit_of_col)
212 {
213         return rh->ah->asic->priv.rc632.fn.iso14443a.transceive_acf(rh->ah,
214                                                          cmd, bit_of_col);
215 }
216
217 static int
218 openpcd_14443a_init(struct rfid_reader_handle *rh)
219 {
220         return rh->ah->asic->priv.rc632.fn.iso14443a.init(rh->ah);
221 }
222
223 static int
224 openpcd_14443a_set_speed(struct rfid_reader_handle *rh, 
225                         unsigned int tx,
226                         unsigned int speed)
227 {
228         u_int8_t rate;
229         
230         DEBUGP("setting rate: ");
231         switch (speed) {
232         case RFID_14443A_SPEED_106K:
233                 rate = 0x00;
234                 DEBUGPC("106K\n");
235                 break;
236         case RFID_14443A_SPEED_212K:
237                 rate = 0x01;
238                 DEBUGPC("212K\n");
239                 break;
240         case RFID_14443A_SPEED_424K:
241                 rate = 0x02;
242                 DEBUGPC("424K\n");
243                 break;
244         case RFID_14443A_SPEED_848K:
245                 rate = 0x03;
246                 DEBUGPC("848K\n");
247                 break;
248         default:
249                 return -EINVAL;
250                 break;
251         }
252         return rh->ah->asic->priv.rc632.fn.iso14443a.set_speed(rh->ah,
253                                                                 tx, rate);
254 }
255
256 static int
257 openpcd_14443b_init(struct rfid_reader_handle *rh)
258 {
259         return rh->ah->asic->priv.rc632.fn.iso14443b.init(rh->ah);
260 }
261
262 static int
263 openpcd_15693_init(struct rfid_reader_handle *rh)
264 {
265         return rh->ah->asic->priv.rc632.fn.iso15693.init(rh->ah);
266 }
267
268 static int
269 openpcd_mifare_setkey(struct rfid_reader_handle *rh, const u_int8_t *key)
270 {
271         return rh->ah->asic->priv.rc632.fn.mifare_classic.setkey(rh->ah, key);
272 }
273
274 static int
275 openpcd_mifare_auth(struct rfid_reader_handle *rh, u_int8_t cmd, 
276                    u_int32_t serno, u_int8_t block)
277 {
278         return rh->ah->asic->priv.rc632.fn.mifare_classic.auth(rh->ah, 
279                                                         cmd, serno, block);
280 }
281
282 struct rfid_asic_transport openpcd_ccid = {
283         .name = "OpenPCD Dumb USB Protocol",
284         .priv.rc632 = {
285                 .fn = {
286                         .reg_write      = &openpcd_reg_write,
287                         .reg_read       = &openpcd_reg_read,
288                         .fifo_write     = &openpcd_fifo_write,
289                         .fifo_read      = &openpcd_fifo_read,
290                 },
291         },
292 };
293
294 static struct rfid_reader_handle *
295 openpcd_open(void *data)
296 {
297         struct rfid_reader_handle *rh;
298         struct rfid_asic_transport_handle *rath;
299
300         snd_hdr = (struct openpcd_hdr *)snd_buf;
301         rcv_hdr = (struct openpcd_hdr *)rcv_buf;
302
303         usb_init();
304         if (!usb_find_busses())
305                 return NULL;
306         if (!usb_find_devices())
307                 return NULL;
308         
309         dev = find_opcd_device();
310         if (!dev)
311                 return NULL;
312
313         hdl = usb_open(dev);
314         if (!hdl)
315                 return NULL;
316
317         if (usb_claim_interface(hdl, 0) < 0) {
318                 usb_close(hdl);
319                 return NULL;
320         }
321
322         rh = malloc(sizeof(*rh));
323         if (!rh)
324                 return NULL;
325         memset(rh, 0, sizeof(*rh));
326
327         rath = malloc(sizeof(*rath));
328         if (!rath)
329                 goto out_rh;
330         memset(rath, 0, sizeof(*rath));
331
332         rath->rat = &openpcd_ccid;
333         rh->reader = &rfid_reader_openpcd;
334
335         rh->ah = rc632_open(rath);
336         if (!rh->ah) 
337                 goto out_rath;
338
339         DEBUGP("returning %p\n", rh);
340         return rh;
341
342 out_rath:
343         free(rath);
344 out_rh:
345         free(rh);
346
347         return NULL;
348 }
349
350 static void
351 openpcd_close(struct rfid_reader_handle *rh)
352 {
353         struct rfid_asic_transport_handle *rath = rh->ah->rath;
354
355         usb_close(hdl);
356
357         rc632_close(rh->ah);
358         free(rath);
359         free(rh);
360 }
361
362 struct rfid_reader rfid_reader_openpcd = {
363         .name   = "OpenPCD RFID Reader",
364         .id = RFID_READER_OPENPCD,
365         .open = &openpcd_open,
366         .close = &openpcd_close,
367         .transceive = &openpcd_transceive,
368         .iso14443a = {
369                 .init = &openpcd_14443a_init,
370                 .transceive_sf = &openpcd_transceive_sf,
371                 .transceive_acf = &openpcd_transceive_acf,
372                 .speed = RFID_14443A_SPEED_106K | RFID_14443A_SPEED_212K |
373                          RFID_14443A_SPEED_424K, //| RFID_14443A_SPEED_848K,
374                 .set_speed = &openpcd_14443a_set_speed,
375         },
376         .iso14443b = {
377                 .init = &openpcd_14443b_init,
378         },
379         .mifare_classic = {
380                 .setkey = &openpcd_mifare_setkey,
381                 .auth = &openpcd_mifare_auth,
382         },
383 };
384
385