1 /*
2  * UPEK TouchChip driver for libfprint
3  * Copyright (C) 2007 Jan-Michael Brummer <buzz2@gmx.de>
4  * Copyright (C) 2012 Vasily Khoruzhick <anarsoul@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #define FP_COMPONENT "upektc"
22 
23 #include <errno.h>
24 #include <string.h>
25 #include <libusb.h>
26 #include <fp_internal.h>
27 
28 #include "upektc.h"
29 #include "driver_ids.h"
30 
31 #define UPEKTC_EP_IN (2 | LIBUSB_ENDPOINT_IN)
32 #define UPEKTC_EP_OUT (3 | LIBUSB_ENDPOINT_OUT)
33 #define UPEKET_EP_IN (1 | LIBUSB_ENDPOINT_IN)
34 #define UPEKET_EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
35 #define BULK_TIMEOUT 4000
36 
37 struct upektc_dev {
38 	gboolean deactivating;
39 	const struct setup_cmd *setup_commands;
40 	size_t setup_commands_len;
41 	int ep_in;
42 	int ep_out;
43 	int init_idx;
44 	int sum_threshold;
45 };
46 
47 enum upektc_driver_data {
48 	UPEKTC_2015,
49 	UPEKTC_3001,
50 };
51 
52 static void start_capture(struct fp_img_dev *dev);
53 static void complete_deactivation(struct fp_img_dev *dev);
54 static void start_finger_detection(struct fp_img_dev *dev);
55 
56 /****** INITIALIZATION/DEINITIALIZATION ******/
57 
58 enum activate_states {
59 	WRITE_INIT,
60 	READ_DATA,
61 	ACTIVATE_NUM_STATES,
62 };
63 
upektc_next_init_cmd(struct fpi_ssm * ssm)64 static void upektc_next_init_cmd(struct fpi_ssm *ssm)
65 {
66 	struct fp_img_dev *dev = ssm->priv;
67 	struct upektc_dev *upekdev = dev->priv;
68 
69 	upekdev->init_idx += 1;
70 	if (upekdev->init_idx == upekdev->setup_commands_len)
71 		fpi_ssm_mark_completed(ssm);
72 	else
73 		fpi_ssm_jump_to_state(ssm, WRITE_INIT);
74 }
75 
write_init_cb(struct libusb_transfer * transfer)76 static void write_init_cb(struct libusb_transfer *transfer)
77 {
78 	struct fpi_ssm *ssm = transfer->user_data;
79 	struct fp_img_dev *dev = ssm->priv;
80 	struct upektc_dev *upekdev = dev->priv;
81 
82 	if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
83 		(transfer->length == transfer->actual_length)) {
84 		if (upekdev->setup_commands[upekdev->init_idx].response_len)
85 			fpi_ssm_next_state(ssm);
86 		else
87 			upektc_next_init_cmd(ssm);
88 	} else {
89 		fpi_ssm_mark_aborted(ssm, -EIO);
90 	}
91 	libusb_free_transfer(transfer);
92 }
93 
read_init_data_cb(struct libusb_transfer * transfer)94 static void read_init_data_cb(struct libusb_transfer *transfer)
95 {
96 	struct fpi_ssm *ssm = transfer->user_data;
97 
98 	if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
99 		upektc_next_init_cmd(ssm);
100 	else
101 		fpi_ssm_mark_aborted(ssm, -EIO);
102 	g_free(transfer->buffer);
103 	libusb_free_transfer(transfer);
104 }
105 
activate_run_state(struct fpi_ssm * ssm)106 static void activate_run_state(struct fpi_ssm *ssm)
107 {
108 	struct fp_img_dev *dev = ssm->priv;
109 	struct upektc_dev *upekdev = dev->priv;
110 	int r;
111 
112 	switch (ssm->cur_state) {
113 	case WRITE_INIT:
114 	{
115 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
116 		if (!transfer) {
117 			fpi_ssm_mark_aborted(ssm, -ENOMEM);
118 			return;
119 		}
120 		libusb_fill_bulk_transfer(transfer, dev->udev, upekdev->ep_out,
121 			(unsigned char*)upekdev->setup_commands[upekdev->init_idx].cmd,
122 			UPEKTC_CMD_LEN, write_init_cb, ssm, BULK_TIMEOUT);
123 		r = libusb_submit_transfer(transfer);
124 		if (r < 0) {
125 			libusb_free_transfer(transfer);
126 			fpi_ssm_mark_aborted(ssm, -ENOMEM);
127 		}
128 	}
129 	break;
130 	case READ_DATA:
131 	{
132 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
133 		unsigned char *data;
134 
135 		if (!transfer) {
136 			fpi_ssm_mark_aborted(ssm, -ENOMEM);
137 			break;
138 		}
139 
140 		data = g_malloc(upekdev->setup_commands[upekdev->init_idx].response_len);
141 		libusb_fill_bulk_transfer(transfer, dev->udev, upekdev->ep_in, data,
142 			upekdev->setup_commands[upekdev->init_idx].response_len,
143 			read_init_data_cb, ssm, BULK_TIMEOUT);
144 
145 		r = libusb_submit_transfer(transfer);
146 		if (r < 0) {
147 			g_free(data);
148 			libusb_free_transfer(transfer);
149 			fpi_ssm_mark_aborted(ssm, r);
150 		}
151 	}
152 	break;
153 	}
154 }
155 
activate_sm_complete(struct fpi_ssm * ssm)156 static void activate_sm_complete(struct fpi_ssm *ssm)
157 {
158 	struct fp_img_dev *dev = ssm->priv;
159 	fp_dbg("status %d", ssm->error);
160 	fpi_imgdev_activate_complete(dev, ssm->error);
161 
162 	if (!ssm->error)
163 		start_finger_detection(dev);
164 	fpi_ssm_free(ssm);
165 }
166 
167 
168 /****** FINGER PRESENCE DETECTION ******/
169 
finger_present(unsigned char * img,size_t len,int sum_threshold)170 static int finger_present(unsigned char *img, size_t len, int sum_threshold)
171 {
172 	int i, sum;
173 
174 	sum = 0;
175 
176 	for (i = 0; i < len; i++) {
177 		if (img[i] < 160) {
178 			sum++;
179 		}
180 	}
181 
182 	fp_dbg("finger_present: sum is %d\n", sum);
183 	return sum < sum_threshold ? 0 : 1;
184 }
185 
finger_det_data_cb(struct libusb_transfer * transfer)186 static void finger_det_data_cb(struct libusb_transfer *transfer)
187 {
188 	struct fp_img_dev *dev = transfer->user_data;
189 	struct upektc_dev *upekdev = dev->priv;
190 	unsigned char *data = transfer->buffer;
191 
192 	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
193 		fp_dbg("data transfer status %d\n", transfer->status);
194 		fpi_imgdev_session_error(dev, -EIO);
195 		goto out;
196 	} else if (transfer->length != transfer->actual_length) {
197 		fp_dbg("expected %d, got %d bytes", transfer->length,
198 			transfer->actual_length);
199 		fpi_imgdev_session_error(dev, -EPROTO);
200 	}
201 
202 	if (finger_present(data, IMAGE_SIZE, upekdev->sum_threshold)) {
203 		/* finger present, start capturing */
204 		fpi_imgdev_report_finger_status(dev, TRUE);
205 		start_capture(dev);
206 	} else {
207 		/* no finger, poll for a new histogram */
208 		start_finger_detection(dev);
209 	}
210 
211 out:
212 	g_free(data);
213 	libusb_free_transfer(transfer);
214 }
215 
finger_det_cmd_cb(struct libusb_transfer * t)216 static void finger_det_cmd_cb(struct libusb_transfer *t)
217 {
218 	struct libusb_transfer *transfer;
219 	unsigned char *data;
220 	int r;
221 	struct fp_img_dev *dev = t->user_data;
222 	struct upektc_dev *upekdev = dev->priv;
223 
224 	if (t->status != LIBUSB_TRANSFER_COMPLETED) {
225 		fp_dbg("req transfer status %d\n", t->status);
226 		fpi_imgdev_session_error(dev, -EIO);
227 		goto exit_free_transfer;
228 	} else if (t->length != t->actual_length) {
229 		fp_dbg("expected %d, sent %d bytes", t->length, t->actual_length);
230 		fpi_imgdev_session_error(dev, -EPROTO);
231 		goto exit_free_transfer;
232 	}
233 
234 	transfer = libusb_alloc_transfer(0);
235 	if (!transfer) {
236 		fpi_imgdev_session_error(dev, -ENOMEM);
237 		goto exit_free_transfer;
238 	}
239 
240 	data = g_malloc(IMAGE_SIZE);
241 	libusb_fill_bulk_transfer(transfer, dev->udev, upekdev->ep_in, data, IMAGE_SIZE,
242 		finger_det_data_cb, dev, BULK_TIMEOUT);
243 
244 	r = libusb_submit_transfer(transfer);
245 	if (r < 0) {
246 		g_free(data);
247 		libusb_free_transfer(transfer);
248 		fpi_imgdev_session_error(dev, r);
249 	}
250 exit_free_transfer:
251 	libusb_free_transfer(t);
252 }
253 
start_finger_detection(struct fp_img_dev * dev)254 static void start_finger_detection(struct fp_img_dev *dev)
255 {
256 	int r;
257 	struct upektc_dev *upekdev = dev->priv;
258 	struct libusb_transfer *transfer;
259 	fp_dbg("");
260 
261 	if (upekdev->deactivating) {
262 		complete_deactivation(dev);
263 		return;
264 	}
265 
266 	transfer = libusb_alloc_transfer(0);
267 	if (!transfer) {
268 		fpi_imgdev_session_error(dev, -ENOMEM);
269 		return;
270 	}
271 	libusb_fill_bulk_transfer(transfer, dev->udev, upekdev->ep_out,
272 		(unsigned char *)scan_cmd, UPEKTC_CMD_LEN,
273 		finger_det_cmd_cb, dev, BULK_TIMEOUT);
274 	r = libusb_submit_transfer(transfer);
275 	if (r < 0) {
276 		libusb_free_transfer(transfer);
277 		fpi_imgdev_session_error(dev, r);
278 	}
279 }
280 
281 /****** CAPTURE ******/
282 
283 enum capture_states {
284 	CAPTURE_WRITE_CMD,
285 	CAPTURE_READ_DATA,
286 	CAPTURE_NUM_STATES,
287 };
288 
capture_cmd_cb(struct libusb_transfer * transfer)289 static void capture_cmd_cb(struct libusb_transfer *transfer)
290 {
291 	struct fpi_ssm *ssm = transfer->user_data;
292 
293 	if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
294 		(transfer->length == transfer->actual_length)) {
295 		fpi_ssm_next_state(ssm);
296 	} else {
297 		fpi_ssm_mark_aborted(ssm, -EIO);
298 	}
299 	libusb_free_transfer(transfer);
300 }
301 
capture_read_data_cb(struct libusb_transfer * transfer)302 static void capture_read_data_cb(struct libusb_transfer *transfer)
303 {
304 	struct fpi_ssm *ssm = transfer->user_data;
305 	struct fp_img_dev *dev = ssm->priv;
306 	unsigned char *data = transfer->buffer;
307 	struct fp_img *img;
308 
309 	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
310 		fp_dbg("request is not completed, %d", transfer->status);
311 		fpi_ssm_mark_aborted(ssm, -EIO);
312 		goto out;
313 	} else if (transfer->length != transfer->actual_length) {
314 		fp_dbg("expected %d, sent %d bytes", transfer->length, transfer->actual_length);
315 		fpi_ssm_mark_aborted(ssm, -EPROTO);
316 		goto out;
317 	}
318 
319 	img = fpi_img_new(IMAGE_SIZE);
320 	memcpy(img->data, data, IMAGE_SIZE);
321 	fpi_imgdev_image_captured(dev, img);
322 	fpi_imgdev_report_finger_status(dev, FALSE);
323 	fpi_ssm_mark_completed(ssm);
324 out:
325 	g_free(transfer->buffer);
326 	libusb_free_transfer(transfer);
327 }
328 
capture_run_state(struct fpi_ssm * ssm)329 static void capture_run_state(struct fpi_ssm *ssm)
330 {
331 	struct fp_img_dev *dev = ssm->priv;
332 	struct upektc_dev *upekdev = dev->priv;
333 	int r;
334 
335 	switch (ssm->cur_state) {
336 	case CAPTURE_WRITE_CMD:
337 	{
338 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
339 		if (!transfer) {
340 			fpi_ssm_mark_aborted(ssm, -ENOMEM);
341 			return;
342 		}
343 		libusb_fill_bulk_transfer(transfer, dev->udev, upekdev->ep_out,
344 			(unsigned char *)scan_cmd, UPEKTC_CMD_LEN,
345 			capture_cmd_cb, ssm, BULK_TIMEOUT);
346 		r = libusb_submit_transfer(transfer);
347 		if (r < 0) {
348 			libusb_free_transfer(transfer);
349 			fpi_ssm_mark_aborted(ssm, -ENOMEM);
350 		}
351 	}
352 	break;
353 	case CAPTURE_READ_DATA:
354 	{
355 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
356 		unsigned char *data;
357 
358 		if (!transfer) {
359 			fpi_ssm_mark_aborted(ssm, -ENOMEM);
360 			break;
361 		}
362 
363 		data = g_malloc(IMAGE_SIZE);
364 		libusb_fill_bulk_transfer(transfer, dev->udev, upekdev->ep_in, data, IMAGE_SIZE,
365 			capture_read_data_cb, ssm, BULK_TIMEOUT);
366 
367 		r = libusb_submit_transfer(transfer);
368 		if (r < 0) {
369 			g_free(data);
370 			libusb_free_transfer(transfer);
371 			fpi_ssm_mark_aborted(ssm, r);
372 		}
373 	}
374 	break;
375 	};
376 }
377 
capture_sm_complete(struct fpi_ssm * ssm)378 static void capture_sm_complete(struct fpi_ssm *ssm)
379 {
380 	struct fp_img_dev *dev = ssm->priv;
381 	struct upektc_dev *upekdev = dev->priv;
382 
383 	fp_dbg("Capture completed");
384 	if (upekdev->deactivating)
385 		complete_deactivation(dev);
386 	else if (ssm->error)
387 		fpi_imgdev_session_error(dev, ssm->error);
388 	else
389 		start_finger_detection(dev);
390 	fpi_ssm_free(ssm);
391 }
392 
start_capture(struct fp_img_dev * dev)393 static void start_capture(struct fp_img_dev *dev)
394 {
395 	struct upektc_dev *upekdev = dev->priv;
396 	struct fpi_ssm *ssm;
397 
398 	if (upekdev->deactivating) {
399 		complete_deactivation(dev);
400 		return;
401 	}
402 
403 	ssm = fpi_ssm_new(dev->dev, capture_run_state, CAPTURE_NUM_STATES);
404 	fp_dbg("");
405 	ssm->priv = dev;
406 	fpi_ssm_start(ssm, capture_sm_complete);
407 }
408 
dev_activate(struct fp_img_dev * dev,enum fp_imgdev_state state)409 static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
410 {
411 	struct upektc_dev *upekdev = dev->priv;
412 	struct fpi_ssm *ssm = fpi_ssm_new(dev->dev, activate_run_state,
413 		ACTIVATE_NUM_STATES);
414 	ssm->priv = dev;
415 	upekdev->init_idx = 0;
416 	fpi_ssm_start(ssm, activate_sm_complete);
417 	return 0;
418 }
419 
dev_deactivate(struct fp_img_dev * dev)420 static void dev_deactivate(struct fp_img_dev *dev)
421 {
422 	struct upektc_dev *upekdev = dev->priv;
423 
424 	upekdev->deactivating = TRUE;
425 }
426 
complete_deactivation(struct fp_img_dev * dev)427 static void complete_deactivation(struct fp_img_dev *dev)
428 {
429 	struct upektc_dev *upekdev = dev->priv;
430 	fp_dbg("");
431 
432 	upekdev->deactivating = FALSE;
433 	fpi_imgdev_deactivate_complete(dev);
434 }
435 
dev_init(struct fp_img_dev * dev,unsigned long driver_data)436 static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
437 {
438 	/* TODO check that device has endpoints we're using */
439 	int r;
440 	struct upektc_dev *upekdev;
441 
442 	r = libusb_claim_interface(dev->udev, 0);
443 	if (r < 0) {
444 		fp_err("could not claim interface 0: %s", libusb_error_name(r));
445 		return r;
446 	}
447 
448 	dev->priv = upekdev = g_malloc0(sizeof(struct upektc_dev));
449 	switch (driver_data) {
450 	case UPEKTC_2015:
451 		upekdev->ep_in = UPEKTC_EP_IN;
452 		upekdev->ep_out = UPEKTC_EP_OUT;
453 		upekdev->setup_commands = upektc_setup_commands;
454 		upekdev->setup_commands_len = array_n_elements(upektc_setup_commands);
455 		upekdev->sum_threshold = UPEKTC_SUM_THRESHOLD;
456 		break;
457 	case UPEKTC_3001:
458 		upekdev->ep_in = UPEKET_EP_IN;
459 		upekdev->ep_out = UPEKET_EP_OUT;
460 		upekdev->setup_commands = upeket_setup_commands;
461 		upekdev->setup_commands_len = array_n_elements(upeket_setup_commands);
462 		upekdev->sum_threshold = UPEKET_SUM_THRESHOLD;
463 		break;
464 	default:
465 		fp_err("Device variant %d is not known\n", driver_data);
466 		g_free(upekdev);
467 		dev->priv = NULL;
468 		return -ENODEV;
469 		break;
470 	}
471 	fpi_imgdev_open_complete(dev, 0);
472 	return 0;
473 }
474 
dev_deinit(struct fp_img_dev * dev)475 static void dev_deinit(struct fp_img_dev *dev)
476 {
477 	g_free(dev->priv);
478 	libusb_release_interface(dev->udev, 0);
479 	fpi_imgdev_close_complete(dev);
480 }
481 
482 static const struct usb_id id_table[] = {
483 	{ .vendor = 0x0483, .product = 0x2015, .driver_data = UPEKTC_2015 },
484 	{ .vendor = 0x147e, .product = 0x3001, .driver_data = UPEKTC_3001 },
485 	{ 0, 0, 0, },
486 };
487 
488 struct fp_img_driver upektc_driver = {
489 	.driver = {
490 		.id = UPEKTC_ID,
491 		.name = FP_COMPONENT,
492 		.full_name = "UPEK TouchChip/Eikon Touch 300",
493 		.id_table = id_table,
494 		.scan_type = FP_SCAN_TYPE_PRESS,
495 	},
496 	.flags = 0,
497 	.img_height = IMAGE_HEIGHT,
498 	.img_width = IMAGE_WIDTH,
499 
500 	.bz3_threshold = 30,
501 	.open = dev_init,
502 	.close = dev_deinit,
503 	.activate = dev_activate,
504 	.deactivate = dev_deactivate,
505 };
506