Fix bitfields for big endian platforms (Jeremy Lainé)
[librfid] / src / rfid_proto_mifare_classic.c
index d45eefc..004e002 100644 (file)
@@ -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,
        },
 };