Add RFID_OPT_14443A_WUPA to request WUPA instead of REQA (Rainer Keller <mail@rainerk...
[librfid] / src / rfid_proto_mifare_ul.c
1
2 /* Mifare Ultralight implementation, PCD side.
3  *
4  * (C) 2005-2006 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 <librfid/rfid.h>
29 #include <librfid/rfid_protocol.h>
30 #include <librfid/rfid_layer2.h>
31 #include <librfid/rfid_protocol_mifare_ul.h>
32
33 #include "rfid_iso14443_common.h"
34
35
36 /* FIXME */
37 #define MIFARE_UL_READ_FWT      100
38 #define MIFARE_UL_WRITE_FWT     100
39
40 static int
41 mful_read(struct rfid_protocol_handle *ph, unsigned int page,
42           unsigned char *rx_data, unsigned int *rx_len)
43 {
44         unsigned char rx_buf[16];
45         unsigned int real_rx_len = sizeof(rx_buf);
46         unsigned char tx[2];
47         int ret;
48
49         if (page > MIFARE_UL_PAGE_MAX)
50                 return -EINVAL;
51
52         tx[0] = MIFARE_UL_CMD_READ;
53         tx[1] = page & 0xff;
54
55         ret = rfid_layer2_transceive(ph->l2h, RFID_14443A_FRAME_REGULAR,
56                                      tx, sizeof(tx), rx_buf, 
57                                      &real_rx_len, MIFARE_UL_READ_FWT, 0);
58
59         if (ret < 0)
60                 return ret;
61
62         if (real_rx_len < *rx_len)
63                 *rx_len = real_rx_len;
64
65         memcpy(rx_data, rx_buf, *rx_len);
66
67         return ret;
68 }
69
70 static int
71 mful_write(struct rfid_protocol_handle *ph, unsigned int page,
72            unsigned char *tx_data, unsigned int tx_len)
73 {
74         unsigned int i;
75         unsigned char tx[6];
76         unsigned char rx[10];
77         unsigned int rx_len = sizeof(rx);
78         int ret;
79
80         if (tx_len != 4 || page > MIFARE_UL_PAGE_MAX)
81                 return -EINVAL;
82
83         tx[0] = MIFARE_UL_CMD_WRITE;
84         tx[1] = page & 0xff;
85
86         for (i = 0; i < 4; i++)
87                 tx[2+i] = tx_data[i];
88
89         ret = rfid_layer2_transceive(ph->l2h, RFID_14443A_FRAME_REGULAR,
90                                      tx, sizeof(tx), rx, &rx_len, 
91                                      MIFARE_UL_WRITE_FWT, 0);
92                                         
93         if (ret < 0)
94                 return ret;
95
96         if (rx[0] != MIFARE_UL_RESP_ACK)
97                 return -EIO;
98
99         return ret;
100 }
101
102 static int
103 mful_transceive(struct rfid_protocol_handle *ph,
104                 const unsigned char *tx_data, unsigned int tx_len,
105                 unsigned char *rx_data, unsigned int *rx_len,
106                 unsigned int timeout, unsigned int flags)
107 {
108         return -EINVAL;
109 }
110
111 static int 
112 mful_getopt(struct rfid_protocol_handle *ph, int optname, void *optval,
113             unsigned int *optlen)
114 {
115         int ret = -EINVAL;
116         u_int16_t atqa;
117         unsigned int *size = optval;
118
119         switch (optname) {
120         case RFID_OPT_PROTO_SIZE:
121                 ret = 0;
122                 *size = 512;
123                 break;
124         }
125
126         return ret;
127 }
128
129
130 static struct rfid_protocol_handle *
131 mful_init(struct rfid_layer2_handle *l2h)
132 {
133         struct rfid_protocol_handle *ph;
134         u_int16_t atqa;
135         unsigned int atqa_len = sizeof(atqa);
136
137         if (l2h->l2->id != RFID_LAYER2_ISO14443A)
138                 return NULL;
139         
140         /* According to "Type Identification Procedure Rev. 1.3" */
141         rfid_layer2_getopt(l2h, RFID_OPT_14443A_ATQA,
142                            &atqa, &atqa_len);
143         if (atqa != 0x0044)
144                 return NULL;
145
146         /* according to "Functional Specification Rev. 3.0 */
147         if (l2h->uid_len != 7)
148                 return NULL;
149
150         ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
151         return ph;
152 }
153
154 static int mful_fini(struct rfid_protocol_handle *ph)
155 {
156         free_protocol_handle(ph);
157         return 0;
158 }
159
160 const struct rfid_protocol rfid_protocol_mful = {
161         .id     = RFID_PROTOCOL_MIFARE_UL,
162         .name   = "Mifare Ultralight",
163         .fn     = {
164                 .init           = &mful_init,
165                 .read           = &mful_read,
166                 .write          = &mful_write,
167                 .fini           = &mful_fini,
168                 .getopt         = &mful_getopt,
169         },
170 };
171
172 /* Functions below are not (yet? covered in the generic librfid api */
173
174
175 /* lock a certain page */
176 int rfid_mful_lock_page(struct rfid_protocol_handle *ph, unsigned int page)
177 {
178         unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 };
179
180         if (ph->proto != &rfid_protocol_mful)
181                 return -EINVAL;
182
183         if (page < 3 || page > 15)
184                 return -EINVAL;
185
186         if (page > 8)
187                 buf[2] = (1 << page);
188         else
189                 buf[3] = (1 << (page - 8));
190
191         return mful_write(ph, MIFARE_UL_PAGE_LOCK, buf, sizeof(buf));
192 }
193
194 /* convenience wrapper to lock the otp page */
195 int rfid_mful_lock_otp(struct rfid_protocol_handle *ph)
196 {
197         return rfid_mful_lock_page(ph, MIFARE_UL_PAGE_OTP);
198 }