[Fingerforce-commits] r112 - /packages/fprint/libfprint/trunk/libfprint/drivers/fdu2000.c

dererk-guest at users.alioth.debian.org dererk-guest at users.alioth.debian.org
Fri Mar 28 18:26:59 UTC 2008


Author: dererk-guest
Date: Fri Mar 28 18:26:59 2008
New Revision: 112

URL: http://svn.debian.org/wsvn/fingerforce/?sc=1&rev=112
Log:
Adding 0.0.6 new release driver fdu2000

Added:
    packages/fprint/libfprint/trunk/libfprint/drivers/fdu2000.c

Added: packages/fprint/libfprint/trunk/libfprint/drivers/fdu2000.c
URL: http://svn.debian.org/wsvn/fingerforce/packages/fprint/libfprint/trunk/libfprint/drivers/fdu2000.c?rev=112&op=file
==============================================================================
--- packages/fprint/libfprint/trunk/libfprint/drivers/fdu2000.c (added)
+++ packages/fprint/libfprint/trunk/libfprint/drivers/fdu2000.c Fri Mar 28 18:26:59 2008
@@ -1,0 +1,311 @@
+/*
+ * Secugen FDU2000 driver for libfprint
+ * Copyright (C) 2007 Gustavo Chain <g at 0xff.cl>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <usb.h>
+
+#define FP_COMPONENT "fdu2000"
+#include <fp_internal.h>
+
+#ifndef HAVE_MEMMEM
+gpointer
+memmem(const gpointer haystack, size_t haystack_len, const gpointer needle, size_t needle_len) {
+	const gchar *begin;
+	const char *const last_possible = (const char *) haystack + haystack_len - needle_len;
+
+	/* The first occurrence of the empty string is deemed to occur at 
+	 * the beginning of the string. */
+	if (needle_len == 0)
+		return (void *) haystack;
+	
+	/* Sanity check, otherwise the loop might search through the whole
+	 * memory.  */
+	if (haystack_len < needle_len)
+		return NULL;
+	
+	for (begin = (const char *) haystack; begin <= last_possible; ++begin)
+		if (begin[0] == ((const char *) needle)[0] &&
+			!memcmp((const void *) &begin[1],
+				(const void *) ((const char *) needle + 1),
+				needle_len - 1))
+			return (void *) begin;
+	
+	return NULL;
+}
+#endif	/* HAVE_MEMMEM */
+
+#define EP_IMAGE	( 0x02 | USB_ENDPOINT_IN )
+#define EP_REPLY	( 0x01 | USB_ENDPOINT_IN )
+#define EP_CMD		( 0x01 | USB_ENDPOINT_OUT )
+#define BULK_TIMEOUT	200
+
+/* fdu_req[] index */
+typedef enum {
+	CAPTURE_READY,
+	CAPTURE_READ,
+	CAPTURE_END,
+	LED_OFF,
+	LED_ON
+} req_index;
+
+
+#define CMD_LEN 2
+#define ACK_LEN 8
+static const struct fdu2000_req {
+	const gchar cmd[CMD_LEN];	// Command to send
+	const gchar ack[ACK_LEN];	// Expected ACK
+	const guint ack_len;	// ACK has variable length
+} fdu_req[] = {
+	/* Capture */
+	{
+		.cmd = { 0x00, 0x04 },
+		.ack = { 0x00, 0x04, 0x01, 0x01 },
+		.ack_len = 4
+	},
+	
+	{
+		.cmd = { 0x00, 0x01 },
+		.ack = { 0x00, 0x01, 0x01, 0x01 },
+		.ack_len = 4
+	},
+
+	{
+		.cmd = { 0x00, 0x05 },
+		.ack = { 0x00, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+		.ack_len = 8
+	},
+
+	/* Led */
+	{
+		.cmd = { 0x05, 0x00 },
+		.ack = {},
+		.ack_len = 0
+	},
+
+	{
+		.cmd = { 0x05, 0x01 },
+		.ack = {},
+		.ack_len = 0
+	}
+};
+
+/*
+ * Write a command and verify reponse
+ */
+static gint
+bulk_write_safe(usb_dev_handle *dev, req_index rIndex) {
+
+	gchar reponse[ACK_LEN];
+	gint r;
+	gchar *cmd = (gchar *)fdu_req[rIndex].cmd;
+	gchar *ack = (gchar *)fdu_req[rIndex].ack;
+	gint ack_len = fdu_req[rIndex].ack_len;
+
+	r = usb_bulk_write(dev, EP_CMD, cmd, sizeof(cmd), BULK_TIMEOUT);
+	if (r < 0)
+		return r;
+
+	if (ack_len == 0)
+		return 0;
+
+	/* Check reply from FP */
+	r = usb_bulk_read (dev, EP_REPLY,
+			reponse, sizeof(reponse), BULK_TIMEOUT);
+	if (r < 0)
+		return r;
+
+	if (!strncmp(ack, reponse, ack_len))
+		return 0;
+	
+	fp_err("Expected different ACK from dev");
+	return 1;	/* Error */
+}
+
+static gint
+capture(struct fp_img_dev *dev, gboolean unconditional,
+	struct fp_img **ret)
+{
+#define RAW_IMAGE_WIDTH		398
+#define RAW_IMAGE_HEIGTH	301
+#define RAW_IMAGE_SIZE		(RAW_IMAGE_WIDTH * RAW_IMAGE_HEIGTH)
+
+	struct fp_img *img = NULL;
+	guint bytes, r;
+	const gchar SOF[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x07 };  // Start of frame
+	const gchar SOL[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0b, 0x06 };  // Start of line + { L L } (L: Line num) (8 nibbles)
+	gchar *buffer;
+	gchar *image;
+	gchar *p;
+	guint offset;
+
+	buffer = g_malloc0(RAW_IMAGE_SIZE * 6);
+	image  = g_malloc0(RAW_IMAGE_SIZE);
+
+	if ((r = bulk_write_safe(dev->udev, LED_ON))) {
+		fp_err("Command: LED_ON");
+		goto out;
+	}
+	
+	if ((r = bulk_write_safe(dev->udev, CAPTURE_READY))) {
+		fp_err("Command: CAPTURE_READY");
+		goto out;
+	}
+
+read:	
+	if ((r = bulk_write_safe(dev->udev, CAPTURE_READ))) {
+		fp_err("Command: CAPTURE_READ");
+		goto out;
+	}
+
+	/* Now we are ready to read from dev */
+
+	bytes = usb_bulk_read(dev->udev,
+			EP_IMAGE,
+			buffer, RAW_IMAGE_SIZE * 6,
+			BULK_TIMEOUT * 10);
+
+	if (bytes < 1)
+		goto read;
+
+	/*
+	 * Find SOF (start of line)
+	 */
+	p = memmem(buffer, RAW_IMAGE_SIZE * 6,
+			(const gpointer)SOF, sizeof SOF);
+	fp_dbg("Read %d byte/s from dev", bytes);
+	if (!p)
+		goto out;
+
+	p += sizeof SOF;
+
+	int i = 0;
+	bytes = 0;
+	while(p) {
+		if ( i >= RAW_IMAGE_HEIGTH )
+			break;
+
+		offset = p - buffer;
+		p = memmem(p, (RAW_IMAGE_SIZE * 6) - (offset),
+				(const gpointer)SOL, sizeof SOL);
+		if (p) {
+			p += sizeof SOL + 4;
+			int j;
+			for (j = 0; j < RAW_IMAGE_WIDTH; j++) {
+				/**
+				 * Convert from 4 to 8 bits
+				 * The SECUGEN-FDU2000 has 4 lines of data, so we need to join 2 bytes into 1
+				 */
+				*(image + bytes + j)  = *(p + (j * 2) + 0) << 4 & 0xf0;
+				*(image + bytes + j) |= *(p + (j * 2) + 1) & 0x0f;
+			}
+			p += RAW_IMAGE_WIDTH * 2;
+			bytes += RAW_IMAGE_WIDTH;
+			i++;
+		}
+	}
+
+	if ((r = bulk_write_safe(dev->udev, CAPTURE_END))) {
+		fp_err("Command: CAPTURE_END");
+		goto out;
+	}
+
+	if ((r = bulk_write_safe(dev->udev, LED_OFF))) {
+		fp_err("Command: LED_OFF");
+		goto out;
+	}
+
+	img = fpi_img_new_for_imgdev(dev);
+	memcpy(img->data, image, RAW_IMAGE_SIZE);
+	img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
+	*ret = img;
+
+out:
+	g_free(buffer);
+	g_free(image);
+
+	return r;
+}
+
+static
+gint dev_init(struct fp_img_dev *dev, unsigned long driver_data)
+{
+	gint r;
+	if ( (r = usb_set_configuration(dev->udev, 1)) < 0 )
+		goto out;
+
+	if ( (r = usb_claim_interface(dev->udev, 0)) < 0 )
+		goto out;
+
+	if ( (r = usb_set_altinterface(dev->udev, 1)) < 0 )
+		goto out;
+
+	if ( (r = usb_clear_halt(dev->udev, EP_CMD)) < 0 )
+		goto out;
+
+	/* Make sure sensor mode is not capture_{ready|read} */
+	if ((r = bulk_write_safe(dev->udev, CAPTURE_END))) {
+		fp_err("Command: CAPTURE_END");
+		goto out;
+	}
+
+	if ((r = bulk_write_safe(dev->udev, LED_OFF))) {
+		fp_err("Command: LED_OFF");
+		goto out;
+	}
+
+	return 0;
+
+out:
+	fp_err("could not init dev");
+	fp_err(usb_strerror());
+	return r;
+}
+
+static
+void dev_exit(struct fp_img_dev *dev)
+{
+	if (bulk_write_safe(dev->udev, CAPTURE_END))
+		fp_err("Command: CAPTURE_END");
+
+	usb_release_interface(dev->udev, 0);
+}
+
+static const struct usb_id id_table[] = {
+	{ .vendor = 0x1162, .product = 0x0300 },
+	{ 0, 0, 0, },
+};
+
+struct fp_img_driver fdu2000_driver = {
+	.driver = {
+		.id = 7,
+		.name = FP_COMPONENT,
+		.full_name = "Secugen FDU 2000",
+		.id_table = id_table,
+	},
+	.img_height = RAW_IMAGE_HEIGTH,
+	.img_width = RAW_IMAGE_WIDTH,
+	.bz3_threshold = 23,
+
+	.init = dev_init,
+	.exit = dev_exit,
+	.capture = capture,
+};




More information about the Fingerforce-commits mailing list