mifare ultraligh have pages 0-15, not only 0-7
[librfid] / rfid_proto_mifare_ul.c
1
2 /* Mifare Ultralight implementation, PCD side.
3  *
4  * (C) 2005 by Harald Welte <laforge@gnumonks.org>
5  *
6  */
7
8 /*
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License version 2 
11  *  as published by the Free Software Foundation
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include <rfid/rfid.h>
29 #include <rfid/rfid_protocol.h>
30 #include <rfid/rfid_layer2.h>
31 #include <rfid/rfid_protocol_mifare_ul.h>
32
33 //#include <rfid/rfid_asic.h>
34 //#include <rfid/rfid_reader.h>
35
36 #include "rfid_iso14443_common.h"
37
38
39 /* FIXME */
40 #define MIFARE_UL_READ_FWT      100
41 #define MIFARE_UL_WRITE_FWT     100
42
43 static int
44 mful_read(struct rfid_protocol_handle *ph, unsigned int page,
45           unsigned char *rx_data, unsigned int *rx_len)
46 {
47         unsigned char rx_buf[16];
48         unsigned int real_rx_len = sizeof(rx_buf);
49         unsigned char tx[2];
50         int ret;
51
52         if (page > MIFARE_UL_PAGE_MAX)
53                 return -EINVAL;
54
55         tx[0] = MIFARE_UL_CMD_READ;
56         tx[1] = page & 0xff;
57
58         ret = ph->l2h->l2->fn.transcieve(ph->l2h, tx, sizeof(tx), rx_buf,
59                                          &real_rx_len, MIFARE_UL_READ_FWT, 0);
60
61         if (ret < 0)
62                 return ret;
63
64         if (real_rx_len < *rx_len)
65                 *rx_len = real_rx_len;
66
67         memcpy(rx_data, rx_buf, *rx_len);
68
69         return ret;
70 }
71
72 static int
73 mful_write(struct rfid_protocol_handle *ph, unsigned int page,
74            unsigned char *tx_data, unsigned int tx_len)
75 {
76         unsigned int i;
77         unsigned char tx[6];
78         unsigned char rx[10];
79         unsigned int rx_len = sizeof(rx);
80         int ret;
81
82 #if 0
83         if (tx_len != 4 || page > MIFARE_UL_PAGE_MAX)
84                 return -EINVAL;
85 #endif
86
87         tx[0] = MIFARE_UL_CMD_WRITE;
88         tx[1] = page & 0xff;
89
90         for (i = 0; i < 4; i++)
91                 tx[2+i] = tx_data[i];
92
93         ret = ph->l2h->l2->fn.transcieve(ph->l2h, tx, sizeof(tx), rx,
94                                          &rx_len, MIFARE_UL_WRITE_FWT, 0);
95                                         
96         if (ret < 0)
97                 return ret;
98
99         if (rx[0] != MIFARE_UL_RESP_ACK)
100                 return -EIO;
101
102         return ret;
103 }
104
105 static int
106 mful_transcieve(struct rfid_protocol_handle *ph,
107                 const unsigned char *tx_data, unsigned int tx_len,
108                 unsigned char *rx_data, unsigned int *rx_len,
109                 unsigned int timeout, unsigned int flags)
110 {
111         return -EINVAL;
112 }
113
114 static struct rfid_protocol_handle *
115 mful_init(struct rfid_layer2_handle *l2h)
116 {
117         struct rfid_protocol_handle *ph;
118         ph = malloc(sizeof(struct rfid_protocol_handle));
119         return ph;
120 }
121
122 static int mful_fini(struct rfid_protocol_handle *ph)
123 {
124         free(ph);
125         return 0;
126 }
127
128 struct rfid_protocol rfid_protocol_mful = {
129         .id     = RFID_PROTOCOL_MIFARE_UL,
130         .name   = "Mifare Ultralight",
131         .fn     = {
132                 .init           = &mful_init,
133                 /* .transcieve  = &mful_transcieve,*/
134                 .read           = &mful_read,
135                 .write          = &mful_write,
136                 .fini           = &mful_fini,
137         },
138 };