/* OpenPC specific RC632 transport layer * * (C) 2006 by Harald Welte * * The OpenPCD is an Atmel AT91SAM7Sxx based USB RFID reader. * It's CL RC632 is connected via SPI. * * TODO: * - put hdl from static variable into asic transport or reader handle */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include /* FIXME */ #include "rc632.h" #define SENDBUF_LEN (256+7+10) /* 256bytes max FSD/FSC, plus 7 bytes header, plus 10 bytes reserve */ #define RECVBUF_LEN SENDBUF_LEN static char snd_buf[SENDBUF_LEN]; static char rcv_buf[RECVBUF_LEN]; static struct openpcd_hdr *snd_hdr; static struct openpcd_hdr *rcv_hdr; static struct usb_device *dev; static struct usb_dev_handle *hdl; static int openpcd_send_command(u_int8_t cmd, u_int8_t reg, u_int8_t val, u_int16_t len, const unsigned char *data) { int ret; u_int16_t cur; snd_hdr->cmd = cmd; snd_hdr->reg = reg; snd_hdr->val = val; snd_hdr->len = len; if (data && len) memcpy(snd_hdr->data, data, len); cur = sizeof(*snd_hdr) + len; return usb_bulk_write(hdl, OPENPCD_OUT_EP, snd_hdr, cur, 0); } static int openpcd_recv_reply(void) { int ret; ret = usb_bulk_read(hdl, OPENPCD_IN_EP, rcv_buf, sizeof(rcv_buf), 1000); return ret; } static struct usb_device *find_opcd_device(void) { struct usb_bus *bus; for (bus = usb_busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor == OPENPCD_VENDOR_ID && dev->descriptor.idProduct == OPENPCD_PRODUCT_ID && dev->descriptor.iManufacturer == 0 && dev->descriptor.iProduct == 0 && dev->descriptor.bNumConfigurations == 1 && dev->config->bNumInterfaces == 1 && dev->config->iConfiguration == 0) return dev; } } return NULL; } static int openpcd_reg_write(struct rfid_asic_transport_handle *rath, unsigned char reg, unsigned char value) { int ret; DEBUGP("reg=0x%02x, val=%02x: ", reg, value); ret = openpcd_send_command(OPENPCD_CMD_WRITE_REG, reg, value, 0, NULL); if (ret < 0) DEBUGPC("ERROR sending command\n"); else DEBUGPC("OK\n"); return ret; } static int openpcd_reg_read(struct rfid_asic_transport_handle *rath, unsigned char reg, unsigned char *value) { int ret; DEBUGP("reg=0x%02x, ", reg); ret = openpcd_send_command(OPENPCD_CMD_READ_REG, reg, 0, 0, NULL); if (ret < 0) { DEBUGPC("ERROR sending command\n"); return ret; } ret = openpcd_recv_reply(); if (ret < 0) { DEBUGPC("ERROR receiving reply\n"); return ret; } *value = rcv_hdr->val; DEBUGPC("val=%02x: OK\n", *value); return ret; } static int openpcd_fifo_read(struct rfid_asic_transport_handle *rath, unsigned char num_bytes, unsigned char *buf) { int ret; DEBUGP(" "); ret = openpcd_send_command(OPENPCD_CMD_READ_FIFO, 0x00, num_bytes, 0, NULL); if (ret < 0) { DEBUGPC("ERROR sending command\n"); return ret; } ret = openpcd_recv_reply(); if (ret < 0) { DEBUGPC("ERROR receiving reply\n"); return ret; } memcpy(buf, rcv_hdr->data, rcv_hdr->len); DEBUGPC("len=%u val=%s: OK\n", rcv_hdr->len, rfid_hexdump(rcv_hdr->data, rcv_hdr->len)); return ret; } static int openpcd_fifo_write(struct rfid_asic_transport_handle *rath, unsigned char len, const unsigned char *bytes, unsigned char flags) { int ret; DEBUGP("len=%u, data=%s\n", len, rfid_hexdump(bytes, len)); ret = openpcd_send_command(OPENPCD_CMD_WRITE_FIFO, 0, 0, len, bytes); return ret; } static int openpcd_transceive(struct rfid_reader_handle *rh, enum rfid_frametype frametype, const unsigned char *tx_data, unsigned int tx_len, unsigned char *rx_data, unsigned int *rx_len, u_int64_t timeout, unsigned int flags) { return rh->ah->asic->priv.rc632.fn.transceive(rh->ah, frametype, tx_data, tx_len, rx_data, rx_len, timeout, flags); } static int openpcd_transceive_sf(struct rfid_reader_handle *rh, unsigned char cmd, struct iso14443a_atqa *atqa) { return rh->ah->asic->priv.rc632.fn.iso14443a.transceive_sf(rh->ah, cmd, atqa); } static int openpcd_transceive_acf(struct rfid_reader_handle *rh, struct iso14443a_anticol_cmd *cmd, unsigned int *bit_of_col) { return rh->ah->asic->priv.rc632.fn.iso14443a.transceive_acf(rh->ah, cmd, bit_of_col); } static int openpcd_14443a_init(struct rfid_reader_handle *rh) { return rh->ah->asic->priv.rc632.fn.iso14443a.init(rh->ah); } static int openpcd_14443a_set_speed(struct rfid_reader_handle *rh, unsigned int tx, unsigned int speed) { u_int8_t rate; DEBUGP("setting rate: "); switch (speed) { case RFID_14443A_SPEED_106K: rate = 0x00; DEBUGPC("106K\n"); break; case RFID_14443A_SPEED_212K: rate = 0x01; DEBUGPC("212K\n"); break; case RFID_14443A_SPEED_424K: rate = 0x02; DEBUGPC("424K\n"); break; case RFID_14443A_SPEED_848K: rate = 0x03; DEBUGPC("848K\n"); break; default: return -EINVAL; break; } return rh->ah->asic->priv.rc632.fn.iso14443a.set_speed(rh->ah, tx, rate); } static int openpcd_14443b_init(struct rfid_reader_handle *rh) { return rh->ah->asic->priv.rc632.fn.iso14443b.init(rh->ah); } static int openpcd_15693_init(struct rfid_reader_handle *rh) { return rh->ah->asic->priv.rc632.fn.iso15693.init(rh->ah); } static int openpcd_mifare_setkey(struct rfid_reader_handle *rh, const u_int8_t *key) { return rh->ah->asic->priv.rc632.fn.mifare_classic.setkey(rh->ah, key); } static int openpcd_mifare_auth(struct rfid_reader_handle *rh, u_int8_t cmd, u_int32_t serno, u_int8_t block) { return rh->ah->asic->priv.rc632.fn.mifare_classic.auth(rh->ah, cmd, serno, block); } struct rfid_asic_transport openpcd_ccid = { .name = "OpenPCD Dumb USB Protocol", .priv.rc632 = { .fn = { .reg_write = &openpcd_reg_write, .reg_read = &openpcd_reg_read, .fifo_write = &openpcd_fifo_write, .fifo_read = &openpcd_fifo_read, }, }, }; static struct rfid_reader_handle * openpcd_open(void *data) { struct rfid_reader_handle *rh; struct rfid_asic_transport_handle *rath; snd_hdr = (struct openpcd_hdr *)snd_buf; rcv_hdr = (struct openpcd_hdr *)rcv_buf; usb_init(); if (!usb_find_busses()) return NULL; if (!usb_find_devices()) return NULL; dev = find_opcd_device(); if (!dev) return NULL; hdl = usb_open(dev); if (!hdl) return NULL; if (usb_claim_interface(hdl, 0) < 0) { usb_close(hdl); return NULL; } rh = malloc(sizeof(*rh)); if (!rh) return NULL; memset(rh, 0, sizeof(*rh)); rath = malloc(sizeof(*rath)); if (!rath) goto out_rh; memset(rath, 0, sizeof(*rath)); rath->rat = &openpcd_ccid; rh->reader = &rfid_reader_openpcd; rh->ah = rc632_open(rath); if (!rh->ah) goto out_rath; DEBUGP("returning %p\n", rh); return rh; out_rath: free(rath); out_rh: free(rh); return NULL; } static void openpcd_close(struct rfid_reader_handle *rh) { struct rfid_asic_transport_handle *rath = rh->ah->rath; rc632_close(rh->ah); free(rath); free(rh); usb_close(hdl); } struct rfid_reader rfid_reader_openpcd = { .name = "OpenPCD RFID Reader", .id = RFID_READER_OPENPCD, .open = &openpcd_open, .close = &openpcd_close, .transceive = &openpcd_transceive, .iso14443a = { .init = &openpcd_14443a_init, .transceive_sf = &openpcd_transceive_sf, .transceive_acf = &openpcd_transceive_acf, .speed = RFID_14443A_SPEED_106K | RFID_14443A_SPEED_212K | RFID_14443A_SPEED_424K, //| RFID_14443A_SPEED_848K, .set_speed = &openpcd_14443a_set_speed, }, .iso14443b = { .init = &openpcd_14443b_init, }, .mifare_classic = { .setkey = &openpcd_mifare_setkey, .auth = &openpcd_mifare_auth, }, };