1 /*
2  * UPEK TouchStrip Sensor-Only driver for libfprint
3  * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
4  *
5  * TCS4C (USB ID 147e:1000) support:
6  * Copyright (C) 2010 Hugo Grostabussiat <dw23.devel@gmail.com>
7  *
8  * TCRD5B (USB ID 147e:1001) support:
9  * Copyright (C) 2014 Vasily Khoruzhick <anarsoul@gmail.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  */
25 
26 #define IMG_WIDTH_2016	288
27 #define IMG_WIDTH_1000	288
28 #define IMG_WIDTH_1001	216
29 
30 struct sonly_regwrite {
31 	uint8_t reg;
32 	uint8_t value;
33 };
34 
35 /***** AWAIT FINGER *****/
36 
37 static const struct sonly_regwrite awfsm_2016_writev_1[] = {
38 	{ 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b },
39 	{ 0x00, 0x67 }, { 0x00, 0x67 },
40 };
41 
42 static const struct sonly_regwrite awfsm_1000_writev_1[] = {
43 	/* Initialize sensor settings */
44 	{ 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f },
45 	{ 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d },
46 	{ 0x0e, 0x0e }, { 0x0f, 0x0d },
47 
48 	{ 0x13, 0x05 }, { 0x13, 0x45 },
49 
50 	/* Initialize finger detection registers (not enabling yet) */
51 	{ 0x30, 0xe0 }, { 0x15, 0x26 },
52 
53 	{ 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 },
54 	{ 0x10, 0x00 }, { 0x11, 0xbf },
55 };
56 
57 static const struct sonly_regwrite awfsm_2016_writev_2[] = {
58 	{ 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
59 	{ 0x0f, 0x0d }, { 0x0b, 0x00 },
60 };
61 
62 static const struct sonly_regwrite awfsm_1000_writev_2[] = {
63 	/* Enable finger detection */
64 	{ 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 },
65 };
66 
67 static const struct sonly_regwrite awfsm_2016_writev_3[] = {
68 	{ 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 },
69 	{ 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 },
70 };
71 
72 static const struct sonly_regwrite awfsm_2016_writev_4[] = {
73 	{ 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf },
74 	{ 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 },\
75 	{ 0x05, 0x00 }, { 0x0b, 0x00 },
76 
77 	/* enter finger detection mode */
78 	{ 0x15, 0x20 }, { 0x30, 0xe1 }, { 0x15, 0x24 }, { 0x15, 0x04 },
79 	{ 0x15, 0x84 },
80 };
81 
82 /***** CAPTURE MODE *****/
83 
84 static const struct sonly_regwrite capsm_2016_writev[] = {
85 	/* enter capture mode */
86 	{ 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 },
87 	{ 0x05, 0x00 },
88 };
89 
90 static const struct sonly_regwrite capsm_1000_writev[] = {
91 	{ 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */
92 };
93 
94 static const struct sonly_regwrite capsm_1001_writev_1[] = {
95 	{ 0x1a, 0x02 },
96 	{ 0x4a, 0x9d },
97 	{ 0x4e, 0x05 },
98 };
99 
100 
101 static const struct sonly_regwrite capsm_1001_writev_2[] = {
102 	{ 0x4d, 0xc0 }, { 0x4e, 0x09 },
103 };
104 
105 static const struct sonly_regwrite capsm_1001_writev_3[] = {
106 	{ 0x4a, 0x9c },
107 	{ 0x1a, 0x00 },
108 	{ 0x0b, 0x00 },
109 	{ 0x04, 0x00 },
110 	{ 0x05, 0x00 },
111 	{ 0x1a, 0x02 },
112 	{ 0x4a, 0x9d },
113 	{ 0x4d, 0x40 }, { 0x4e, 0x09 },
114 };
115 
116 static const struct sonly_regwrite capsm_1001_writev_4[] = {
117 	{ 0x4a, 0x9c },
118 	{ 0x1a, 0x00 },
119 	{ 0x1a, 0x02 },
120 	{ 0x4a, 0x9d },
121 	{ 0x4e, 0x08 },
122 };
123 
124 
125 static const struct sonly_regwrite capsm_1001_writev_5[] = {
126 	{ 0x4a, 0x9c },
127 	{ 0x1a, 0x00 },
128 	{ 0x1a, 0x02 },
129 	{ 0x00, 0x5f }, { 0x01, 0xee },
130 	{ 0x03, 0x2c },
131 	{ 0x07, 0x00 }, { 0x08, 0x00 }, { 0x09, 0x29 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
132 	{ 0x0f, 0x0d }, { 0x10, 0x00 }, { 0x11, 0x8f }, { 0x12, 0x01 }, { 0x13, 0x45 },
133 	{ 0x15, 0x26 },
134 	{ 0x1e, 0x02 },
135 	{ 0x20, 0x01 },
136 	{ 0x25, 0x8f },
137 	{ 0x27, 0x23 },
138 	{ 0x30, 0xe0 },
139 	{ 0x07, 0x10 },
140 	{ 0x09, 0x21 },
141 	{ 0x13, 0x75 },
142 	{ 0x0b, 0x80 },
143 };
144 
145 /***** DEINITIALIZATION *****/
146 
147 static const struct sonly_regwrite deinitsm_2016_writev[] = {
148 	/* reset + enter low power mode */
149 	{ 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 },
150 };
151 
152 static const struct sonly_regwrite deinitsm_1000_writev[] = {
153 	{ 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */
154 
155 	{ 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */
156 };
157 
158 static const struct sonly_regwrite deinitsm_1001_writev[] = {
159 	{ 0x0b, 0x00 },
160 	{ 0x13, 0x45 },
161 	{ 0x09, 0x29 },
162 	{ 0x1a, 0x00 },
163 };
164 
165 /***** INITIALIZATION *****/
166 
167 static const struct sonly_regwrite initsm_2016_writev_1[] = {
168 	{ 0x49, 0x00 },
169 
170 	/* BSAPI writes different values to register 0x3e each time. I initially
171 	 * thought this was some kind of clever authentication, but just blasting
172 	 * these sniffed values each time seems to work. */
173 	{ 0x3e, 0x83 }, { 0x3e, 0x4f }, { 0x3e, 0x0f }, { 0x3e, 0xbf },
174 	{ 0x3e, 0x45 }, { 0x3e, 0x35 }, { 0x3e, 0x1c }, { 0x3e, 0xae },
175 
176 	{ 0x44, 0x01 }, { 0x43, 0x06 }, { 0x43, 0x05 }, { 0x43, 0x04 },
177 	{ 0x44, 0x00 }, { 0x0b, 0x00 },
178 };
179 
180 static const struct sonly_regwrite initsm_1000_writev_1[] = {
181 	{ 0x49, 0x00 }, /* Encryption disabled */
182 
183 	/* Setting encryption key. Doesn't need to be random since we don't use any
184 	 * encryption. */
185 	{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
186 	{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
187 
188 	{ 0x04, 0x00 }, { 0x05, 0x00 },
189 
190 	{ 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */
191 };
192 
193 static const struct sonly_regwrite initsm_1001_writev_1[] = {
194 	{ 0x4a, 0x9d },
195 	{ 0x4f, 0x06 },
196 	{ 0x4f, 0x05 },
197 	{ 0x4f, 0x04 },
198 	{ 0x4a, 0x9c },
199 	{ 0x3e, 0xa6 },
200 	{ 0x3e, 0x01 },
201 	{ 0x3e, 0x68 },
202 	{ 0x3e, 0xfd },
203 	{ 0x3e, 0x72 },
204 	{ 0x3e, 0xef },
205 	{ 0x3e, 0x5d },
206 	{ 0x3e, 0xc5 },
207 	{ 0x1a, 0x02 },
208 	{ 0x4a, 0x9d },
209 	{ 0x4c, 0x1f }, { 0x4d, 0xb8 }, { 0x4e, 0x00 },
210 };
211 
212 
213 static const struct sonly_regwrite initsm_1001_writev_2[] = {
214 	{ 0x4c, 0x03 }, { 0x4d, 0xb8 }, { 0x4e, 0x00 },
215 };
216 
217 static const struct sonly_regwrite initsm_1001_writev_3[] = {
218 	{ 0x4a, 0x9c },
219 	{ 0x1a, 0x00 },
220 	{ 0x1a, 0x02 },
221 	{ 0x4a, 0x9d },
222 	{ 0x4c, 0xff }, { 0x4d, 0xc0 }, { 0x4e, 0x00 },
223 };
224 
225 
226 static const struct sonly_regwrite initsm_1001_writev_4[] = {
227 	{ 0x4a, 0x9c },
228 	{ 0x1a, 0x00 },
229 	{ 0x09, 0x27 },
230 	{ 0x1a, 0x02 },
231 	{ 0x49, 0x01 },
232 	{ 0x47, 0x02 },
233 	{ 0x47, 0x02 },
234 	{ 0x47, 0x02 },
235 	{ 0x47, 0x02 },
236 	{ 0x47, 0x02 },
237 	{ 0x47, 0x02 },
238 	{ 0x47, 0x02 },
239 	{ 0x47, 0x0a },
240 	{ 0x47, 0x00 },
241 	{ 0x47, 0x04 },
242 	{ 0x47, 0x04 },
243 	{ 0x47, 0x04 },
244 	{ 0x47, 0x04 },
245 	{ 0x47, 0x04 },
246 	{ 0x47, 0x04 },
247 	{ 0x47, 0x04 },
248 	{ 0x47, 0x04 },
249 	{ 0x47, 0x02 },
250 	{ 0x47, 0x02 },
251 	{ 0x47, 0x02 },
252 	{ 0x47, 0x02 },
253 	{ 0x47, 0x02 },
254 	{ 0x47, 0x02 },
255 	{ 0x47, 0x02 },
256 	{ 0x47, 0x0a },
257 	{ 0x47, 0x00 },
258 	{ 0x47, 0x04 },
259 	{ 0x47, 0x04 },
260 	{ 0x47, 0x04 },
261 	{ 0x47, 0x04 },
262 	{ 0x47, 0x04 },
263 	{ 0x47, 0x04 },
264 	{ 0x47, 0x04 },
265 	{ 0x47, 0x04 },
266 	{ 0x47, 0x02 },
267 	{ 0x47, 0x02 },
268 	{ 0x47, 0x02 },
269 	{ 0x47, 0x02 },
270 	{ 0x47, 0x02 },
271 	{ 0x47, 0x02 },
272 	{ 0x47, 0x02 },
273 	{ 0x47, 0x0a },
274 	{ 0x47, 0x00 },
275 	{ 0x47, 0x04 },
276 	{ 0x47, 0x04 },
277 	{ 0x47, 0x04 },
278 	{ 0x47, 0x04 },
279 	{ 0x47, 0x04 },
280 	{ 0x47, 0x04 },
281 	{ 0x47, 0x04 },
282 	{ 0x47, 0x04 },
283 	{ 0x47, 0x02 },
284 	{ 0x47, 0x02 },
285 	{ 0x47, 0x02 },
286 	{ 0x47, 0x02 },
287 	{ 0x47, 0x02 },
288 	{ 0x47, 0x02 },
289 	{ 0x47, 0x02 },
290 	{ 0x47, 0x0a },
291 	{ 0x47, 0x00 },
292 	{ 0x47, 0x04 },
293 	{ 0x47, 0x04 },
294 	{ 0x47, 0x04 },
295 	{ 0x47, 0x04 },
296 	{ 0x47, 0x04 },
297 	{ 0x47, 0x04 },
298 	{ 0x47, 0x04 },
299 	{ 0x47, 0x04 },
300 	{ 0x49, 0x00 },
301 	{ 0x3e, 0x90 },
302 	{ 0x3e, 0xbd },
303 	{ 0x3e, 0xbf },
304 	{ 0x3e, 0x48 },
305 	{ 0x3e, 0x2a },
306 	{ 0x3e, 0xe3 },
307 	{ 0x3e, 0xd2 },
308 	{ 0x3e, 0x58 },
309 	{ 0x09, 0x2f },
310 	{ 0x1a, 0x00 },
311 	{ 0x1a, 0x02 },
312 	{ 0x4a, 0x9d },
313 	{ 0x4d, 0x40 }, { 0x4e, 0x03 },
314 };
315 
316 static const struct sonly_regwrite initsm_1001_writev_5[] = {
317 	{ 0x4a, 0x9c },
318 	{ 0x1a, 0x00 },
319 };
320