1 /* Siemens ID Mouse driver v0.5
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License as
5 published by the Free Software Foundation; either version 2 of
6 the License, or (at your option) any later version.
8 Copyright (C) 2004-5 by Florian 'Floe' Echtler <echtler@fs.tum.de>
9 and Andreas 'ad' Deresch <aderesch@fs.tum.de>
11 Derived from the USB Skeleton driver 1.1,
12 Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com)
16 #include <linux/config.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/delay.h>
20 #include <linux/init.h>
21 #include <linux/slab.h>
22 #include <linux/module.h>
23 #include <linux/smp_lock.h>
24 #include <linux/completion.h>
25 #include <asm/uaccess.h>
26 #include <linux/usb.h>
30 #define HEADER "P5 225 288 255 "
31 #define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1)
33 /* Version Information */
34 #define DRIVER_VERSION "0.5"
35 #define DRIVER_SHORT "idmouse"
36 #define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>"
37 #define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver"
39 /* Siemens ID Mouse */
40 #define USB_IDMOUSE_VENDOR_ID 0x0681
41 #define USB_IDMOUSE_PRODUCT_ID 0x0005
43 /* we still need a minor number */
44 #define USB_IDMOUSE_MINOR_BASE 132
46 static struct usb_device_id idmouse_table
[] = {
47 {USB_DEVICE(USB_IDMOUSE_VENDOR_ID
, USB_IDMOUSE_PRODUCT_ID
)},
48 {} /* null entry at the end */
51 MODULE_DEVICE_TABLE(usb
, idmouse_table
);
53 /* structure to hold all of our device specific stuff */
56 struct usb_device
*udev
; /* save off the usb device pointer */
57 struct usb_interface
*interface
; /* the interface for this device */
59 unsigned char *bulk_in_buffer
; /* the buffer to receive data */
60 size_t bulk_in_size
; /* the size of the receive buffer */
61 __u8 bulk_in_endpointAddr
; /* the address of the bulk in endpoint */
63 int open
; /* if the port is open or not */
64 int present
; /* if the device is not disconnected */
65 struct semaphore sem
; /* locks this structure */
69 /* local function prototypes */
70 static ssize_t
idmouse_read(struct file
*file
, char __user
*buffer
,
71 size_t count
, loff_t
* ppos
);
73 static int idmouse_open(struct inode
*inode
, struct file
*file
);
74 static int idmouse_release(struct inode
*inode
, struct file
*file
);
76 static int idmouse_probe(struct usb_interface
*interface
,
77 const struct usb_device_id
*id
);
79 static void idmouse_disconnect(struct usb_interface
*interface
);
81 /* file operation pointers */
82 static struct file_operations idmouse_fops
= {
86 .release
= idmouse_release
,
89 /* class driver information for devfs */
90 static struct usb_class_driver idmouse_class
= {
91 .name
= "usb/idmouse%d",
92 .fops
= &idmouse_fops
,
93 .mode
= S_IFCHR
| S_IRUSR
| S_IRGRP
| S_IROTH
, /* filemode (char, 444) */
94 .minor_base
= USB_IDMOUSE_MINOR_BASE
,
97 /* usb specific object needed to register this driver with the usb subsystem */
98 static struct usb_driver idmouse_driver
= {
100 .name
= DRIVER_SHORT
,
101 .probe
= idmouse_probe
,
102 .disconnect
= idmouse_disconnect
,
103 .id_table
= idmouse_table
,
106 // prevent races between open() and disconnect()
107 static DECLARE_MUTEX(disconnect_sem
);
109 static int idmouse_create_image(struct usb_idmouse
*dev
)
115 if (dev
->bulk_in_size
< sizeof(HEADER
))
118 memcpy(dev
->bulk_in_buffer
,HEADER
,sizeof(HEADER
)-1);
119 bytes_read
+= sizeof(HEADER
)-1;
121 /* Dump the setup packets. Yes, they are uncommented, simply
122 because they were sniffed under Windows using SnoopyPro.
123 I _guess_ that 0x22 is a kind of reset command and 0x21
126 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
127 0x21, 0x42, 0x0001, 0x0002, NULL
, 0, 1000);
130 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
131 0x20, 0x42, 0x0001, 0x0002, NULL
, 0, 1000);
134 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
135 0x22, 0x42, 0x0000, 0x0002, NULL
, 0, 1000);
139 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
140 0x21, 0x42, 0x0001, 0x0002, NULL
, 0, 1000);
143 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
144 0x20, 0x42, 0x0001, 0x0002, NULL
, 0, 1000);
147 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
148 0x20, 0x42, 0x0000, 0x0002, NULL
, 0, 1000);
152 /* loop over a blocking bulk read to get data from the device */
153 while (bytes_read
< IMGSIZE
) {
154 result
= usb_bulk_msg (dev
->udev
,
155 usb_rcvbulkpipe (dev
->udev
, dev
->bulk_in_endpointAddr
),
156 dev
->bulk_in_buffer
+ bytes_read
,
157 dev
->bulk_in_size
, &bulk_read
, 5000);
160 if (signal_pending(current
))
162 bytes_read
+= bulk_read
;
165 /* reset the device */
166 result
= usb_control_msg (dev
->udev
, usb_sndctrlpipe (dev
->udev
, 0),
167 0x22, 0x42, 0x0000, 0x0002, NULL
, 0, 1000);
171 /* should be IMGSIZE == 64815 */
172 dbg("read %d bytes fingerprint data", bytes_read
);
176 static inline void idmouse_delete(struct usb_idmouse
*dev
)
178 kfree(dev
->bulk_in_buffer
);
182 static int idmouse_open(struct inode
*inode
, struct file
*file
)
184 struct usb_idmouse
*dev
= NULL
;
185 struct usb_interface
*interface
;
188 /* prevent disconnects */
189 down(&disconnect_sem
);
191 /* get the interface from minor number and driver information */
192 interface
= usb_find_interface (&idmouse_driver
, iminor (inode
));
197 /* get the device information block from the interface */
198 dev
= usb_get_intfdata(interface
);
204 /* lock this device */
207 /* check if already open */
210 /* already open, so fail */
215 /* create a new image and check for success */
216 result
= idmouse_create_image (dev
);
220 /* increment our usage count for the driver */
223 /* save our object in the file's private structure */
224 file
->private_data
= dev
;
230 /* unlock this device */
233 /* unlock the disconnect semaphore */
238 static int idmouse_release(struct inode
*inode
, struct file
*file
)
240 struct usb_idmouse
*dev
;
242 /* prevent a race condition with open() */
243 down(&disconnect_sem
);
245 dev
= (struct usb_idmouse
*) file
->private_data
;
252 /* lock our device */
255 /* are we really open? */
256 if (dev
->open
<= 0) {
265 /* the device was unplugged before the file was released */
277 static ssize_t
idmouse_read(struct file
*file
, char __user
*buffer
, size_t count
,
280 struct usb_idmouse
*dev
;
283 dev
= (struct usb_idmouse
*) file
->private_data
;
288 // verify that the device wasn't unplugged
294 if (*ppos
>= IMGSIZE
) {
299 if (count
> IMGSIZE
- *ppos
)
300 count
= IMGSIZE
- *ppos
;
302 if (copy_to_user (buffer
, dev
->bulk_in_buffer
+ *ppos
, count
)) {
314 static int idmouse_probe(struct usb_interface
*interface
,
315 const struct usb_device_id
*id
)
317 struct usb_device
*udev
= interface_to_usbdev(interface
);
318 struct usb_idmouse
*dev
= NULL
;
319 struct usb_host_interface
*iface_desc
;
320 struct usb_endpoint_descriptor
*endpoint
;
324 /* check if we have gotten the data or the hid interface */
325 iface_desc
= &interface
->altsetting
[0];
326 if (iface_desc
->desc
.bInterfaceClass
!= 0x0A)
329 /* allocate memory for our device state and initialize it */
330 dev
= kmalloc(sizeof(*dev
), GFP_KERNEL
);
333 memset(dev
, 0x00, sizeof(*dev
));
335 init_MUTEX(&dev
->sem
);
337 dev
->interface
= interface
;
339 /* set up the endpoint information - use only the first bulk-in endpoint */
340 endpoint
= &iface_desc
->endpoint
[0].desc
;
341 if (!dev
->bulk_in_endpointAddr
342 && (endpoint
->bEndpointAddress
& USB_DIR_IN
)
343 && ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) ==
344 USB_ENDPOINT_XFER_BULK
)) {
346 /* we found a bulk in endpoint */
347 buffer_size
= le16_to_cpu(endpoint
->wMaxPacketSize
);
348 dev
->bulk_in_size
= buffer_size
;
349 dev
->bulk_in_endpointAddr
= endpoint
->bEndpointAddress
;
350 dev
->bulk_in_buffer
=
351 kmalloc(IMGSIZE
+ buffer_size
, GFP_KERNEL
);
353 if (!dev
->bulk_in_buffer
) {
354 err("Unable to allocate input buffer.");
360 if (!(dev
->bulk_in_endpointAddr
)) {
361 err("Unable to find bulk-in endpoint.");
365 /* allow device read, write and ioctl */
368 /* we can register the device now, as it is ready */
369 usb_set_intfdata(interface
, dev
);
370 result
= usb_register_dev(interface
, &idmouse_class
);
372 /* something prevented us from registering this device */
373 err("Unble to allocate minor number.");
374 usb_set_intfdata(interface
, NULL
);
380 dev_info(&interface
->dev
,"%s now attached\n",DRIVER_DESC
);
385 static void idmouse_disconnect(struct usb_interface
*interface
)
387 struct usb_idmouse
*dev
;
389 /* prevent races with open() */
390 down(&disconnect_sem
);
392 /* get device structure */
393 dev
= usb_get_intfdata(interface
);
394 usb_set_intfdata(interface
, NULL
);
399 /* give back our minor */
400 usb_deregister_dev(interface
, &idmouse_class
);
402 /* prevent device read, write and ioctl */
408 /* if the device is opened, idmouse_release will clean this up */
414 info("%s disconnected", DRIVER_DESC
);
417 static int __init
usb_idmouse_init(void)
421 info(DRIVER_DESC
" " DRIVER_VERSION
);
423 /* register this driver with the USB subsystem */
424 result
= usb_register(&idmouse_driver
);
426 err("Unable to register device (error %d).", result
);
431 static void __exit
usb_idmouse_exit(void)
433 /* deregister this driver with the USB subsystem */
434 usb_deregister(&idmouse_driver
);
437 module_init(usb_idmouse_init
);
438 module_exit(usb_idmouse_exit
);
440 MODULE_AUTHOR(DRIVER_AUTHOR
);
441 MODULE_DESCRIPTION(DRIVER_DESC
);
442 MODULE_LICENSE("GPL");