diff options
Diffstat (limited to 'firmware/src')
32 files changed, 858 insertions, 1983 deletions
diff --git a/firmware/src/config.h b/firmware/src/config.h new file mode 100644 index 0000000..92918e4 --- /dev/null +++ b/firmware/src/config.h @@ -0,0 +1,4 @@ +#ifndef _CONFIG_H +//#define CONFIG_USB_STRING + +#endif diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index dc97624..f5abe46 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -569,7 +569,11 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = { USB_DT_DFU_SIZE, .bNumInterfaces = 1, .bConfigurationValue = 1, +#ifdef CONFIG_USB_STRING .iConfiguration = 3, +#else + .iConfiguration = 0, +#endif .bmAttributes = USB_CONFIG_ATT_ONE, .bMaxPower = 100, }, @@ -582,7 +586,11 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = { .bInterfaceClass = 0xfe, .bInterfaceSubClass = 0x01, .bInterfaceProtocol = 0x02, +#ifdef CONFIG_USB_STRING .iInterface = 4, +#else + .iInterface = 0, +#endif }, .uif[1] = { .bLength = USB_DT_INTERFACE_SIZE, @@ -593,7 +601,11 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = { .bInterfaceClass = 0xfe, .bInterfaceSubClass = 0x01, .bInterfaceProtocol = 0x02, +#ifdef CONFIG_USB_STRING .iInterface = 5, +#else + .iInterface = 0, +#endif }, .func_dfu = DFU_FUNC_DESC, diff --git a/firmware/src/dfu/dfu.h b/firmware/src/dfu/dfu.h index 084883b..a4184b4 100644 --- a/firmware/src/dfu/dfu.h +++ b/firmware/src/dfu/dfu.h @@ -26,6 +26,7 @@ #include <sys/types.h> #include <usb_ch9.h> #include <usb_dfu.h> +#include "../config.h" /* USB DFU functional descriptor */ #define DFU_FUNC_DESC { \ @@ -38,6 +39,7 @@ } /* USB Interface descriptor in Runtime mode */ +#ifdef CONFIG_USB_STRING #define DFU_RT_IF_DESC { \ { \ .bLength = USB_DT_INTERFACE_SIZE, \ @@ -61,6 +63,31 @@ .iInterface = 2, \ }, \ } +#else +#define DFU_RT_IF_DESC { \ + { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = 0x01, \ + .bAlternateSetting = 0x00, \ + .bNumEndpoints = 0x00, \ + .bInterfaceClass = 0xfe, \ + .bInterfaceSubClass = 0x01, \ + .bInterfaceProtocol = 0x01, \ + .iInterface = 0, \ + }, { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = 0x02, \ + .bAlternateSetting = 0x00, \ + .bNumEndpoints = 0x00, \ + .bInterfaceClass = 0xfe, \ + .bInterfaceSubClass = 0x01, \ + .bInterfaceProtocol = 0x01, \ + .iInterface = 0, \ + }, \ +} +#endif #define __dfufunctab __attribute__ ((section (".dfu.functab"))) #define __dfudata __attribute__ ((section (".data.shared"))) diff --git a/firmware/src/os/dbgu.c b/firmware/src/os/dbgu.c index e71b62e..32432a3 100644 --- a/firmware/src/os/dbgu.c +++ b/firmware/src/os/dbgu.c @@ -41,9 +41,12 @@ #include <os/led.h> #include <os/main.h> #include <os/system_irq.h> +#include <os/pcd_enumerate.h> #include <asm/system.h> #include <compile.h> +//#define DEBUG_UNBUFFERED + #define USART_SYS_LEVEL 4 /*---------------------------- Global Variable ------------------------------*/ //*--------------------------1-------------------------------------------------- @@ -324,8 +327,11 @@ void debugp(const char *format, ...) dbg_buf[sizeof(dbg_buf)-1] = '\0'; //AT91F_DBGU_Frame(dbg_buf); - //AT91F_DBGU_Printk(dbg_buf); +#ifdef DEBUG_UNBUFFERED + AT91F_DBGU_Printk(dbg_buf); +#else dbgu_rb_append(dbg_buf, strlen(dbg_buf)); +#endif } #else void dbgu_rb_flush(void) {} diff --git a/firmware/src/os/led.c b/firmware/src/os/led.c index 2a57558..fbe3f58 100644 --- a/firmware/src/os/led.c +++ b/firmware/src/os/led.c @@ -31,16 +31,6 @@ static const int ledport[] = { [2] = OPENPCD_PIO_LED2, }; -static int led2port(int led) -{ - if (led == 1) - return OPENPCD_PIO_LED1; - else if (led == 2) - return OPENPCD_PIO_LED2; - else - return 0; -} - void led_switch(int led, int on) { int port; diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c index f201a32..6c45af6 100644 --- a/firmware/src/os/pcd_enumerate.c +++ b/firmware/src/os/pcd_enumerate.c @@ -42,6 +42,8 @@ #include "../openpcd.h" #include <os/dbgu.h> +#include "../config.h" + //#define DEBUG_UDP_IRQ //#define DEBUG_UDP_IRQ_IN //#define DEBUG_UDP_IRQ_OUT @@ -65,13 +67,18 @@ #define DEBUGIO(x, args ...) do { } while (0) #endif +#ifdef DEBUG_UDP_EP0 +#define DEBUGE(x, args ...) DEBUGP(x, ## args) +#else +#define DEBUGE(x, args ...) do { } while (0) +#endif #define CONFIG_DFU #ifdef CONFIG_DFU static const struct dfuapi *dfu = DFU_API_LOCATION; #define udp_init dfu->udp_init -#define udp_ep0_send_data dfu->ep0_send_data +//#define udp_ep0_send_data dfu->ep0_send_data #define udp_ep0_send_zlp dfu->ep0_send_zlp #define udp_ep0_send_stall dfu->ep0_send_stall #else @@ -83,7 +90,7 @@ static struct udp_pcd upcd; const struct usb_device_descriptor dev_descriptor = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, + .bcdUSB = 0x0100, .bDeviceClass = USB_CLASS_VENDOR_SPEC, .bDeviceSubClass = 0xff, .bDeviceProtocol = 0xff, @@ -91,9 +98,15 @@ const struct usb_device_descriptor dev_descriptor = { .idVendor = USB_VENDOR_ID, .idProduct = USB_PRODUCT_ID, .bcdDevice = 0x0030, /* Version 0.3 */ +#ifdef CONFIG_USB_STRING .iManufacturer = 3, .iProduct = 4, - .iSerialNumber = 0x00, + .iSerialNumber = 0, +#else + .iManufacturer = 0, + .iProduct = 0, + .iSerialNumber = 0, +#endif .bNumConfigurations = 0x01, }; @@ -121,7 +134,11 @@ const struct _desc cfg_descriptor = { .bNumInterfaces = 1, #endif .bConfigurationValue = 1, +#ifdef CONFIG_USB_STRING .iConfiguration = 5, +#else + .iConfiguration = 0, +#endif .bmAttributes = USB_CONFIG_ATT_ONE, .bMaxPower = 250, /* 500mA */ }, @@ -134,7 +151,11 @@ const struct _desc cfg_descriptor = { .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0xff, +#ifdef CONFIG_SB_STRING .iInterface = 6, +#else + .iInterface = 0, +#endif }, .ep= { { @@ -179,6 +200,53 @@ static const struct epstate epstate[] = { .state_pending = RCTX_STATE_UDP_EP3_PENDING }, }; +/* Send Data through the control endpoint */ +static void udp_ep0_send_data(const char *pData, u_int32_t length) +{ + AT91PS_UDP pUdp = AT91C_BASE_UDP; + u_int32_t cpt = 0; + AT91_REG csr; + + DEBUGE("send_data: %u bytes ", length); + + do { + cpt = MIN(length, 8); + length -= cpt; + + DEBUGE("fifo_fill "); + while (cpt--) + pUdp->UDP_FDR[0] = *pData++; + + if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { + DEBUGE("wait_txcomp_clear "); + pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ; + } + + DEBUGE("set_txpktrdy "); + pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; + DEBUGE("wait_txcomp "); + do { + csr = pUdp->UDP_CSR[0]; + + /* Data IN stage has been stopped by a status OUT */ + if (csr & AT91C_UDP_RX_DATA_BK0) { + pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0); + DEBUGE("stopped by status out "); + return; + } + } while (!(csr & AT91C_UDP_TXCOMP)); + + } while (length); + + DEBUGE("clear_txcomp "); + if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { + pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ; + } + DEBUGE("done "); +} + static void reset_ep(unsigned int ep) { AT91PS_UDP pUDP = upcd.pUdp; @@ -490,13 +558,17 @@ out: void udp_pullup_on(void) { AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP); +#ifdef PCD AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4); +#endif } void udp_pullup_off(void) { AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP); +#ifdef PCD AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4); +#endif } /* Open USB Device Port */ @@ -519,8 +591,6 @@ void udp_open(void) /* End-of-Bus-Reset is always enabled */ /* Set the Pull up resistor */ - AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP); - AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4); udp_pullup_on(); } @@ -534,12 +604,6 @@ void udp_reset(void) udp_pullup_on(); } -#ifdef DEBUG_UDP_EP0 -#define DEBUGE(x, args ...) DEBUGP(x, ## args) -#else -#define DEBUGE(x, args ...) do { } while (0) -#endif - /* Handle requests on the USB Control Endpoint */ static void udp_ep0_handler(void) { @@ -628,6 +692,7 @@ static void udp_ep0_handler(void) MIN(sizeof(cfg_descriptor), wLength)); break; case USB_DT_STRING: +#ifdef CONFIG_USB_STRING /* Return String descriptor */ if (desc_index > ARRAY_SIZE(usb_strings)) goto out_stall; @@ -636,6 +701,9 @@ static void udp_ep0_handler(void) udp_ep0_send_data((const char *) usb_strings[desc_index], MIN(usb_strings[desc_index]->bLength, wLength)); +#else + goto out_stall; +#endif break; case USB_DT_CS_DEVICE: /* Return Function descriptor */ @@ -852,8 +920,8 @@ static void udp_ep0_handler(void) upcd.cur_interface = wIndex; upcd.cur_altsett = wValue; /* USB spec mandates that if we only support one altsetting in - * the given interface, we shall respond with STALL in the status - * stage */ + * the given interface, we shall respond with STALL in the + * status stage */ udp_ep0_send_stall(); break; default: diff --git a/firmware/src/os/pio_irq.c b/firmware/src/os/pio_irq.c index 4e94350..5fb777a 100644 --- a/firmware/src/os/pio_irq.c +++ b/firmware/src/os/pio_irq.c @@ -35,14 +35,14 @@ static struct pioirq_state pirqs; /* low-level handler, used by Cstartup_app.S PIOA fast forcing and * by regular interrupt handler below */ -void __pio_irq_demux(u_int32_t pio) +void __ramfunc __pio_irq_demux(u_int32_t pio) { u_int8_t send_usb = 0; int i; DEBUGPCRF("PIO_ISR_STATUS = 0x%08x", pio); - for (i = 0; i < NR_PIO; i++) { + for (i = 27; i < NR_PIO; i++) { if (pio & (1 << i) && pirqs.handlers[i]) pirqs.handlers[i](i); if (pirqs.usbmask & (1 << i)) diff --git a/firmware/src/os/pit.c b/firmware/src/os/pit.c index 6b68e84..50ec19f 100644 --- a/firmware/src/os/pit.c +++ b/firmware/src/os/pit.c @@ -106,7 +106,6 @@ void timer_add(struct timer_list *tl) static void pit_irq(u_int32_t sr) { struct timer_list *tl, *next; - unsigned long flags; if (!(sr & 0x1)) return; @@ -135,6 +134,17 @@ void pit_mdelay(u_int32_t ms) while (end < AT91F_PITGetPIIR(AT91C_BASE_PITC)) { } } +void mdelay(u_int32_t ms) +{ + return pit_mdelay(ms); +} + +void usleep(u_int32_t us) +{ + return; + return pit_mdelay(us/1000); +} + void pit_init(void) { AT91F_PITC_CfgPMC(); diff --git a/firmware/src/os/pwm.c b/firmware/src/os/pwm.c index 285f4e7..70858bb 100644 --- a/firmware/src/os/pwm.c +++ b/firmware/src/os/pwm.c @@ -138,7 +138,7 @@ static int pwm_usb_in(struct req_ctx *rctx) case OPENPCD_CMD_PWM_FREQ_SET: if (rctx->tot_len < sizeof(*poh)+4) break; - freq = (unsigned char *) poh + sizeof(*poh); + freq = (u_int32_t *) ((unsigned char *) poh) + sizeof(*poh); pwm_freq_set(0, *freq); break; case OPENPCD_CMD_PWM_FREQ_GET: diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c index d03fcd1..36c3059 100644 --- a/firmware/src/os/req_ctx.c +++ b/firmware/src/os/req_ctx.c @@ -50,7 +50,7 @@ struct req_ctx __ramfunc *req_ctx_find_get(int large, else i = 0; - for (1; i < NUM_REQ_CTX; i++) { + for (; i < NUM_REQ_CTX; i++) { local_irq_save(flags); if (req_ctx[i].state == old_state) { req_ctx[i].state = new_state; diff --git a/firmware/src/os/req_ctx.h b/firmware/src/os/req_ctx.h index 2df8497..ac9ab3f 100644 --- a/firmware/src/os/req_ctx.h +++ b/firmware/src/os/req_ctx.h @@ -34,6 +34,8 @@ struct req_ctx { #define RCTX_STATE_SSC_RX_BUSY 0x20 +#define RCTX_STATE_LIBRFID_BUSY 0x30 + #define RCTX_STATE_PIOIRQ_BUSY 0x80 #define RCTX_STATE_INVALID 0xff diff --git a/firmware/src/os/syscalls.c b/firmware/src/os/syscalls.c index ed989f1..18f755a 100644 --- a/firmware/src/os/syscalls.c +++ b/firmware/src/os/syscalls.c @@ -40,7 +40,7 @@ _ssize_t _read_r( size_t len) { char c; - int i; + unsigned int i; unsigned char *p; p = (unsigned char*)ptr; diff --git a/firmware/src/os/tc_cdiv.c b/firmware/src/os/tc_cdiv.c index 99a0975..6f06ba5 100644 --- a/firmware/src/os/tc_cdiv.c +++ b/firmware/src/os/tc_cdiv.c @@ -80,7 +80,7 @@ void tc_cdiv_init(void) AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR | AT91C_TC_BEEVT_SET | AT91C_TC_BCPB_CLEAR | AT91C_TC_EEVT_XC2 | AT91C_TC_ETRGEDG_RISING | - AT91C_TC_BSWTRG_CLEAR; /* clear on swtrg */ + AT91C_TC_BSWTRG_CLEAR | AT91C_TC_ASWTRG_CLEAR; tc_cdiv_set_divider(128); diff --git a/firmware/src/os/usb_benchmark.c b/firmware/src/os/usb_benchmark.c index 967efbb..2802d90 100644 --- a/firmware/src/os/usb_benchmark.c +++ b/firmware/src/os/usb_benchmark.c @@ -30,23 +30,6 @@ static struct req_ctx dummy_rctx; static struct req_ctx empty_rctx; -static void usbtest_tx_transfer(unsigned int num_pkts) -{ - unsigned int i; - -#if 0 -#warning please reimplement refill userspecified rctx - for (i = 0; i < num_pkts; i++) { - /* send 16 packets of 64byte */ - while (udp_refill_ep(2, &dummy_rctx) < 0) - ; - } - /* send one packet of 0 byte */ - while (udp_refill_ep(2, &empty_rctx) < 0) - ; -#endif -} - static int usbtest_rx(struct req_ctx *rctx) { struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data; diff --git a/firmware/src/pcd/main_analog.c b/firmware/src/pcd/main_analog.c index 799a98b..0f61693 100644 --- a/firmware/src/pcd/main_analog.c +++ b/firmware/src/pcd/main_analog.c @@ -34,6 +34,16 @@ #include <os/trigger.h> #include <os/pcd_enumerate.h> #include <os/main.h> +#include <pcd/rc632_highlevel.h> + +#include <librfid/rfid_reader.h> +#include <librfid/rfid_layer2.h> +#include <librfid/rfid_protocol.h> + +#define RAH NULL + +static struct rfid_reader_handle *rh; +static struct rfid_layer2_handle *l2h; void _init_func(void) { @@ -43,9 +53,11 @@ void _init_func(void) rc632_turn_on_rf(RAH); /* FIXME: do we need this? */ DEBUGPCRF("initializing 14443A operation"); - rc632_iso14443a_init(RAH); + rh = rfid_reader_open(NULL, RFID_READER_OPENPCD); + l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A); + /* Switch to 848kBps (1subcp / bit) */ - //rc632_clear_bits(RAH, RC632_REG_RX_CONTROL1, RC632_RXCTRL1_SUBCP_MASK); + //opcd_rc632_clear_bits(RAH, RC632_REG_RX_CONTROL1, RC632_RXCTRL1_SUBCP_MASK); } int _main_dbgu(char key) @@ -76,7 +88,7 @@ int _main_dbgu(char key) if (ret == 1) { ana_out_sel &= 0x0f; DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel); - rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); + opcd_rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); } return ret; @@ -91,7 +103,7 @@ void _main_func(void) trigger_pulse(); - if (rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_WUPA, &atqa) < 0) { + if (iso14443a_transceive_sf(l2h, ISO14443A_SF_CMD_WUPA, &atqa) < 0) { DEBUGPCRF("error during transceive_sf"); led_switch(1, 0); } else { diff --git a/firmware/src/pcd/main_dumbreader.c b/firmware/src/pcd/main_dumbreader.c index d5db8a5..dab4d77 100644 --- a/firmware/src/pcd/main_dumbreader.c +++ b/firmware/src/pcd/main_dumbreader.c @@ -28,6 +28,8 @@ #include "../openpcd.h" #include <os/main.h> +#define RAH NULL + void _init_func(void) { rc632_init(); @@ -48,13 +50,13 @@ int _main_dbgu(char key) break; case '5': - rc632_reg_read(RAH, RC632_REG_RX_WAIT, &value); + opcd_rc632_reg_read(RAH, RC632_REG_RX_WAIT, &value); DEBUGPCR("Reading RC632 Reg RxWait: 0x%02xr", value); break; case '6': DEBUGPCR("Writing RC632 Reg RxWait: 0x55"); - rc632_reg_write(RAH, RC632_REG_RX_WAIT, 0x55); + opcd_rc632_reg_write(RAH, RC632_REG_RX_WAIT, 0x55); break; case '7': rc632_dump(); diff --git a/firmware/src/pcd/main_librfid.c b/firmware/src/pcd/main_librfid.c new file mode 100644 index 0000000..8bb7ccb --- /dev/null +++ b/firmware/src/pcd/main_librfid.c @@ -0,0 +1,215 @@ +/* main_librfid - OpenPCD firmware using in-firmware librfid + * + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 <errno.h> +#include <string.h> +#include <lib_AT91SAM7.h> +#include <librfid/rfid.h> +#include <librfid/rfid_scan.h> +#include <librfid/rfid_reader.h> +#include <librfid/rfid_layer2.h> +#include <librfid/rfid_protocol.h> +//#include "rc632.h" +#include <os/dbgu.h> +#include <os/led.h> +#include <os/pcd_enumerate.h> +#include <os/trigger.h> +#include <os/req_ctx.h> + +#include "../openpcd.h" + +static struct rfid_reader_handle *rh; +static struct rfid_layer2_handle *l2h; +static struct rfid_protocol_handle *ph; + +void _init_func(void) +{ + trigger_init(); + rc632_init(); + rc632_test(); + DEBUGP("opening reader "); +#if 1 + rh = rfid_reader_open(NULL, RFID_READER_OPENPCD); + DEBUGP("rh=%p ", rh); +#endif + led_switch(2, 1); +} + +int _main_dbgu(char key) +{ + int ret = -EINVAL; + return ret; +} + +struct openpcd_l2_connectinfo { + u_int32_t proto_supported; + + u_int8_t speed_rx; + u_int8_t speed_tx; + + u_int8_t uid_len; + u_int8_t uid[10]; +} __attribute__ ((packed)); + +struct openpcd_proto_connectinfo { +} __attribute__ ((packed)); + +struct openpcd_proto_tcl_connectinfo { + u_int8_t fsc; + u_int8_t fsd; + u_int8_t ta; + u_int8_t sfgt; + + u_int8_t flags; + u_int8_t cid; + u_int8_t nad; + + u_int8_t ats_tot_len; + u_int8_t ats_snippet[0]; +} __attribute__ ((packed)); + +static int init_proto(void) +{ + struct req_ctx *detect_rctx; + struct openpcd_hdr *opcdh; + struct openpcd_l2_connectinfo *l2c; + struct openpcd_proto_connectinfo *pc; + unsigned int size; + + l2h = rfid_layer2_scan(rh); + if (!l2h) + return 0; + + DEBUGP("l2='%s' ", rfid_layer2_name(l2h)); + + detect_rctx = req_ctx_find_get(0, RCTX_STATE_FREE, + RCTX_STATE_LIBRFID_BUSY); + if (detect_rctx) { + unsigned int uid_len; + opcdh = (struct openpcd_hdr *) detect_rctx->data; + l2c = (struct openpcd_l2_connectinfo *) + (char *) opcdh + sizeof(opcdh); + l2c->uid_len = sizeof(l2c->uid); + opcdh->cmd = OPENPCD_CMD_LRFID_DETECT_IRQ; + opcdh->flags = 0x00; + opcdh->reg = 0x03; + opcdh->val = l2h->l2->id; + +#if 0 + /* copy UID / PUPI into data section */ + rfid_layer2_getopt(l2h, RFID_OPT_LAYER2_UID, (void *)l2c->uid, + &uid_len); + l2c->uid_len = uid_len & 0xff; + + size = sizeof(l2c->proto_supported); + rfid_layer2_getopt(l2h, RFID_OPT_LAYER2_PROTO_SUPP, + &l2c->proto_supported, &size); + + detect_rctx->tot_len = sizeof(*opcdh) + sizeof(*l2c); + + switch (l2h->l2->id) { + case RFID_LAYER2_ISO14443A: + break; + case RFID_LAYER2_ISO14443B: + break; + case RFID_LAYER2_ISO15693: + break; + } +#endif + req_ctx_set_state(detect_rctx, RCTX_STATE_UDP_EP3_PENDING); + } + ph = rfid_protocol_scan(l2h); + if (!ph) + return 3; + + DEBUGP("p='%s' ", rfid_protocol_name(ph)); + detect_rctx = req_ctx_find_get(0, RCTX_STATE_FREE, + RCTX_STATE_LIBRFID_BUSY); + if (detect_rctx) { + opcdh = (struct openpcd_hdr *) detect_rctx->data; + pc = (struct openpcd_proto_connectinfo *) + ((char *) opcdh + sizeof(*opcdh)); + detect_rctx->tot_len = sizeof(*opcdh) + sizeof(*pc); + opcdh->cmd = OPENPCD_CMD_LRFID_DETECT_IRQ; + opcdh->flags = 0x00; + opcdh->reg = 0x04; + opcdh->val = ph->proto->id; + /* copy L4 info into data section */ + +#if 0 + switch (ph->proto->id) { + case RFID_PROTOCOL_TCL: { + struct openpcd_proto_tcl_connectinfo *ptc + = (struct openpcd_proto_tcl_connectinfo *) + ((char *) ph + sizeof(*ph)); + unsigned int space; + detect_rctx->tot_len += sizeof(*ptc); + space = detect_rctx->size - sizeof(*opcdh)-sizeof(*pc); + size = space; + rfid_protocol_getopt(ph, RFID_OPT_P_TCL_ATS, + &ptc->ats_snippet, &size); + if (size == space) { + /* we've only copied part of the ATS */ + size = sizeof(ptc->ats_tot_len); + rfid_protocol_getopt(ph, + RFID_OPT_P_TCL_ATS_LEN, + &ptc->ats_tot_len, &size); + } else { + ptc->ats_tot_len = size; + } + + } break; + } +#endif + req_ctx_set_state(detect_rctx, RCTX_STATE_UDP_EP3_PENDING); + } + led_switch(1, 1); + + return 4; +} + +static int opcd_lrfid_usb_in(struct req_ctx *rctx) +{ + struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data; + return 0; +} + + +void _main_func(void) +{ + int ret; + + usb_out_process(); + usb_in_process(); + + ret = init_proto(); + + if (ret >= 4) + rfid_protocol_close(ph); + if (ret >= 3) + rfid_layer2_close(l2h); + + rc632_turn_off_rf(NULL); + { volatile int i; for (i = 0; i < 0x3ffff; i++) ; } + rc632_turn_on_rf(NULL); + + led_switch(1, 0); + led_toggle(2); +} diff --git a/firmware/src/pcd/main_pwm.c b/firmware/src/pcd/main_pwm.c index 58010ee..7db6b72 100644 --- a/firmware/src/pcd/main_pwm.c +++ b/firmware/src/pcd/main_pwm.c @@ -37,6 +37,8 @@ #include <pcd/ssc.h> #endif +#define RAH NULL + static u_int8_t force_100ask = 1; static u_int8_t mod_conductance = 0x3f; static u_int8_t cw_conductance = 0x3f; @@ -48,7 +50,7 @@ static u_int8_t pwm_freq_idx = 0; static void rc632_modulate_mfin() { - rc632_reg_write(RAH, RC632_REG_TX_CONTROL, + opcd_rc632_reg_write(RAH, RC632_REG_TX_CONTROL, RC632_TXCTRL_MOD_SRC_MFIN|RC632_TXCTRL_TX2_INV| RC632_TXCTRL_TX1_RF_EN|RC632_TXCTRL_TX2_RF_EN); } @@ -178,41 +180,41 @@ int _main_dbgu(char key) DEBUGPCRF("%sabling Force100ASK", force_100ask ? "Dis":"En"); if (force_100ask) { force_100ask = 0; - rc632_clear_bits(RAH, RC632_REG_TX_CONTROL, - RC632_TXCTRL_FORCE_100_ASK); + opcd_rc632_clear_bits(RAH, RC632_REG_TX_CONTROL, + RC632_TXCTRL_FORCE_100_ASK); } else { force_100ask = 1; - rc632_set_bits(RAH, RC632_REG_TX_CONTROL, - RC632_TXCTRL_FORCE_100_ASK); + opcd_rc632_set_bits(RAH, RC632_REG_TX_CONTROL, + RC632_TXCTRL_FORCE_100_ASK); } return 0; break; case 'v': if (mod_conductance > 0) { mod_conductance--; - rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE, - rsrel_table[mod_conductance]); + opcd_rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE, + rsrel_table[mod_conductance]); } break; case 'b': if (mod_conductance < 0x3f) { mod_conductance++; - rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE, - rsrel_table[mod_conductance]); + opcd_rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE, + rsrel_table[mod_conductance]); } break; case 'g': if (cw_conductance > 0) { cw_conductance--; - rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE, - rsrel_table[cw_conductance]); + opcd_rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE, + rsrel_table[cw_conductance]); } break; case 'h': if (cw_conductance < 0x3f) { cw_conductance++; - rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE, - rsrel_table[cw_conductance]); + opcd_rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE, + rsrel_table[cw_conductance]); } break; case '?': diff --git a/firmware/src/pcd/main_reqa.c b/firmware/src/pcd/main_reqa.c index 9f46569..717926a 100644 --- a/firmware/src/pcd/main_reqa.c +++ b/firmware/src/pcd/main_reqa.c @@ -33,6 +33,10 @@ #include <os/led.h> #include <os/pcd_enumerate.h> #include <os/trigger.h> +#include <pcd/rc632_highlevel.h> + +#include <librfid/rfid_reader.h> +#include <librfid/rfid_layer2.h> #include "../openpcd.h" @@ -40,6 +44,11 @@ #include "tc.h" #endif +#define RAH NULL + +static struct rfid_reader_handle *rh; +static struct rfid_layer2_handle *l2h; + void _init_func(void) { trigger_init(); @@ -52,7 +61,8 @@ void _init_func(void) DEBUGPCRF("turning on RF"); rc632_turn_on_rf(RAH); DEBUGPCRF("initializing 14443A operation"); - rc632_iso14443a_init(RAH); + rh = rfid_reader_open(NULL, RFID_READER_OPENPCD); + l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A); } #define MODE_REQA 0x01 @@ -62,21 +72,30 @@ void _init_func(void) static volatile int mode = MODE_REQA; -static const char frame_14443a[] = { 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; +static const char frame_14443a[] = { + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x00, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, +}; static void reg_inc(u_int8_t reg) { u_int8_t val; - rc632_reg_read(RAH, reg, &val); - rc632_reg_write(RAH, reg, val++); + opcd_rc632_reg_read(RAH, reg, &val); + opcd_rc632_reg_write(RAH, reg, val++); DEBUGPCRF("reg 0x%02x = 0x%02x", reg, val); } static void reg_dec(u_int8_t reg) { u_int8_t val; - rc632_reg_read(RAH, reg, &val); - rc632_reg_write(RAH, reg, val--); + opcd_rc632_reg_read(RAH, reg, &val); + opcd_rc632_reg_write(RAH, reg, val--); DEBUGPCRF("reg 0x%02x = 0x%02x", reg, val); } @@ -100,7 +119,7 @@ static u_int16_t cdivs[] = { 128, 64, 32, 16 }; int _main_dbgu(char key) { int ret = 0; - static int cdiv_idx = 0; + static int cdiv_idx = 2; switch (key) { case '?': @@ -137,7 +156,8 @@ int _main_dbgu(char key) if (ana_out_sel > 0) { ana_out_sel--; DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel); - rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); + opcd_rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, + ana_out_sel); } ret = 1; break; @@ -145,7 +165,8 @@ int _main_dbgu(char key) if (ana_out_sel < 0xc) { ana_out_sel++; DEBUGPCR("switching to analog output mode 0x%x\n", ana_out_sel); - rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); + opcd_rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, + ana_out_sel); } ret = 1; break; @@ -153,7 +174,7 @@ int _main_dbgu(char key) if (mfout_sel > 0) { mfout_sel--; DEBUGPCR("switching to MFOUT mode 0x%x\n", mfout_sel); - rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel); + opcd_rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel); } ret = 1; break; @@ -161,7 +182,7 @@ int _main_dbgu(char key) if (mfout_sel < 5) { mfout_sel++; DEBUGPCR("switching to MFOUT mode 0x%x\n", mfout_sel); - rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel); + opcd_rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel); } ret = 1; break; @@ -208,27 +229,17 @@ void _main_func(void) { int status; struct iso14443a_atqa atqa; - struct rfid_layer2_handle l2h; volatile int i; - memset(&atqa, 0, sizeof(atqa)); - - /* fake layer2 handle initialization */ - memset(&l2h, 0, sizeof(l2h)); - l2h.l2 = &rfid_layer2_iso14443a; - l2h.priv.iso14443a.state = ISO14443A_STATE_NONE; - l2h.priv.iso14443a.level = ISO14443A_LEVEL_NONE; - /* FIXME: why does this only work every second attempt without reset or * power-cycle? */ - rc632_turn_off_rf(); + //rc632_turn_off_rf(); //rc632_reset(); - rc632_turn_on_rf(); + //rc632_turn_on_rf(); - rc632_iso14443a_init(RAH); - rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); - rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel); - for (i = 0; i < 0x3ffff; i++) {} + opcd_rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, ana_out_sel); + opcd_rc632_reg_write(RAH, RC632_REG_MFOUT_SELECT, mfout_sel); + for (i = 0; i < 0xfffff; i++) {} //rc632_dump(); #ifdef WITH_TC tc_cdiv_print(); @@ -236,21 +247,21 @@ void _main_func(void) switch (mode) { case MODE_REQA: - status = rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_REQA, &atqa); + status = iso14443a_transceive_sf(l2h, ISO14443A_SF_CMD_REQA, &atqa); if (status < 0) DEBUGPCRF("error during transceive_sf REQA"); else DEBUGPCRF("received ATQA: %s", hexdump((char *)&atqa, sizeof(atqa))); break; case MODE_WUPA: - status = rc632_iso14443a_transceive_sf(RAH, ISO14443A_SF_CMD_WUPA, &atqa); + status = iso14443a_transceive_sf(l2h, ISO14443A_SF_CMD_WUPA, &atqa); if (status < 0) DEBUGPCRF("error during transceive_sf WUPA"); else DEBUGPCRF("received WUPA: %s", hexdump((char *)&atqa, sizeof(atqa))); break; case MODE_ANTICOL: - status = rfid_layer2_iso14443a.fn.open(&l2h); + status = rfid_layer2_open(l2h); if (status < 0) DEBUGPCR("error during anticol"); else @@ -260,11 +271,11 @@ void _main_func(void) { char rx_buf[4]; int rx_len = sizeof(rx_buf); - rfid_layer2_iso14443a.fn.setopt(&l2h, RFID_OPT_14443A_SPEED_RX, + rfid_layer2_setopt(l2h, RFID_OPT_14443A_SPEED_RX, &speed_idx, sizeof(speed_idx)); - rfid_layer2_iso14443a.fn.setopt(&l2h, RFID_OPT_14443A_SPEED_TX, + rfid_layer2_setopt(l2h, RFID_OPT_14443A_SPEED_TX, &speed_idx, sizeof(speed_idx)); - rfid_layer2_iso14443a.fn.transceive(&l2h, RFID_14443A_FRAME_REGULAR, + rfid_layer2_transceive(l2h, RFID_14443A_FRAME_REGULAR, &frame_14443a, sizeof(frame_14443a), &rx_buf, &rx_len, 1, 0); } diff --git a/firmware/src/pcd/rc632.c b/firmware/src/pcd/rc632.c index 5287300..731574c 100644 --- a/firmware/src/pcd/rc632.c +++ b/firmware/src/pcd/rc632.c @@ -38,6 +38,8 @@ #include <os/req_ctx.h> #include "rc632.h" +#include <librfid/rfid_asic.h> + #define NOTHING do {} while(0) #if 0 @@ -102,6 +104,9 @@ static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, return -1; } + /* disable RC632 interrupt because it wants to do SPI transactions */ + AT91F_AIC_DisableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632); + AT91F_SPI_ReceiveFrame(pSPI, rx_data, tx_len, NULL, 0); AT91F_SPI_SendFrame(pSPI, tx_data, tx_len, NULL, 0); @@ -113,6 +118,9 @@ static int spi_transceive(const u_int8_t *tx_data, u_int16_t tx_len, while (! (pSPI->SPI_SR & AT91C_SPI_ENDRX)) ; + /* Re-enable RC632 interrupts */ + AT91F_AIC_EnableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632); + DEBUGPSPI("DMA Xfer finished rx=%s\r\n", hexdump(rx_data, tx_len)); *rx_len = tx_len; @@ -178,19 +186,12 @@ static u_int8_t spi_inbuf[SPI_MAX_XFER_LEN]; #define FIFO_ADDR (RC632_REG_FIFO_DATA << 1) -struct rc632 { - u_int16_t flags; - struct fifo fifo; -}; -#define RC632_F_FIFO_TX 0x0001 -static struct rc632 rc632; - #define RC632_WRITE_ADDR(x) ((x << 1) & 0x7e) /* RC632 access primitives */ -int rc632_reg_write(struct rfid_asic_handle *hdl, - u_int8_t addr, u_int8_t data) +int opcd_rc632_reg_write(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t data) { u_int16_t rx_len = 2; @@ -201,17 +202,16 @@ int rc632_reg_write(struct rfid_asic_handle *hdl, spi_outbuf[0] = addr; spi_outbuf[1] = data; - //spi_transceive(spi_outbuf, 2, NULL, NULL); return spi_transceive(spi_outbuf, 2, spi_inbuf, &rx_len); } #define RC632_REGSET_START 0x10 #define RC632_REGSET_END 0x3f #define RC632_REGSET_MAXSIZE (RC632_REGSET_END-RC632_REGSET_START) -static char regset_buf[RC632_REGSET_MAXSIZE * 2]; +static u_int8_t regset_buf[RC632_REGSET_MAXSIZE * 2]; -int rc632_reg_write_set(struct rfid_asic_handle *hdl, - u_int8_t *regs, int len) +int opcd_rc632_reg_write_set(struct rfid_asic_handle *hdl, + u_int8_t *regs, int len) { u_int8_t i, j = 0; u_int16_t rx_len; @@ -231,8 +231,8 @@ int rc632_reg_write_set(struct rfid_asic_handle *hdl, return spi_transceive(regset_buf, j, spi_inbuf, &rx_len); } -int rc632_fifo_write(struct rfid_asic_handle *hdl, - u_int8_t len, u_int8_t *data, u_int8_t flags) +int opcd_rc632_fifo_write(struct rfid_asic_handle *hdl, + u_int8_t len, u_int8_t *data, u_int8_t flags) { u_int16_t rx_len = sizeof(spi_inbuf); if (len > sizeof(spi_outbuf)-1) @@ -246,8 +246,8 @@ int rc632_fifo_write(struct rfid_asic_handle *hdl, return spi_transceive(spi_outbuf, len+1, spi_inbuf, &rx_len); } -int rc632_reg_read(struct rfid_asic_handle *hdl, - u_int8_t addr, u_int8_t *val) +int opcd_rc632_reg_read(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t *val) { u_int16_t rx_len = 2; @@ -264,15 +264,15 @@ int rc632_reg_read(struct rfid_asic_handle *hdl, return 0; } -int rc632_fifo_read(struct rfid_asic_handle *hdl, - u_int8_t max_len, u_int8_t *data) +int opcd_rc632_fifo_read(struct rfid_asic_handle *hdl, + u_int8_t max_len, u_int8_t *data) { int ret; u_int8_t fifo_length; u_int8_t i; u_int16_t rx_len; - ret = rc632_reg_read(hdl, RC632_REG_FIFO_LENGTH, &fifo_length); + ret = opcd_rc632_reg_read(hdl, RC632_REG_FIFO_LENGTH, &fifo_length); if (ret < 0) return ret; @@ -295,34 +295,34 @@ int rc632_fifo_read(struct rfid_asic_handle *hdl, return rx_len-1; } -int rc632_set_bits(struct rfid_asic_handle *hdl, +int opcd_rc632_set_bits(struct rfid_asic_handle *hdl, u_int8_t reg, u_int8_t bits) { u_int8_t val; int ret; - ret = rc632_reg_read(hdl, reg, &val); + ret = opcd_rc632_reg_read(hdl, reg, &val); if (ret < 0) return ret; val |= bits; - return rc632_reg_write(hdl, reg, val); + return opcd_rc632_reg_write(hdl, reg, val); } -int rc632_clear_bits(struct rfid_asic_handle *hdl, +int opcd_rc632_clear_bits(struct rfid_asic_handle *hdl, u_int8_t reg, u_int8_t bits) { u_int8_t val; int ret; - ret = rc632_reg_read(hdl, reg, &val); + ret = opcd_rc632_reg_read(hdl, reg, &val); if (ret < 0) return ret; val &= ~bits; - return rc632_reg_write(hdl, reg, val); + return opcd_rc632_reg_write(hdl, reg, val); } /* RC632 interrupt handling */ @@ -334,11 +334,11 @@ static void rc632_irq(void) u_int8_t cause; /* CL RC632 has interrupted us */ - rc632_reg_read(RAH, RC632_REG_INTERRUPT_RQ, &cause); + opcd_rc632_reg_read(NULL, RC632_REG_INTERRUPT_RQ, &cause); /* ACK all interrupts */ - //rc632_reg_write(RAH, RC632_REG_INTERRUPT_RQ, cause); - rc632_reg_write(RAH, RC632_REG_INTERRUPT_RQ, RC632_INT_TIMER); + //rc632_reg_write(NULL, RC632_REG_INTERRUPT_RQ, cause); + opcd_rc632_reg_write(NULL, RC632_REG_INTERRUPT_RQ, RC632_INT_TIMER); DEBUGP("rc632_irq: "); if (cause & RC632_INT_LOALERT) { @@ -369,7 +369,7 @@ static void rc632_irq(void) irq_rctx = req_ctx_find_get(0, RCTX_STATE_FREE, RCTX_STATE_RC632IRQ_BUSY); if (!irq_rctx) { - DEBUGPCRF("NO RCTX!\n"); + DEBUGPCRF("NO RCTX!"); /* disable rc632 interrupt until RCTX is free */ AT91F_AIC_DisableIt(AT91C_BASE_AIC, OPENPCD_IRQ_RC632); return; @@ -415,13 +415,13 @@ void rc632_reset(void) /* wait for startup phase to finish */ while (1) { u_int8_t val; - rc632_reg_read(RAH, RC632_REG_COMMAND, &val); + opcd_rc632_reg_read(NULL, RC632_REG_COMMAND, &val); if (val == 0x00) break; } /* turn off register paging */ - rc632_reg_write(RAH, RC632_REG_PAGE0, 0x00); + opcd_rc632_reg_write(NULL, RC632_REG_PAGE0, 0x00); } static int rc632_usb_in(struct req_ctx *rctx) @@ -434,7 +434,7 @@ static int rc632_usb_in(struct req_ctx *rctx) switch (poh->cmd) { case OPENPCD_CMD_READ_REG: - rc632_reg_read(RAH, poh->reg, &poh->val); + opcd_rc632_reg_read(NULL, poh->reg, &poh->val); DEBUGP("READ REG(0x%02x)=0x%02x ", poh->reg, poh->val); /* register read always has to provoke a response */ poh->flags &= OPENPCD_FLAG_RESPOND; @@ -448,7 +448,7 @@ static int rc632_usb_in(struct req_ctx *rctx) if (req_len > MAX_PAYLOAD_LEN) { pih_len = MAX_PAYLOAD_LEN; remain_len -= pih_len; - rc632_fifo_read(RAH, pih_len, poh->data); + opcd_rc632_fifo_read(NULL, pih_len, poh->data); rctx->tot_len += pih_len; DEBUGP("READ FIFO(len=%u)=%s ", req_len, hexdump(poh->data, pih_len)); @@ -466,7 +466,7 @@ static int rc632_usb_in(struct req_ctx *rctx) rctx->tot_len = sizeof(*poh); pih_len = remain_len; - rc632_fifo_read(RAH, pih_len, poh->data); + opcd_rc632_fifo_read(NULL, pih_len, poh->data); rctx->tot_len += pih_len; DEBUGP("READ FIFO(len=%u)=%s ", pih_len, hexdump(poh->data, pih_len)); @@ -474,7 +474,7 @@ static int rc632_usb_in(struct req_ctx *rctx) * body will do this after switch statement */ } else { #endif - poh->val = rc632_fifo_read(RAH, req_len, poh->data); + poh->val = opcd_rc632_fifo_read(NULL, req_len, poh->data); rctx->tot_len += poh->val; DEBUGP("READ FIFO(len=%u)=%s ", poh->val, hexdump(poh->data, poh->val)); @@ -483,16 +483,16 @@ static int rc632_usb_in(struct req_ctx *rctx) break; case OPENPCD_CMD_WRITE_REG: DEBUGP("WRITE_REG(0x%02x, 0x%02x) ", poh->reg, poh->val); - rc632_reg_write(RAH, poh->reg, poh->val); + opcd_rc632_reg_write(NULL, poh->reg, poh->val); break; case OPENPCD_CMD_WRITE_REG_SET: DEBUGP("WRITE_REG_SET(%s) ", hexdump(poh->data, len)); - rc632_reg_write_set(RAH, poh->data, len); + opcd_rc632_reg_write_set(NULL, poh->data, len); break; case OPENPCD_CMD_WRITE_FIFO: DEBUGP("WRITE FIFO(len=%u): %s ", len, hexdump(poh->data, len)); - rc632_fifo_write(RAH, len, poh->data, 0); + opcd_rc632_fifo_write(NULL, len, poh->data, 0); break; case OPENPCD_CMD_READ_VFIFO: DEBUGP("READ VFIFO "); @@ -504,11 +504,11 @@ static int rc632_usb_in(struct req_ctx *rctx) break; case OPENPCD_CMD_REG_BITS_CLEAR: DEBUGP("CLEAR BITS "); - poh->val = rc632_clear_bits(RAH, poh->reg, poh->val); + poh->val = opcd_rc632_clear_bits(NULL, poh->reg, poh->val); break; case OPENPCD_CMD_REG_BITS_SET: DEBUGP("SET BITS "); - poh->val = rc632_set_bits(RAH, poh->reg, poh->val); + poh->val = opcd_rc632_set_bits(NULL, poh->reg, poh->val); break; case OPENPCD_CMD_DUMP_REGS: DEBUGP("DUMP REGS "); @@ -575,13 +575,13 @@ void rc632_init(void) rc632_reset(); /* configure IRQ pin */ - rc632_reg_write(RAH, RC632_REG_IRQ_PIN_CONFIG, - RC632_IRQCFG_CMOS|RC632_IRQCFG_INV); + opcd_rc632_reg_write(NULL, RC632_REG_IRQ_PIN_CONFIG, + RC632_IRQCFG_CMOS|RC632_IRQCFG_INV); /* enable interrupts */ - rc632_reg_write(RAH, RC632_REG_INTERRUPT_EN, RC632_INT_TIMER); + opcd_rc632_reg_write(NULL, RC632_REG_INTERRUPT_EN, RC632_INT_TIMER); /* configure AUX to test signal four */ - rc632_reg_write(RAH, RC632_REG_TEST_ANA_SELECT, 0x04); + opcd_rc632_reg_write(NULL, RC632_REG_TEST_ANA_SELECT, 0x04); usb_hdlr_register(&rc632_usb_in, OPENPCD_CMD_CLS_RC632); }; @@ -602,8 +602,8 @@ static int rc632_reg_write_verify(struct rfid_asic_handle *hdl, { u_int8_t tmp; - rc632_reg_write(hdl, reg, val); - rc632_reg_read(hdl, reg, &tmp); + opcd_rc632_reg_write(hdl, reg, val); + opcd_rc632_reg_read(hdl, reg, &tmp); DEBUGPCRF("reg=0x%02x, write=0x%02x, read=0x%02x ", reg, val, tmp); diff --git a/firmware/src/pcd/rc632.h b/firmware/src/pcd/rc632.h index 1a4dc22..bb56d18 100644 --- a/firmware/src/pcd/rc632.h +++ b/firmware/src/pcd/rc632.h @@ -4,19 +4,20 @@ #include <sys/types.h> #include <cl_rc632.h> #include <librfid/rfid.h> +#include <librfid/rfid_asic.h> -extern int rc632_reg_write(struct rfid_asic_handle *hdl, - u_int8_t addr, u_int8_t data); -extern int rc632_fifo_write(struct rfid_asic_handle *hdl, - u_int8_t len, u_int8_t *data, u_int8_t flags); -extern int rc632_reg_read(struct rfid_asic_handle *hdl, - u_int8_t addr, u_int8_t *val); -extern int rc632_fifo_read(struct rfid_asic_handle *hdl, - u_int8_t max_len, u_int8_t *data); -extern int rc632_clear_bits(struct rfid_asic_handle *hdl, - u_int8_t reg, u_int8_t bits); -extern int rc632_set_bits(struct rfid_asic_handle *hdl, - u_int8_t reg, u_int8_t bits); +extern int opcd_rc632_reg_write(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t data); +extern int opcd_rc632_fifo_write(struct rfid_asic_handle *hdl, + u_int8_t len, u_int8_t *data, u_int8_t flags); +extern int opcd_rc632_reg_read(struct rfid_asic_handle *hdl, + u_int8_t addr, u_int8_t *val); +extern int opcd_rc632_fifo_read(struct rfid_asic_handle *hdl, + u_int8_t max_len, u_int8_t *data); +extern int opcd_rc632_clear_bits(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t bits); +extern int opcd_rc632_set_bits(struct rfid_asic_handle *hdl, + u_int8_t reg, u_int8_t bits); extern void rc632_init(void); extern void rc632_exit(void); diff --git a/firmware/src/pcd/rc632_highlevel.c b/firmware/src/pcd/rc632_highlevel.c index 0701da2..b83f52b 100644 --- a/firmware/src/pcd/rc632_highlevel.c +++ b/firmware/src/pcd/rc632_highlevel.c @@ -54,7 +54,7 @@ rc632_set_bit_mask(struct rfid_asic_handle *handle, int ret; u_int8_t tmp; - ret = rc632_reg_read(handle, reg, &tmp); + ret = opcd_rc632_reg_read(handle, reg, &tmp); if (ret < 0) return ret; @@ -62,317 +62,38 @@ rc632_set_bit_mask(struct rfid_asic_handle *handle, if ((tmp & mask) == val) return 0; - return rc632_reg_write(handle, reg, (tmp & ~mask)|(val & mask)); + return opcd_rc632_reg_write(handle, reg, (tmp & ~mask)|(val & mask)); } int rc632_turn_on_rf(struct rfid_asic_handle *handle) { ENTER(); - return rc632_set_bits(handle, RC632_REG_TX_CONTROL, 0x03); + return opcd_rc632_set_bits(handle, RC632_REG_TX_CONTROL, 0x03); } int rc632_turn_off_rf(struct rfid_asic_handle *handle) { ENTER(); - return rc632_clear_bits(handle, RC632_REG_TX_CONTROL, 0x03); + return opcd_rc632_clear_bits(handle, RC632_REG_TX_CONTROL, 0x03); } static int rc632_power_up(struct rfid_asic_handle *handle) { ENTER(); - return rc632_clear_bits(handle, RC632_REG_CONTROL, + return opcd_rc632_clear_bits(handle, RC632_REG_CONTROL, RC632_CONTROL_POWERDOWN); } static int rc632_power_down(struct rfid_asic_handle *handle) { - return rc632_set_bits(handle, RC632_REG_CONTROL, + return opcd_rc632_set_bits(handle, RC632_REG_CONTROL, RC632_CONTROL_POWERDOWN); } -/* calculate best 8bit prescaler and divisor for given usec timeout */ -static int best_prescaler(u_int64_t timeout, u_int8_t *prescaler, - u_int8_t *divisor) -{ - u_int8_t best_presc, best_divisor, i; - int64_t smallest_diff; - - smallest_diff = 0x7fffffffffffffff; - best_presc = 0; - - for (i = 0; i < 21; i++) { - u_int64_t clk, tmp_div, res; - int64_t diff; - clk = 13560000 / (1 << i); - tmp_div = (clk * timeout) / 1000000; - tmp_div++; - - if (tmp_div > 0xff) - continue; - - res = 1000000 / (clk / tmp_div); - diff = res - timeout; - - if (diff < 0) - continue; - - if (diff < smallest_diff) { - best_presc = i; - best_divisor = tmp_div; - smallest_diff = diff; - } - } - - *prescaler = best_presc; - *divisor = best_divisor; - - DEBUGPCRF("timeout %u usec, prescaler = %u, divisor = %u", timeout, best_presc, best_divisor); - - return 0; -} - -static int -rc632_timer_set(struct rfid_asic_handle *handle, - u_int64_t timeout) -{ - int ret; - u_int8_t prescaler, divisor; - - ret = best_prescaler(timeout*RC632_TIMEOUT_FUZZ_FACTOR, - &prescaler, &divisor); - - ret = rc632_reg_write(handle, RC632_REG_TIMER_CLOCK, - prescaler & 0x1f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_TIMER_CONTROL, - RC632_TMR_START_TX_END|RC632_TMR_STOP_RX_BEGIN); - - /* clear timer irq bit */ - ret |= rc632_set_bits(handle, RC632_REG_INTERRUPT_RQ, RC632_INT_TIMER); - -#ifdef USE_IRQ_ - /* enable interrupt for expired timer */ - ret |= rc632_reg_write(handle, RC632_REG_INTERRUPT_EN, - RC632_INT_TIMER|RC632_INT_SET); -#endif - - ret |= rc632_reg_write(handle, RC632_REG_TIMER_RELOAD, divisor); - - return ret; -} - -/* Wait until RC632 is idle or TIMER IRQ has happened */ -static int rc632_wait_idle_timer(struct rfid_asic_handle *handle) -{ - int ret; - u_int8_t irq, cmd; - - while (1) { - ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_RQ, &irq); - if (ret < 0) - return ret; - - /* FIXME: currently we're lazy: If we actually received - * something even after the timer expired, we accept it */ - if (irq & RC632_INT_TIMER && !(irq & RC632_INT_RX)) { - u_int8_t foo; - rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo); - DEBUGPCRF("TIMER && !INT_RX, PRIM_STATUS=0x%02x", foo); - if (foo & 0x04) { - rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo); - DEBUGPCRF("ERROR_FLAG=0x%02x, returning timeout", foo); - } - - return -ETIMEDOUT; - } - - ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); - if (ret < 0) - return ret; - - if (cmd == 0 || irq & RC632_INT_RX) - return 0; - - /* poll every millisecond */ - /* FIXME usleep(1000);*/ - } -} - -/* Stupid RC632 implementations don't evaluate interrupts but poll the - * command register for "status idle" */ -static int -rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t timeout) -{ - u_int8_t cmd = 0xff; - int ret, cycles = 0; -#define USLEEP_PER_CYCLE 128 - - while (cmd != 0) { - ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd); - if (ret < 0) - return ret; - - if (cmd == 0) { - /* FIXME: read second time ?? */ - return 0; - } - - { - u_int8_t foo; - rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo); - if (foo & 0x04) - rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo); - } - - /* Abort after some timeout */ - if (cycles > timeout*RC632_TIMEOUT_FUZZ_FACTOR/USLEEP_PER_CYCLE) { - return -ETIMEDOUT; - } - - cycles++; - usleep(USLEEP_PER_CYCLE); - } - - return 0; -} - -static int -rc632_transmit(struct rfid_asic_handle *handle, - const u_int8_t *buf, - u_int8_t len, - u_int64_t timeout) -{ - int ret, cur_len; - const u_int8_t *cur_buf = buf; - - if (len > 64) - cur_len = 64; - else - cur_len = len; - - do { - ret = rc632_fifo_write(handle, cur_len, cur_buf, 0x03); - if (ret < 0) - return ret; - - if (cur_buf == buf) { - /* only start transmit first time */ - ret = rc632_reg_write(handle, RC632_REG_COMMAND, - RC632_CMD_TRANSMIT); - if (ret < 0) - return ret; - } - - cur_buf += cur_len; - if (cur_buf < buf + len) { - cur_len = buf - cur_buf; - if (cur_len > 64) - cur_len = 64; - } else - cur_len = 0; - - } while (cur_len); - - return rc632_wait_idle(handle, timeout); -} - -static int -tcl_toggle_pcb(struct rfid_asic_handle *handle) -{ - // FIXME: toggle something between 0x0a and 0x0b - return 0; -} - -static int -rc632_transceive(struct rfid_asic_handle *handle, - const u_int8_t *tx_buf, - u_int8_t tx_len, - u_int8_t *rx_buf, - u_int8_t *rx_len, - u_int64_t timer, - unsigned int toggle) -{ - int ret, cur_tx_len; - const u_int8_t *cur_tx_buf = tx_buf; - - DEBUGPCRF("tx_len=%u, rx_len=%u, timer=%llu", tx_len, *rx_len, timer); - - if (tx_len > 64) - cur_tx_len = 64; - else - cur_tx_len = tx_len; - - ret = rc632_reg_write(handle, RC632_REG_COMMAND, 0x00); - /* clear all interrupts */ - ret = rc632_reg_write(handle, RC632_REG_INTERRUPT_RQ, 0x7f); - if (ret < 0) - return ret; - - ret = rc632_timer_set(handle, timer); - if (ret < 0) - return ret; - - do { - ret = rc632_fifo_write(handle, cur_tx_len, cur_tx_buf, 0x03); - if (ret < 0) - return ret; - - if (cur_tx_buf == tx_buf) { - ret = rc632_reg_write(handle, RC632_REG_COMMAND, - RC632_CMD_TRANSCEIVE); - if (ret < 0) - return ret; - } - - cur_tx_buf += cur_tx_len; - if (cur_tx_buf < tx_buf + tx_len) { - u_int8_t fifo_fill; - ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, - &fifo_fill); - if (ret < 0) - return ret; - - cur_tx_len = 64 - fifo_fill; - DEBUGPCRF("refilling tx fifo with %u bytes", cur_tx_len); - } else - cur_tx_len = 0; - - } while (cur_tx_len); - - if (toggle == 1) - tcl_toggle_pcb(handle); - - ret = rc632_wait_idle_timer(handle); - if (ret < 0) - return ret; - - ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, rx_len); - if (ret < 0) - return ret; - - DEBUGPCRF("rx_len = %u\n", *rx_len); - - if (*rx_len == 0) { - u_int8_t tmp, tmp2; - - rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &tmp); - rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp2); - - DEBUGPCRF("rx_len == 0, error_flag=0x%02x, channel_red=0x%02x", - tmp, tmp2); - - return -1; - } - - return rc632_fifo_read(handle, *rx_len, rx_buf); -} - int rc632_read_eeprom(struct rfid_asic_handle *handle, u_int16_t addr, u_int8_t len, u_int8_t *recvbuf) @@ -385,1094 +106,31 @@ rc632_read_eeprom(struct rfid_asic_handle *handle, u_int16_t addr, u_int8_t len, sndbuf[1] = addr >> 8; sndbuf[2] = len; - ret = rc632_fifo_write(handle, 3, sndbuf, 0x03); + ret = opcd_rc632_fifo_write(handle, 3, sndbuf, 0x03); if (ret < 0) return ret; - ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_READ_E2); + ret = opcd_rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_READ_E2); if (ret < 0) return ret; /* usleep(20000); */ - ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &err); + ret = opcd_rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &err); if (err & RC632_ERR_FLAG_ACCESS_ERR) return -EPERM; - ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, &err); + ret = opcd_rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, &err); if (err < len) len = err; - ret = rc632_fifo_read(handle, len, recvbuf); + ret = opcd_rc632_fifo_read(handle, len, recvbuf); if (ret < 0) return ret; return len; } -static int -rc632_calc_crc16_from(struct rfid_asic_handle *handle) -{ - u_int8_t sndbuf[2] = { 0x01, 0x02 }; - u_int8_t crc_lsb = 0x00 , crc_msb = 0x00; - int ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x12); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xe0); - if (ret < 0) - return ret; - - ret = rc632_fifo_write(handle, sizeof(sndbuf), sndbuf, 3); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_CALC_CRC); - if (ret < 0) - return ret; - - usleep(10000); // FIXME: no checking for cmd completion? - - ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_LSB, &crc_lsb); - if (ret < 0) - return ret; - - ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_MSB, &crc_msb); - if (ret < 0) - return ret; - - // FIXME: what to do with crc result? - return ret; -} - - -int -rc632_register_dump(struct rfid_asic_handle *handle, u_int8_t *buf) -{ - int ret; - u_int8_t i; - - for (i = 0; i <= 0x3f; i++) { - ret = rc632_reg_read(handle, i, &buf[i]); - // do we want error checks? - } - return 0; -} - - -#if 0 -static int -rc632_init(struct rfid_asic_handle *ah) -{ - int ret; - - /* switch off rf (make sure PICCs are reset at init time) */ - ret = rc632_power_down(ah); - if (ret < 0) - return ret; - - usleep(10000); - - /* switch on rf */ - ret = rc632_power_up(ah); - if (ret < 0) - return ret; - - /* disable register paging */ - ret = rc632_reg_write(ah, 0x00, 0x00); - if (ret < 0) - return ret; - - /* set some sane default values */ - ret = rc632_reg_write(ah, 0x11, 0x5b); - if (ret < 0) - return ret; - - /* switch on rf */ - ret = rc632_turn_on_rf(ah); - if (ret < 0) - return ret; - - return 0; -} - -static int -rc632_fini(struct rfid_asic_handle *ah) -{ - int ret; - - /* switch off rf */ - ret = rc632_turn_off_rf(ah); - if (ret < 0) - return ret; - - ret = rc632_power_down(ah); - if (ret < 0) - return ret; - - return 0; -} -#endif - - -/* - * Philips CL RC632 primitives for ISO 14443-A compliant PICC's - * - * (C) 2005 by Harald Welte <laforge@gnumonks.org> - * - */ - -int -rc632_iso14443a_init(struct rfid_asic_handle *handle) -{ - int ret; - - // FIXME: some fifo work (drain fifo?) - - /* flush fifo (our way) */ - ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01); - - ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL, - (RC632_TXCTRL_TX1_RF_EN | - RC632_TXCTRL_TX2_RF_EN | - RC632_TXCTRL_TX2_INV | - RC632_TXCTRL_FORCE_100_ASK | - RC632_TXCTRL_MOD_SRC_INT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, - OPENPCD_CW_CONDUCTANCE); - if (ret < 0) - return ret; - - /* Since FORCE_100_ASK is set (cf mc073930.pdf), this line may be left out? */ - ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, - OPENPCD_MOD_CONDUCTANCE); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL, - (RC632_CDRCTRL_TXCD_14443A | - RC632_CDRCTRL_RATE_106K)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1, - (RC632_RXCTRL1_GAIN_35DB | - RC632_RXCTRL1_ISO14443 | - RC632_RXCTRL1_SUBCP_8)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL, - (RC632_DECCTRL_MANCHESTER | - RC632_DECCTRL_RXFR_14443A)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE, - OPENPCD_14443A_BITPHASE); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, - OPENPCD_14443A_THRESHOLD); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2, - (RC632_RXCTRL2_DECSRC_INT | - RC632_RXCTRL2_CLK_Q)); - if (ret < 0) - return ret; - - /* Omnikey proprietary driver has 0x03, but 0x06 is the default reset value ?!? */ - ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x06); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_PARITY_ENABLE | - RC632_CR_PARITY_ODD)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x63); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0x63); - if (ret < 0) - return ret; - - return 0; -} - -static int -rc632_iso14443a_fini(struct iso14443a_handle *handle_14443) -{ - -#if 0 - ret = rc632_turn_off_rf(handle); - if (ret < 0) - return ret; -#endif - - - return 0; -} - - -/* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */ -int -rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle, - u_int8_t cmd, - struct iso14443a_atqa *atqa) -{ - int ret; - u_int8_t tx_buf[1]; - u_int8_t rx_len = 2; - - DEBUGPCRF(""); - memset(atqa, 0, sizeof(*atqa)); - - tx_buf[0] = cmd; - - /* transfer only 7 bits of last byte in frame */ - ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07); - if (ret < 0) - return ret; - - ret = rc632_clear_bits(handle, RC632_REG_CONTROL, - RC632_CONTROL_CRYPTO1_ON); - if (ret < 0) - return ret; - -#if 0 - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_PARITY_ENABLE | - RC632_CR_PARITY_ODD)); -#else - ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); - -#endif - if (ret < 0) - return ret; - - ret = rc632_transceive(handle, tx_buf, sizeof(tx_buf), - (u_int8_t *)atqa, &rx_len, - ISO14443A_FDT_ANTICOL_LAST1, 0); - if (ret < 0) { - DEBUGPCRF("error during rc632_transceive()"); - return ret; - } - - /* switch back to normal 8bit last byte */ - ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00); - if (ret < 0) - return ret; - - if (rx_len != 2) { - DEBUGPCRF("rx_len(%d) != 2", rx_len); - return -1; - } - - return 0; -} - -/* transceive regular frame */ -int -rc632_iso14443ab_transceive(struct rfid_asic_handle *handle, - unsigned int frametype, - const u_int8_t *tx_buf, unsigned int tx_len, - u_int8_t *rx_buf, unsigned int *rx_len, - u_int64_t timeout, unsigned int flags) -{ - int ret; - u_int8_t rxl = *rx_len & 0xff; - u_int8_t channel_red; - - DEBUGPCRF("tx_len=%u, rx_len=%u", tx_len, *rx_len); - - memset(rx_buf, 0, *rx_len); - - switch (frametype) { - case RFID_14443A_FRAME_REGULAR: - case RFID_MIFARE_FRAME: - channel_red = RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE - |RC632_CR_PARITY_ENABLE|RC632_CR_PARITY_ODD; - break; - case RFID_14443B_FRAME_REGULAR: - channel_red = RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE - |RC632_CR_CRC3309; - break; -#if 0 - case RFID_MIFARE_FRAME: - channel_red = RC632_CR_PARITY_ENABLE|RC632_CR_PARITY_ODD; - break; -#endif - default: - return -EINVAL; - break; - } - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - channel_red); - if (ret < 0) - return ret; - - ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, timeout, 0); - *rx_len = rxl; - if (ret < 0) - return ret; - - - return 0; -} - -/* transceive anti collission bitframe */ -int -rc632_iso14443a_transceive_acf(struct rfid_asic_handle *handle, - struct iso14443a_anticol_cmd *acf, - unsigned int *bit_of_col) -{ - int ret; - u_int8_t rx_buf[64]; - u_int8_t rx_len = sizeof(rx_buf); - u_int8_t rx_align = 0, tx_last_bits, tx_bytes; - u_int8_t boc; - u_int8_t error_flag; - *bit_of_col = ISO14443A_BITOFCOL_NONE; - memset(rx_buf, 0, sizeof(rx_buf)); - - /* disable mifare cryto */ - ret = rc632_clear_bits(handle, RC632_REG_CONTROL, - RC632_CONTROL_CRYPTO1_ON); - if (ret < 0) - return ret; - - /* disable CRC summing */ -#if 0 - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_PARITY_ENABLE | - RC632_CR_PARITY_ODD)); -#else - ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); -#endif - if (ret < 0) - return ret; - - tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */ - tx_bytes = acf->nvb >> 4; - if (tx_last_bits) { - tx_bytes++; - rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */ - } - - //rx_align = 8 - tx_last_bits;/* rx frame complements tx */ - - /* set RxAlign and TxLastBits*/ - ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, - (rx_align << 4) | (tx_last_bits)); - if (ret < 0) - return ret; - - ret = rc632_transceive(handle, (u_int8_t *)acf, tx_bytes, - rx_buf, &rx_len, 0x32, 0); - if (ret < 0) - return ret; - - /* bitwise-OR the two halves of the split byte */ - acf->uid_bits[tx_bytes-2] = ( - (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits))) - | rx_buf[0]); - /* copy the rest */ - memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1); - - /* determine whether there was a collission */ - ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); - if (ret < 0) - return ret; - - if (error_flag & RC632_ERR_FLAG_COL_ERR) { - /* retrieve bit of collission */ - ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc); - if (ret < 0) - return ret; - - /* bit of collission relative to start of part 1 of - * anticollision frame (!) */ - *bit_of_col = 2*8 + boc; - } - - return 0; -} - -enum rc632_rate { - RC632_RATE_106 = 0x00, - RC632_RATE_212 = 0x01, - RC632_RATE_424 = 0x02, - RC632_RATE_848 = 0x03, -}; - -struct rx_config { - u_int8_t subc_pulses; - u_int8_t rx_coding; - u_int8_t rx_threshold; - u_int8_t bpsk_dem_ctrl; -}; - -struct tx_config { - u_int8_t rate; - u_int8_t mod_width; -}; - -static const struct rx_config rx_configs[] = { - { - .subc_pulses = RC632_RXCTRL1_SUBCP_8, - .rx_coding = RC632_DECCTRL_MANCHESTER, - .rx_threshold = 0x88, - .bpsk_dem_ctrl = 0x00, - }, - { - .subc_pulses = RC632_RXCTRL1_SUBCP_4, - .rx_coding = RC632_DECCTRL_BPSK, - .rx_threshold = 0x50, - .bpsk_dem_ctrl = 0x0c, - }, - { - .subc_pulses = RC632_RXCTRL1_SUBCP_2, - .rx_coding = RC632_DECCTRL_BPSK, - .rx_threshold = 0x50, - .bpsk_dem_ctrl = 0x0c, - }, - { - .subc_pulses = RC632_RXCTRL1_SUBCP_1, - .rx_coding = RC632_DECCTRL_BPSK, - .rx_threshold = 0x50, - .bpsk_dem_ctrl = 0x0c, - }, -}; - -static const struct tx_config tx_configs[] = { - { - .rate = RC632_CDRCTRL_RATE_106K, - .mod_width = 0x13, - }, - { - .rate = RC632_CDRCTRL_RATE_212K, - .mod_width = 0x07, - }, - { - .rate = RC632_CDRCTRL_RATE_424K, - .mod_width = 0x03, - }, - { - .rate = RC632_CDRCTRL_RATE_848K, - .mod_width = 0x01, - }, -}; - -int rc632_iso14443a_set_speed(struct rfid_asic_handle *handle, - unsigned int tx, - u_int8_t rate) -{ - int rc; - u_int8_t reg; - - - if (!tx) { - /* Rx */ - if (rate > ARRAY_SIZE(rx_configs)) - return -EINVAL; - - rc = rc632_set_bit_mask(handle, RC632_REG_RX_CONTROL1, - RC632_RXCTRL1_SUBCP_MASK, - rx_configs[rate].subc_pulses); - if (rc < 0) - return rc; - - rc = rc632_set_bit_mask(handle, RC632_REG_DECODER_CONTROL, - RC632_DECCTRL_BPSK, - rx_configs[rate].rx_coding); - if (rc < 0) - return rc; - - rc = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, - rx_configs[rate].rx_threshold); - if (rc < 0) - return rc; - - if (rx_configs[rate].rx_coding == RC632_DECCTRL_BPSK) { - rc = rc632_reg_write(handle, - RC632_REG_BPSK_DEM_CONTROL, - rx_configs[rate].bpsk_dem_ctrl); - if (rc < 0) - return rc; - } - } else { - /* Tx */ - if (rate > ARRAY_SIZE(tx_configs)) - return -EINVAL; - - rc = rc632_set_bit_mask(handle, RC632_REG_CODER_CONTROL, - RC632_CDRCTRL_RATE_MASK, - tx_configs[rate].rate); - if (rc < 0) - return rc; - - rc = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, - tx_configs[rate].mod_width); - if (rc < 0) - return rc; - } - - return 0; -} - -static int rc632_iso14443b_init(struct rfid_asic_handle *handle) -{ - int ret; - - // FIXME: some FIFO work - - /* flush fifo (our way) */ - ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL, - (RC632_TXCTRL_TX1_RF_EN | - RC632_TXCTRL_TX2_RF_EN | - RC632_TXCTRL_TX2_INV | - RC632_TXCTRL_MOD_SRC_INT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, 0x04); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL, - (RC632_CDRCTRL_TXCD_NRZ | - RC632_CDRCTRL_RATE_14443B)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING, - (RC632_TBFRAMING_SOF_11L_3H | - (6 << RC632_TBFRAMING_SPACE_SHIFT) | - RC632_TBFRAMING_EOF_11)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1, - (RC632_RXCTRL1_GAIN_35DB | - RC632_RXCTRL1_ISO14443 | - RC632_RXCTRL1_SUBCP_8)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL, - (RC632_DECCTRL_BPSK | - RC632_DECCTRL_RXFR_14443B)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE, - OPENPCD_14443B_BITPHASE); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD, - OPENPCD_14443B_THRESHOLD); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, - ((0x2 & RC632_BPSKD_TAUB_MASK)<<RC632_BPSKD_TAUB_SHIFT | - (0x3 & RC632_BPSKD_TAUD_MASK)<<RC632_BPSKD_TAUD_SHIFT | - RC632_BPSKD_FILTER_AMP_DETECT | - RC632_BPSKD_NO_RX_EOF | - RC632_BPSKD_NO_RX_EGT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2, - (RC632_RXCTRL2_AUTO_PD | - RC632_RXCTRL2_DECSRC_INT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_TX_CRC_ENABLE | - RC632_CR_RX_CRC_ENABLE | - RC632_CR_CRC3309)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0xff); - if (ret < 0) - return ret; - - ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xff); - if (ret < 0) - return ret; - - return 0; -} - -static int -rc632_iso15693_init(struct rfid_asic_handle *h) -{ - int ret; - - ret = rc632_reg_write(h, RC632_REG_TX_CONTROL, - (RC632_TXCTRL_MOD_SRC_INT | - RC632_TXCTRL_TX2_INV | - RC632_TXCTRL_TX2_RF_EN | - RC632_TXCTRL_TX1_RF_EN)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x03); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, - (RC632_CDRCTRL_RATE_15693 | - 0x03)); /* FIXME */ - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_TYPE_B_FRAMING, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, - (RC632_RXCTRL1_SUBCP_16 | - RC632_RXCTRL1_ISO15693 | - RC632_RXCTRL1_GAIN_35DB)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, - (RC632_DECCTRL_RXFR_15693 | - RC632_DECCTRL_RX_INVERT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0xe0); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0xff); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2, - (RC632_RXCTRL2_AUTO_PD | - RC632_RXCTRL2_DECSRC_INT)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_CRC3309 | - RC632_CR_RX_CRC_ENABLE | - RC632_CR_TX_CRC_ENABLE)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0xff); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xff); - if (ret < 0) - return ret; - - return 0; -} - -static int -rc632_iso15693_icode_init(struct rfid_asic_handle *h) -{ - int ret; - - ret = rc632_reg_write(h, RC632_REG_TX_CONTROL, - (RC632_TXCTRL_MOD_SRC_INT | - RC632_TXCTRL_TX2_INV | - RC632_TXCTRL_TX2_RF_EN | - RC632_TXCTRL_TX1_RF_EN)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x02); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, 0x2c); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_TYPE_B_FRAMING, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, 0x8b); /* FIXME */ - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0x52); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0x66); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2, - RC632_RXCTRL2_DECSRC_INT); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_RX_CRC_ENABLE | - RC632_CR_TX_CRC_ENABLE)); - ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0xfe); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xff); - if (ret < 0) - return ret; - - return 0; -} - -static int -rc632_iso15693_icl_init(struct rfid_asic_handle *h) -{ - int ret; - - /* ICL */ - - ret = rc632_reg_write(h, RC632_REG_TX_CONTROL, - (RC632_TXCTRL_MOD_SRC_INT | - RC632_TXCTRL_TX2_INV | - RC632_TXCTRL_TX2_RF_EN | - RC632_TXCTRL_TX1_RF_EN)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CW_CONDUCTANCE, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_CONDUCTANCE, 0x11); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CODER_CONTROL, - (RC632_CDRCTRL_RATE_15693 | - RC632_CDRCTRL_TXCD_ICODE_STD | - 0x03)); /* FIXME */ - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH, 0x3f); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_MOD_WIDTH_SOF, 0x3f); - if (ret < 0) - return ret; - ret = rc632_reg_write(h, RC632_REG_RX_CONTROL1, - (RC632_RXCTRL1_SUBCP_16| - RC632_RXCTRL1_ISO15693| - RC632_RXCTRL1_GAIN_35DB)); - if (ret < 0) - return ret; - ret = rc632_reg_write(h, RC632_REG_DECODER_CONTROL, - (RC632_DECCTRL_RX_INVERT| - RC632_DECCTRL_RXFR_15693)); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_BIT_PHASE, 0xbd); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_THRESHOLD, 0xff); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_BPSK_DEM_CONTROL, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_RX_CONTROL2, - RC632_RXCTRL2_DECSRC_INT); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY, 0x00); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_LSB, 0x12); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_CRC_PRESET_MSB, 0xe0); - if (ret < 0) - return ret; - - return 0; -} - -struct mifare_authcmd { - u_int8_t auth_cmd; - u_int8_t block_address; - u_int32_t serno; /* lsb 1 2 msb */ -} __attribute__ ((packed)); - - -#define RFID_MIFARE_KEY_LEN 6 -#define RFID_MIFARE_KEY_CODED_LEN 12 - -/* Transform crypto1 key from generic 6byte into rc632 specific 12byte */ -static int -rc632_mifare_transform_key(const u_int8_t *key6, u_int8_t *key12) -{ - int i; - u_int8_t ln; - u_int8_t hn; - - for (i = 0; i < RFID_MIFARE_KEY_LEN; i++) { - ln = key6[i] & 0x0f; - hn = key6[i] >> 4; - key12[i * 2 + 1] = (~ln << 4) | ln; - key12[i * 2] = (~hn << 4) | hn; - } - return 0; -} - -static int -rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key) -{ - u_int8_t coded_key[RFID_MIFARE_KEY_CODED_LEN]; - u_int8_t reg; - int ret; - - ret = rc632_mifare_transform_key(key, coded_key); - if (ret < 0) - return ret; - - ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_LOAD_KEY); - if (ret < 0) - return ret; - - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); - if (ret < 0) - return ret; - - ret = rc632_reg_read(h, RC632_REG_ERROR_FLAG, ®); - if (ret < 0) - return ret; - - if (reg & RC632_ERR_FLAG_KEY_ERR) - return -EINVAL; - - return 0; -} - -static int -rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno, - u_int8_t block) -{ - int ret; - struct mifare_authcmd acmd; - u_int8_t reg; - - if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) - return -EINVAL; - - /* Initialize acmd */ - acmd.block_address = block & 0xff; - acmd.auth_cmd = cmd; - //acmd.serno = htonl(serno); - acmd.serno = serno; - - /* Clear Rx CRC */ - ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_RX_CRC_ENABLE); - if (ret < 0) - return ret; - - /* Send Authent1 Command */ - ret = rc632_fifo_write(h, sizeof(acmd), (unsigned char *)&acmd, 0x03); - if (ret < 0) - return ret; - - ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT1); - if (ret < 0) - return ret; - - /* Wait until transmitter is idle */ - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); - if (ret < 0) - return ret; - - ret = rc632_reg_read(h, RC632_REG_SECONDARY_STATUS, ®); - if (ret < 0) - return ret; - if (reg & 0x07) - return -EIO; - - /* Clear Tx CRC */ - ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_TX_CRC_ENABLE); - if (ret < 0) - return ret; - - /* Send Authent2 Command */ - ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT2); - if (ret < 0) - return ret; - - /* Wait until transmitter is idle */ - ret = rc632_wait_idle(h, RC632_TMO_AUTH1); - if (ret < 0) - return ret; - - /* Check whether authentication was successful */ - ret = rc632_reg_read(h, RC632_REG_CONTROL, ®); - if (ret < 0) - return ret; - - if (!(reg & RC632_CONTROL_CRYPTO1_ON)) - return -EACCES; - - return 0; - -} - -/* transceive regular frame */ -static int -rc632_mifare_transceive(struct rfid_asic_handle *handle, - const u_int8_t *tx_buf, unsigned int tx_len, - u_int8_t *rx_buf, unsigned int *rx_len, - u_int64_t timeout, unsigned int flags) -{ - int ret; - u_int8_t rxl = *rx_len & 0xff; - - DEBUGP("entered\n"); - memset(rx_buf, 0, *rx_len); - -#if 1 - ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY, - (RC632_CR_PARITY_ENABLE | - RC632_CR_PARITY_ODD | - RC632_CR_TX_CRC_ENABLE | - RC632_CR_RX_CRC_ENABLE)); -#else - ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY, - RC632_CR_RX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE); -#endif - if (ret < 0) - return ret; - - ret = rc632_transceive(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0); - *rx_len = rxl; - if (ret < 0) - return ret; - - - return 0; -} - #define RC632_E2_PRODUCT_TYPE 0 #define RC632_E2_PRODUCT_SERIAL 8 #define RC632_E2_RS_MAX_P 14 diff --git a/firmware/src/pcd/rc632_highlevel.h b/firmware/src/pcd/rc632_highlevel.h new file mode 100644 index 0000000..40e80e0 --- /dev/null +++ b/firmware/src/pcd/rc632_highlevel.h @@ -0,0 +1,19 @@ +#ifndef _RC632_HIGHLEVEL_H +#define _RC632_HIGHLEVEL_H + +#include <sys/types.h> +#include <librfid/rfid_asic.h> + +int +rc632_turn_on_rf(struct rfid_asic_handle *handle); + +int +rc632_turn_off_rf(struct rfid_asic_handle *handle); + +int +rc632_read_eeprom(struct rfid_asic_handle *handle, u_int16_t addr, u_int8_t len, + u_int8_t *recvbuf); + +int rc632_get_serial(struct rfid_asic_handle *handle, + u_int32_t *serial); +#endif /* _RC632_HIGHLEVEL_H */ diff --git a/firmware/src/pcd/rfid_layer2_iso14443a.c b/firmware/src/pcd/rfid_layer2_iso14443a.c deleted file mode 100644 index d4f910d..0000000 --- a/firmware/src/pcd/rfid_layer2_iso14443a.c +++ /dev/null @@ -1,319 +0,0 @@ -/* ISO 14443-3 A anticollision implementation - * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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 <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include <librfid/rfid.h> -#include <librfid/rfid_layer2.h> -//#include <librfid/rfid_reader.h> -#include <librfid/rfid_layer2_iso14443a.h> - -#define TIMEOUT 1236 - -/* Transceive a 7-bit short frame */ -static int -iso14443a_transceive_sf(struct rfid_layer2_handle *handle, - unsigned char cmd, - struct iso14443a_atqa *atqa) -{ - //struct rfid_reader *rdr = handle->rh->reader; - DEBUGPCRF(""); - - return rc632_iso14443a_transceive_sf(handle->rh, cmd, atqa); -} - -/* Transmit an anticollission bit frame */ -static int -iso14443a_transceive_acf(struct rfid_layer2_handle *handle, - struct iso14443a_anticol_cmd *acf, - unsigned int *bit_of_col) -{ - //struct rfid_reader *rdr = handle->rh->reader; - DEBUGPCRF(""); - - return rc632_iso14443a_transceive_acf(handle->rh, acf, bit_of_col); -} - -/* Transmit a regular frame */ -static int -iso14443a_transceive(struct rfid_layer2_handle *handle, - enum rfid_frametype frametype, - const unsigned char *tx_buf, unsigned int tx_len, - unsigned char *rx_buf, unsigned int *rx_len, - u_int64_t timeout, unsigned int flags) -{ - DEBUGPCRF("tx_len=%u, rx_len=%u", tx_len, *rx_len); - return rc632_iso14443ab_transceive(handle->rh, frametype, tx_buf, - tx_len, rx_buf, rx_len, timeout, flags); -} - -static int -iso14443a_code_nvb_bits(unsigned char *nvb, unsigned int bits) -{ - unsigned int byte_count = bits / 8; - unsigned int bit_count = bits % 8; - - if (byte_count < 2 || byte_count > 7) - return -1; - - *nvb = ((byte_count & 0xf) << 4) | bit_count; - - return 0; -} - -/* first bit is '1', second bit '2' */ -static void -set_bit_in_field(unsigned char *bitfield, unsigned int bit) -{ - unsigned int byte_count = bit / 8; - unsigned int bit_count = bit % 8; - - DEBUGP("bitfield=%p, byte_count=%u, bit_count=%u\n", - bitfield, byte_count, bit_count); - DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count)); - *(bitfield+byte_count) |= 1 << (bit_count-1); - DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count)); -} - -static int -iso14443a_anticol(struct rfid_layer2_handle *handle) -{ - int ret; - unsigned int uid_size; - struct iso14443a_handle *h = &handle->priv.iso14443a; - struct iso14443a_atqa atqa; - struct iso14443a_anticol_cmd acf; - unsigned int bit_of_col; - unsigned char sak[3]; - unsigned int rx_len = sizeof(sak); - char *aqptr = (char *) &atqa; - - memset(handle->uid, 0, sizeof(handle->uid)); - memset(sak, 0, sizeof(sak)); - memset(&atqa, 0, sizeof(atqa)); - memset(&acf, 0, sizeof(acf)); - - ret = iso14443a_transceive_sf(handle, ISO14443A_SF_CMD_REQA, &atqa); - if (ret < 0) { - h->state = ISO14443A_STATE_REQA_SENT; - DEBUGP("error during transceive_sf: %d\n", ret); - return ret; - } - h->state = ISO14443A_STATE_ATQA_RCVD; - - DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1)); - - if (!atqa.bf_anticol) { - h->state = ISO14443A_STATE_NO_BITFRAME_ANTICOL; - DEBUGP("no bitframe anticollission bits set, aborting\n"); - return -1; - } - - if (atqa.uid_size == 2 || atqa.uid_size == 3) - uid_size = 3; - else if (atqa.uid_size == 1) - uid_size = 2; - else - uid_size = 1; - - acf.sel_code = ISO14443A_AC_SEL_CODE_CL1; - - h->state = ISO14443A_STATE_ANTICOL_RUNNING; - h->level = ISO14443A_LEVEL_CL1; - -cascade: - iso14443a_code_nvb_bits(&acf.nvb, 16); - - ret = iso14443a_transceive_acf(handle, &acf, &bit_of_col); - if (ret < 0) - return ret; - DEBUGP("bit_of_col = %d\n", bit_of_col); - - while (bit_of_col != ISO14443A_BITOFCOL_NONE) { - set_bit_in_field(&acf.uid_bits[0], bit_of_col-16); - iso14443a_code_nvb_bits(&acf.nvb, bit_of_col); - ret = iso14443a_transceive_acf(handle, &acf, &bit_of_col); - DEBUGP("bit_of_col = %d\n", bit_of_col); - if (ret < 0) - return ret; - } - - iso14443a_code_nvb_bits(&acf.nvb, 7*8); - rx_len = sizeof(sak); - ret = iso14443a_transceive(handle, RFID_14443A_FRAME_REGULAR, - (unsigned char *)&acf, 7, - (unsigned char *) &sak, &rx_len, - TIMEOUT, 0); - if (ret < 0) - return ret; - - if (sak[0] & 0x04) { - /* Cascade bit set, UID not complete */ - switch (acf.sel_code) { - case ISO14443A_AC_SEL_CODE_CL1: - /* cascading from CL1 to CL2 */ - if (acf.uid_bits[0] != 0x88) { - DEBUGP("Cascade bit set, but UID0 != 0x88\n"); - return -1; - } - memcpy(&handle->uid[0], &acf.uid_bits[1], 3); - acf.sel_code = ISO14443A_AC_SEL_CODE_CL2; - h->level = ISO14443A_LEVEL_CL2; - break; - case ISO14443A_AC_SEL_CODE_CL2: - /* cascading from CL2 to CL3 */ - memcpy(&handle->uid[3], &acf.uid_bits[1], 3); - acf.sel_code = ISO14443A_AC_SEL_CODE_CL3; - h->level = ISO14443A_LEVEL_CL3; - break; - default: - DEBUGP("cannot cascade any further than CL3\n"); - h->state = ISO14443A_STATE_ERROR; - return -1; - break; - } - goto cascade; - - } else { - switch (acf.sel_code) { - case ISO14443A_AC_SEL_CODE_CL1: - /* single size UID (4 bytes) */ - memcpy(&handle->uid[0], &acf.uid_bits[0], 4); - break; - case ISO14443A_AC_SEL_CODE_CL2: - /* double size UID (7 bytes) */ - memcpy(&handle->uid[3], &acf.uid_bits[0], 4); - break; - case ISO14443A_AC_SEL_CODE_CL3: - /* triple size UID (10 bytes) */ - memcpy(&handle->uid[6], &acf.uid_bits[0], 4); - break; - } - } - - h->level = ISO14443A_LEVEL_NONE; - h->state = ISO14443A_STATE_SELECTED; - - { - if (uid_size == 1) - handle->uid_len = 4; - else if (uid_size == 2) - handle->uid_len = 7; - else - handle->uid_len = 10; - - DEBUGP("UID %s\n", rfid_hexdump(handle->uid, handle->uid_len)); - } - - if (sak[0] & 0x20) { - DEBUGP("we have a T=CL compliant PICC\n"); - h->tcl_capable = 1; - } else { - DEBUGP("we have a T!=CL PICC\n"); - h->tcl_capable = 0; - } - - return 0; -} - -static int -iso14443a_hlta(struct rfid_layer2_handle *handle) -{ - int ret; - unsigned char tx_buf[2] = { 0x50, 0x00 }; - unsigned char rx_buf[10]; - unsigned int rx_len = sizeof(rx_buf); - - ret = iso14443a_transceive(handle, RFID_14443A_FRAME_REGULAR, - tx_buf, sizeof(tx_buf), - rx_buf, &rx_len, 1000 /* 1ms */, 0); - if (ret < 0) { - /* "error" case: we don't get somethng back from the card */ - return 0; - } - return -1; -} - -static int -iso14443a_setopt(struct rfid_layer2_handle *handle, int optname, - const void *optval, unsigned int optlen) -{ - int ret = -EINVAL; - unsigned int speed; - - switch (optname) { - case RFID_OPT_14443A_SPEED_RX: - speed = *(unsigned int *)optval; - ret = rc632_iso14443a_set_speed(handle->rh, 0, speed); - break; - case RFID_OPT_14443A_SPEED_TX: - speed = *(unsigned int *)optval; - ret = rc632_iso14443a_set_speed(handle->rh, 1, speed); - break; - }; - - return ret; -} - - -static struct rfid_layer2_handle * -iso14443a_init(struct rfid_reader_handle *rh) -{ - int ret; - struct rfid_layer2_handle *h = malloc(sizeof(*h)); - if (!h) - return NULL; - - h->l2 = &rfid_layer2_iso14443a; - h->rh = rh; - h->priv.iso14443a.state = ISO14443A_STATE_NONE; - h->priv.iso14443a.level = ISO14443A_LEVEL_NONE; - - ret = rc632_iso14443a_init(h->rh); - if (ret < 0) { - free(h); - return NULL; - } - - return h; -} - -static int -iso14443a_fini(struct rfid_layer2_handle *handle) -{ - free(handle); - return 0; -} - -struct rfid_layer2 rfid_layer2_iso14443a = { - .id = RFID_LAYER2_ISO14443A, - .name = "ISO 14443-3 A", - .fn = { - .init = &iso14443a_init, - .open = &iso14443a_anticol, - .transceive = &iso14443a_transceive, - .close = &iso14443a_hlta, - .fini = &iso14443a_fini, - .setopt = &iso14443a_setopt, - }, -}; diff --git a/firmware/src/picc/main_openpicc.c b/firmware/src/picc/main_openpicc.c index df754de..ff89dc2 100644 --- a/firmware/src/picc/main_openpicc.c +++ b/firmware/src/picc/main_openpicc.c @@ -35,8 +35,8 @@ #include <picc/ssc_picc.h> #include <picc/load_modulation.h> -static const u_int16_t cdivs[] = { 128, 64, 32, 16 }; -static u_int8_t cdiv_idx = 0; +static const u_int16_t cdivs[] = { 8192, 2048, 1024, 512, 128, 64, 32, 16 }; +static u_int8_t cdiv_idx = 6; static u_int16_t duty_percent = 22; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -53,12 +53,12 @@ void _init_func(void) poti_init(); load_mod_init(); tc_cdiv_init(); - //tc_fdt_init(); + tc_fdt_init(); pwm_init(); adc_init(); ssc_rx_init(); - // ssc_tx_init(); - + ssc_tx_init(); + /* high-level protocol */ decoder_init(); opicc_usbapi_init(); @@ -80,7 +80,7 @@ static void help(void) DEBUGPCR("v: decrease load_mod b: increase load_mod\r\n" "B: read button S: toggle nSLAVE_RESET\r\n" "a: SSC stop s: SSC start\r\n" - "d: SSC mode select"); + "d: SSC mode select T: TC_CDIV_HELP enable\r\n"); } int _main_dbgu(char key) @@ -88,6 +88,7 @@ int _main_dbgu(char key) static u_int8_t poti = 64; static u_int8_t pll_inh = 1; static u_int8_t ssc_mode = 1; + static u_int8_t sync_enabled = 0; DEBUGPCRF("main_dbgu"); @@ -218,12 +219,25 @@ int _main_dbgu(char key) ssc_rx_start(); break; case 'd': - ssc_rx_mode_set(++ssc_mode); + ssc_mode++; + if (ssc_mode >= 6) + ssc_mode = 0; + ssc_rx_mode_set(ssc_mode); DEBUGPCRF("SSC MODE %u", ssc_mode); break; + case 'T': + if (sync_enabled) { + tc_cdiv_sync_disable(); + sync_enabled = 0; + } else { + tc_cdiv_sync_enable(); + sync_enabled = 1; + } + break; } tc_cdiv_print(); + //tc_fdt_print(); return -EINVAL; } @@ -236,5 +250,6 @@ void _main_func(void) /* next we deal with incoming reqyests from USB EP1 (OUT) */ usb_in_process(); + udp_unthrottle(); ssc_rx_unthrottle(); } diff --git a/firmware/src/picc/openpicc.c b/firmware/src/picc/openpicc.c index 7b2b5f2..fa1f840 100644 --- a/firmware/src/picc/openpicc.c +++ b/firmware/src/picc/openpicc.c @@ -20,6 +20,7 @@ static u_int16_t opicc_regs[_OPICC_NUM_REGS] = { [OPICC_REG_14443A_FDT0] = 1236, [OPICC_REG_14443A_FDT1] = 1172, [OPICC_REG_14443A_STATE] = ISO14443A_ST_POWEROFF, + [OPICC_REG_14443A_ATQA] = 0x0001, [OPICC_REG_RX_CLK_DIV] = 32, [OPICC_REG_RX_CLK_PHASE] = 0, [OPICC_REG_RX_CONTROL] = 0, @@ -62,9 +63,10 @@ static int opicc_reg_usb_in(struct req_ctx *rctx) break; case OPENPCD_CMD_PICC_REG_WRITE: if (rctx->tot_len < sizeof(*poh) + sizeof(u_int16_t)) { - poh->flags = OPENPCD_FLAG_ERROR; - } - opicc_reg_write(poh->reg, *val16); + /* we only have an 8bit write */ + opicc_reg_write(poh->reg, poh->val); + } else + opicc_reg_write(poh->reg, *val16); break; default: return USB_ERR(USB_ERR_CMD_UNKNOWN); diff --git a/firmware/src/picc/pll.c b/firmware/src/picc/pll.c index 7eb49a4..e48911d 100644 --- a/firmware/src/picc/pll.c +++ b/firmware/src/picc/pll.c @@ -43,9 +43,9 @@ static void pll_lock_change_cb(u_int32_t pio) DEBUGPCRF("PLL LOCK: %d", pll_is_locked()); #if 1 if (pll_is_locked()) - led_switch(1, 1); + led_switch(2, 1); else - led_switch(1, 0); + led_switch(2, 0); #endif } diff --git a/firmware/src/picc/poti.c b/firmware/src/picc/poti.c index 4c94994..e5701dc 100644 --- a/firmware/src/picc/poti.c +++ b/firmware/src/picc/poti.c @@ -31,7 +31,6 @@ void poti_comp_carr(u_int8_t position) while (!(spi->SPI_SR & AT91C_SPI_TDRE)) { } AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SS2_DT_THRESH); - //for (i = 0; i < 0xff; i++) { } /* shift one left, since it is a seven-bit value written as 8 bit xfer */ spi->SPI_TDR = position & 0x7f; while (!(spi->SPI_SR & AT91C_SPI_TDRE)) { } diff --git a/firmware/src/picc/ssc_picc.c b/firmware/src/picc/ssc_picc.c index d4db71a..50dce06 100644 --- a/firmware/src/picc/ssc_picc.c +++ b/firmware/src/picc/ssc_picc.c @@ -22,6 +22,8 @@ * TX side is interconnected with load modulation circuitry */ +//#undef DEBUG + #include <errno.h> #include <string.h> #include <sys/types.h> @@ -31,8 +33,13 @@ #include <os/usb_handler.h> #include <os/dbgu.h> +#include <os/led.h> #include "../openpcd.h" +#include <picc/tc_cdiv_sync.h> + +//#define DEBUG_SSC_REFILL + /* definitions for four-times oversampling */ #define REQA 0x10410441 #define WUPA 0x04041041 @@ -46,6 +53,7 @@ enum ssc_mode { SSC_MODE_14443A_STANDARD, SSC_MODE_14443B, SSC_MODE_EDGE_ONE_SHOT, + SSC_MODE_CONTINUOUS, }; struct ssc_state { @@ -54,23 +62,41 @@ struct ssc_state { }; static struct ssc_state ssc_state; +static const u_int16_t ssc_dmasize[] = { + [SSC_MODE_NONE] = 16, + [SSC_MODE_14443A_SHORT] = 16, /* 64 bytes */ + [SSC_MODE_14443A_STANDARD] = 16, /* 64 bytes */ + [SSC_MODE_14443B] = 16, /* 64 bytes */ + [SSC_MODE_EDGE_ONE_SHOT] = 16, /* 64 bytes */ + [SSC_MODE_CONTINUOUS] = 511, /* 2044 bytes */ +}; + /* This is for four-times oversampling */ -#define ISO14443A_SOF_SAMPLE 0x08 +#define ISO14443A_SOF_SAMPLE 0x01 #define ISO14443A_SOF_LEN 4 +#define SSC_RX_IRQ_MASK (AT91C_SSC_RXRDY | \ + AT91C_SSC_OVRUN | \ + AT91C_SSC_ENDRX | \ + AT91C_SSC_RXBUFF | \ + AT91C_SSC_RXSYN | \ + AT91C_SSC_CP0 | \ + AT91C_SSC_CP1) + +#define SSC_TX_IRQ_MASK (AT91C_SSC_TXRDY | \ + AT91C_SSC_TXEMPTY | \ + AT91C_SSC_ENDTX | \ + AT91C_SSC_TXBUFE | \ + AT91C_SSC_TXSYN) + void ssc_rx_mode_set(enum ssc_mode ssc_mode) { u_int8_t data_len, num_data, sync_len; u_int32_t start_cond; - /* disable Rx */ - ssc->SSC_CR = AT91C_SSC_RXDIS; - - /* disable all Rx related interrupt sources */ - AT91F_SSC_DisableIt(ssc, AT91C_SSC_RXRDY | - AT91C_SSC_OVRUN | AT91C_SSC_ENDRX | - AT91C_SSC_RXBUFF | AT91C_SSC_RXSYN | - AT91C_SSC_CP0 | AT91C_SSC_CP1); + /* disable Rx and all Rx interrupt sources */ + AT91F_SSC_DisableRx(AT91C_BASE_SSC); + AT91F_SSC_DisableIt(ssc, SSC_RX_IRQ_MASK); switch (ssc_mode) { case SSC_MODE_14443A_SHORT: @@ -78,41 +104,48 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode) sync_len = ISO14443A_SOF_LEN; ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; data_len = 32; - num_data = 1; + num_data = 16; break; case SSC_MODE_14443A_STANDARD: start_cond = AT91C_SSC_START_0; sync_len = ISO14443A_SOF_LEN; ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; - data_len = 1; - num_data = 1; /* FIXME */ + data_len = 32; + num_data = 16; /* FIXME */ break; case SSC_MODE_14443B: /* start sampling at first falling data edge */ //start_cond = break; case SSC_MODE_EDGE_ONE_SHOT: + case SSC_MODE_CONTINUOUS: + /* unfortunately we don't have RD and RF interconnected + * (at least not yet in the current hardware) */ //start_cond = AT91C_SSC_START_EDGE_RF; start_cond = AT91C_SSC_START_CONTINOUS; sync_len = 0; - data_len = 8; - num_data = 50; + data_len = 32; + num_data = 16; + break; + case SSC_MODE_NONE: + goto out_set_mode; break; - default: - return; } + //ssc->SSC_RFMR = AT91C_SSC_MSBF | (data_len-1) & 0x1f | ssc->SSC_RFMR = (data_len-1) & 0x1f | (((num_data-1) & 0x0f) << 8) | (((sync_len-1) & 0x0f) << 16); - ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond; + ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | + AT91C_SSC_CKI | start_cond; + /* Enable Rx DMA */ AT91F_PDC_EnableRx(rx_pdc); + /* Enable RX interrupts */ - AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | + AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | AT91C_SSC_CP0 | AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); - +out_set_mode: ssc_state.mode = ssc_mode; - } static void ssc_tx_mode_set(enum ssc_mode ssc_mode) @@ -121,16 +154,15 @@ static void ssc_tx_mode_set(enum ssc_mode ssc_mode) u_int32_t start_cond; /* disable Tx */ - ssc->SSC_CR = AT91C_SSC_TXDIS; + AT91F_SSC_DisableTx(AT91C_BASE_SSC); /* disable all Tx related interrupt sources */ - ssc->SSC_IDR = AT91C_SSC_TXRDY | AT91C_SSC_TXEMPTY | AT91C_SSC_ENDTX | - AT91C_SSC_TXBUFE | AT91C_SSC_TXSYN; + AT91F_SSC_DisableIt(ssc, SSC_TX_IRQ_MASK); switch (ssc_mode) { case SSC_MODE_14443A_SHORT: start_cond = AT91C_SSC_START_RISE_RF; - sync_len = ISO14443A_SOF_LEN; + sync_len = 0; data_len = 32; num_data = 1; break; @@ -138,7 +170,7 @@ static void ssc_tx_mode_set(enum ssc_mode ssc_mode) start_cond = AT91C_SSC_START_0; sync_len = ISO14443A_SOF_LEN; ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; - data_len = 1; + data_len = 32; num_data = 1; /* FIXME */ break; } @@ -147,11 +179,13 @@ static void ssc_tx_mode_set(enum ssc_mode ssc_mode) (((sync_len-1) & 0x0f) << 16); ssc->SSC_TCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond; + AT91F_SSC_EnableIt(ssc, AT91C_SSC_TXSYN); + AT91F_SSC_EnableTx(AT91C_BASE_SSC); #if 0 /* Enable RX interrupts */ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | - AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); - AT91F_PDC_EnableRx(rx_pdc); + AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE); + AT91F_PDC_EnableTx(tx_pdc); ssc_state.mode = ssc_mode; #endif @@ -167,7 +201,7 @@ static struct openpcd_hdr opcd_ssc_hdr = { static inline void init_opcdhdr(struct req_ctx *rctx) { memcpy(rctx->data, &opcd_ssc_hdr, sizeof(opcd_ssc_hdr)); - rctx->tot_len = MAX_HDRSIZE + MAX_REQSIZE -1; + rctx->tot_len = sizeof(opcd_ssc_hdr); } #ifdef DEBUG_SSC_REFILL @@ -176,6 +210,36 @@ static inline void init_opcdhdr(struct req_ctx *rctx) #define DEBUGR(x, args ...) #endif +static int __ramfunc __ssc_rx_refill(int secondary) +{ + struct req_ctx *rctx; + + rctx = req_ctx_find_get(1, RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY); + if (!rctx) { + DEBUGP("no_rctx_for_refill! "); + return -1; + } + init_opcdhdr(rctx); + DEBUGR("filling SSC RX%u dma ctx: %u (len=%u) ", secondary, + req_ctx_num(rctx), rctx->size); + rctx->tot_len = ssc_dmasize[ssc_state.mode]*4 + + sizeof(struct openpcd_hdr); + if (secondary) { + AT91F_PDC_SetNextRx(rx_pdc, rctx->data+MAX_HDRSIZE, + ssc_dmasize[ssc_state.mode]); + ssc_state.rx_ctx[1] = rctx; + } else { + AT91F_PDC_SetRx(rx_pdc, rctx->data+MAX_HDRSIZE, + ssc_dmasize[ssc_state.mode]); + ssc_state.rx_ctx[0] = rctx; + } + + tc_cdiv_sync_reset(); + + return 0; +} + +#if 0 static char dmabuf1[512]; static char dmabuf2[512]; @@ -188,19 +252,16 @@ static char dmabuf2[512]; */ static int8_t ssc_rx_refill(void) { -#if 1 struct req_ctx *rctx; - + DEBUGR("refill "); +#if 1 rctx = req_ctx_find_get(1, RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY); - if (!rctx) { - DEBUGPCRF("no rctx for refill!"); - return -1; - } - init_opcdhdr(rctx); - + DEBUGP("SSC_SR=0x%08x ", ssc->SSC_SR); if (AT91F_PDC_IsRxEmpty(rx_pdc)) { - DEBUGR("filling primary SSC RX dma ctx"); - AT91F_PDC_SetRx(rx_pdc, &rctx->data[MAX_HDRSIZE], + DEBUGR("filling primary SSC RX dma ctx: %u (len=%u) ", + req_ctx_num(rctx), rctx->size); + rctx->tot_len = rctx->size; + AT91F_PDC_SetRx(rx_pdc, rctx->data+MAX_HDRSIZE, (rctx->size-MAX_HDRSIZE)>>2); ssc_state.rx_ctx[0] = rctx; @@ -215,8 +276,10 @@ static int8_t ssc_rx_refill(void) } if (AT91F_PDC_IsNextRxEmpty(rx_pdc)) { - DEBUGR("filling secondary SSC RX dma ctx"); - AT91F_PDC_SetNextRx(rx_pdc, &rctx->data[MAX_HDRSIZE], + DEBUGR("filling secondary SSC RX dma ctx: %u (len=%u) ", + req_ctx_num(rctx), rctx->size); + rctx->tot_len = rctx->size; + AT91F_PDC_SetNextRx(rx_pdc, rctx->data+MAX_HDRSIZE, (rctx->size-MAX_HDRSIZE)>2); ssc_state.rx_ctx[1] = rctx; return 2; @@ -236,17 +299,74 @@ static int8_t ssc_rx_refill(void) DEBUGPCRF("prim/secnd DMA busy, can't refill"); #endif } +#endif #define ISO14443A_FDT_SHORT_1 1236 #define ISO14443A_FDT_SHORT_0 1172 -static void ssc_irq(void) +static void __ramfunc ssc_irq(void) { u_int32_t ssc_sr = ssc->SSC_SR; DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode); + if (ssc_sr & AT91C_SSC_ENDRX) { +#if 1 + /* in a one-shot sample, we don't want to keep + * sampling further after having received the first + * packet. */ + if (ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT) { + DEBUGP("DISABLE_RX "); + AT91F_SSC_DisableRx(AT91C_BASE_SSC); + } + //AT91F_SSC_DisableIt(AT91C_BASE_SSC, SSC_RX_IRQ_MASK); +#endif + //DEBUGP("Sending primary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len); + /* Mark primary RCTX as ready to send for usb */ + req_ctx_set_state(ssc_state.rx_ctx[0], + RCTX_STATE_UDP_EP2_PENDING); + //RCTX_STATE_FREE); + /* second buffer gets propagated to primary */ + ssc_state.rx_ctx[0] = ssc_state.rx_ctx[1]; + ssc_state.rx_ctx[1] = NULL; + if (ssc_sr & AT91C_SSC_RXBUFF) { + DEBUGP("RXBUFF! "); + if (ssc_state.rx_ctx[0]) { + //DEBUGP("Sending secondary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len); + req_ctx_set_state(ssc_state.rx_ctx[0], + RCTX_STATE_UDP_EP2_PENDING); + //RCTX_STATE_FREE); + } + if (__ssc_rx_refill(0) == -1) + AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX | + AT91C_SSC_RXBUFF | + AT91C_SSC_OVRUN); + } + + if (__ssc_rx_refill(1) == -1) + AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX | + AT91C_SSC_RXBUFF | + AT91C_SSC_OVRUN); + + udp_refill_ep(2); + +#if 0 + if (__ssc_rx_refill(1) == -1) + AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX | + AT91C_SSC_RXBUFF | + AT91C_SSC_OVRUN); +#endif + } + if (ssc_sr & AT91C_SSC_OVRUN) - DEBUGP("RX OVERRUN "); + DEBUGP("RX_OVERRUN "); + + if (ssc_sr & AT91C_SSC_CP0) + DEBUGP("CP0 "); + + if (ssc_sr & AT91C_SSC_TXSYN) + DEBUGP("TXSYN "); +#if 0 + led_toggle(1); switch (ssc_state.mode) { case SSC_MODE_14443A_SHORT: @@ -269,54 +389,39 @@ static void ssc_irq(void) case SSC_MODE_14443A_STANDARD: case SSC_MODE_EDGE_ONE_SHOT: - - if (ssc_sr & (AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF)) { -#if 1 - /* Mark primary RCTX as ready to send for usb */ - req_ctx_set_state(ssc_state.rx_ctx[0], - RCTX_STATE_UDP_EP2_PENDING); - /* second buffer gets propagated to primary */ - ssc_state.rx_ctx[0] = ssc_state.rx_ctx[1]; - ssc_state.rx_ctx[1] = NULL; -#endif - - if (ssc_sr & AT91C_SSC_RXBUFF) { - DEBUGP("RXBUFF, shouldn't happen! "); -#if 0 - req_ctx_set_state(ssc_state.rx_ctx[0], - RCTX_STATE_UDP_EP2_PENDING); -#endif - } - if (ssc_rx_refill() == -1) - AT91F_AIC_DisableIt(ssc, AT91C_SSC_ENDRX | - AT91C_SSC_RXBUFF | - AT91C_SSC_OVRUN); - } + DEBUGP("ONE_SHOT "); + break; + default: + DEBUGP("UNKNOWN_MODE "); break; } - DEBUGPCR(""); + +#endif + DEBUGPCR("I"); AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SSC); } void ssc_rx_unthrottle(void) { - AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | + AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN); } void ssc_rx_start(void) { - DEBUGPCRF("starting SSC RX\n"); + //DEBUGPCRF("starting SSC RX\n"); /* Enable Reception */ - AT91F_SSC_EnableRx(ssc); + AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | + AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN); + AT91F_SSC_EnableRx(AT91C_BASE_SSC); } void ssc_rx_stop(void) { /* Disable reception */ - AT91F_SSC_DisableRx(ssc); + AT91F_SSC_DisableRx(AT91C_BASE_SSC); } void ssc_tx_init(void) @@ -325,8 +430,10 @@ void ssc_tx_init(void) * PA17 !! */ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN_PWM); AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN_SSC_TX | - OPENPCD_PIO_MFOUT_SSC_RX | OPENPCD_PIO_SSP_CKIN, - 0); + OPENPCD_PIO_MFOUT_SSC_RX | OPENPCD_PIO_SSP_CKIN | + AT91C_PIO_PA15, 0); + + ssc_tx_mode_set(SSC_MODE_14443A_SHORT); } static int ssc_usb_in(struct req_ctx *rctx) @@ -338,19 +445,25 @@ static int ssc_usb_in(struct req_ctx *rctx) /* FIXME: allow host to specify mode */ ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT); ssc_rx_start(); + req_ctx_put(rctx); + return 0; break; case OPENPCD_CMD_SSC_WRITE: /* FIXME: implement this */ //ssc_tx_start() break; + default: + return USB_ERR(USB_ERR_CMD_UNKNOWN); + break; } - req_ctx_put(rctx); - return -EINVAL; + return (poh->flags & OPENPCD_FLAG_RESPOND) ? USB_RET_RESPOND : 0; } void ssc_rx_init(void) -{ +{ + tc_cdiv_sync_init(); + rx_pdc = (AT91PS_PDC) &(ssc->SSC_RPR); AT91F_SSC_CfgPMC(); @@ -362,27 +475,37 @@ void ssc_rx_init(void) AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SSC, OPENPCD_IRQ_PRIO_SSC, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &ssc_irq); - /* Reset */ - //ssc->SSC_CR = AT91C_SSC_SWRST; /* don't divide clock inside SSC, we do that in tc_cdiv */ ssc->SSC_CMR = 0; +#if 0 ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | - AT91C_SSC_START_CONTINOUS; - /* Data bits per Data N = 32-1, Data words per Frame = 15-1 (=60 byte)*/ + AT91C_SSC_CKI | AT91C_SSC_START_CONTINOUS; + /* Data bits per Data N = 32-1 + * Data words per Frame = 15-1 (=60 byte)*/ ssc->SSC_RFMR = 31 | AT91C_SSC_MSBF | (14 << 8); +#endif - ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT); + __ssc_rx_refill(0); + __ssc_rx_refill(1); + ssc_rx_mode_set(SSC_MODE_NONE); +#if 0 AT91F_PDC_EnableRx(rx_pdc); /* Enable RX interrupts */ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); +#endif + /* FIXME: This is hardcoded for REQA 0x26 */ + tc_fdt_set(ISO14443A_FDT_SHORT_0); + AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SSC); - usb_hdlr_register(&ssc_usb_in, OPENPCD_CMD_CLS_SSC); + //usb_hdlr_register(&ssc_usb_in, OPENPCD_CMD_CLS_SSC); + + DEBUGP("\r\n"); } void ssc_fini(void) diff --git a/firmware/src/picc/tc_cdiv_sync.c b/firmware/src/picc/tc_cdiv_sync.c index 5762c2c..b87d9e5 100644 --- a/firmware/src/picc/tc_cdiv_sync.c +++ b/firmware/src/picc/tc_cdiv_sync.c @@ -14,11 +14,6 @@ static u_int8_t enabled; static void pio_data_change(u_int32_t pio) { - DEBUGPCRF("PIO=%d", pio); - - if (pio != 27) - return; - /* FIXME: start ssc if we're in one-shot mode */ //ssc_rx_start(); } @@ -34,7 +29,7 @@ static void __ramfunc cdsync_cb(void) DEBUGP("SWTRG CV=0x%08x ", *AT91C_TC0_CV); #ifdef DISABLE DEBUGP("CDIV_SYNC_FLIP "); - *AT91C_PIOA_IDR = PIO_DATA; + //now in fiq *AT91C_PIOA_IDR = PIO_DATA; #endif //ssc_rx_start(); } @@ -70,6 +65,9 @@ void tc_cdiv_sync_enable(void) DEBUGP("CDIV_SYNC_ENABLE "); tc_cdiv_sync_reset(); +#ifndef DISABLE + *AT91C_PIOA_IER = PIO_DATA; +#endif } extern void (*fiq_handler)(void); diff --git a/firmware/src/picc/tc_fdt.c b/firmware/src/picc/tc_fdt.c index b5e6a27..1651b32 100644 --- a/firmware/src/picc/tc_fdt.c +++ b/firmware/src/picc/tc_fdt.c @@ -21,11 +21,11 @@ /* PICC Simulator Side: * In order to support responding to synchronous frames (REQA/WUPA/ANTICOL), * we need a second Timer/Counter (TC2). This unit is reset by an external - * event (rising edge of modulation pause PCD->PICC) connected to TIOB2, and - * counts up to a configurable number of carrier clock cycles (RA). Once the - * RA value is reached, TIOA2 will see a rising edge. This rising edge will - * be interconnected to TF (Tx Frame) of the SSC to start transmitting our - * synchronous response. + * event (rising edge of modulation pause PCD->PICC, falling edge of + * demodulated data) connected to TIOB2, and counts up to a configurable + * number of carrier clock cycles (RA). Once the RA value is reached, TIOA2 + * will see a rising edge. This rising edge will be interconnected to TF (Tx + * Frame) of the SSC to start transmitting our synchronous response. * */ @@ -37,9 +37,55 @@ #include <os/tc_cdiv.h> #include <picc/tc_fdt.h> +static AT91PS_TC tcfdt = AT91C_BASE_TC2; + void tc_fdt_set(u_int16_t count) { - tcb->TCB_TC2.TC_RA = count; + tcfdt->TC_RA = count; +} + + +/* 'count' number of carrier cycles after the last modulation pause, + * we deem the frame to have ended */ +void tc_frame_end_set(u_int16_t count) +{ + tcfdt->TC_RB = count; +} + +static void tc_fdt_irq(void) +{ + u_int32_t sr = tcfdt->TC_SR; + DEBUGP("tc_fdt_irq: TC2_SR=0x%08x TC2_CV=0x%08x ", + sr, tcfdt->TC_CV); + + if (sr & AT91C_TC_ETRGS) { + DEBUGP("Ext_trigger "); + } + if (sr & AT91C_TC_CPAS) { + DEBUGP("FDT_expired "); + /* FIXME: if we are in anticol / sync mode, + * we could do software triggering of SSC TX, + * but IIRC the hardware does this by TF */ + } + if (sr & AT91C_TC_CPBS) { + DEBUGP("Frame_end "); + /* FIXME: stop ssc (in continuous mode), + * take care of preparing synchronous response if + * we operate in anticol mode.*/ + } + if (sr & AT91C_TC_CPCS) { + DEBUGP("Compare_C "); + } + DEBUGPCR(""); +} + +void tc_fdt_print(void) +{ + DEBUGP("TC2_CV=0x%08x ", tcfdt->TC_CV); + DEBUGP("TC2_CMR=0x%08x ", tcfdt->TC_CMR); + DEBUGP("TC2_SR=0x%08x ", tcfdt->TC_SR); + DEBUGP("TC2_RA=0x%04x, TC2_RB=0x%04x, TC2_RC=0x%04x", + tcfdt->TC_RA, tcfdt->TC_RB, tcfdt->TC_RC); } void tc_fdt_init(void) @@ -49,19 +95,32 @@ void tc_fdt_init(void) AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, ((unsigned int) 1 << AT91C_ID_TC2)); /* Enable Clock for TC2 */ - tcb->TCB_TC2.TC_CCR = AT91C_TC_CLKEN; + tcfdt->TC_CCR = AT91C_TC_CLKEN; + + tcfdt->TC_RC = 0xffff; + tc_frame_end_set(128*2); /* Clock XC1, Wave Mode, No automatic reset on RC comp * TIOA2 in RA comp = set, TIOA2 on RC comp = clear, + * TIOA2 on EEVT = clear * TIOB2 as input, EEVT = TIOB2, Reset/Trigger on EEVT */ - tcb->TCB_TC2.TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE | - AT91C_TC_WAVESEL_UP | - AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR | - AT91C_TC_BEEVT_NONE | AT91C_TC_BCPB_NONE | - AT91C_TC_EEVT_TIOB | AT91C_TC_ETRGEDG_RISING | - AT91C_TC_ENETRG ; + tcfdt->TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE | + AT91C_TC_WAVESEL_UP | + AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR | + AT91C_TC_AEEVT_CLEAR | + AT91C_TC_BEEVT_NONE | AT91C_TC_BCPB_NONE | + AT91C_TC_EEVT_TIOB | AT91C_TC_ETRGEDG_FALLING | + AT91C_TC_ENETRG | AT91C_TC_CPCSTOP ; /* Reset to start timers */ tcb->TCB_BCR = 1; + + AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC2, + OPENPCD_IRQ_PRIO_TC_FDT, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &tc_fdt_irq); + AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC2); + + tcfdt->TC_IER = AT91C_TC_CPAS | AT91C_TC_CPBS | AT91C_TC_CPCS | + AT91C_TC_ETRGS; } diff --git a/firmware/src/start/Cstartup_app.S b/firmware/src/start/Cstartup_app.S index fb70272..448cc93 100644 --- a/firmware/src/start/Cstartup_app.S +++ b/firmware/src/start/Cstartup_app.S @@ -124,6 +124,9 @@ exit: .endfunc +#define LED_TRIGGER +#define CALL_PIO_IRQ_DEMUX + .text .arm .section .fastrun, "ax" @@ -140,25 +143,32 @@ fiq_handler: r13 stack r14 lr */ -#if 0 - mov r11, #PIO_LED1 - str r11, [r10, #PIOA_CODR] /* enable LED */ - str r11, [r10, #PIOA_SODR] /* disable LED */ -#endif ldr r8, [r10, #PIOA_ISR] tst r8, #PIO_DATA /* check for PIO_DATA change */ ldrne r11, [r10, #PIOA_PDSR] tstne r11, #PIO_DATA /* check for PIO_DATA == 1 */ strne r9, [r12, #TC_CCR] /* software trigger */ +#ifdef LED_TRIGGER + movne r11, #PIO_LED1 + strne r11, [r10, #PIOA_CODR] /* enable LED */ +#endif +#if 1 movne r11, #PIO_DATA strne r11, [r10, #PIOA_IDR] /* disable further PIO_DATA FIQ */ +#endif /*- Mark the End of Interrupt on the AIC */ ldr r11, =AT91C_BASE_AIC str r11, [r11, #AIC_EOICR] +#ifdef LED_TRIGGER + mov r11, #PIO_LED1 + str r11, [r10, #PIOA_SODR] /* disable LED */ +#endif + +#ifdef CALL_PIO_IRQ_DEMUX /* push r0, r1-r3, r12, r14 onto FIQ stack */ stmfd sp!, { r0-r3, r12, lr} mov r0, r8 @@ -172,43 +182,9 @@ fiq_handler: bx r11 /* msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ */ - ldmia sp!, { r0-r3, r12, lr } - -#if 0 -/*- Save and r0 in FIQ_Register */ - mov r9, r0 - ldr r0, [r11, #AIC_FVR] - str r8, [r11, #AIC_FVR] - /* msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_SVC */ - - /*- Save scratch/used registers and LR in User Stack */ - stmfd sp!, { r1-r3, r12, lr} - - led1on - - /*- Branch to the routine pointed by the AIC_FVR */ - mov r14, pc - bx r0 - - /*- Restore scratch/used registers and LR from User Stack */ - ldmia sp!, { r1-r3, r12, lr} - - /*- Leave Interrupts disabled and switch back in FIQ mode */ - /* msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ */ - - /*- Mark the End of Interrupt on the AIC */ - ldr r0, =AT91C_BASE_AIC - str r0, [r0, #AIC_EOICR] - - /*- Restore the R0 ARM_MODE_SVC register */ - mov r0,r9 - - ldr r10, =PIOA_SODR - mov r11, #(1 << LED1) - str r11, [r10] - #endif + /*- Restore the Program Counter using the LR_fiq directly in the PC */ subs pc, lr, #4 |