X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_proto_mifare_classic.c;h=004e00267bb93692848471193062bd766f471faf;hb=b66544b49bba04489f389c8720651f5f1db962e6;hp=d45eefc392012b7757f215f6eddba172ef3cc1b2;hpb=fb488a0210b1c694dba762ba086f43a5d4655c4f;p=librfid diff --git a/src/rfid_proto_mifare_classic.c b/src/rfid_proto_mifare_classic.c index d45eefc..004e002 100644 --- a/src/rfid_proto_mifare_classic.c +++ b/src/rfid_proto_mifare_classic.c @@ -79,29 +79,91 @@ 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 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; - tx[0] = MIFARE_CL_CMD_WRITE16; - tx[1] = page & 0xff; + if (tx_len != 16 && tx_len != 4) + return -EINVAL; + + if (tx_len == 16) { + 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, - MIFARE_CL_WRITE_FWT, 0); - - if (ret < 0) - return ret; + 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; + + if (rx[0] != MIFARE_UL_RESP_ACK) + return -EIO; + + ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx, + sizeof(tx), rx, &rx_len, + MIFARE_CL_WRITE_FWT, 0); + if (ret < 0) + return ret; + + if (rx[0] != MIFARE_UL_RESP_ACK) + return -EIO; + + } else if (tx_len == 4) { + + tx[0] = MIFARE_CL_CMD_WRITE4; + tx[1] = page & 0xff; - if (rx[0] != MIFARE_UL_RESP_ACK) - return -EIO; + memcpy(tx+2, tx_data, 4); + + ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx, + 2+4, rx, &rx_len, + MIFARE_CL_WRITE_FWT, 0); + if (ret < 0) + return ret; + + if (rx[0] != MIFARE_UL_RESP_ACK) + return -EIO; + + } + + 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]; + unsigned int atqa_size = sizeof(atqa); + 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); + if (atqa[0] == 0x04 && atqa[1] == 0x00) + *size = 1024; + else if (atqa[0] == 0x02 && atqa[1] == 0x00) + *size = 4096; + else + ret = -EIO; + break; + } return ret; } @@ -110,6 +172,13 @@ 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 +197,7 @@ const struct rfid_protocol rfid_protocol_mfcl = { .read = &mfcl_read, .write = &mfcl_write, .fini = &mfcl_fini, + .getopt = &mfcl_getopt, }, };