remove autogenerated file
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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_getopt(struct rfid_protocol_handle *ph, int optname, void *optval,
104             unsigned int *optlen)
105 {
106         int ret = -EINVAL;
107         unsigned int *size = optval;
108
109         switch (optname) {
110         case RFID_OPT_PROTO_SIZE:
111                 ret = 0;
112                 /* we have to return the size in bytes, not bits */
113                 *size = 512/8;
114                 break;
115         }
116
117         return ret;
118 }
119
120
121 static struct rfid_protocol_handle *
122 mful_init(struct rfid_layer2_handle *l2h)
123 {
124         struct rfid_protocol_handle *ph;
125         u_int8_t atqa[2];
126         unsigned int atqa_len = sizeof(atqa);
127
128         if (l2h->l2->id != RFID_LAYER2_ISO14443A)
129                 return NULL;
130         
131         /* According to "Type Identification Procedure Rev. 1.3" */
132         rfid_layer2_getopt(l2h, RFID_OPT_14443A_ATQA,
133                            atqa, &atqa_len);
134         if (atqa[0] != 0x44 || atqa[1] != 0x00)
135                 return NULL;
136
137         /* according to "Functional Specification Rev. 3.0 */
138         if (l2h->uid_len != 7)
139                 return NULL;
140
141         ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
142         return ph;
143 }
144
145 static int mful_fini(struct rfid_protocol_handle *ph)
146 {
147         free_protocol_handle(ph);
148         return 0;
149 }
150
151 const struct rfid_protocol rfid_protocol_mful = {
152         .id     = RFID_PROTOCOL_MIFARE_UL,
153         .name   = "Mifare Ultralight",
154         .fn     = {
155                 .init           = &mful_init,
156                 .read           = &mful_read,
157                 .write          = &mful_write,
158                 .fini           = &mful_fini,
159                 .getopt         = &mful_getopt,
160         },
161 };
162
163 /* Functions below are not (yet? covered in the generic librfid api */
164
165
166 /* lock a certain page */
167 int rfid_mful_lock_page(struct rfid_protocol_handle *ph, unsigned int page)
168 {
169         unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 };
170
171         if (ph->proto != &rfid_protocol_mful)
172                 return -EINVAL;
173
174         if (page < 3 || page > 15)
175                 return -EINVAL;
176
177         if (page > 8)
178                 buf[2] = (1 << page);
179         else
180                 buf[3] = (1 << (page - 8));
181
182         return mful_write(ph, MIFARE_UL_PAGE_LOCK, buf, sizeof(buf));
183 }
184
185 /* convenience wrapper to lock the otp page */
186 int rfid_mful_lock_otp(struct rfid_protocol_handle *ph)
187 {
188         return rfid_mful_lock_page(ph, MIFARE_UL_PAGE_OTP);
189 }