X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_layer2_iso15693.c;h=d06f7763ec4a0cc054dffcbc71a0a17ebe42fbf2;hb=76a801fda4aeea4107c4c6c0ef85f1df6b75f167;hp=dab741863024c398e3db22f17ecb5481c5a28950;hpb=bbb902ddc903f9e6f7bb3dbdbf9a5a237f09a90b;p=librfid diff --git a/src/rfid_layer2_iso15693.c b/src/rfid_layer2_iso15693.c index dab7418..d06f776 100644 --- a/src/rfid_layer2_iso15693.c +++ b/src/rfid_layer2_iso15693.c @@ -1,7 +1,7 @@ /* ISO 15693 anticollision implementation * - * (C) 2005-2006 by Harald Welte - * + * (C) 2005-2008 by Harald Welte + * (C) 2007 by Bjoern Riemer */ /* @@ -16,12 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include +#include #include #include @@ -34,10 +35,84 @@ struct iso15693_request_read { u_int8_t blocknum; } __attribute__ ((packed)); +struct iso15693_request_adressed { + struct iso15693_request head; + u_int64_t uid; +} __attribute__ ((packed)); + #define ISO15693_BLOCK_SIZE_MAX (256/8) #define ISO15693_RESP_SIZE_MAX (4+ISO15693_BLOCK_SIZE_MAX) +const unsigned int iso15693_timing[2][5] = { + [ISO15693_T_SLOW] = { + [ISO15693_T1] = 1216, /* max time after VCD EOF before VICC SOF */ + [ISO15693_T2] = 1200, /* min time before VCD EOF after VICC response */ + [ISO15693_T3] = 1502, /* min time after VCD EOF before next EOF if no VICC response */ + [ISO15693_T4] = 1216, /* time after wich VICC transmits after VCD EOF */ + [ISO15693_T4_WRITE]=20000, /* time after wich VICC transmits after VCD EOF */ + }, + [ISO15693_T_FAST] = { + [ISO15693_T1] = 304, /* max time after VCD EOF before VICC SOF */ + [ISO15693_T2] = 300, /* min time before VCD EOF after VICC response */ + [ISO15693_T3] = 602, /* min time after VCD EOF before next EOF if no VICC response */ + [ISO15693_T4] = 304, /* time after wich VICC transmits after VCD EOF */ + [ISO15693_T4_WRITE]=20000, /* time after wich VICC transmits after VCD EOF */ + }, +}; + +unsigned char +iso15693_get_response_error_name(u_int8_t error){ + switch (error){ + case RFID_15693_ERR_NOTSUPP: + return "ERR_NOTSUPP"; + case RFID_15693_ERR_INVALID: /* command not recognized */ + return "ERR_INVALID"; + case RFID_15693_ERR_UNKNOWN: /* unknown error */ + return "ERR_UNKNOWN"; + case RFID_15693_ERR_BLOCK_NA: /* block not available */ + return "ERR_BLOCK_N"; + case RFID_15693_ERR_BLOCK_LOCKED: + return "ERR_BLOCK_LOCKE"; + case RFID_15693_ERR_BLOCK_LOCKED_CH: + return "ERR_BLOCK_LOCKED_CH"; + case RFID_15693_ERR_BLOCK_NOTPROG: + return "ERR_BLOCK_NOTPROG"; + case RFID_15693_ERR_BLOCK_NOTLOCK: + return "ERR_BLOCK_NOTLOCK"; + case 0xA0: /* until 0xDF*/ + return "Custom Command error Code"; + case 0xE0: + default: + return "Undef."; + } +} + +static int iso15693_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) +{ + return handle->rh->reader->transceive(handle->rh, frametype, tx_buf, + tx_len, rx_buf, rx_len, timeout, flags); +} + +/* Transmit an anticollission frame */ +static int +iso15693_transceive_acf(struct rfid_layer2_handle *handle, + const struct iso15693_anticol_cmd *acf, + unsigned int acf_len, + struct iso15693_anticol_resp *resp, + unsigned int *rx_len, char *bit_of_col) +{ + const struct rfid_reader *rdr = handle->rh->reader; + if (!rdr->iso15693.transceive_ac) + return -1; + return rdr->iso15693.transceive_ac(handle->rh, acf, acf_len, resp, rx_len, bit_of_col); +} + #if 0 + static int iso15693_read_block(struct rfid_layer2_handle *handle, u_int8_t blocknr, u_int32_t *data) @@ -86,8 +161,360 @@ iso15693_lock_block() #endif +/* Helper function to build an ISO 15693 anti collision frame */ +static int +iso15693_build_acf(u_int8_t *target, u_int8_t flags, u_int8_t afi, + u_int8_t mask_len, u_int8_t *mask) +{ + struct iso15693_request *req = (struct iso15693_request *) target; + int i = 0, j; + + req->flags = flags; + req->command = ISO15693_CMD_INVENTORY; + if (flags & RFID_15693_F5_AFI_PRES) + req->data[i++] = afi; + req->data[i++] = mask_len; + + for (j = 0; j < mask_len; j++) + req->data[i++] = mask[j]; + + return i + sizeof(*req); +} + static int iso15693_anticol(struct rfid_layer2_handle *handle) +{ + int i, ret; + int tx_len, rx_len; + int num_valid = 0; + union { + struct iso15693_anticol_cmd_afi w_afi; + struct iso15693_anticol_cmd no_afi; + } acf; + + struct iso15693_anticol_resp resp; + + u_int8_t boc; +#define MAX_SLOTS 16 + int num_slots = MAX_SLOTS; + + u_int8_t uuid_list[MAX_SLOTS][ISO15693_UID_LEN]; + int uuid_list_valid[MAX_SLOTS]; + + u_int8_t flags; + +#define MY_NONE 0 +#define MY_COLL 1 +#define MY_UUID 2 + + memset(uuid_list_valid, MY_NONE, sizeof(uuid_list_valid)); + memset(uuid_list, 0, sizeof(uuid_list)); + + //memset(&acf, 0, sizeof(acf)); + + /* FIXME: we can't use multiple slots at this point, since the RC632 + * with librfid on the host PC has too much latency between 'EOF pulse + * to mark start of next slot' and 'receive data' commands :( */ + + flags = RFID_15693_F_INV_TABLE_5; + if (handle->priv.iso15693.vicc_fast) + flags |= RFID_15693_F_RATE_HIGH; + if (handle->priv.iso15693.vicc_two_subc) + flags |= RFID_15693_F_SUBC_TWO; + if (handle->priv.iso15693.single_slot) { + flags |= RFID_15693_F5_NSLOTS_1; + num_slots = 1; + } + if (handle->priv.iso15693.use_afi) + flags |= RFID_15693_F5_AFI_PRES; + + tx_len = iso15693_build_acf((u_int8_t *)&acf, flags, + handle->priv.iso15693.afi, 0, NULL); + + for (i = 0; i < num_slots; i++) { + rx_len = sizeof(resp); + ret = iso15693_transceive_acf(handle, (u_int8_t *) &acf, tx_len, &resp, &rx_len, &boc); + if (ret == -ETIMEDOUT) { + DEBUGP("no answer from vicc in slot %d\n", i); + uuid_list_valid[i] = MY_NONE; + } else if (ret < 0) { + DEBUGP("ERROR ret: %d, slot %d\n", ret, i); + uuid_list_valid[i] = MY_NONE; + } else { + + if (boc) { + DEBUGP("Collision during anticol. slot %d bit %d\n", + i, boc); + uuid_list_valid[i] = -boc; + memcpy(uuid_list[i], resp.uuid, ISO15693_UID_LEN); + } else { + DEBUGP("Slot %d ret: %d DSFID: %02x UUID: %s\n", i, ret, + resp.dsfid, rfid_hexdump(resp.uuid, ISO15693_UID_LEN)); + uuid_list_valid[i] = MY_UUID; + memcpy(&uuid_list[i][0], resp.uuid, ISO15693_UID_LEN); + } + } + } + + for (i = 0; i < num_slots; i++) { + if (uuid_list_valid[i] == MY_NONE) { + DEBUGP("slot[%d]: timeout\n",i); + } else if (uuid_list_valid[i] == MY_UUID) { + DEBUGP("slot[%d]: VALID uuid: %s\n", i, + rfid_hexdump(uuid_list[i], ISO15693_UID_LEN)); + memcpy(handle->uid, uuid_list[i], ISO15693_UID_LEN); + /* FIXME: move to init */ + handle->uid_len = ISO15693_UID_LEN; + num_valid++; + } else if (uuid_list_valid[i] < 0) { + DEBUGP("slot[%d]: collision(%d %d,%d) uuid: %s\n", + i,uuid_list_valid[i]*-1, + (uuid_list_valid[i]*-1)/8, + (uuid_list_valid[i]*-1)%8, + rfid_hexdump(uuid_list[i], ISO15693_UID_LEN)); + } + } + + if (num_valid == 0) + return -1; + + return num_valid; +} + +static int +iso15693_select(struct rfid_layer2_handle *l2h) +{ + struct iso15693_request_adressed tx_req; + int ret; + unsigned int rx_len, tx_len; + + struct { + struct iso15693_response head; + u_int8_t error; + unsigned char crc[2]; + } rx_buf; + rx_len = sizeof(rx_buf); + + tx_req.head.command = ISO15693_CMD_SELECT; + tx_req.head.flags = RFID_15693_F4_ADDRESS; + if (l2h->priv.iso15693.vicc_fast) + tx_req.head.flags |= RFID_15693_F_RATE_HIGH; + if (l2h->priv.iso15693.vicc_two_subc) + tx_req.head.flags |= RFID_15693_F_SUBC_TWO; + memcpy(&tx_req.uid, l2h->uid, ISO15693_UID_LEN); + tx_len = sizeof(tx_req); + + DEBUGP("tx_len=%u", tx_len); DEBUGPC(" rx_len=%u\n",rx_len); + + DEBUGP("ret: %d%s, error_flag: %d", ret,(ret==-ETIMEDOUT)?"(TIMEOUT)":"", + rx_buf.head.flags&RFID_15693_RF_ERROR); + if (rx_buf.head.flags&RFID_15693_RF_ERROR){ + DEBUGPC(" -> error: %02x '%s'\n", rx_buf.error, + iso15693_get_response_error_name(rx_buf.error)); + l2h->priv.iso15693.state = RFID_15693_STATE_SELECTED; + return 0; + }else{ + DEBUGPC("\n"); + return -1; + } +} + +static int +iso15693_stay_quiet(struct rfid_layer2_handle *l2h) +{ + struct iso15693_request_adressed tx_req; + int ret; + unsigned int rx_len, tx_len; + + struct { + struct iso15693_response head; + u_int8_t error; + unsigned char crc[2]; + } rx_buf; + rx_len = sizeof(rx_buf); + + tx_req.head.command = ISO15693_CMD_STAY_QUIET; + + tx_req.head.flags = RFID_15693_F4_ADDRESS; + if (l2h->priv.iso15693.vicc_fast) + tx_req.head.flags |= RFID_15693_F_RATE_HIGH; + if (l2h->priv.iso15693.vicc_two_subc) + tx_req.head.flags |= RFID_15693_F_SUBC_TWO; + memcpy(&tx_req.uid, l2h->uid, ISO15693_UID_LEN); + tx_len = sizeof(tx_req); + + DEBUGP("tx_len=%u", tx_len); DEBUGPC(" rx_len=%u\n",rx_len); + + ret = iso15693_transceive(l2h, RFID_15693_FRAME, (u_int8_t*)&tx_req, + tx_len, (u_int8_t*)&rx_buf, &rx_len, 10,0); + + l2h->priv.iso15693.state = RFID_15693_STATE_QUIET; + + DEBUGP("ret: %d%s, error_flag: %d", ret,(ret==-ETIMEDOUT)?"(TIMEOUT)":"", + rx_buf.head.flags&RFID_15693_RF_ERROR); + if (rx_buf.head.flags&RFID_15693_RF_ERROR) + DEBUGPC(" -> error: %02x\n", rx_buf.error); + else + DEBUGPC("\n"); + + return 0; +} + +static int +iso15693_getopt(struct rfid_layer2_handle *handle, + int optname, void *optval, unsigned int *optlen) +{ + unsigned int *val = optval; + u_int8_t *val_u8 = optval; + + if (!optlen || !optval || *optlen < sizeof(unsigned int)) + return -EINVAL; + + *optlen = sizeof(unsigned int); + + switch (optname) { + case RFID_OPT_15693_MOD_DEPTH: + if (handle->priv.iso15693.vcd_ask100) + *val = RFID_15693_MOD_100ASK; + else + *val = RFID_15693_MOD_10ASK; + break; + case RFID_OPT_15693_VCD_CODING: + if (handle->priv.iso15693.vcd_out256) + *val = RFID_15693_VCD_CODING_1OUT256; + else + *val = RFID_15693_VCD_CODING_1OUT4; + break; + case RFID_OPT_15693_VICC_SUBC: + if (handle->priv.iso15693.vicc_two_subc) + *val = RFID_15693_VICC_SUBC_DUAL; + else + *val = RFID_15693_VICC_SUBC_SINGLE; + break; + case RFID_OPT_15693_VICC_SPEED: + if (handle->priv.iso15693.vicc_fast) + *val = RFID_15693_VICC_SPEED_FAST; + else + *val = RFID_15693_VICC_SPEED_SLOW; + break; + case RFID_OPT_15693_VCD_SLOTS: + if (handle->priv.iso15693.single_slot) + *val = 1; + else + *val = 16; + break; + case RFID_OPT_15693_USE_AFI: + if (handle->priv.iso15693.use_afi) + *val = 1; + else + *val = 0; + break; + case RFID_OPT_15693_AFI: + *val_u8 = handle->priv.iso15693.afi; + *optlen = sizeof(u_int8_t); + break; + default: + return -EINVAL; + break; + } + + return 0; +} + +static int +iso15693_setopt(struct rfid_layer2_handle *handle, int optname, + const void *optval, unsigned int optlen) +{ + unsigned int val; + + if (optlen < sizeof(u_int8_t) || !optval) + return -EINVAL; + + if (optlen == sizeof(u_int8_t)) + val = *((u_int8_t *) optval); + if (optlen == sizeof(u_int16_t)) + val = *((u_int16_t *) optval); + if (optlen == sizeof(unsigned int)) + val = *((unsigned int *) optval); + + switch (optname) { + case RFID_OPT_15693_MOD_DEPTH: + switch (val) { + case RFID_15693_MOD_10ASK: + handle->priv.iso15693.vcd_ask100 = 0; + break; + case RFID_15693_MOD_100ASK: + handle->priv.iso15693.vcd_ask100 = 1; + break; + default: + return -EINVAL; + } + break; + case RFID_OPT_15693_VCD_CODING: + switch (val) { + case RFID_15693_VCD_CODING_1OUT256: + handle->priv.iso15693.vcd_out256 = 1; + break; + case RFID_15693_VCD_CODING_1OUT4: + handle->priv.iso15693.vcd_out256 = 0; + break; + default: + return -EINVAL; + } + break; + case RFID_OPT_15693_VICC_SUBC: + switch (val) { + case RFID_15693_VICC_SUBC_SINGLE: + handle->priv.iso15693.vicc_two_subc = 0; + break; + case RFID_15693_VICC_SUBC_DUAL: + handle->priv.iso15693.vicc_two_subc = 1; + break; + default: + return -EINVAL; + } + break; + case RFID_OPT_15693_VICC_SPEED: + switch (val) { + case RFID_15693_VICC_SPEED_SLOW: + handle->priv.iso15693.vicc_fast = 0; + break; + case RFID_15693_VICC_SPEED_FAST: + handle->priv.iso15693.vicc_fast = 1; + break; + default: + return -EINVAL; + } + case RFID_OPT_15693_VCD_SLOTS: + switch (val) { + case 16: + handle->priv.iso15693.single_slot = 0; + break; + case 1: + handle->priv.iso15693.single_slot = 1; + break; + default: + return -EINVAL; + } + break; + case RFID_OPT_15693_USE_AFI: + if (val) + handle->priv.iso15693.use_afi = 1; + else + handle->priv.iso15693.use_afi = 0; + break; + case RFID_OPT_15693_AFI: + if (val > 0xff) + return -EINVAL; + handle->priv.iso15693.afi = val; + break; + default: + return -EINVAL; + } + return 0; +} + +static int transceive_inventory(struct rfid_layer2_handle *l2h) { return -1; } @@ -103,7 +530,15 @@ iso15693_init(struct rfid_reader_handle *rh) h->l2 = &rfid_layer2_iso15693; h->rh = rh; h->priv.iso15693.state = ISO15693_STATE_NONE; - ret = h->rh->reader->iso15693.init(h->rh); + h->priv.iso15693.vcd_ask100 = 1; /* 100ASK is easier to generate */ + h->priv.iso15693.vicc_two_subc = 0; + h->priv.iso15693.vicc_fast = 1; + h->priv.iso15693.single_slot = 1; + h->priv.iso15693.vcd_out256 = 0; + h->priv.iso15693.use_afi = 0; /* not all VICC support AFI */ + h->priv.iso15693.afi = 0; + + ret = h->rh->reader->init(h->rh, RFID_LAYER2_ISO15693); if (ret < 0) { free_layer2_handle(h); return NULL; @@ -126,9 +561,12 @@ const struct rfid_layer2 rfid_layer2_iso15693 = { .fn = { .init = &iso15693_init, .open = &iso15693_anticol, + //.open = &iso15693_select, //.transceive = &iso15693_transceive, - //.close = &iso14443a_hlta, + .close = &iso15693_stay_quiet, .fini = &iso15693_fini, + .setopt = &iso15693_setopt, + .getopt = &iso15693_getopt, }, };