uru4000: add Digital Persona U.are.U 4000 support

My UareU4000 device isn't working properly -- only seeing an all-white
image and no finger-on detection, however I think this code should work
for working devices.
This commit is contained in:
Daniel Drake 2007-11-04 21:12:48 +00:00
parent f498fcd1ea
commit 8e7afef736

View file

@ -50,6 +50,7 @@ enum {
enum { enum {
REG_HWSTAT = 0x07, REG_HWSTAT = 0x07,
REG_MODE = 0x4e, REG_MODE = 0x4e,
FIRMWARE_START = 0x100,
}; };
enum { enum {
@ -77,27 +78,28 @@ static const struct uru4k_dev_profile {
} uru4k_dev_info[] = { } uru4k_dev_info[] = {
[MS_KBD] = { [MS_KBD] = {
.name = "Microsoft Keyboard with Fingerprint Reader", .name = "Microsoft Keyboard with Fingerprint Reader",
.firmware_start = 0x100, .fw_enc_offset = 0x411,
.fw_enc_offset = 0x42b,
}, },
[MS_INTELLIMOUSE] = { [MS_INTELLIMOUSE] = {
.name = "Microsoft Wireless IntelliMouse with Fingerprint Reader", .name = "Microsoft Wireless IntelliMouse with Fingerprint Reader",
.firmware_start = 0x100, .fw_enc_offset = 0x411,
.fw_enc_offset = 0x42b,
}, },
[MS_STANDALONE] = { [MS_STANDALONE] = {
.name = "Microsoft Fingerprint Reader", .name = "Microsoft Fingerprint Reader",
.firmware_start = 0x100, .fw_enc_offset = 0x411,
.fw_enc_offset = 0x42b, },
[DP_URU4000] = {
.name = "Digital Persona U.are.U 4000",
.fw_enc_offset = 0x693,
}, },
[DP_URU4000B] = { [DP_URU4000B] = {
.name = "Digital Persona U.are.U 4000B", .name = "Digital Persona U.are.U 4000B",
.firmware_start = 0x100, .fw_enc_offset = 0x411,
.fw_enc_offset = 0x42b,
}, },
}; };
struct uru4k_dev { struct uru4k_dev {
const struct uru4k_dev_profile *profile;
uint8_t interface; uint8_t interface;
}; };
@ -362,6 +364,36 @@ err:
return r; return r;
} }
static int fix_firmware(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = dev->priv;
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
unsigned char val, new;
int r;
r = usb_control_msg(dev->udev, 0xc0, 0x0c, enc_addr, 0, &val, 1,
CTRL_TIMEOUT);
if (r < 0)
return r;
fp_dbg("encryption byte at %x reads %02x", enc_addr, val);
if (val != 0x07 && val != 0x17)
fp_dbg("strange encryption byte value, please report this");
new = val & 0xef;
//new = 0x17;
if (new == val)
return 0;
r = usb_control_msg(dev->udev, 0x40, 0x04, enc_addr, 0, &new, 1,
CTRL_TIMEOUT);
if (r < 0)
return r;
fp_dbg("fixed encryption byte to %02x", new);
return 1;
}
static int do_init(struct fp_img_dev *dev) static int do_init(struct fp_img_dev *dev)
{ {
unsigned char status; unsigned char status;
@ -411,7 +443,10 @@ retry:
return r; return r;
} }
/* FIXME fix firmware (disable encryption) */
r = fix_firmware(dev);
if (r < 0)
return r;
/* Power up device and wait for interrupt notification */ /* Power up device and wait for interrupt notification */
/* The combination of both modifying firmware *and* doing C-R auth on /* The combination of both modifying firmware *and* doing C-R auth on
@ -519,6 +554,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
} }
urudev = g_malloc0(sizeof(*urudev)); urudev = g_malloc0(sizeof(*urudev));
urudev->profile = &uru4k_dev_info[driver_data];
urudev->interface = iface_desc->bInterfaceNumber; urudev->interface = iface_desc->bInterfaceNumber;
dev->priv = urudev; dev->priv = urudev;
@ -553,6 +589,9 @@ static const struct usb_id id_table[] = {
/* ms fp rdr (standalone) */ /* ms fp rdr (standalone) */
{ .vendor = 0x045e, .product = 0x00bd, .driver_data = MS_STANDALONE }, { .vendor = 0x045e, .product = 0x00bd, .driver_data = MS_STANDALONE },
/* dp uru4000 (standalone) */
{ .vendor = 0x05ba, .product = 0x0007, .driver_data = DP_URU4000 },
/* dp uru4000b (standalone) */ /* dp uru4000b (standalone) */
{ .vendor = 0x05ba, .product = 0x000a, .driver_data = DP_URU4000B }, { .vendor = 0x05ba, .product = 0x000a, .driver_data = DP_URU4000B },