2 * Shared functions between libfprint Authentec drivers
3 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #define FP_COMPONENT "aeslib"
27 #include "fp_internal.h"
30 #define MAX_REGWRITES_PER_REQUEST 16
32 #define BULK_TIMEOUT 4000
33 #define EP_IN (1 | LIBUSB_ENDPOINT_IN)
34 #define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
36 struct write_regv_data
{
37 struct fp_img_dev
*imgdev
;
38 unsigned int num_regs
;
39 const struct aes_regwrite
*regs
;
41 aes_write_regv_cb callback
;
45 static void continue_write_regv(struct write_regv_data
*wdata
);
47 /* libusb bulk callback for regv write completion transfer. continues the
49 static void write_regv_trf_complete(struct libusb_transfer
*transfer
)
51 struct write_regv_data
*wdata
= transfer
->user_data
;
53 if (transfer
->status
!= LIBUSB_TRANSFER_COMPLETED
)
54 wdata
->callback(wdata
->imgdev
, -EIO
, wdata
->user_data
);
55 else if (transfer
->length
!= transfer
->actual_length
)
56 wdata
->callback(wdata
->imgdev
, -EPROTO
, wdata
->user_data
);
58 continue_write_regv(wdata
);
60 g_free(transfer
->buffer
);
61 libusb_free_transfer(transfer
);
64 /* write from wdata->offset to upper_bound (inclusive) of wdata->regs */
65 static int do_write_regv(struct write_regv_data
*wdata
, int upper_bound
)
67 unsigned int offset
= wdata
->offset
;
68 unsigned int num
= upper_bound
- offset
+ 1;
69 size_t alloc_size
= num
* 2;
70 unsigned char *data
= g_malloc(alloc_size
);
72 size_t data_offset
= 0;
73 struct libusb_transfer
*transfer
= libusb_alloc_transfer(0);
81 for (i
= offset
; i
< offset
+ num
; i
++) {
82 const struct aes_regwrite
*regwrite
= &wdata
->regs
[i
];
83 data
[data_offset
++] = regwrite
->reg
;
84 data
[data_offset
++] = regwrite
->value
;
87 libusb_fill_bulk_transfer(transfer
, wdata
->imgdev
->udev
, EP_OUT
, data
,
88 alloc_size
, write_regv_trf_complete
, wdata
, BULK_TIMEOUT
);
89 r
= libusb_submit_transfer(transfer
);
92 libusb_free_transfer(transfer
);
98 /* write the next batch of registers to be written, or if there are no more,
99 * indicate completion to the caller */
100 static void continue_write_regv(struct write_regv_data
*wdata
)
102 unsigned int offset
= wdata
->offset
;
103 unsigned int regs_remaining
;
105 unsigned int upper_bound
;
109 /* skip all zeros and ensure there is still work to do */
111 if (offset
>= wdata
->num_regs
) {
112 fp_dbg("all registers written");
113 wdata
->callback(wdata
->imgdev
, 0, wdata
->user_data
);
116 if (wdata
->regs
[offset
].reg
)
121 wdata
->offset
= offset
;
122 regs_remaining
= wdata
->num_regs
- offset
;
123 limit
= MIN(regs_remaining
, MAX_REGWRITES_PER_REQUEST
);
124 upper_bound
= offset
+ limit
- 1;
126 /* determine if we can write the entire of the regs at once, or if there
127 * is a zero dividing things up */
128 for (i
= offset
; i
<= upper_bound
; i
++)
129 if (!wdata
->regs
[i
].reg
) {
134 r
= do_write_regv(wdata
, upper_bound
);
136 wdata
->callback(wdata
->imgdev
, r
, wdata
->user_data
);
140 wdata
->offset
= upper_bound
+ 1;
143 /* write a load of registers to the device, combining multiple writes in a
144 * single URB up to a limit. insert writes to non-existent register 0 to force
145 * specific groups of writes to be separated by different URBs. */
146 void aes_write_regv(struct fp_img_dev
*dev
, const struct aes_regwrite
*regs
,
147 unsigned int num_regs
, aes_write_regv_cb callback
, void *user_data
)
149 struct write_regv_data
*wdata
= g_malloc(sizeof(*wdata
));
150 fp_dbg("write %d regs", num_regs
);
152 wdata
->num_regs
= num_regs
;
155 wdata
->callback
= callback
;
156 wdata
->user_data
= user_data
;
157 continue_write_regv(wdata
);
160 void aes_assemble_image(unsigned char *input
, size_t width
, size_t height
,
161 unsigned char *output
)
165 for (column
= 0; column
< width
; column
++) {
166 for (row
= 0; row
< height
; row
+= 2) {
167 output
[width
* row
+ column
] = (*input
& 0x07) * 36;
168 output
[width
* (row
+ 1) + column
] = ((*input
& 0x70) >> 4) * 36;