X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_proto_mifare_classic.c;h=a6e2e4f7fe66e6d6d57bb82016fcb5f5cfb896ab;hb=893a580c6f1c7f1cc50d9bd1acc51c9fd6307a17;hp=d45eefc392012b7757f215f6eddba172ef3cc1b2;hpb=e404cccecd20a2418c2429cd182c18218e54bd28;p=librfid diff --git a/src/rfid_proto_mifare_classic.c b/src/rfid_proto_mifare_classic.c index d45eefc..a6e2e4f 100644 --- a/src/rfid_proto_mifare_classic.c +++ b/src/rfid_proto_mifare_classic.c @@ -1,7 +1,7 @@ /* Mifare Classic implementation, PCD side. * - * (C) 2005-2006 by Harald Welte + * (C) 2005-2008 by Harald Welte * */ @@ -17,7 +17,7 @@ * * 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 @@ -38,9 +38,8 @@ #define MIFARE_UL_CMD_WRITE 0xA2 #define MIFARE_UL_CMD_READ 0x30 -/* FIXME */ -#define MIFARE_CL_READ_FWT 100 -#define MIFARE_CL_WRITE_FWT 100 +#define MIFARE_CL_READ_FWT 250 +#define MIFARE_CL_WRITE_FWT 600 static int mfcl_read(struct rfid_protocol_handle *ph, unsigned int page, @@ -79,24 +78,28 @@ static int mfcl_write(struct rfid_protocol_handle *ph, unsigned int page, unsigned char *tx_data, unsigned int tx_len) { - unsigned int i; - unsigned char tx[18]; + unsigned char tx[2]; unsigned char rx[1]; - unsigned int rx_len; + unsigned int rx_len = sizeof(rx); int ret; - if (tx_len != 16 || page > MIFARE_CL_PAGE_MAX) + if (page > MIFARE_CL_PAGE_MAX) return -EINVAL; + if (tx_len != 16) + return -EINVAL; + tx[0] = MIFARE_CL_CMD_WRITE16; tx[1] = page & 0xff; - memcpy(tx+2, tx_data, 16); + ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx, 2, rx, + &rx_len, MIFARE_CL_WRITE_FWT, 0); + if (ret < 0) + return ret; - ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx, - sizeof(tx), rx, &rx_len, + ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx_data, + tx_len, rx, &rx_len, MIFARE_CL_WRITE_FWT, 0); - if (ret < 0) return ret; @@ -106,10 +109,54 @@ mfcl_write(struct rfid_protocol_handle *ph, unsigned int page, return ret; } +static int +mfcl_getopt(struct rfid_protocol_handle *ph, int optname, void *optval, + unsigned int *optlen) +{ + int ret = -EINVAL; + u_int8_t atqa[2]; + u_int8_t sak; + unsigned int atqa_size = sizeof(atqa); + unsigned int sak_size = sizeof(sak); + unsigned int *size = optval; + + switch (optname) { + case RFID_OPT_PROTO_SIZE: + if (*optlen < sizeof(*size)) + return -EINVAL; + *optlen = sizeof(*size); + ret = 0; + rfid_layer2_getopt(ph->l2h, RFID_OPT_14443A_ATQA, + atqa, &atqa_size); + rfid_layer2_getopt(ph->l2h, RFID_OPT_14443A_SAK, + &sak, &sak_size); + if (atqa[0] == 0x04 && atqa[1] == 0x00) { + if (sak == 0x09) { + /* mifare mini */ + *size = 320; + } else + *size = 1024; + } else if (atqa[0] == 0x02 && atqa[1] == 0x00) + *size = 4096; + else + ret = -EIO; + break; + } + + return ret; +} + static struct rfid_protocol_handle * mfcl_init(struct rfid_layer2_handle *l2h) { struct rfid_protocol_handle *ph; + + if (l2h->l2->id != RFID_LAYER2_ISO14443A) + return NULL; + + if (l2h->uid_len != 4) + return NULL; + ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle)); return ph; } @@ -128,6 +175,7 @@ const struct rfid_protocol rfid_protocol_mfcl = { .read = &mfcl_read, .write = &mfcl_write, .fini = &mfcl_fini, + .getopt = &mfcl_getopt, }, }; @@ -139,6 +187,14 @@ int mfcl_set_key(struct rfid_protocol_handle *ph, unsigned char *key) return ph->l2h->rh->reader->mifare_classic.setkey(ph->l2h->rh, key); } +int mfcl_set_key_ee(struct rfid_protocol_handle *ph, unsigned int addr) +{ + if (!ph->l2h->rh->reader->mifare_classic.setkey_ee) + return -ENODEV; + + return ph->l2h->rh->reader->mifare_classic.setkey_ee(ph->l2h->rh, addr); +} + int mfcl_auth(struct rfid_protocol_handle *ph, u_int8_t cmd, u_int8_t block) { u_int32_t serno = *((u_int32_t *)ph->l2h->uid); @@ -149,3 +205,33 @@ int mfcl_auth(struct rfid_protocol_handle *ph, u_int8_t cmd, u_int8_t block) return ph->l2h->rh->reader->mifare_classic.auth(ph->l2h->rh, cmd, serno, block); } + +int mfcl_block2sector(u_int8_t block) +{ + if (block < MIFARE_CL_SMALL_SECTORS * MIFARE_CL_BLOCKS_P_SECTOR_1k) + return block/MIFARE_CL_BLOCKS_P_SECTOR_1k; + else + return (block - MIFARE_CL_SMALL_SECTORS * MIFARE_CL_BLOCKS_P_SECTOR_1k) + / MIFARE_CL_BLOCKS_P_SECTOR_4k; +} + +int mfcl_sector2block(u_int8_t sector) +{ + if (sector < MIFARE_CL_SMALL_SECTORS) + return sector * MIFARE_CL_BLOCKS_P_SECTOR_1k; + else if (sector < MIFARE_CL_SMALL_SECTORS + MIFARE_CL_LARGE_SECTORS) + return MIFARE_CL_SMALL_SECTORS * MIFARE_CL_BLOCKS_P_SECTOR_1k + + (sector - MIFARE_CL_SMALL_SECTORS) * MIFARE_CL_BLOCKS_P_SECTOR_4k; + else + return -EINVAL; +} + +int mfcl_sector_blocks(u_int8_t sector) +{ + if (sector < MIFARE_CL_SMALL_SECTORS) + return MIFARE_CL_BLOCKS_P_SECTOR_1k; + else if (sector < MIFARE_CL_SMALL_SECTORS + MIFARE_CL_LARGE_SECTORS) + return MIFARE_CL_BLOCKS_P_SECTOR_4k; + else + return -EINVAL; +}