-
Notifications
You must be signed in to change notification settings - Fork 0
/
go_fprint.go
233 lines (203 loc) · 6.33 KB
/
go_fprint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
package gofprint
/*
#include <stdio.h>
#include <stdlib.h>
#include <libfprint/fprint.h>
#include <unistd.h>
#cgo LDFLAGS: -lfprint
*/
import "C"
import (
"fmt"
"os"
"unsafe"
)
//This method discovers a given device
func GoDiscoverDevice(discovered_devs **C.struct_fp_dscv_dev) *C.struct_fp_dscv_dev {
ddev := discovered_devs
if ddev == nil{
os.Exit(1)
}
//The two lines below discover the name of the device
//drv := C.fp_dscv_dev_get_driver(*ddev)
//fmt.Println(fmt.Sprintf("Found device claimed by %v driver", test))
return *ddev
}
//This method frees the data generated during the enroll process
func GoFreeData(data *C.struct_fp_print_data){
C.fp_print_data_free(data)
}
//This method closes the device
func GoCloseDevice(dev *C.struct_fp_dev){
C.fp_dev_close(dev)
}
//This method deinitialises libfprint
func GoFpExit(){
C.fp_exit()
}
//This method enrolls one's fingerprint and returns the fingerprint data
func GoEnroll(channel chan string, dev *C.struct_fp_dev ) *C.struct_fp_print_data {
C.fp_dev_get_nr_enroll_stages(dev)
var enrolled_print *C.struct_fp_print_data
channel <- "Position your finger on the scanner now."
for i := 0; i < 5; i++ {
r := C.fp_enroll_finger(dev, &enrolled_print)
if r < 0 {
channel <- "Enroll failed with error"
os.Exit(9)
}
switch r {
case C.FP_ENROLL_COMPLETE:
channel <- "Enroll complete!"
break
case C.FP_ENROLL_FAIL:
channel <- "Enroll failed, something wen't wrong."
break
case C.FP_ENROLL_PASS:
channel <- fmt.Sprintf("Enroll stage %d passed. Position your finger on the scanner again.", i)
break
case C.FP_ENROLL_RETRY:
channel <- "Didn't quite catch that. Please try again."
break
case C.FP_ENROLL_RETRY_TOO_SHORT:
channel <- "Your swipe was too short, please try again."
break
case C.FP_ENROLL_RETRY_CENTER_FINGER:
channel <- "Didn't catch that, please center your finger on the sensor and try again"
break
case C.FP_ENROLL_RETRY_REMOVE_FINGER:
channel <- "Scan failed, please remove your finger and then try again"
break
}
}
return enrolled_print
}
//This method checks one's fingerprint against fingerprint data passed as parameter
//and returns an integer.
// If the integer returned is -2, the verification failed.
// If the integer returned is -1, the fingerprint tested didn't match any of the fingerprints passed in gallery.
func GoVerify(channel chan string, dev *C.struct_fp_dev, data *C.struct_fp_print_data) int {
for {
channel <- "Scan your finger now."
r := C.fp_verify_finger(dev, data)
if r < 0 {
channel <- fmt.Sprintf("Verification failed with error : %v", r)
return -2
}
switch r {
case C.FP_VERIFY_NO_MATCH:
channel <- "NO MATCH"
return -1
case C.FP_VERIFY_MATCH:
channel <- "MATCH"
return 1
case C.FP_VERIFY_RETRY:
channel <- "Scan didn't quite work. Please try again"
return 0
case C.FP_VERIFY_RETRY_TOO_SHORT:
channel <- "Swipe was too short, please try again."
return 0
case C.FP_VERIFY_RETRY_CENTER_FINGER:
channel <- "Please center your finger on the sensor and try again."
return 0
case C.FP_VERIFY_RETRY_REMOVE_FINGER:
channel <- "Please remove finger from the sensor and try again."
return 0
}
}
return -1
}
//This method checks one's fingerprint against an array of fingerprint data passed as parameter
//and returns an integer.
// If the integer returned is -2, the verification failed.
// If the integer returned is -1, the fingerprint tested didn't match any of the fingerprints passed in gallery.
func GoIdentify(channel chan string, dev *C.struct_fp_dev, gallery []*C.struct_fp_print_data) int {
var match_offset C.size_t
match_offset = 0
for {
channel <- "Scan your finger now."
r := C.fp_identify_finger(dev, &gallery[0], &match_offset)
if r < 0 {
channel <- fmt.Sprintf("Verification failed with error : %v", r)
return -2
}
switch r {
case C.FP_VERIFY_NO_MATCH:
channel <- "NO MATCH"
return -1
case C.FP_VERIFY_MATCH:
channel <- "MATCH"
return (int)(match_offset)
case C.FP_VERIFY_RETRY:
channel <- "Scan didn't quite work. Please try again"
//return 0
case C.FP_VERIFY_RETRY_TOO_SHORT:
channel <- "Swipe was too short, please try again."
//return 0
case C.FP_VERIFY_RETRY_CENTER_FINGER:
channel <- "Please center your finger on the sensor and try again."
//return 0
case C.FP_VERIFY_RETRY_REMOVE_FINGER:
channel <- "Please remove finger from the sensor and try again."
//return 0
}
}
return -1
}
//This method opens the device
func GoOpenDevice(channel chan string) *C.struct_fp_dev {
i := C.fp_init()
if i < 0 {
channel <- "Failed to initialize libfprint"
}
discovered_devs := C.fp_discover_devs()
if discovered_devs == nil {
channel <- "Could not discover devices"
return nil
}
ddev := GoDiscoverDevice(discovered_devs)
if ddev == nil {
channel <- "No devices detected."
return nil
}
dev := C.fp_dev_open(ddev)
C.fp_dscv_devs_free(discovered_devs)
if dev == nil {
channel <- "Could not open device."
return nil
}
return dev
}
//This method converts fingerprint data to Go's byte slice
func GoFprintDataToByteSlice(data *C.struct_fp_print_data) []byte {
var ret *C.uchar
//Converting fprint_data_struct to file
//size is of type size_t
size := C.fp_print_data_get_data(data, &ret)
//Converting size_t to C.int
final_fprint_size := C.int(size)
//Converting ret (fprint_file) to go []byte
byteSlice := C.GoBytes(unsafe.Pointer(ret), final_fprint_size)
return byteSlice
}
//This method converts Go's byte slice to fingerprint data
func GoByteSliceDataToFprint(byteSlice []byte) *C.struct_fp_print_data {
//This way I don't have to receive the size_t
sizeSlice := cap(byteSlice)
x := (*C.size_t)(unsafe.Pointer(&sizeSlice))
//Converts mySlice to array of unsigned char
cstr := (*C.uchar)(unsafe.Pointer(&byteSlice[0]))
sliced_data := C.fp_print_data_from_data(cstr, *x)
return sliced_data
}
//This method converts Go's byte bidimensional slice to a struct_fp_print_data array and sends it
//as a parameter to be identified
func GoIdentifyFingerprints(channel chan string, dev *C.struct_fp_dev, byteSlices [][]byte) int {
var print_gallery []*C.struct_fp_print_data
for _, byteSlice := range byteSlices{
print_gallery = append(print_gallery, GoByteSliceDataToFprint(byteSlice))
}
print_gallery = append(print_gallery, nil)
index := GoIdentify(channel, dev, print_gallery)
return index
}