/* Mifare Classic implementation, PCD side.
*
- * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2008 by Harald Welte <laforge@gnumonks.org>
*
*/
*
* 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 <stdio.h>
#include <stdlib.h>
#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,
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 (page > MIFARE_CL_PAGE_MAX)
return -EINVAL;
- if (tx_len != 16 && tx_len != 4)
+ if (tx_len != 16)
return -EINVAL;
- if (tx_len == 16) {
- tx[0] = MIFARE_CL_CMD_WRITE16;
- tx[1] = page & 0xff;
-
- 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_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;
-
- memcpy(tx+2, tx_data, 4);
+ tx[0] = MIFARE_CL_CMD_WRITE16;
+ tx[1] = page & 0xff;
- 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;
+ ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx, 2, 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_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;
return ret;
}
unsigned int *optlen)
{
int ret = -EINVAL;
- u_int16_t atqa;
+ 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) {
*optlen = sizeof(*size);
ret = 0;
rfid_layer2_getopt(ph->l2h, RFID_OPT_14443A_ATQA,
- (void *) &atqa, &atqa_size);
- if (atqa == 0x0004)
- *size = 1024;
- else if (atqa == 0x0002)
+ 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;
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);
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;
+}