├── .github
└── stale.yml
├── .gitignore
├── LICENSE
├── README.md
├── Unosquare.Labs.LibFprint.Tests
├── Program.cs
└── Unosquare.Labs.LibFprint.Tests.csproj
├── Unosquare.Labs.LibFprint.sln
├── Unosquare.Labs.LibFprint
├── EnrollResult.cs
├── EnrollStageResult.cs
├── Extensions.cs
├── FingerprintDevice.cs
├── FingerprintDeviceManager.cs
├── FingerprintGallery.cs
├── Interop.Types.cs
├── Interop.cs
├── PgmFormatReader.cs
├── Unosquare.Labs.LibFprint.csproj
└── fprint.h
├── appveyor.yml
├── docfx.json
└── toc.yml
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: wontfix
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: false
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | *_i.c
42 | *_p.c
43 | *_i.h
44 | *.ilk
45 | *.meta
46 | *.obj
47 | *.pch
48 | *.pdb
49 | *.pgc
50 | *.pgd
51 | *.rsp
52 | *.sbr
53 | *.tlb
54 | *.tli
55 | *.tlh
56 | *.tmp
57 | *.tmp_proj
58 | *.log
59 | *.vspscc
60 | *.vssscc
61 | .builds
62 | *.pidb
63 | *.svclog
64 | *.scc
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 | # TODO: Comment the next line if you want to checkin your web deploy settings
133 | # but database connection strings (with potential passwords) will be unencrypted
134 | *.pubxml
135 | *.publishproj
136 |
137 | # NuGet Packages
138 | *.nupkg
139 | # The packages folder can be ignored because of Package Restore
140 | **/packages/*
141 | # except build/, which is used as an MSBuild target.
142 | !**/packages/build/
143 | # Uncomment if necessary however generally it will be regenerated when needed
144 | #!**/packages/repositories.config
145 |
146 | # Windows Azure Build Output
147 | csx/
148 | *.build.csdef
149 |
150 | # Windows Store app package directory
151 | AppPackages/
152 |
153 | # Others
154 | *.[Cc]ache
155 | ClientBin/
156 | [Ss]tyle[Cc]op.*
157 | ~$*
158 | *~
159 | *.dbmdl
160 | *.dbproj.schemaview
161 | *.pfx
162 | *.publishsettings
163 | node_modules/
164 | bower_components/
165 |
166 | # RIA/Silverlight projects
167 | Generated_Code/
168 |
169 | # Backup & report files from converting an old project file
170 | # to a newer Visual Studio version. Backup files are not needed,
171 | # because we have git ;-)
172 | _UpgradeReport_Files/
173 | Backup*/
174 | UpgradeLog*.XML
175 | UpgradeLog*.htm
176 |
177 | # SQL Server files
178 | *.mdf
179 | *.ldf
180 |
181 | # Business Intelligence projects
182 | *.rdl.data
183 | *.bim.layout
184 | *.bim_*.settings
185 |
186 | # Microsoft Fakes
187 | FakesAssemblies/
188 |
189 | # Node.js Tools for Visual Studio
190 | .ntvs_analysis.dat
191 |
192 | # Visual Studio 6 build log
193 | *.plg
194 |
195 | # Visual Studio 6 workspace options file
196 | *.opt
197 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 2.1, February 1999
3 |
4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | (This is the first released version of the Lesser GPL. It also counts
10 | as the successor of the GNU Library Public License, version 2, hence
11 | the version number 2.1.)
12 |
13 | Preamble
14 |
15 | The licenses for most software are designed to take away your
16 | freedom to share and change it. By contrast, the GNU General Public
17 | Licenses are intended to guarantee your freedom to share and change
18 | free software--to make sure the software is free for all its users.
19 |
20 | This license, the Lesser General Public License, applies to some
21 | specially designated software packages--typically libraries--of the
22 | Free Software Foundation and other authors who decide to use it. You
23 | can use it too, but we suggest you first think carefully about whether
24 | this license or the ordinary General Public License is the better
25 | strategy to use in any particular case, based on the explanations below.
26 |
27 | When we speak of free software, we are referring to freedom of use,
28 | not price. Our General Public Licenses are designed to make sure that
29 | you have the freedom to distribute copies of free software (and charge
30 | for this service if you wish); that you receive source code or can get
31 | it if you want it; that you can change the software and use pieces of
32 | it in new free programs; and that you are informed that you can do
33 | these things.
34 |
35 | To protect your rights, we need to make restrictions that forbid
36 | distributors to deny you these rights or to ask you to surrender these
37 | rights. These restrictions translate to certain responsibilities for
38 | you if you distribute copies of the library or if you modify it.
39 |
40 | For example, if you distribute copies of the library, whether gratis
41 | or for a fee, you must give the recipients all the rights that we gave
42 | you. You must make sure that they, too, receive or can get the source
43 | code. If you link other code with the library, you must provide
44 | complete object files to the recipients, so that they can relink them
45 | with the library after making changes to the library and recompiling
46 | it. And you must show them these terms so they know their rights.
47 |
48 | We protect your rights with a two-step method: (1) we copyright the
49 | library, and (2) we offer you this license, which gives you legal
50 | permission to copy, distribute and/or modify the library.
51 |
52 | To protect each distributor, we want to make it very clear that
53 | there is no warranty for the free library. Also, if the library is
54 | modified by someone else and passed on, the recipients should know
55 | that what they have is not the original version, so that the original
56 | author's reputation will not be affected by problems that might be
57 | introduced by others.
58 |
59 | Finally, software patents pose a constant threat to the existence of
60 | any free program. We wish to make sure that a company cannot
61 | effectively restrict the users of a free program by obtaining a
62 | restrictive license from a patent holder. Therefore, we insist that
63 | any patent license obtained for a version of the library must be
64 | consistent with the full freedom of use specified in this license.
65 |
66 | Most GNU software, including some libraries, is covered by the
67 | ordinary GNU General Public License. This license, the GNU Lesser
68 | General Public License, applies to certain designated libraries, and
69 | is quite different from the ordinary General Public License. We use
70 | this license for certain libraries in order to permit linking those
71 | libraries into non-free programs.
72 |
73 | When a program is linked with a library, whether statically or using
74 | a shared library, the combination of the two is legally speaking a
75 | combined work, a derivative of the original library. The ordinary
76 | General Public License therefore permits such linking only if the
77 | entire combination fits its criteria of freedom. The Lesser General
78 | Public License permits more lax criteria for linking other code with
79 | the library.
80 |
81 | We call this license the "Lesser" General Public License because it
82 | does Less to protect the user's freedom than the ordinary General
83 | Public License. It also provides other free software developers Less
84 | of an advantage over competing non-free programs. These disadvantages
85 | are the reason we use the ordinary General Public License for many
86 | libraries. However, the Lesser license provides advantages in certain
87 | special circumstances.
88 |
89 | For example, on rare occasions, there may be a special need to
90 | encourage the widest possible use of a certain library, so that it becomes
91 | a de-facto standard. To achieve this, non-free programs must be
92 | allowed to use the library. A more frequent case is that a free
93 | library does the same job as widely used non-free libraries. In this
94 | case, there is little to gain by limiting the free library to free
95 | software only, so we use the Lesser General Public License.
96 |
97 | In other cases, permission to use a particular library in non-free
98 | programs enables a greater number of people to use a large body of
99 | free software. For example, permission to use the GNU C Library in
100 | non-free programs enables many more people to use the whole GNU
101 | operating system, as well as its variant, the GNU/Linux operating
102 | system.
103 |
104 | Although the Lesser General Public License is Less protective of the
105 | users' freedom, it does ensure that the user of a program that is
106 | linked with the Library has the freedom and the wherewithal to run
107 | that program using a modified version of the Library.
108 |
109 | The precise terms and conditions for copying, distribution and
110 | modification follow. Pay close attention to the difference between a
111 | "work based on the library" and a "work that uses the library". The
112 | former contains code derived from the library, whereas the latter must
113 | be combined with the library in order to run.
114 |
115 | GNU LESSER GENERAL PUBLIC LICENSE
116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117 |
118 | 0. This License Agreement applies to any software library or other
119 | program which contains a notice placed by the copyright holder or
120 | other authorized party saying it may be distributed under the terms of
121 | this Lesser General Public License (also called "this License").
122 | Each licensee is addressed as "you".
123 |
124 | A "library" means a collection of software functions and/or data
125 | prepared so as to be conveniently linked with application programs
126 | (which use some of those functions and data) to form executables.
127 |
128 | The "Library", below, refers to any such software library or work
129 | which has been distributed under these terms. A "work based on the
130 | Library" means either the Library or any derivative work under
131 | copyright law: that is to say, a work containing the Library or a
132 | portion of it, either verbatim or with modifications and/or translated
133 | straightforwardly into another language. (Hereinafter, translation is
134 | included without limitation in the term "modification".)
135 |
136 | "Source code" for a work means the preferred form of the work for
137 | making modifications to it. For a library, complete source code means
138 | all the source code for all modules it contains, plus any associated
139 | interface definition files, plus the scripts used to control compilation
140 | and installation of the library.
141 |
142 | Activities other than copying, distribution and modification are not
143 | covered by this License; they are outside its scope. The act of
144 | running a program using the Library is not restricted, and output from
145 | such a program is covered only if its contents constitute a work based
146 | on the Library (independent of the use of the Library in a tool for
147 | writing it). Whether that is true depends on what the Library does
148 | and what the program that uses the Library does.
149 |
150 | 1. You may copy and distribute verbatim copies of the Library's
151 | complete source code as you receive it, in any medium, provided that
152 | you conspicuously and appropriately publish on each copy an
153 | appropriate copyright notice and disclaimer of warranty; keep intact
154 | all the notices that refer to this License and to the absence of any
155 | warranty; and distribute a copy of this License along with the
156 | Library.
157 |
158 | You may charge a fee for the physical act of transferring a copy,
159 | and you may at your option offer warranty protection in exchange for a
160 | fee.
161 |
162 | 2. You may modify your copy or copies of the Library or any portion
163 | of it, thus forming a work based on the Library, and copy and
164 | distribute such modifications or work under the terms of Section 1
165 | above, provided that you also meet all of these conditions:
166 |
167 | a) The modified work must itself be a software library.
168 |
169 | b) You must cause the files modified to carry prominent notices
170 | stating that you changed the files and the date of any change.
171 |
172 | c) You must cause the whole of the work to be licensed at no
173 | charge to all third parties under the terms of this License.
174 |
175 | d) If a facility in the modified Library refers to a function or a
176 | table of data to be supplied by an application program that uses
177 | the facility, other than as an argument passed when the facility
178 | is invoked, then you must make a good faith effort to ensure that,
179 | in the event an application does not supply such function or
180 | table, the facility still operates, and performs whatever part of
181 | its purpose remains meaningful.
182 |
183 | (For example, a function in a library to compute square roots has
184 | a purpose that is entirely well-defined independent of the
185 | application. Therefore, Subsection 2d requires that any
186 | application-supplied function or table used by this function must
187 | be optional: if the application does not supply it, the square
188 | root function must still compute square roots.)
189 |
190 | These requirements apply to the modified work as a whole. If
191 | identifiable sections of that work are not derived from the Library,
192 | and can be reasonably considered independent and separate works in
193 | themselves, then this License, and its terms, do not apply to those
194 | sections when you distribute them as separate works. But when you
195 | distribute the same sections as part of a whole which is a work based
196 | on the Library, the distribution of the whole must be on the terms of
197 | this License, whose permissions for other licensees extend to the
198 | entire whole, and thus to each and every part regardless of who wrote
199 | it.
200 |
201 | Thus, it is not the intent of this section to claim rights or contest
202 | your rights to work written entirely by you; rather, the intent is to
203 | exercise the right to control the distribution of derivative or
204 | collective works based on the Library.
205 |
206 | In addition, mere aggregation of another work not based on the Library
207 | with the Library (or with a work based on the Library) on a volume of
208 | a storage or distribution medium does not bring the other work under
209 | the scope of this License.
210 |
211 | 3. You may opt to apply the terms of the ordinary GNU General Public
212 | License instead of this License to a given copy of the Library. To do
213 | this, you must alter all the notices that refer to this License, so
214 | that they refer to the ordinary GNU General Public License, version 2,
215 | instead of to this License. (If a newer version than version 2 of the
216 | ordinary GNU General Public License has appeared, then you can specify
217 | that version instead if you wish.) Do not make any other change in
218 | these notices.
219 |
220 | Once this change is made in a given copy, it is irreversible for
221 | that copy, so the ordinary GNU General Public License applies to all
222 | subsequent copies and derivative works made from that copy.
223 |
224 | This option is useful when you wish to copy part of the code of
225 | the Library into a program that is not a library.
226 |
227 | 4. You may copy and distribute the Library (or a portion or
228 | derivative of it, under Section 2) in object code or executable form
229 | under the terms of Sections 1 and 2 above provided that you accompany
230 | it with the complete corresponding machine-readable source code, which
231 | must be distributed under the terms of Sections 1 and 2 above on a
232 | medium customarily used for software interchange.
233 |
234 | If distribution of object code is made by offering access to copy
235 | from a designated place, then offering equivalent access to copy the
236 | source code from the same place satisfies the requirement to
237 | distribute the source code, even though third parties are not
238 | compelled to copy the source along with the object code.
239 |
240 | 5. A program that contains no derivative of any portion of the
241 | Library, but is designed to work with the Library by being compiled or
242 | linked with it, is called a "work that uses the Library". Such a
243 | work, in isolation, is not a derivative work of the Library, and
244 | therefore falls outside the scope of this License.
245 |
246 | However, linking a "work that uses the Library" with the Library
247 | creates an executable that is a derivative of the Library (because it
248 | contains portions of the Library), rather than a "work that uses the
249 | library". The executable is therefore covered by this License.
250 | Section 6 states terms for distribution of such executables.
251 |
252 | When a "work that uses the Library" uses material from a header file
253 | that is part of the Library, the object code for the work may be a
254 | derivative work of the Library even though the source code is not.
255 | Whether this is true is especially significant if the work can be
256 | linked without the Library, or if the work is itself a library. The
257 | threshold for this to be true is not precisely defined by law.
258 |
259 | If such an object file uses only numerical parameters, data
260 | structure layouts and accessors, and small macros and small inline
261 | functions (ten lines or less in length), then the use of the object
262 | file is unrestricted, regardless of whether it is legally a derivative
263 | work. (Executables containing this object code plus portions of the
264 | Library will still fall under Section 6.)
265 |
266 | Otherwise, if the work is a derivative of the Library, you may
267 | distribute the object code for the work under the terms of Section 6.
268 | Any executables containing that work also fall under Section 6,
269 | whether or not they are linked directly with the Library itself.
270 |
271 | 6. As an exception to the Sections above, you may also combine or
272 | link a "work that uses the Library" with the Library to produce a
273 | work containing portions of the Library, and distribute that work
274 | under terms of your choice, provided that the terms permit
275 | modification of the work for the customer's own use and reverse
276 | engineering for debugging such modifications.
277 |
278 | You must give prominent notice with each copy of the work that the
279 | Library is used in it and that the Library and its use are covered by
280 | this License. You must supply a copy of this License. If the work
281 | during execution displays copyright notices, you must include the
282 | copyright notice for the Library among them, as well as a reference
283 | directing the user to the copy of this License. Also, you must do one
284 | of these things:
285 |
286 | a) Accompany the work with the complete corresponding
287 | machine-readable source code for the Library including whatever
288 | changes were used in the work (which must be distributed under
289 | Sections 1 and 2 above); and, if the work is an executable linked
290 | with the Library, with the complete machine-readable "work that
291 | uses the Library", as object code and/or source code, so that the
292 | user can modify the Library and then relink to produce a modified
293 | executable containing the modified Library. (It is understood
294 | that the user who changes the contents of definitions files in the
295 | Library will not necessarily be able to recompile the application
296 | to use the modified definitions.)
297 |
298 | b) Use a suitable shared library mechanism for linking with the
299 | Library. A suitable mechanism is one that (1) uses at run time a
300 | copy of the library already present on the user's computer system,
301 | rather than copying library functions into the executable, and (2)
302 | will operate properly with a modified version of the library, if
303 | the user installs one, as long as the modified version is
304 | interface-compatible with the version that the work was made with.
305 |
306 | c) Accompany the work with a written offer, valid for at
307 | least three years, to give the same user the materials
308 | specified in Subsection 6a, above, for a charge no more
309 | than the cost of performing this distribution.
310 |
311 | d) If distribution of the work is made by offering access to copy
312 | from a designated place, offer equivalent access to copy the above
313 | specified materials from the same place.
314 |
315 | e) Verify that the user has already received a copy of these
316 | materials or that you have already sent this user a copy.
317 |
318 | For an executable, the required form of the "work that uses the
319 | Library" must include any data and utility programs needed for
320 | reproducing the executable from it. However, as a special exception,
321 | the materials to be distributed need not include anything that is
322 | normally distributed (in either source or binary form) with the major
323 | components (compiler, kernel, and so on) of the operating system on
324 | which the executable runs, unless that component itself accompanies
325 | the executable.
326 |
327 | It may happen that this requirement contradicts the license
328 | restrictions of other proprietary libraries that do not normally
329 | accompany the operating system. Such a contradiction means you cannot
330 | use both them and the Library together in an executable that you
331 | distribute.
332 |
333 | 7. You may place library facilities that are a work based on the
334 | Library side-by-side in a single library together with other library
335 | facilities not covered by this License, and distribute such a combined
336 | library, provided that the separate distribution of the work based on
337 | the Library and of the other library facilities is otherwise
338 | permitted, and provided that you do these two things:
339 |
340 | a) Accompany the combined library with a copy of the same work
341 | based on the Library, uncombined with any other library
342 | facilities. This must be distributed under the terms of the
343 | Sections above.
344 |
345 | b) Give prominent notice with the combined library of the fact
346 | that part of it is a work based on the Library, and explaining
347 | where to find the accompanying uncombined form of the same work.
348 |
349 | 8. You may not copy, modify, sublicense, link with, or distribute
350 | the Library except as expressly provided under this License. Any
351 | attempt otherwise to copy, modify, sublicense, link with, or
352 | distribute the Library is void, and will automatically terminate your
353 | rights under this License. However, parties who have received copies,
354 | or rights, from you under this License will not have their licenses
355 | terminated so long as such parties remain in full compliance.
356 |
357 | 9. You are not required to accept this License, since you have not
358 | signed it. However, nothing else grants you permission to modify or
359 | distribute the Library or its derivative works. These actions are
360 | prohibited by law if you do not accept this License. Therefore, by
361 | modifying or distributing the Library (or any work based on the
362 | Library), you indicate your acceptance of this License to do so, and
363 | all its terms and conditions for copying, distributing or modifying
364 | the Library or works based on it.
365 |
366 | 10. Each time you redistribute the Library (or any work based on the
367 | Library), the recipient automatically receives a license from the
368 | original licensor to copy, distribute, link with or modify the Library
369 | subject to these terms and conditions. You may not impose any further
370 | restrictions on the recipients' exercise of the rights granted herein.
371 | You are not responsible for enforcing compliance by third parties with
372 | this License.
373 |
374 | 11. If, as a consequence of a court judgment or allegation of patent
375 | infringement or for any other reason (not limited to patent issues),
376 | conditions are imposed on you (whether by court order, agreement or
377 | otherwise) that contradict the conditions of this License, they do not
378 | excuse you from the conditions of this License. If you cannot
379 | distribute so as to satisfy simultaneously your obligations under this
380 | License and any other pertinent obligations, then as a consequence you
381 | may not distribute the Library at all. For example, if a patent
382 | license would not permit royalty-free redistribution of the Library by
383 | all those who receive copies directly or indirectly through you, then
384 | the only way you could satisfy both it and this License would be to
385 | refrain entirely from distribution of the Library.
386 |
387 | If any portion of this section is held invalid or unenforceable under any
388 | particular circumstance, the balance of the section is intended to apply,
389 | and the section as a whole is intended to apply in other circumstances.
390 |
391 | It is not the purpose of this section to induce you to infringe any
392 | patents or other property right claims or to contest validity of any
393 | such claims; this section has the sole purpose of protecting the
394 | integrity of the free software distribution system which is
395 | implemented by public license practices. Many people have made
396 | generous contributions to the wide range of software distributed
397 | through that system in reliance on consistent application of that
398 | system; it is up to the author/donor to decide if he or she is willing
399 | to distribute software through any other system and a licensee cannot
400 | impose that choice.
401 |
402 | This section is intended to make thoroughly clear what is believed to
403 | be a consequence of the rest of this License.
404 |
405 | 12. If the distribution and/or use of the Library is restricted in
406 | certain countries either by patents or by copyrighted interfaces, the
407 | original copyright holder who places the Library under this License may add
408 | an explicit geographical distribution limitation excluding those countries,
409 | so that distribution is permitted only in or among countries not thus
410 | excluded. In such case, this License incorporates the limitation as if
411 | written in the body of this License.
412 |
413 | 13. The Free Software Foundation may publish revised and/or new
414 | versions of the Lesser General Public License from time to time.
415 | Such new versions will be similar in spirit to the present version,
416 | but may differ in detail to address new problems or concerns.
417 |
418 | Each version is given a distinguishing version number. If the Library
419 | specifies a version number of this License which applies to it and
420 | "any later version", you have the option of following the terms and
421 | conditions either of that version or of any later version published by
422 | the Free Software Foundation. If the Library does not specify a
423 | license version number, you may choose any version ever published by
424 | the Free Software Foundation.
425 |
426 | 14. If you wish to incorporate parts of the Library into other free
427 | programs whose distribution conditions are incompatible with these,
428 | write to the author to ask for permission. For software which is
429 | copyrighted by the Free Software Foundation, write to the Free
430 | Software Foundation; we sometimes make exceptions for this. Our
431 | decision will be guided by the two goals of preserving the free status
432 | of all derivatives of our free software and of promoting the sharing
433 | and reuse of software generally.
434 |
435 | NO WARRANTY
436 |
437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446 |
447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456 | DAMAGES.
457 |
458 | END OF TERMS AND CONDITIONS
459 |
460 | How to Apply These Terms to Your New Libraries
461 |
462 | If you develop a new library, and you want it to be of the greatest
463 | possible use to the public, we recommend making it free software that
464 | everyone can redistribute and change. You can do so by permitting
465 | redistribution under these terms (or, alternatively, under the terms of the
466 | ordinary General Public License).
467 |
468 | To apply these terms, attach the following notices to the library. It is
469 | safest to attach them to the start of each source file to most effectively
470 | convey the exclusion of warranty; and each file should have at least the
471 | "copyright" line and a pointer to where the full notice is found.
472 |
473 | {description}
474 | Copyright (C) {year} {fullname}
475 |
476 | This library is free software; you can redistribute it and/or
477 | modify it under the terms of the GNU Lesser General Public
478 | License as published by the Free Software Foundation; either
479 | version 2.1 of the License, or (at your option) any later version.
480 |
481 | This library is distributed in the hope that it will be useful,
482 | but WITHOUT ANY WARRANTY; without even the implied warranty of
483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
484 | Lesser General Public License for more details.
485 |
486 | You should have received a copy of the GNU Lesser General Public
487 | License along with this library; if not, write to the Free Software
488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
489 | USA
490 |
491 | Also add information on how to contact you by electronic and paper mail.
492 |
493 | You should also get your employer (if you work as a programmer) or your
494 | school, if any, to sign a "copyright disclaimer" for the library, if
495 | necessary. Here is a sample; alter the names:
496 |
497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the
498 | library `Frob' (a library for tweaking knobs) written by James Random
499 | Hacker.
500 |
501 | {signature of Ty Coon}, 1 April 1990
502 | Ty Coon, President of Vice
503 |
504 | That's all there is to it!
505 |
506 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/igrigorik/ga-beacon)
2 | [](https://travis-ci.org/unosquare/libfprint-cs)
3 | [](https://ci.appveyor.com/project/geoperez/libfprint-cs/branch/master)
4 |
5 | # libfprint-cs
6 |
7 | **WE ARE LOOKING FOR A NEW HOME FOR THIS PROJECT. APPLY AT:** https://adoptoposs.org/p/c905cc68-9a61-4b69-bf52-b27bda1fd6b3
8 |
9 | The long-awaited C# (.net/mono) wrapper for the great fingerprint reader interfacing library libfprint
10 | *Note: A few people have reported a System.DllNotFoundException being thrown at runtime. This is a Linux project. There is no libfprint.dll for Windows*
11 |
12 | From the libfprint website:
13 |
14 | libfprint is an open source software library designed to make it easy for application developers to add support for consumer fingerprint readers to their software.
15 |
16 |
17 | This wrapper makes interfacing with your fingerprint reader extremely easy.
18 |
19 | ## Simple guidelines
20 |
21 | - Use the FingerprintDeviceManager to discover connected fingerprint devices
22 | - Use the FingerprintDevice objects provided by the device manager to Enroll, Verify and Identify fingerprints
23 | - Use the FingerprintGallery to keep a database of fingerprints to match against. You can load the contents of the gallery from files, a database or pretty much any byte array prodiced by the Enroll functionality.
24 | - Finally, (and optionally) use the PgmFormatReader to turn PGM image files to Bitmaps
25 | - Have fun!
26 |
27 |
28 | ## Super quick code example
29 |
30 | ```cs
31 | using (var manager = FingerprintDeviceManager.Instance)
32 | {
33 | manager.Initialize();
34 | using (var gallery = new FingerprintGallery())
35 | {
36 | var device = manager.DiscoverDevices().FirstOrDefault();
37 | device.Open();
38 | var enrollResult = device.EnrollFingerprint("enroll.pgm");
39 | if (enrollResult.IsEnrollComplete)
40 | {
41 | var isVerified = device.VerifyFingerprint(enrollResult, "verify.pgm");
42 | if (isVerified)
43 | {
44 | gallery.Add("username_gose_here", enrollResult);
45 | }
46 | }
47 |
48 | var identified = device.IdentifyFingerprint(gallery, "identify.pgm");
49 | }
50 | }
51 | ```
52 |
53 | ## Getting it to run on the Raspberry Pi (Raspbian)
54 |
55 | Raspbian has a fairly outdated libfprint-dev package (0.4.0). The following script will remove the installed libfprint-dev, install dependencies, pull code from 0.5.1, build it, and install the library.
56 |
57 | ```shell
58 | sudo apt-get remove -y libfprint-dev
59 | sudo apt-get autoremove -y
60 | sudo apt-get install -y libusb-1.0-0-dev
61 | sudo apt-get install -y libnss3-dev
62 | sudo apt-get install -y libgtk2.0-dev
63 |
64 | wget http://people.freedesktop.org/~hadess/libfprint-0.5.1.tar.xz
65 | tar xf libfprint-0.5.1.tar.xz
66 | rm libfprint-0.5.1.tar.xz
67 | cd libfprint-0.5.1
68 | ./configure
69 | make
70 | sudo make install
71 | sudo make clean
72 | cd ..
73 | sudo cp /usr/local/lib/libfprint.so libfprint.so
74 | sudo find / -iname "libfprint.so"
75 | ```
76 |
77 | You will also obviously want to install mono for any of the above to work . . .
78 | ```shell
79 | sudo apt-get install mono-complete
80 | ```
81 |
82 | ## Futures
83 |
84 | The identification logic seems to be fairly slow when we start adding many fingerprints. Maybe using this library for imaging and then using something like SourceAFIS for identification would work better...
85 |
86 | ## Thanks
87 |
88 | Thanks to the libfprint developers!
89 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint.Tests/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace Unosquare.Labs.LibFprint.Tests
5 | {
6 | public class MainClass
7 | {
8 | public static void Main(string[] args)
9 | {
10 | // The device manager discovers devices. It's a singleton and is used to detect connected devices
11 | // it also create references to the fingerprint scanners
12 | using var manager = FingerprintDeviceManager.Instance;
13 | // We always need to call this method to make sure the library is initialized
14 | manager.Initialize();
15 | Console.WriteLine("Initialized Device Manager.");
16 |
17 | // Now we call the device discovery method
18 | var devices = manager.DiscoverDevices();
19 |
20 | // Let's do stuff with each of the discovered devices (typically only 1)
21 | foreach (var device in devices)
22 | {
23 | var thread = new Thread(() =>
24 | {
25 |
26 | // Before we do anything, we need to open the device.
27 | device.Open();
28 |
29 | // Now we print some info about the device.
30 | Console.ForegroundColor = ConsoleColor.Cyan;
31 | Console.WriteLine();
32 | Console.WriteLine("Device {0} - {1}", device.DriverName, device.DriverFullName);
33 | Console.WriteLine(" Enroll Stages: {0}", device.EnrollStagesCount);
34 | Console.WriteLine(" Supports Imaging: {0}", device.SupportsImaging);
35 | Console.WriteLine(" Supports Ident: {0}", device.SupportsIdentification);
36 | Console.WriteLine(" Imaging Dimensions: {0}x{1}", device.ImageWidth, device.ImageHeight);
37 |
38 | // We will enroll a few fingerprints into the gallery.
39 | using var gallery = new FingerprintGallery();
40 | var enrollCount = 0;
41 | while (enrollCount < 5)
42 | {
43 | Console.ForegroundColor = ConsoleColor.Green;
44 | Console.WriteLine(" >> ENROLL: Enroll count: {0}. Enroll a new finger now . . .", enrollCount);
45 |
46 | // Call the enrollment method
47 | var enrollResult = device.EnrollFingerprint("enroll.pgm");
48 | if (enrollResult.IsEnrollComplete)
49 | {
50 |
51 | Console.ForegroundColor = ConsoleColor.Green;
52 | Console.WriteLine(" >> VERIFY: Now, verify your scan just to make sure . . .");
53 |
54 | // Although not necessary, we are adding verification just to make sure
55 | var isVerified = device.VerifyFingerprint(enrollResult, "verify.pgm");
56 | if (isVerified)
57 | {
58 | enrollCount++;
59 | var printName = "The print " + enrollCount;
60 | gallery.Add(printName, enrollResult);
61 | }
62 | else
63 | {
64 | Console.ForegroundColor = ConsoleColor.Red;
65 | Console.WriteLine("Could not verify. Try again!");
66 | Console.WriteLine();
67 | }
68 | }
69 | else
70 | {
71 | Console.ForegroundColor = ConsoleColor.Red;
72 | Console.WriteLine("Try Again -- Error Code {0} - {1}", enrollResult.ResultCode, enrollResult.Result);
73 | Console.WriteLine();
74 | // HACK: for some reason we needed the Reset method to be called. Otherwise the reader would blink rapidly and get stuck
75 | device.Reset();
76 | }
77 | }
78 |
79 | Console.ForegroundColor = ConsoleColor.Gray;
80 | Console.WriteLine();
81 |
82 | // Now, let's try some identification in the gallery we created earlier
83 | // with enrollment and verification operations
84 | while (true)
85 | {
86 | Console.ForegroundColor = ConsoleColor.Green;
87 | Console.WriteLine(" >> IDENTIFY: Press finger against scanner to identify . . .");
88 |
89 | // Let's try to identify a fingerprint and getting it's key back.
90 | // a null key means the FP was not identified.
91 | var identified = device.IdentifyFingerprint(gallery, "identify.pgm");
92 | if (identified == null)
93 | {
94 | Console.ForegroundColor = ConsoleColor.Red;
95 | Console.WriteLine("Could not identify.");
96 | Console.WriteLine();
97 | }
98 | else
99 | {
100 | Console.ForegroundColor = ConsoleColor.Blue;
101 | Console.WriteLine("Fingerprint was identified: {0}.", identified);
102 | Console.WriteLine();
103 | }
104 | }
105 | })
106 | { IsBackground = true };
107 |
108 |
109 | Console.ForegroundColor = ConsoleColor.DarkYellow;
110 | Console.WriteLine("Press A to abort the thread . . .");
111 |
112 | thread.Start();
113 |
114 | while (true)
115 | {
116 | if (Console.ReadKey(true).Key == ConsoleKey.A)
117 | {
118 | thread.Abort();
119 | var terminationTimeout = DateTime.Now.AddSeconds(10);
120 | while (thread.IsAlive)
121 | {
122 | Console.ForegroundColor = ConsoleColor.DarkYellow;
123 | Console.WriteLine("Waiting for thread termination. {0.00} seconds to terminate forcefully.", terminationTimeout.Subtract(DateTime.Now).TotalSeconds);
124 | thread.Abort();
125 |
126 | if (DateTime.Now > terminationTimeout)
127 | {
128 | Console.ForegroundColor = ConsoleColor.Red;
129 | Console.WriteLine("Termination timeout reached. Forcefully disposing the device.");
130 | }
131 |
132 | Thread.Sleep(1000);
133 | }
134 |
135 | break;
136 | }
137 |
138 | Console.ForegroundColor = ConsoleColor.Red;
139 | Console.WriteLine("Press A to abort the thread . . .");
140 | }
141 |
142 | // We release unmanaged resources for the device.
143 | device.Dispose();
144 | }
145 | }
146 | }
147 | }
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint.Tests/Unosquare.Labs.LibFprint.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp3.0
4 | Copyright (c) 2019 - Unosquare
5 | Unosquare
6 | Unosquare.Labs.LibFprint.Test
7 | 8.0
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.Labs.LibFprint", "Unosquare.Labs.LibFprint\Unosquare.Labs.LibFprint.csproj", "{88E552BF-2F88-4C04-A24C-45518EE574C5}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.Labs.LibFprint.Tests", "Unosquare.Labs.LibFprint.Tests\Unosquare.Labs.LibFprint.Tests.csproj", "{C1863959-C3E2-4593-B05B-074842C2AE10}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|Mixed Platforms = Debug|Mixed Platforms
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|Mixed Platforms = Release|Mixed Platforms
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
21 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
22 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Debug|x86.ActiveCfg = Debug|Any CPU
23 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
26 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
27 | {88E552BF-2F88-4C04-A24C-45518EE574C5}.Release|x86.ActiveCfg = Release|Any CPU
28 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
31 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
32 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Debug|x86.ActiveCfg = Debug|Any CPU
33 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Debug|x86.Build.0 = Debug|Any CPU
34 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
37 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Release|Mixed Platforms.Build.0 = Release|Any CPU
38 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Release|x86.ActiveCfg = Release|Any CPU
39 | {C1863959-C3E2-4593-B05B-074842C2AE10}.Release|x86.Build.0 = Release|Any CPU
40 | EndGlobalSection
41 | GlobalSection(MonoDevelopProperties) = preSolution
42 | StartupItem = Unosquare.Labs.LibFprint.Tests\Unosquare.Labs.LibFprint.Tests.csproj
43 | Policies = $0
44 | $0.DotNetNamingPolicy = $1
45 | $1.DirectoryNamespaceAssociation = None
46 | $1.ResourceNamePolicy = FileFormatDefault
47 | $0.StandardHeader = $2
48 | $2.Text =
49 | $2.IncludeInNewFiles = True
50 | $0.NameConventionPolicy = $3
51 | $3.Rules = $4
52 | $4.NamingRule = $5
53 | $5.Name = Namespaces
54 | $5.AffectedEntity = Namespace
55 | $5.VisibilityMask = VisibilityMask
56 | $5.NamingStyle = PascalCase
57 | $5.IncludeInstanceMembers = True
58 | $5.IncludeStaticEntities = True
59 | $4.NamingRule = $6
60 | $6.Name = Types
61 | $6.AffectedEntity = Class, Struct, Enum, Delegate
62 | $6.VisibilityMask = Public
63 | $6.NamingStyle = PascalCase
64 | $6.IncludeInstanceMembers = True
65 | $6.IncludeStaticEntities = True
66 | $4.NamingRule = $7
67 | $7.Name = Interfaces
68 | $7.RequiredPrefixes = $8
69 | $8.String = I
70 | $7.AffectedEntity = Interface
71 | $7.VisibilityMask = Public
72 | $7.NamingStyle = PascalCase
73 | $7.IncludeInstanceMembers = True
74 | $7.IncludeStaticEntities = True
75 | $4.NamingRule = $9
76 | $9.Name = Attributes
77 | $9.RequiredSuffixes = $10
78 | $10.String = Attribute
79 | $9.AffectedEntity = CustomAttributes
80 | $9.VisibilityMask = Public
81 | $9.NamingStyle = PascalCase
82 | $9.IncludeInstanceMembers = True
83 | $9.IncludeStaticEntities = True
84 | $4.NamingRule = $11
85 | $11.Name = Event Arguments
86 | $11.RequiredSuffixes = $12
87 | $12.String = EventArgs
88 | $11.AffectedEntity = CustomEventArgs
89 | $11.VisibilityMask = Public
90 | $11.NamingStyle = PascalCase
91 | $11.IncludeInstanceMembers = True
92 | $11.IncludeStaticEntities = True
93 | $4.NamingRule = $13
94 | $13.Name = Exceptions
95 | $13.RequiredSuffixes = $14
96 | $14.String = Exception
97 | $13.AffectedEntity = CustomExceptions
98 | $13.VisibilityMask = VisibilityMask
99 | $13.NamingStyle = PascalCase
100 | $13.IncludeInstanceMembers = True
101 | $13.IncludeStaticEntities = True
102 | $4.NamingRule = $15
103 | $15.Name = Methods
104 | $15.AffectedEntity = Methods
105 | $15.VisibilityMask = Protected, Public
106 | $15.NamingStyle = PascalCase
107 | $15.IncludeInstanceMembers = True
108 | $15.IncludeStaticEntities = True
109 | $4.NamingRule = $16
110 | $16.Name = Static Readonly Fields
111 | $16.AffectedEntity = ReadonlyField
112 | $16.VisibilityMask = Protected, Public
113 | $16.NamingStyle = PascalCase
114 | $16.IncludeInstanceMembers = False
115 | $16.IncludeStaticEntities = True
116 | $4.NamingRule = $17
117 | $17.Name = Fields
118 | $17.AffectedEntity = Field
119 | $17.VisibilityMask = Protected, Public
120 | $17.NamingStyle = PascalCase
121 | $17.IncludeInstanceMembers = True
122 | $17.IncludeStaticEntities = True
123 | $4.NamingRule = $18
124 | $18.Name = ReadOnly Fields
125 | $18.AffectedEntity = ReadonlyField
126 | $18.VisibilityMask = Protected, Public
127 | $18.NamingStyle = PascalCase
128 | $18.IncludeInstanceMembers = True
129 | $18.IncludeStaticEntities = False
130 | $4.NamingRule = $19
131 | $19.Name = Constant Fields
132 | $19.AffectedEntity = ConstantField
133 | $19.VisibilityMask = Protected, Public
134 | $19.NamingStyle = PascalCase
135 | $19.IncludeInstanceMembers = True
136 | $19.IncludeStaticEntities = True
137 | $4.NamingRule = $20
138 | $20.Name = Properties
139 | $20.AffectedEntity = Property
140 | $20.VisibilityMask = Protected, Public
141 | $20.NamingStyle = PascalCase
142 | $20.IncludeInstanceMembers = True
143 | $20.IncludeStaticEntities = True
144 | $4.NamingRule = $21
145 | $21.Name = Events
146 | $21.AffectedEntity = Event
147 | $21.VisibilityMask = Protected, Public
148 | $21.NamingStyle = PascalCase
149 | $21.IncludeInstanceMembers = True
150 | $21.IncludeStaticEntities = True
151 | $4.NamingRule = $22
152 | $22.Name = Enum Members
153 | $22.AffectedEntity = EnumMember
154 | $22.VisibilityMask = VisibilityMask
155 | $22.NamingStyle = PascalCase
156 | $22.IncludeInstanceMembers = True
157 | $22.IncludeStaticEntities = True
158 | $4.NamingRule = $23
159 | $23.Name = Parameters
160 | $23.AffectedEntity = Parameter
161 | $23.VisibilityMask = VisibilityMask
162 | $23.NamingStyle = CamelCase
163 | $23.IncludeInstanceMembers = True
164 | $23.IncludeStaticEntities = True
165 | $4.NamingRule = $24
166 | $24.Name = Type Parameters
167 | $24.RequiredPrefixes = $25
168 | $25.String = T
169 | $24.AffectedEntity = TypeParameter
170 | $24.VisibilityMask = VisibilityMask
171 | $24.NamingStyle = PascalCase
172 | $24.IncludeInstanceMembers = True
173 | $24.IncludeStaticEntities = True
174 | $0.TextStylePolicy = $26
175 | $26.FileWidth = 120
176 | $26.EolMarker = Windows
177 | $26.inheritsSet = VisualStudio
178 | $26.inheritsScope = text/plain
179 | $26.scope = text/plain
180 | $0.TextStylePolicy = $27
181 | $27.inheritsSet = null
182 | $27.scope = text/x-chdr
183 | EndGlobalSection
184 | GlobalSection(SolutionProperties) = preSolution
185 | HideSolutionNode = FALSE
186 | EndGlobalSection
187 | EndGlobal
188 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/EnrollResult.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | ///
4 | /// An enumeration that represents enrollment results.
5 | ///
6 | public enum EnrollResult
7 | {
8 | ///
9 | /// The unspecified
10 | ///
11 | Unspecified = 0,
12 |
13 | ///
14 | /// The enroll complete
15 | ///
16 | EnrollComplete = 1,
17 |
18 | ///
19 | /// The enroll failed
20 | ///
21 | EnrollFailed = 2,
22 |
23 | ///
24 | /// The enroll stage passed
25 | ///
26 | EnrollStagePassed = 3,
27 |
28 | ///
29 | /// The retry
30 | ///
31 | Retry = 100,
32 |
33 | ///
34 | /// The retry scan too short
35 | ///
36 | RetryScanTooShort = 101,
37 |
38 | ///
39 | /// The retry finger not centered
40 | ///
41 | RetryFingerNotCentered = 102,
42 |
43 | ///
44 | /// The retry remove finger
45 | ///
46 | RetryRemoveFinger = 103,
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/EnrollStageResult.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | ///
4 | /// Represents the state of a Fingerprint Enrollment operation.
5 | ///
6 | public class EnrollStageResult
7 | {
8 | ///
9 | /// Initializes a new instance of the class.
10 | ///
11 | /// The enroll code.
12 | /// The fingerprint data.
13 | public EnrollStageResult(int enrollCode, byte[] fingerprintData)
14 | {
15 | ResultCode = enrollCode;
16 |
17 | Result = ResultCode < 0 ? EnrollResult.Unspecified : (EnrollResult)enrollCode;
18 |
19 | FingerprintData = fingerprintData;
20 | }
21 |
22 | ///
23 | /// Gets or sets the raw result code.
24 | ///
25 | ///
26 | /// The result code.
27 | ///
28 | public int ResultCode { get; protected set; }
29 |
30 | ///
31 | /// Gets or sets the friendly result code.
32 | ///
33 | ///
34 | /// The result.
35 | ///
36 | public EnrollResult Result { get; protected set; }
37 |
38 | ///
39 | /// Gets the buffer data holding the fingerprint scan.
40 | /// This is what needs to be saved in a database that will later be loased on to a
41 | /// FingerprintGallery object.
42 | ///
43 | ///
44 | /// The fingerprint data.
45 | ///
46 | public byte[] FingerprintData { get; protected set; }
47 |
48 | ///
49 | /// Gets a value indicating whether the enrollment requires retry.
50 | ///
51 | ///
52 | /// true if [requires retry]; otherwise, false.
53 | ///
54 | public bool RequiresRetry
55 | {
56 | get
57 | {
58 | if (IsFatalError) return false;
59 |
60 | return
61 | Result == EnrollResult.Retry ||
62 | Result == EnrollResult.RetryFingerNotCentered ||
63 | Result == EnrollResult.RetryRemoveFinger ||
64 | Result == EnrollResult.RetryScanTooShort;
65 | }
66 | }
67 |
68 | ///
69 | /// Gets a value indicating whether the result contains a fatal error.
70 | ///
71 | ///
72 | /// true if this instance is fatal error; otherwise, false.
73 | ///
74 | public bool IsFatalError => ResultCode < 0;
75 |
76 | ///
77 | /// Gets a value indicating whether the result was a successful scan.
78 | ///
79 | ///
80 | /// true if this instance is success; otherwise, false.
81 | ///
82 | public bool IsSuccess => IsFatalError == false && (Result == EnrollResult.EnrollComplete || Result == EnrollResult.EnrollStagePassed);
83 |
84 | ///
85 | /// Gets a value indicating whether this instance represents an enrollment failure.
86 | ///
87 | ///
88 | /// true if this instance is enroll failure; otherwise, false.
89 | ///
90 | public bool IsEnrollFailure => IsFatalError == false && Result == EnrollResult.EnrollFailed;
91 |
92 | ///
93 | /// Gets a value indicating whether this instance represents an enrollment completion.
94 | ///
95 | ///
96 | /// true if this instance is enroll complete; otherwise, false.
97 | ///
98 | public bool IsEnrollComplete => IsFatalError == false && Result == EnrollResult.EnrollComplete;
99 |
100 | ///
101 | /// Gets a value indicating whether a new call to the Enroll Fingerprint method is required to advance or to retry.
102 | ///
103 | ///
104 | /// true if [requires new call]; otherwise, false.
105 | ///
106 | public bool RequiresNewCall => RequiresRetry || Result == EnrollResult.EnrollStagePassed;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/Extensions.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | using System;
4 |
5 | ///
6 | /// Helper methods for pointer management.
7 | ///
8 | internal static class Extensions
9 | {
10 | ///
11 | /// Dereferences the PTR into the given type.
12 | ///
13 | ///
14 | /// The PTR.
15 | ///
16 | public static T DereferencePtr(this IntPtr ptr) => (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(T));
17 |
18 | ///
19 | /// Turns the given base address to an array of pointers.
20 | ///
21 | /// The base address.
22 | ///
23 | public static IntPtr[] ToPointerArray(this IntPtr baseAddress)
24 | {
25 | var ptrList = new System.Collections.Generic.List();
26 |
27 | if (baseAddress == IntPtr.Zero) return ptrList.ToArray();
28 |
29 | while (true)
30 | {
31 | var itemPtr = baseAddress.DereferencePtr();
32 | if (itemPtr == IntPtr.Zero)
33 | break;
34 |
35 | ptrList.Add(itemPtr);
36 | baseAddress = IntPtr.Add(baseAddress, IntPtr.Size);
37 | }
38 |
39 | return ptrList.ToArray();
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/FingerprintDevice.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | using System;
4 | using System.Runtime.InteropServices;
5 |
6 | ///
7 | /// Provides properties and methods to control and access fingerprint device finctionality.
8 | /// Use the FingerPrintDeviceManager class to discover and open instances of this class.
9 | /// Please note this class makes use of unmanaged resources. Dispose accordingly.
10 | ///
11 | public class FingerprintDevice : IDisposable
12 | {
13 | #region Properties
14 |
15 | internal Interop.fp_dscv_dev? DiscoveredDevice { get; set; }
16 | internal IntPtr DiscoveredDevicePtr { get; set; }
17 | internal Interop.fp_driver? Driver { get; set; }
18 | internal IntPtr RealDevicePtr { get; set; }
19 | internal Interop.fp_dev? RealDevice { get; set; }
20 |
21 | ///
22 | /// Gets a value indicating whether this device is open and ready for operation.
23 | ///
24 | ///
25 | /// true if this instance is open; otherwise, false.
26 | ///
27 | public bool IsOpen => RealDevice.HasValue;
28 |
29 | ///
30 | /// Gets or sets a value indicating whether this device supports imaging.
31 | ///
32 | ///
33 | /// true if [supports imaging]; otherwise, false.
34 | ///
35 | public bool SupportsImaging { get; protected set; }
36 |
37 | ///
38 | /// Gets or sets a value indicating whether this device supports identification.
39 | ///
40 | ///
41 | /// true if [supports identification]; otherwise, false.
42 | ///
43 | public bool SupportsIdentification { get; protected set; }
44 |
45 | ///
46 | /// Gets or sets the height of the image.
47 | ///
48 | ///
49 | /// The height of the image.
50 | ///
51 | public int ImageHeight { get; protected set; }
52 |
53 | ///
54 | /// Gets or sets the width of the image.
55 | ///
56 | ///
57 | /// The width of the image.
58 | ///
59 | public int ImageWidth { get; protected set; }
60 |
61 | ///
62 | /// Gets or sets a value indicating whether this device supports variable imaging dimensions.
63 | ///
64 | ///
65 | /// true if [supports variable imaging dimensions]; otherwise, false.
66 | ///
67 | public bool SupportsVariableImagingDimensions { get; protected set; }
68 |
69 | ///
70 | /// Gets the enroll stages count for this device.
71 | ///
72 | ///
73 | /// The enroll stages count.
74 | ///
75 | public int EnrollStagesCount { get; protected set; }
76 |
77 | ///
78 | /// Gets the name of the driver.
79 | ///
80 | ///
81 | /// The name of the driver.
82 | ///
83 | public string DriverName => Driver?.name;
84 |
85 | ///
86 | /// Gets the full name of the driver.
87 | ///
88 | ///
89 | /// The full name of the driver.
90 | ///
91 | public string DriverFullName => Driver?.full_name;
92 |
93 | #endregion
94 |
95 | #region Basic functions
96 |
97 | ///
98 | /// Prevents ourside instantiation of the class.
99 | ///
100 | internal FingerprintDevice()
101 | {
102 | // We want to prevent standalone instances of this class.
103 | // Only instances created via FingerprintDeviceManager are valid.
104 | }
105 |
106 | ///
107 | /// Helper method to save and free scanned images.
108 | ///
109 | /// The print image PTR.
110 | /// The PGM file path.
111 | /// if set to true [free image].
112 | private static void SaveImageToDisk(IntPtr printImagePtr, string pgmFilePath, bool freeImage)
113 | {
114 | // Save the PGM file if required by the user
115 | if (string.IsNullOrWhiteSpace(pgmFilePath) == false && printImagePtr != IntPtr.Zero)
116 | {
117 | Interop.fp_img_save_to_file(printImagePtr, pgmFilePath);
118 | }
119 |
120 | // Free the image pointer immediately
121 | if (freeImage && printImagePtr != IntPtr.Zero)
122 | {
123 | Interop.fp_img_free(printImagePtr);
124 | }
125 | }
126 |
127 | ///
128 | /// Opens this fingerprint scanning device.
129 | /// This method has to be called before operating the device.
130 | ///
131 | /// Could not open device.
132 | public void Open()
133 | {
134 | RealDevicePtr = Interop.fp_dev_open(DiscoveredDevicePtr);
135 | if (RealDevicePtr == IntPtr.Zero)
136 | throw new InvalidOperationException("Could not open device.");
137 |
138 | RealDevice = RealDevicePtr.DereferencePtr();
139 |
140 | // Populate device info upon opening
141 | var realDevice = RealDevice.Value;
142 | SupportsImaging = Interop.fp_dev_supports_imaging(ref realDevice) != 0;
143 | SupportsIdentification = Interop.fp_dev_supports_identification(ref realDevice) != 0;
144 | ImageHeight = Interop.fp_dev_get_img_height(ref realDevice);
145 | ImageWidth = Interop.fp_dev_get_img_width(ref realDevice);
146 | SupportsVariableImagingDimensions = ImageWidth <= 0 || ImageHeight <= 0;
147 | EnrollStagesCount = Interop.fp_dev_get_nr_enroll_stages(ref realDevice);
148 | }
149 |
150 | ///
151 | /// Resets the device by closing and re-opening it.
152 | ///
153 | public void Reset()
154 | {
155 | if (IsOpen == false) return;
156 | Interop.fp_dev_close(RealDevicePtr);
157 | Open();
158 | }
159 |
160 | #endregion
161 |
162 | #region Enrollment
163 |
164 | ///
165 | /// Enrolls the fingerprint.
166 | ///
167 | /// The PGM file path.
168 | ///
169 | public EnrollStageResult EnrollFingerprint(string pgmFilePath)
170 | {
171 | // Make sure the device is open
172 | if (IsOpen == false)
173 | Open();
174 |
175 | byte[] fingerprintData = null;
176 |
177 | var enrollResultCode =
178 | Interop.fp_enroll_finger_img(RealDevicePtr, out var printDataPtr, out var printImagePtr);
179 |
180 | // Save the PGM file if required by the user
181 | SaveImageToDisk(printImagePtr, pgmFilePath, true);
182 |
183 | // Create the fingerprint data buffer if the enroll fp data is available
184 | if (enrollResultCode == (int)EnrollResult.EnrollStagePassed ||
185 | enrollResultCode == (int)EnrollResult.EnrollComplete)
186 | {
187 | if (printDataPtr != IntPtr.Zero)
188 | {
189 | var bufferLength = Convert.ToInt32(Interop.fp_print_data_get_data(printDataPtr, out var bufferPtr));
190 | fingerprintData = new byte[bufferLength];
191 | Marshal.Copy(bufferPtr, fingerprintData, 0, fingerprintData.Length);
192 | Interop.fp_print_data_free(printDataPtr);
193 | // TODO: free(bufferPtr) // Maybe Marshal.FreeHGlobal as done in the following line?
194 | Marshal.FreeHGlobal(bufferPtr);
195 | }
196 | }
197 |
198 | return new EnrollStageResult(enrollResultCode, fingerprintData);
199 | }
200 |
201 | ///
202 | /// Enrolls the fingerprint.
203 | ///
204 | ///
205 | public EnrollStageResult EnrollFingerprint() => EnrollFingerprint(null);
206 |
207 | #endregion
208 |
209 | #region Verification
210 |
211 | ///
212 | /// Verifies the fingerprint.
213 | ///
214 | /// The gallery key.
215 | /// The gallery.
216 | /// The PGM file path.
217 | ///
218 | public bool VerifyFingerprint(string galleryKey, FingerprintGallery gallery, string pgmFilePath)
219 | {
220 | // Make sure the device is open
221 | if (IsOpen == false)
222 | Open();
223 |
224 | // Acquire the pointer to the stored fingerprint
225 | var fingerprintPtr = gallery.GetFingerprintPointer(galleryKey);
226 | if (fingerprintPtr == IntPtr.Zero) return false;
227 |
228 | // Perform verification
229 | var resultCode = Interop.fp_verify_finger_img(RealDevicePtr, fingerprintPtr, out var printImagePtr);
230 |
231 | // Save the PGM file if required by the user
232 | SaveImageToDisk(printImagePtr, pgmFilePath, true);
233 |
234 | return resultCode == (int)Interop.fp_verify_result.FP_VERIFY_MATCH;
235 | }
236 |
237 | ///
238 | /// Verifies the fingerprint.
239 | ///
240 | /// The gallery key.
241 | /// The gallery.
242 | ///
243 | public bool VerifyFingerprint(string galleryKey, FingerprintGallery gallery) =>
244 | VerifyFingerprint(galleryKey, gallery, null);
245 |
246 | ///
247 | /// Verifies the fingerprint.
248 | ///
249 | /// The enroll result.
250 | /// The PGM file path.
251 | ///
252 | public bool VerifyFingerprint(EnrollStageResult enrollResult, string pgmFilePath)
253 | {
254 | const string galleryKey = "dummy";
255 | using var gallery = new FingerprintGallery();
256 | gallery.Add(galleryKey, enrollResult);
257 | return VerifyFingerprint(galleryKey, gallery, pgmFilePath);
258 | }
259 |
260 | ///
261 | /// Verifies the fingerprint.
262 | ///
263 | /// The enroll result.
264 | ///
265 | public bool VerifyFingerprint(EnrollStageResult enrollResult) => VerifyFingerprint(enrollResult, null);
266 |
267 | #endregion
268 |
269 | #region Identification
270 |
271 | ///
272 | /// Identifies the fingerprint.
273 | ///
274 | /// The gallery.
275 | /// The PGM file path.
276 | ///
277 | public string IdentifyFingerprint(FingerprintGallery gallery, string pgmFilePath)
278 | {
279 | // Make sure the device is open
280 | if (IsOpen == false)
281 | Open();
282 |
283 | var matchResult = Interop.fp_identify_finger_img(RealDevicePtr, gallery.PointerArray, out var matchOffset,
284 | out var printImagePtr);
285 |
286 | // Save the PGM file if required by the user
287 | SaveImageToDisk(printImagePtr, pgmFilePath, true);
288 |
289 | // Return the key string based on the offset
290 | return matchResult == 1 ? gallery[Convert.ToInt32(matchOffset)] : null;
291 | }
292 |
293 | ///
294 | /// Identifies the fingerprint.
295 | ///
296 | /// The gallery.
297 | ///
298 | public string IdentifyFingerprint(FingerprintGallery gallery) => IdentifyFingerprint(gallery, null);
299 |
300 | #endregion
301 |
302 | #region IDisposable Implementation
303 |
304 | ///
305 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
306 | ///
307 | public void Dispose()
308 | {
309 | Dispose(true);
310 | GC.SuppressFinalize(this);
311 | }
312 |
313 | ///
314 | /// Finalizes an instance of the class.
315 | ///
316 | ~FingerprintDevice()
317 | {
318 | // Finalizer calls Dispose(false)
319 | Dispose(false);
320 | }
321 |
322 | ///
323 | /// Releases unmanaged and - optionally - managed resources.
324 | ///
325 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
326 | protected virtual void Dispose(bool releaseOnlyManaged)
327 | {
328 | if (releaseOnlyManaged)
329 | {
330 | return;
331 | }
332 |
333 | // free native resources if there are any.
334 | if (IsOpen)
335 | {
336 | Interop.fp_dev_close(RealDevicePtr);
337 | RealDevice = null;
338 | RealDevicePtr = IntPtr.Zero;
339 | }
340 | }
341 |
342 | #endregion
343 | }
344 | }
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/FingerprintDeviceManager.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | ///
7 | /// Singleton class to Initialize the fprint library and perform fingerprint reader device discovery.
8 | /// Access properties and methods via the Instance Property.
9 | ///
10 | public sealed class FingerprintDeviceManager : IDisposable
11 | {
12 | #region Singleton Implementation
13 |
14 | ///
15 | /// The static, singleton instance reference.
16 | ///
17 | private static FingerprintDeviceManager m_Instance;
18 |
19 | ///
20 | /// Prevents a default instance of the class from being created.
21 | ///
22 | private FingerprintDeviceManager()
23 | {
24 | // placeholder
25 | }
26 |
27 | ///
28 | /// Gets the single instance of the Fingerprint Device Manager.
29 | ///
30 | ///
31 | /// The instance.
32 | ///
33 | public static FingerprintDeviceManager Instance => m_Instance ??= new FingerprintDeviceManager();
34 |
35 | #endregion
36 |
37 | #region Properties
38 |
39 | ///
40 | /// Gets or sets a value indicating whether the library is initialized.
41 | ///
42 | ///
43 | /// true if this instance is initialized; otherwise, false.
44 | ///
45 | public bool IsInitialized { get; private set; }
46 |
47 |
48 | ///
49 | /// Holds a pointer to the base address of the array containing
50 | /// Discovered device references.
51 | ///
52 | ///
53 | /// The device discovery results PTR.
54 | ///
55 | private IntPtr DeviceDicoveryResultsPtr { get; set; }
56 |
57 | #endregion
58 |
59 | #region Methods
60 |
61 | ///
62 | /// Initializes the fprint library with the given debug level.
63 | /// The dibug level is not documented but 3 seems to have some level of verbosity.
64 | ///
65 | /// The debug level.
66 | ///
67 | public void Initialize(int debugLevel = 0)
68 | {
69 | if (IsInitialized) return;
70 |
71 | var result = Interop.fp_init();
72 | if (result < 0)
73 | throw new InvalidOperationException($"Failed to initialize fprint library. Result code: {result}");
74 |
75 | Interop.fp_set_debug(debugLevel);
76 |
77 | IsInitialized = true;
78 | }
79 |
80 | ///
81 | /// Performs a discovery of currently connected Fingerprint Scanner devices
82 | /// Use the resulting array of FingerPrintDevice to start operating the devices.
83 | ///
84 | ///
85 | public FingerprintDevice[] DiscoverDevices()
86 | {
87 | if (!IsInitialized) Initialize();
88 |
89 | var result = new List();
90 |
91 | ReleaseDeviceDiscoveryResults();
92 | var dicoveredDevicePtrs = Interop.fp_discover_devs_pointers(out var deviceDiscoveryResultsPtr); // This returns the array of pointrs
93 | DeviceDicoveryResultsPtr = deviceDiscoveryResultsPtr;
94 |
95 | foreach (var devicePtr in dicoveredDevicePtrs)
96 | {
97 | var deviceStruct = devicePtr.DereferencePtr();
98 | var driverStruct = Interop.fp_dscv_dev_get_driver_struct(ref deviceStruct);
99 |
100 | var managedDevice = new FingerprintDevice
101 | {
102 | DiscoveredDevice = deviceStruct,
103 | DiscoveredDevicePtr = devicePtr,
104 | Driver = driverStruct,
105 | };
106 |
107 | result.Add(managedDevice);
108 | }
109 |
110 | return result.ToArray();
111 |
112 | }
113 |
114 | #endregion
115 |
116 | #region IDisposable Implementation and cleanup
117 |
118 | ///
119 | /// Releases the device discovery results.
120 | /// This is only for internal purposes.
121 | ///
122 | private void ReleaseDeviceDiscoveryResults()
123 | {
124 | if (DeviceDicoveryResultsPtr != IntPtr.Zero)
125 | {
126 | // Destroy the memory allocation that resulted from device discovery
127 | Interop.fp_dscv_devs_free(DeviceDicoveryResultsPtr);
128 | DeviceDicoveryResultsPtr = IntPtr.Zero;
129 | }
130 | }
131 |
132 | ///
133 | public void Dispose()
134 | {
135 | Dispose(true);
136 | GC.SuppressFinalize(this);
137 | }
138 |
139 | ///
140 | /// Finalizes an instance of the class.
141 | ///
142 | ~FingerprintDeviceManager()
143 | {
144 | // Finalizer calls Dispose(false)
145 | Dispose(false);
146 | }
147 |
148 | ///
149 | /// Releases unmanaged and - optionally - managed resources.
150 | ///
151 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
152 | private void Dispose(bool releaseOnlyManaged)
153 | {
154 | if (releaseOnlyManaged)
155 | {
156 | return;
157 | }
158 |
159 | // free native resources if there are any.
160 | if (IsInitialized)
161 | {
162 | ReleaseDeviceDiscoveryResults();
163 | Interop.fp_exit();
164 | IsInitialized = false;
165 | }
166 |
167 | // remove the reference to the singleton so it can be recreated.
168 | m_Instance = null;
169 | }
170 |
171 | #endregion
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/FingerprintGallery.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | ///
8 | /// Provides means to keeping a fingerprint database.
9 | /// A fingerprint gallery is needed for fingerprint identification.
10 | /// Fingerprints can be loaded from byte arrays or enrollment results.
11 | ///
12 | public class FingerprintGallery : IDisposable
13 | {
14 | #region Support Classes
15 |
16 | ///
17 | /// Tuple holding Identifier-Pointer pairs.
18 | /// Keys are strings, while values are pointers to fingerprint data.
19 | ///
20 | private class Fingerprint
21 | {
22 | public IntPtr Reference { get; set; }
23 | public string Identifier { get; set; }
24 | }
25 |
26 | #endregion
27 |
28 | #region Properties
29 |
30 | ///
31 | /// This is an ordered list of Fingerprint tuples (key-pointer pairs)
32 | /// This is basically an in-memory database.
33 | ///
34 | private readonly List InternalList = new List();
35 |
36 | ///
37 | /// An ordered array of pointers to match an index when identification is required.
38 | /// Whenever the internal list changes, this array gets rebuilt.
39 | ///
40 | ///
41 | /// The pointer array.
42 | ///
43 | internal IntPtr[] PointerArray { get; private set; }
44 |
45 | #endregion
46 |
47 | #region Methods
48 |
49 | ///
50 | /// Initializes a new instance of the class.
51 | ///
52 | public FingerprintGallery()
53 | {
54 | if (FingerprintDeviceManager.Instance.IsInitialized == false)
55 | FingerprintDeviceManager.Instance.Initialize();
56 |
57 | RebuildPointerArray();
58 | }
59 |
60 | ///
61 | /// Rebuilds the pointer array.
62 | /// This method needs to be called whenever the Internal List gets modified in any way.
63 | ///
64 | private void RebuildPointerArray()
65 | {
66 | PointerArray = new IntPtr[InternalList.Count+1];
67 | for (var i = 0; i < InternalList.Count; i++)
68 | PointerArray[i] = InternalList[i].Reference;
69 | PointerArray[InternalList.Count] = IntPtr.Zero;
70 | }
71 |
72 | ///
73 | /// Registers the supplied fingerprint data, associating it with the given key.
74 | ///
75 | /// The key.
76 | /// The fingerprint data.
77 | ///
78 | /// fingerprintData is invalid
79 | /// or
80 | /// key needs to contain a valid string.
81 | ///
82 | /// The fingerprint data buffer is invalid.
83 | private void RegisterFingerprintData(string key, byte[] fingerprintData)
84 | {
85 | if (fingerprintData == null || fingerprintData.Length <= 0)
86 | throw new ArgumentException("fingerprintData is invalid");
87 |
88 | if (string.IsNullOrWhiteSpace(key))
89 | throw new ArgumentException("key needs to contain a valid string");
90 |
91 | var bufferLength = Convert.ToUInt32(fingerprintData.Length);
92 | var printDataFromBufferPtr = Interop.fp_print_data_from_data(fingerprintData, bufferLength);
93 | if (printDataFromBufferPtr == IntPtr.Zero)
94 | throw new FormatException("The fingerprint data buffer is invalid.");
95 |
96 | if (HasKey(key))
97 | Remove(key, false);
98 |
99 | InternalList.Add(new Fingerprint() { Identifier = key, Reference = printDataFromBufferPtr });
100 | }
101 |
102 | ///
103 | /// Adds the specified fingerprint data and associates it with the specified key.
104 | ///
105 | /// The key.
106 | /// The fingerprint data.
107 | public void Add(string key, byte[] fingerprintData)
108 | {
109 | RegisterFingerprintData(key, fingerprintData);
110 | RebuildPointerArray();
111 | }
112 |
113 | ///
114 | /// Adds the specified fingerprint data and associates it with the specified key.
115 | ///
116 | /// The key.
117 | /// The enroll result.
118 | public void Add(string key, EnrollStageResult enrollResult)
119 | {
120 | Add(key, enrollResult.FingerprintData);
121 | }
122 |
123 | ///
124 | /// Adds the specified fingerprint key-value pairs to the gallery.
125 | /// This is the preferred method for bulk loading as it does not rebuild the database
126 | /// for every fingerprint.
127 | ///
128 | /// The fingerprints.
129 | public void AddRange(IEnumerable> fingerprints)
130 | {
131 | foreach (var (key, data) in fingerprints)
132 | {
133 | RegisterFingerprintData(key, data);
134 | }
135 |
136 | RebuildPointerArray();
137 | }
138 |
139 | ///
140 | /// Gets the key with the specified offset.
141 | ///
142 | ///
143 | /// The .
144 | ///
145 | /// The offset.
146 | ///
147 | public string this[int offset] => InternalList[offset].Identifier;
148 |
149 | ///
150 | /// Determines whether the gallery contains the specified keys.
151 | ///
152 | /// The key.
153 | ///
154 | public bool HasKey(string key) => AllKeys().Contains(key);
155 |
156 | ///
157 | /// Gets all the keys registered in this gallery.
158 | ///
159 | ///
160 | public string[] AllKeys() => InternalList.Select(s => s.Identifier).ToArray();
161 |
162 | ///
163 | /// Removes a fingerprint from the gallery given its key.
164 | ///
165 | /// The key.
166 | public void Remove(string key) => Remove(key, true);
167 |
168 | ///
169 | /// Removes a fingerprint from the gallery given its key.
170 | ///
171 | /// The key.
172 | /// if set to true rebuilds the pointer array.
173 | /// The key identifier was not found.
174 | private void Remove(string key, bool rebuild)
175 | {
176 | var items = InternalList.Where(f => f.Identifier.Equals(key)).ToArray();
177 | if (items.Length == 0)
178 | throw new KeyNotFoundException("The key identifier was not found.");
179 |
180 | InternalList.Remove(items[0]);
181 | Interop.fp_print_data_free(items[0].Reference);
182 |
183 | if (rebuild)
184 | RebuildPointerArray();
185 | }
186 |
187 | ///
188 | /// Gets the fingerprint pointer.
189 | ///
190 | /// The key.
191 | ///
192 | internal IntPtr GetFingerprintPointer(string key) => HasKey(key) ? InternalList.FirstOrDefault(f => f.Identifier.Equals(key)).Reference : IntPtr.Zero;
193 |
194 | #endregion
195 |
196 | #region IDisposable Implementation
197 |
198 | ///
199 | public void Dispose()
200 | {
201 | Dispose(true);
202 | GC.SuppressFinalize(this);
203 | }
204 |
205 | ~FingerprintGallery()
206 | {
207 | // Finalizer calls Dispose(false)
208 | Dispose(false);
209 | }
210 |
211 | ///
212 | /// Releases unmanaged and - optionally - managed resources.
213 | ///
214 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
215 | protected virtual void Dispose(bool releaseOnlyManaged)
216 | {
217 | if (releaseOnlyManaged)
218 | {
219 | return;
220 | }
221 |
222 | // free native resources if there are any.
223 | foreach (var fingerprintPtr in PointerArray)
224 | {
225 | if (fingerprintPtr != IntPtr.Zero)
226 | Interop.fp_print_data_free(fingerprintPtr);
227 | }
228 | }
229 |
230 | #endregion
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/Interop.Types.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Unosquare.Labs.LibFprint
4 | {
5 | partial class Interop
6 | {
7 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
8 | public struct GSList
9 | {
10 |
11 | /// gpointer->void*
12 | public IntPtr data;
13 |
14 | /// GSList*
15 | public IntPtr next;
16 | }
17 |
18 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
19 | public struct libusb_device_handle
20 | {
21 | }
22 |
23 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
24 | public struct libusb_device_descriptor
25 | {
26 |
27 | /// uint8_t->unsigned char
28 | public byte bLength;
29 |
30 | /// uint8_t->unsigned char
31 | public byte bDescriptorType;
32 |
33 | /// uint16_t->unsigned short
34 | public ushort bcdUSB;
35 |
36 | /// uint8_t->unsigned char
37 | public byte bDeviceClass;
38 |
39 | /// uint8_t->unsigned char
40 | public byte bDeviceSubClass;
41 |
42 | /// uint8_t->unsigned char
43 | public byte bDeviceProtocol;
44 |
45 | /// uint8_t->unsigned char
46 | public byte bMaxPacketSize0;
47 |
48 | /// uint16_t->unsigned short
49 | public ushort idVendor;
50 |
51 | /// uint16_t->unsigned short
52 | public ushort idProduct;
53 |
54 | /// uint16_t->unsigned short
55 | public ushort bcdDevice;
56 |
57 | /// uint8_t->unsigned char
58 | public byte iManufacturer;
59 |
60 | /// uint8_t->unsigned char
61 | public byte iProduct;
62 |
63 | /// uint8_t->unsigned char
64 | public byte iSerialNumber;
65 |
66 | /// uint8_t->unsigned char
67 | public byte bNumConfigurations;
68 | }
69 |
70 | public enum fp_dev_state
71 | {
72 |
73 | /// DEV_STATE_INITIAL -> 0
74 | DEV_STATE_INITIAL = 0,
75 |
76 | DEV_STATE_ERROR,
77 |
78 | DEV_STATE_INITIALIZING,
79 |
80 | DEV_STATE_INITIALIZED,
81 |
82 | DEV_STATE_DEINITIALIZING,
83 |
84 | DEV_STATE_DEINITIALIZED,
85 |
86 | DEV_STATE_ENROLL_STARTING,
87 |
88 | DEV_STATE_ENROLLING,
89 |
90 | DEV_STATE_ENROLL_STOPPING,
91 |
92 | DEV_STATE_VERIFY_STARTING,
93 |
94 | DEV_STATE_VERIFYING,
95 |
96 | DEV_STATE_VERIFY_DONE,
97 |
98 | DEV_STATE_VERIFY_STOPPING,
99 |
100 | DEV_STATE_IDENTIFY_STARTING,
101 |
102 | DEV_STATE_IDENTIFYING,
103 |
104 | DEV_STATE_IDENTIFY_DONE,
105 |
106 | DEV_STATE_IDENTIFY_STOPPING,
107 |
108 | DEV_STATE_CAPTURE_STARTING,
109 |
110 | DEV_STATE_CAPTURING,
111 |
112 | DEV_STATE_CAPTURE_DONE,
113 |
114 | DEV_STATE_CAPTURE_STOPPING,
115 | }
116 |
117 | public enum fp_driver_type
118 | {
119 |
120 | /// DRIVER_PRIMITIVE -> 0
121 | DRIVER_PRIMITIVE = 0,
122 |
123 | /// DRIVER_IMAGING -> 1
124 | DRIVER_IMAGING = 1,
125 | }
126 |
127 | public enum fp_print_data_type
128 | {
129 |
130 | /// PRINT_DATA_RAW -> 0
131 | PRINT_DATA_RAW = 0,
132 |
133 | PRINT_DATA_NBIS_MINUTIAE,
134 | }
135 |
136 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
137 | public struct fp_dscv_dev
138 | {
139 |
140 | /// libusb_device*
141 | public IntPtr udev;
142 |
143 | /// fp_driver*
144 | public IntPtr drv;
145 |
146 | /// unsigned int
147 | public uint driver_data;
148 |
149 | /// uint32_t->unsigned int
150 | public uint devtype;
151 | }
152 |
153 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
154 | public struct fp_dscv_print
155 | {
156 |
157 | /// uint16_t->unsigned short
158 | public ushort driver_id;
159 |
160 | /// uint32_t->unsigned int
161 | public uint devtype;
162 |
163 | /// fp_finger
164 | public fp_finger finger;
165 |
166 | /// char*
167 | [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
168 | public string path;
169 | }
170 |
171 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
172 | public struct fp_dev
173 | {
174 |
175 | /// fp_driver*
176 | public IntPtr drv;
177 |
178 | /// libusb_device_handle*
179 | public IntPtr udev;
180 |
181 | /// uint32_t->unsigned int
182 | public uint devtype;
183 |
184 | /// void*
185 | public IntPtr priv;
186 |
187 | /// int
188 | public int nr_enroll_stages;
189 |
190 | /// fp_print_data*
191 | public IntPtr verify_data;
192 |
193 | /// fp_dev_state
194 | public fp_dev_state state;
195 |
196 | /// int
197 | public int @__enroll_stage;
198 |
199 | /// int
200 | public int unconditional_capture;
201 |
202 | /// fp_dev_open_cb
203 | public fp_dev_open_cb open_cb;
204 |
205 | /// void*
206 | public IntPtr open_cb_data;
207 |
208 | /// fp_dev_close_cb
209 | public fp_dev_close_cb close_cb;
210 |
211 | /// void*
212 | public IntPtr close_cb_data;
213 |
214 | /// fp_enroll_stage_cb
215 | public fp_enroll_stage_cb enroll_stage_cb;
216 |
217 | /// void*
218 | public IntPtr enroll_stage_cb_data;
219 |
220 | /// fp_enroll_stop_cb
221 | public fp_enroll_stop_cb enroll_stop_cb;
222 |
223 | /// void*
224 | public IntPtr enroll_stop_cb_data;
225 |
226 | /// fp_verify_cb
227 | public fp_verify_cb verify_cb;
228 |
229 | /// void*
230 | public IntPtr verify_cb_data;
231 |
232 | /// fp_verify_stop_cb
233 | public fp_verify_stop_cb verify_stop_cb;
234 |
235 | /// void*
236 | public IntPtr verify_stop_cb_data;
237 |
238 | /// fp_identify_cb
239 | public fp_identify_cb identify_cb;
240 |
241 | /// void*
242 | public IntPtr identify_cb_data;
243 |
244 | /// fp_identify_stop_cb
245 | public fp_identify_stop_cb identify_stop_cb;
246 |
247 | /// void*
248 | public IntPtr identify_stop_cb_data;
249 |
250 | /// fp_capture_cb
251 | public fp_capture_cb capture_cb;
252 |
253 | /// void*
254 | public IntPtr capture_cb_data;
255 |
256 | /// fp_capture_stop_cb
257 | public fp_capture_stop_cb capture_stop_cb;
258 |
259 | /// void*
260 | public IntPtr capture_stop_cb_data;
261 |
262 | /// fp_print_data**
263 | public IntPtr identify_gallery;
264 | }
265 |
266 | /// Return Type: int
267 | ///dsc: libusb_device_descriptor*
268 | ///devtype: uint32_t*
269 | public delegate int fp_driver_discover(ref libusb_device_descriptor dsc, ref uint devtype);
270 |
271 | /// Return Type: int
272 | ///dev: fp_dev*
273 | ///driver_data: unsigned int
274 | public delegate int fp_driver_open(ref fp_dev dev, uint driver_data);
275 |
276 | /// Return Type: void
277 | ///dev: fp_dev*
278 | public delegate void fp_driver_close(ref fp_dev dev);
279 |
280 | /// Return Type: int
281 | ///dev: fp_dev*
282 | public delegate int fp_driver_enroll_start(ref fp_dev dev);
283 |
284 | /// Return Type: int
285 | ///dev: fp_dev*
286 | public delegate int fp_driver_enroll_stop(ref fp_dev dev);
287 |
288 | /// Return Type: int
289 | ///dev: fp_dev*
290 | public delegate int fp_driver_verify_start(ref fp_dev dev);
291 |
292 | /// Return Type: int
293 | ///dev: fp_dev*
294 | ///iterating: gboolean->gint->int
295 | public delegate int fp_driver_verify_stop(ref fp_dev dev, int iterating);
296 |
297 | /// Return Type: int
298 | ///dev: fp_dev*
299 | public delegate int fp_driver_identify_start(ref fp_dev dev);
300 |
301 | /// Return Type: int
302 | ///dev: fp_dev*
303 | ///iterating: gboolean->gint->int
304 | public delegate int fp_driver_identify_stop(ref fp_dev dev, int iterating);
305 |
306 | /// Return Type: int
307 | ///dev: fp_dev*
308 | public delegate int fp_driver_capture_start(ref fp_dev dev);
309 |
310 | /// Return Type: int
311 | ///dev: fp_dev*
312 | public delegate int fp_driver_capture_stop(ref fp_dev dev);
313 |
314 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
315 | public struct fp_driver
316 | {
317 |
318 | /// uint16_t->unsigned short
319 | public ushort id;
320 |
321 | /// char*
322 | [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
323 | public string name;
324 |
325 | /// char*
326 | [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
327 | public string full_name;
328 |
329 | /// usb_id*
330 | public IntPtr id_table;
331 |
332 | /// fp_driver_type
333 | public fp_driver_type type;
334 |
335 | /// fp_scan_type
336 | public fp_scan_type scan_type;
337 |
338 | /// void*
339 | public IntPtr priv;
340 |
341 | /// fp_driver_discover
342 | public fp_driver_discover AnonymousMember1;
343 |
344 | /// fp_driver_open
345 | public fp_driver_open AnonymousMember2;
346 |
347 | /// fp_driver_close
348 | public fp_driver_close AnonymousMember3;
349 |
350 | /// fp_driver_enroll_start
351 | public fp_driver_enroll_start AnonymousMember4;
352 |
353 | /// fp_driver_enroll_stop
354 | public fp_driver_enroll_stop AnonymousMember5;
355 |
356 | /// fp_driver_verify_start
357 | public fp_driver_verify_start AnonymousMember6;
358 |
359 | /// fp_driver_verify_stop
360 | public fp_driver_verify_stop AnonymousMember7;
361 |
362 | /// fp_driver_identify_start
363 | public fp_driver_identify_start AnonymousMember8;
364 |
365 | /// fp_driver_identify_stop
366 | public fp_driver_identify_stop AnonymousMember9;
367 |
368 | /// fp_driver_capture_start
369 | public fp_driver_capture_start AnonymousMember10;
370 |
371 | /// fp_driver_capture_stop
372 | public fp_driver_capture_stop AnonymousMember11;
373 | }
374 |
375 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
376 | public struct fp_print_data
377 | {
378 |
379 | /// uint16_t->unsigned short
380 | public ushort driver_id;
381 |
382 | /// uint32_t->unsigned int
383 | public uint devtype;
384 |
385 | /// fp_print_data_type
386 | public fp_print_data_type type;
387 |
388 | /// GSList*
389 | public IntPtr prints;
390 | }
391 |
392 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
393 | public struct fp_img
394 | {
395 |
396 | /// int
397 | public int width;
398 |
399 | /// int
400 | public int height;
401 |
402 | /// size_t->unsigned int
403 | public uint length;
404 |
405 | /// uint16_t->unsigned short
406 | public ushort flags;
407 |
408 | /// fp_minutiae*
409 | public IntPtr minutiae;
410 |
411 | /// unsigned char*
412 | public IntPtr binarized;
413 |
414 | /// unsigned char[0]
415 | public IntPtr data;
416 | }
417 |
418 | public enum fp_finger
419 | {
420 |
421 | /// LEFT_THUMB -> 1
422 | LEFT_THUMB = 1,
423 |
424 | LEFT_INDEX,
425 |
426 | LEFT_MIDDLE,
427 |
428 | LEFT_RING,
429 |
430 | LEFT_LITTLE,
431 |
432 | RIGHT_THUMB,
433 |
434 | RIGHT_INDEX,
435 |
436 | RIGHT_MIDDLE,
437 |
438 | RIGHT_RING,
439 |
440 | RIGHT_LITTLE,
441 | }
442 |
443 | public enum fp_scan_type
444 | {
445 |
446 | /// FP_SCAN_TYPE_PRESS -> 0
447 | FP_SCAN_TYPE_PRESS = 0,
448 |
449 | FP_SCAN_TYPE_SWIPE,
450 | }
451 |
452 | public enum fp_capture_result
453 | {
454 |
455 | /// FP_CAPTURE_COMPLETE -> 0
456 | FP_CAPTURE_COMPLETE = 0,
457 |
458 | FP_CAPTURE_FAIL,
459 | }
460 |
461 | public enum fp_enroll_result
462 | {
463 |
464 | /// FP_ENROLL_COMPLETE -> 1
465 | FP_ENROLL_COMPLETE = 1,
466 |
467 | FP_ENROLL_FAIL,
468 |
469 | FP_ENROLL_PASS,
470 |
471 | /// FP_ENROLL_RETRY -> 100
472 | FP_ENROLL_RETRY = 100,
473 |
474 | FP_ENROLL_RETRY_TOO_SHORT,
475 |
476 | FP_ENROLL_RETRY_CENTER_FINGER,
477 |
478 | FP_ENROLL_RETRY_REMOVE_FINGER,
479 | }
480 |
481 | public enum fp_verify_result
482 | {
483 |
484 | /// FP_VERIFY_NO_MATCH -> 0
485 | FP_VERIFY_NO_MATCH = 0,
486 |
487 | /// FP_VERIFY_MATCH -> 1
488 | FP_VERIFY_MATCH = 1,
489 |
490 | /// FP_VERIFY_RETRY -> FP_ENROLL_RETRY
491 | FP_VERIFY_RETRY = fp_enroll_result.FP_ENROLL_RETRY,
492 |
493 | /// FP_VERIFY_RETRY_TOO_SHORT -> FP_ENROLL_RETRY_TOO_SHORT
494 | FP_VERIFY_RETRY_TOO_SHORT = fp_enroll_result.FP_ENROLL_RETRY_TOO_SHORT,
495 |
496 | /// FP_VERIFY_RETRY_CENTER_FINGER -> FP_ENROLL_RETRY_CENTER_FINGER
497 | FP_VERIFY_RETRY_CENTER_FINGER = fp_enroll_result.FP_ENROLL_RETRY_CENTER_FINGER,
498 |
499 | /// FP_VERIFY_RETRY_REMOVE_FINGER -> FP_ENROLL_RETRY_REMOVE_FINGER
500 | FP_VERIFY_RETRY_REMOVE_FINGER = fp_enroll_result.FP_ENROLL_RETRY_REMOVE_FINGER,
501 | }
502 |
503 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
504 | public struct fp_minutia
505 | {
506 |
507 | /// int
508 | public int x;
509 |
510 | /// int
511 | public int y;
512 |
513 | /// int
514 | public int ex;
515 |
516 | /// int
517 | public int ey;
518 |
519 | /// int
520 | public int direction;
521 |
522 | /// double
523 | public double reliability;
524 |
525 | /// int
526 | public int type;
527 |
528 | /// int
529 | public int appearing;
530 |
531 | /// int
532 | public int feature_id;
533 |
534 | /// int*
535 | public IntPtr nbrs;
536 |
537 | /// int*
538 | public IntPtr ridge_counts;
539 |
540 | /// int
541 | public int num_nbrs;
542 | }
543 |
544 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
545 | public struct fp_pollfd
546 | {
547 |
548 | /// int
549 | public int fd;
550 |
551 | /// short
552 | public short events;
553 | }
554 |
555 | /// Return Type: void
556 | ///fd: int
557 | ///events: short
558 | public delegate void fp_pollfd_added_cb(int fd, short events);
559 |
560 | /// Return Type: void
561 | ///fd: int
562 | public delegate void fp_pollfd_removed_cb(int fd);
563 |
564 | /// Return Type: void
565 | ///dev: fp_dev*
566 | ///status: int
567 | ///user_data: void*
568 | public delegate void fp_dev_open_cb(ref fp_dev dev, int status, IntPtr user_data);
569 |
570 | /// Return Type: void
571 | ///dev: fp_dev*
572 | ///user_data: void*
573 | public delegate void fp_dev_close_cb(ref fp_dev dev, IntPtr user_data);
574 |
575 | /// Return Type: void
576 | ///dev: fp_dev*
577 | ///result: int
578 | ///print: fp_print_data*
579 | ///img: fp_img*
580 | ///user_data: void*
581 | public delegate void fp_enroll_stage_cb(ref fp_dev dev, int result, ref fp_print_data print, ref fp_img img, IntPtr user_data);
582 |
583 | /// Return Type: void
584 | ///dev: fp_dev*
585 | ///user_data: void*
586 | public delegate void fp_enroll_stop_cb(ref fp_dev dev, IntPtr user_data);
587 |
588 | /// Return Type: void
589 | ///dev: fp_dev*
590 | ///result: int
591 | ///img: fp_img*
592 | ///user_data: void*
593 | public delegate void fp_verify_cb(ref fp_dev dev, int result, ref fp_img img, IntPtr user_data);
594 |
595 | /// Return Type: void
596 | ///dev: fp_dev*
597 | ///user_data: void*
598 | public delegate void fp_verify_stop_cb(ref fp_dev dev, IntPtr user_data);
599 |
600 | /// Return Type: void
601 | ///dev: fp_dev*
602 | ///result: int
603 | ///match_offset: size_t->unsigned int
604 | ///img: fp_img*
605 | ///user_data: void*
606 | public delegate void fp_identify_cb(ref fp_dev dev, int result, IntPtr match_offset, ref fp_img img, IntPtr user_data);
607 |
608 | /// Return Type: void
609 | ///dev: fp_dev*
610 | ///user_data: void*
611 | public delegate void fp_identify_stop_cb(ref fp_dev dev, IntPtr user_data);
612 |
613 | /// Return Type: void
614 | ///dev: fp_dev*
615 | ///result: int
616 | ///img: fp_img*
617 | ///user_data: void*
618 | public delegate void fp_capture_cb(ref fp_dev dev, int result, ref fp_img img, IntPtr user_data);
619 |
620 | /// Return Type: void
621 | ///dev: fp_dev*
622 | ///user_data: void*
623 | public delegate void fp_capture_stop_cb(ref fp_dev dev, IntPtr user_data);
624 |
625 | [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
626 | public struct timeval
627 | {
628 |
629 | /// int
630 | public int tv_sec;
631 |
632 | /// int
633 | public int tv_usec;
634 | }
635 | }
636 | }
637 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/Interop.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Unosquare.Labs.LibFprint
5 | {
6 | ///
7 | /// This file was generated automatically. -- Only very few manual modifications were made.
8 | ///
9 | internal partial class Interop
10 | {
11 | private const string FingerprintLibrary = "libfprint.so";
12 |
13 | /// Return Type: char*
14 | ///drv: fp_driver*
15 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_driver_get_name")]
16 | public static extern IntPtr fp_driver_get_name(ref fp_driver drv);
17 |
18 |
19 | /// Return Type: char*
20 | ///drv: fp_driver*
21 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_driver_get_full_name")]
22 | public static extern IntPtr fp_driver_get_full_name(ref fp_driver drv);
23 |
24 |
25 | /// Return Type: uint16_t->unsigned short
26 | ///drv: fp_driver*
27 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_driver_get_driver_id")]
28 | public static extern ushort fp_driver_get_driver_id(ref fp_driver drv);
29 |
30 |
31 | /// Return Type: fp_scan_type
32 | ///drv: fp_driver*
33 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_driver_get_scan_type")]
34 | public static extern fp_scan_type fp_driver_get_scan_type(ref fp_driver drv);
35 |
36 |
37 | /// Return Type: fp_dscv_dev**
38 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_discover_devs")]
39 | public static extern IntPtr fp_discover_devs();
40 |
41 | public static IntPtr[] fp_discover_devs_pointers(out IntPtr arrayPtr)
42 | {
43 |
44 | var baseAddress = fp_discover_devs();
45 | arrayPtr = baseAddress;
46 |
47 | return baseAddress.ToPointerArray();
48 | }
49 |
50 | public static fp_dscv_dev[] fp_discover_devs_structus(out IntPtr arrayPtr)
51 | {
52 | var devices = new List();
53 | var devicePtrs = fp_discover_devs_pointers(out arrayPtr);
54 |
55 | foreach (var devicePtr in devicePtrs)
56 | {
57 | var device = devicePtr.DereferencePtr();
58 | devices.Add(device);
59 | }
60 |
61 | return devices.ToArray();
62 | }
63 |
64 | /// Return Type: void
65 | ///devs: fp_dscv_dev**
66 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_devs_free")]
67 | public static extern void fp_dscv_devs_free(IntPtr devs);
68 |
69 |
70 | /// Return Type: fp_driver*
71 | ///dev: fp_dscv_dev*
72 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_get_driver")]
73 | public static extern IntPtr fp_dscv_dev_get_driver(ref fp_dscv_dev dev);
74 |
75 | public static fp_driver fp_dscv_dev_get_driver_struct(ref fp_dscv_dev dev)
76 | {
77 | var ptr = fp_dscv_dev_get_driver(ref dev);
78 | return ptr.DereferencePtr();
79 | }
80 |
81 | /// Return Type: uint32_t->unsigned int
82 | ///dev: fp_dscv_dev*
83 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_get_devtype")]
84 | public static extern uint fp_dscv_dev_get_devtype(ref fp_dscv_dev dev);
85 |
86 |
87 | /// Return Type: int
88 | ///dev: fp_dscv_dev*
89 | ///print: fp_print_data*
90 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_supports_print_data")]
91 | public static extern int fp_dscv_dev_supports_print_data(ref fp_dscv_dev dev, ref fp_print_data print);
92 |
93 |
94 | /// Return Type: int
95 | ///dev: fp_dscv_dev*
96 | ///print: fp_dscv_print*
97 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_supports_dscv_print")]
98 | public static extern int fp_dscv_dev_supports_dscv_print(ref fp_dscv_dev dev, ref fp_dscv_print print);
99 |
100 |
101 | /// Return Type: fp_dscv_dev*
102 | ///devs: fp_dscv_dev**
103 | ///print: fp_print_data*
104 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_for_print_data")]
105 | public static extern IntPtr fp_dscv_dev_for_print_data(ref IntPtr devs, ref fp_print_data print);
106 |
107 |
108 | /// Return Type: fp_dscv_dev*
109 | ///devs: fp_dscv_dev**
110 | ///print: fp_dscv_print*
111 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_for_dscv_print")]
112 | public static extern IntPtr fp_dscv_dev_for_dscv_print(ref IntPtr devs, ref fp_dscv_print print);
113 |
114 |
115 | /// Return Type: uint16_t->unsigned short
116 | ///dev: fp_dscv_dev*
117 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_dev_get_driver_id")]
118 | public static extern ushort fp_dscv_dev_get_driver_id(ref fp_dscv_dev dev);
119 |
120 |
121 | /// Return Type: fp_dscv_print**
122 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_discover_prints")]
123 | public static extern IntPtr fp_discover_prints();
124 |
125 |
126 | /// Return Type: void
127 | ///prints: fp_dscv_print**
128 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_prints_free")]
129 | public static extern void fp_dscv_prints_free(ref IntPtr prints);
130 |
131 |
132 | /// Return Type: uint16_t->unsigned short
133 | ///print: fp_dscv_print*
134 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_print_get_driver_id")]
135 | public static extern ushort fp_dscv_print_get_driver_id(ref fp_dscv_print print);
136 |
137 |
138 | /// Return Type: uint32_t->unsigned int
139 | ///print: fp_dscv_print*
140 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_print_get_devtype")]
141 | public static extern uint fp_dscv_print_get_devtype(ref fp_dscv_print print);
142 |
143 |
144 | /// Return Type: fp_finger
145 | ///print: fp_dscv_print*
146 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_print_get_finger")]
147 | public static extern fp_finger fp_dscv_print_get_finger(ref fp_dscv_print print);
148 |
149 |
150 | /// Return Type: int
151 | ///print: fp_dscv_print*
152 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dscv_print_delete")]
153 | public static extern int fp_dscv_print_delete(ref fp_dscv_print print);
154 |
155 |
156 | /// Return Type: fp_dev*
157 | ///ddev: fp_dscv_dev*
158 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_open")]
159 | public static extern IntPtr fp_dev_open(IntPtr ddev);
160 |
161 | public static fp_dev fp_dev_open_struct(IntPtr ddev, out IntPtr devicePtr)
162 | {
163 | devicePtr = fp_dev_open(ddev);
164 | return devicePtr.DereferencePtr();
165 | }
166 |
167 | /// Return Type: void
168 | ///dev: fp_dev*
169 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_close")]
170 | public static extern void fp_dev_close(IntPtr dev);
171 |
172 |
173 | /// Return Type: fp_driver*
174 | ///dev: fp_dev*
175 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_get_driver")]
176 | public static extern IntPtr fp_dev_get_driver(ref fp_dev dev);
177 |
178 |
179 | /// Return Type: int
180 | ///dev: fp_dev*
181 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_get_nr_enroll_stages")]
182 | public static extern int fp_dev_get_nr_enroll_stages(ref fp_dev dev);
183 |
184 |
185 | /// Return Type: uint32_t->unsigned int
186 | ///dev: fp_dev*
187 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_get_devtype")]
188 | public static extern uint fp_dev_get_devtype(ref fp_dev dev);
189 |
190 |
191 | /// Return Type: int
192 | ///dev: fp_dev*
193 | ///data: fp_print_data*
194 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_supports_print_data")]
195 | public static extern int fp_dev_supports_print_data(ref fp_dev dev, ref fp_print_data data);
196 |
197 |
198 | /// Return Type: int
199 | ///dev: fp_dev*
200 | ///print: fp_dscv_print*
201 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_supports_dscv_print")]
202 | public static extern int fp_dev_supports_dscv_print(ref fp_dev dev, ref fp_dscv_print print);
203 |
204 |
205 | /// Return Type: int
206 | ///dev: fp_dev*
207 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_supports_imaging")]
208 | public static extern int fp_dev_supports_imaging(ref fp_dev dev);
209 |
210 |
211 | /// Return Type: int
212 | ///dev: fp_dev*
213 | ///unconditional: int
214 | ///image: fp_img**
215 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_img_capture")]
216 | public static extern int fp_dev_img_capture(IntPtr dev, int unconditional, IntPtr image);
217 |
218 |
219 | /// Return Type: int
220 | ///dev: fp_dev*
221 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_get_img_width")]
222 | public static extern int fp_dev_get_img_width(ref fp_dev dev);
223 |
224 |
225 | /// Return Type: int
226 | ///dev: fp_dev*
227 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_get_img_height")]
228 | public static extern int fp_dev_get_img_height(ref fp_dev dev);
229 |
230 |
231 | /// Return Type: int
232 | ///dev: fp_dev*
233 | ///print_data: fp_print_data**
234 | ///img: fp_img**
235 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_enroll_finger_img")]
236 | public static extern int fp_enroll_finger_img(IntPtr dev, out IntPtr print_data, out IntPtr img);
237 |
238 |
239 | /// Return Type: int
240 | ///dev: fp_dev*
241 | ///print_data: fp_print_data**
242 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_enroll_finger")]
243 | public static extern int fp_enroll_finger(ref fp_dev dev, ref IntPtr print_data);
244 |
245 |
246 | /// Return Type: int
247 | ///dev: fp_dev*
248 | ///enrolled_print: fp_print_data*
249 | ///img: fp_img**
250 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_verify_finger_img")]
251 | public static extern int fp_verify_finger_img(IntPtr dev, IntPtr enrolled_print, out IntPtr img);
252 |
253 |
254 | /// Return Type: int
255 | ///dev: fp_dev*
256 | ///enrolled_print: fp_print_data*
257 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_verify_finger")]
258 | public static extern int fp_verify_finger(ref fp_dev dev, ref fp_print_data enrolled_print);
259 |
260 |
261 | /// Return Type: int
262 | ///dev: fp_dev*
263 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_dev_supports_identification")]
264 | public static extern int fp_dev_supports_identification(ref fp_dev dev);
265 |
266 |
267 | /// Return Type: int
268 | ///dev: fp_dev*
269 | ///print_gallery: fp_print_data**
270 | ///match_offset: size_t*
271 | ///img: fp_img**
272 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_identify_finger_img")]
273 | public static extern int fp_identify_finger_img(IntPtr dev, IntPtr[] print_gallery, out uint match_offset, out IntPtr img);
274 |
275 |
276 | /// Return Type: int
277 | ///dev: fp_dev*
278 | ///print_gallery: fp_print_data**
279 | ///match_offset: size_t*
280 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_identify_finger")]
281 | public static extern int fp_identify_finger(IntPtr dev, ref fp_print_data[] print_gallery, ref uint match_offset);
282 |
283 |
284 | /// Return Type: int
285 | ///dev: fp_dev*
286 | ///finger: fp_finger
287 | ///data: fp_print_data**
288 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_load")]
289 | public static extern int fp_print_data_load(ref fp_dev dev, fp_finger finger, ref IntPtr data);
290 |
291 |
292 | /// Return Type: int
293 | ///print: fp_dscv_print*
294 | ///data: fp_print_data**
295 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_from_dscv_print")]
296 | public static extern int fp_print_data_from_dscv_print(ref fp_dscv_print print, ref IntPtr data);
297 |
298 |
299 | /// Return Type: int
300 | ///data: fp_print_data*
301 | ///finger: fp_finger
302 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_save")]
303 | public static extern int fp_print_data_save(ref fp_print_data data, fp_finger finger);
304 |
305 |
306 | /// Return Type: int
307 | ///dev: fp_dev*
308 | ///finger: fp_finger
309 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_delete")]
310 | public static extern int fp_print_data_delete(ref fp_dev dev, fp_finger finger);
311 |
312 |
313 | /// Return Type: void
314 | ///data: fp_print_data*
315 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_free")]
316 | public static extern void fp_print_data_free(IntPtr data);
317 |
318 |
319 | /// Return Type: size_t->unsigned int
320 | ///data: fp_print_data*
321 | ///ret: unsigned char**
322 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_get_data")]
323 | [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.SysUInt)]
324 | public static extern uint fp_print_data_get_data(IntPtr data, out IntPtr ret);
325 |
326 |
327 | /// Return Type: fp_print_data*
328 | ///buf: unsigned char*
329 | ///buflen: size_t->unsigned int
330 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_from_data")]
331 | public static extern IntPtr fp_print_data_from_data(
332 | byte[] buf
333 | ,[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.SysUInt)] uint buflen);
334 |
335 |
336 | /// Return Type: uint16_t->unsigned short
337 | ///data: fp_print_data*
338 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_get_driver_id")]
339 | public static extern ushort fp_print_data_get_driver_id(ref fp_print_data data);
340 |
341 |
342 | /// Return Type: uint32_t->unsigned int
343 | ///data: fp_print_data*
344 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_print_data_get_devtype")]
345 | public static extern uint fp_print_data_get_devtype(ref fp_print_data data);
346 |
347 |
348 | /// Return Type: int
349 | ///img: fp_img*
350 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_get_height")]
351 | public static extern int fp_img_get_height(ref fp_img img);
352 |
353 |
354 | /// Return Type: int
355 | ///img: fp_img*
356 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_get_width")]
357 | public static extern int fp_img_get_width(ref fp_img img);
358 |
359 |
360 | /// Return Type: unsigned char*
361 | ///img: fp_img*
362 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_get_data")]
363 | public static extern IntPtr fp_img_get_data(ref fp_img img);
364 |
365 |
366 | /// Return Type: int
367 | ///img: fp_img*
368 | ///path: char*
369 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_save_to_file")]
370 | public static extern int fp_img_save_to_file(IntPtr img, string path);
371 |
372 |
373 | /// Return Type: void
374 | ///img: fp_img*
375 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_standardize")]
376 | public static extern void fp_img_standardize(ref fp_img img);
377 |
378 |
379 | /// Return Type: fp_img*
380 | ///img: fp_img*
381 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_binarize")]
382 | public static extern IntPtr fp_img_binarize(ref fp_img img);
383 |
384 |
385 | /// Return Type: fp_minutia**
386 | ///img: fp_img*
387 | ///nr_minutiae: int*
388 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_get_minutiae")]
389 | public static extern IntPtr fp_img_get_minutiae(ref fp_img img, ref int nr_minutiae);
390 |
391 |
392 | /// Return Type: void
393 | ///img: fp_img*
394 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_img_free")]
395 | public static extern void fp_img_free(IntPtr img);
396 |
397 |
398 | /// Return Type: int
399 | ///timeout: timeval*
400 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_handle_events_timeout")]
401 | public static extern int fp_handle_events_timeout(ref timeval timeout);
402 |
403 |
404 | /// Return Type: int
405 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_handle_events")]
406 | public static extern int fp_handle_events();
407 |
408 |
409 | /// Return Type: size_t->unsigned int
410 | ///pollfds: fp_pollfd**
411 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_get_pollfds")]
412 | [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.SysUInt)]
413 | public static extern uint fp_get_pollfds(ref IntPtr pollfds);
414 |
415 |
416 | /// Return Type: int
417 | ///tv: timeval*
418 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_get_next_timeout")]
419 | public static extern int fp_get_next_timeout(ref timeval tv);
420 |
421 |
422 | /// Return Type: void
423 | ///added_cb: fp_pollfd_added_cb
424 | ///removed_cb: fp_pollfd_removed_cb
425 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_set_pollfd_notifiers")]
426 | public static extern void fp_set_pollfd_notifiers(fp_pollfd_added_cb added_cb, fp_pollfd_removed_cb removed_cb);
427 |
428 |
429 | /// Return Type: int
430 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_init")]
431 | public static extern int fp_init();
432 |
433 |
434 | /// Return Type: void
435 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_exit")]
436 | public static extern void fp_exit();
437 |
438 |
439 | /// Return Type: void
440 | ///level: int
441 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_set_debug")]
442 | public static extern void fp_set_debug(int level);
443 |
444 |
445 | /// Return Type: int
446 | ///ddev: fp_dscv_dev*
447 | ///callback: fp_dev_open_cb
448 | ///user_data: void*
449 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_dev_open")]
450 | public static extern int fp_async_dev_open(ref fp_dscv_dev ddev, fp_dev_open_cb callback, IntPtr user_data);
451 |
452 |
453 | /// Return Type: void
454 | ///dev: fp_dev*
455 | ///callback: fp_dev_close_cb
456 | ///user_data: void*
457 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_dev_close")]
458 | public static extern void fp_async_dev_close(ref fp_dev dev, fp_dev_close_cb callback, IntPtr user_data);
459 |
460 |
461 | /// Return Type: int
462 | ///dev: fp_dev*
463 | ///callback: fp_enroll_stage_cb
464 | ///user_data: void*
465 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_enroll_start")]
466 | public static extern int fp_async_enroll_start(ref fp_dev dev, fp_enroll_stage_cb callback, IntPtr user_data);
467 |
468 |
469 | /// Return Type: int
470 | ///dev: fp_dev*
471 | ///callback: fp_enroll_stop_cb
472 | ///user_data: void*
473 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_enroll_stop")]
474 | public static extern int fp_async_enroll_stop(ref fp_dev dev, fp_enroll_stop_cb callback, IntPtr user_data);
475 |
476 |
477 | /// Return Type: int
478 | ///dev: fp_dev*
479 | ///data: fp_print_data*
480 | ///callback: fp_verify_cb
481 | ///user_data: void*
482 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_verify_start")]
483 | public static extern int fp_async_verify_start(ref fp_dev dev, ref fp_print_data data, fp_verify_cb callback, IntPtr user_data);
484 |
485 |
486 | /// Return Type: int
487 | ///dev: fp_dev*
488 | ///callback: fp_verify_stop_cb
489 | ///user_data: void*
490 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_verify_stop")]
491 | public static extern int fp_async_verify_stop(ref fp_dev dev, fp_verify_stop_cb callback, IntPtr user_data);
492 |
493 |
494 | /// Return Type: int
495 | ///dev: fp_dev*
496 | ///gallery: fp_print_data**
497 | ///callback: fp_identify_cb
498 | ///user_data: void*
499 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_identify_start")]
500 | public static extern int fp_async_identify_start(ref fp_dev dev, ref IntPtr gallery, fp_identify_cb callback, IntPtr user_data);
501 |
502 |
503 | /// Return Type: int
504 | ///dev: fp_dev*
505 | ///callback: fp_identify_stop_cb
506 | ///user_data: void*
507 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_identify_stop")]
508 | public static extern int fp_async_identify_stop(ref fp_dev dev, fp_identify_stop_cb callback, IntPtr user_data);
509 |
510 |
511 | /// Return Type: int
512 | ///dev: fp_dev*
513 | ///unconditional: int
514 | ///callback: fp_capture_cb
515 | ///user_data: void*
516 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_capture_start")]
517 | public static extern int fp_async_capture_start(ref fp_dev dev, int unconditional, fp_capture_cb callback, IntPtr user_data);
518 |
519 |
520 | /// Return Type: int
521 | ///dev: fp_dev*
522 | ///callback: fp_capture_stop_cb
523 | ///user_data: void*
524 | [System.Runtime.InteropServices.DllImportAttribute(FingerprintLibrary, EntryPoint = "fp_async_capture_stop")]
525 | public static extern int fp_async_capture_stop(ref fp_dev dev, fp_capture_stop_cb callback, IntPtr user_data);
526 |
527 | }
528 | }
529 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/PgmFormatReader.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.Labs.LibFprint
2 | {
3 | using System;
4 | using System.Drawing;
5 | using System.Drawing.Imaging;
6 | using System.IO;
7 | using System.Text;
8 |
9 | ///
10 | /// Provides utility methods to read PGM files into Bitmap objects.
11 | ///
12 | public static class PgmFormatReader
13 | {
14 | ///
15 | /// The standard grayscale palette that is loaded in the static constructor.
16 | ///
17 | private static readonly ColorPalette GrayscalePalette;
18 |
19 | ///
20 | /// Initializes the static class.
21 | ///
22 | static PgmFormatReader()
23 | {
24 | // We initialize the palette to 256 colors (grayscale)
25 | // PGM files are always grayscale and we will always represent them in
26 | // 256 shades of gray.
27 | using var dummyBitmap = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
28 | GrayscalePalette = dummyBitmap.Palette;
29 | for (var i = 0; i < 256; i++)
30 | {
31 | GrayscalePalette.Entries[i] = Color.FromArgb(i, i, i);
32 | }
33 | }
34 |
35 | ///
36 | /// Reads the specified PGM stream and returns a Bitmap.
37 | ///
38 | /// The stream.
39 | ///
40 | /// PGM Magic Number not found.
41 | public static Bitmap Read(Stream stream)
42 | {
43 | using var reader = new BinaryReader(stream, Encoding.ASCII);
44 | if ((reader.ReadChar() == 'P' && reader.ReadChar() == '5') == false)
45 | throw new BadImageFormatException("PGM Magic Number not found.");
46 |
47 | // Read onew whitespace character
48 | reader.ReadChar();
49 |
50 | // Get basic PGM format properties
51 | var parseBuffer = new StringBuilder();
52 | var pgmWidth = ReadInteger(reader, parseBuffer);
53 | var pgmHeight = ReadInteger(reader, parseBuffer);
54 | var grayscaleLevels = ReadInteger(reader, parseBuffer);
55 | var isTwoByteLevel = (grayscaleLevels > 255);
56 |
57 | // Create the bitmap and assign the 8bpp Indexed palette
58 | var bmp = new Bitmap(pgmWidth, pgmHeight, PixelFormat.Format8bppIndexed) {Palette = GrayscalePalette};
59 |
60 | // Create the target lockbits
61 | var bitmapData = bmp.LockBits(new Rectangle(0, 0, pgmWidth, pgmHeight), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
62 | var rowLengthOffset = bitmapData.Stride - bitmapData.Width;
63 | var dataLength = bitmapData.Stride * bitmapData.Height;
64 | var pixelData = new byte[dataLength];
65 |
66 | var pixelDataIndex = 0;
67 |
68 | for (var rowIndex = 0; rowIndex < pgmHeight; rowIndex++)
69 | {
70 | for (var columnIndex = 0; columnIndex < pgmWidth; columnIndex++)
71 | {
72 | var currentPixelValue = reader.ReadByte();
73 | if (isTwoByteLevel)
74 | currentPixelValue = (byte)(((double)((currentPixelValue << 8) + reader.ReadByte()) / grayscaleLevels) * 255.0);
75 |
76 | pixelData[pixelDataIndex] = currentPixelValue;
77 | pixelDataIndex++;
78 | }
79 |
80 | pixelDataIndex += rowLengthOffset;
81 | }
82 |
83 | // Use a fast copy mechanism to write the data to the bitmap
84 | System.Runtime.InteropServices.Marshal.Copy(pixelData, 0, bitmapData.Scan0, dataLength);
85 |
86 | // Release the write lock on the bits.
87 | bmp.UnlockBits(bitmapData);
88 |
89 | return bmp;
90 | }
91 |
92 | ///
93 | /// Reads the specified PGM buffer and returns a Bitmap.
94 | ///
95 | /// The buffer.
96 | ///
97 | public static Bitmap Read(byte[] buffer)
98 | {
99 | using var ms = new MemoryStream(buffer) {Position = 0};
100 | return Read(ms);
101 | }
102 |
103 | ///
104 | /// Reads the specified PGM file and returns a Bitmap.
105 | ///
106 | /// The path.
107 | ///
108 | public static Bitmap Read(string path)
109 | {
110 | using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
111 | return Read(fs);
112 | }
113 |
114 | ///
115 | /// Reads an integer by reading from a Binary Reader.
116 | /// It uses a StringBuilder to hold and parse numbers.
117 | ///
118 | /// The reader.
119 | /// The sb.
120 | ///
121 | private static int ReadInteger(BinaryReader reader, StringBuilder sb)
122 | {
123 | var c = '\0';
124 | sb.Length = 0;
125 | while (char.IsDigit(c = reader.ReadChar()))
126 | {
127 | sb.Append(c);
128 | }
129 |
130 | return int.Parse(sb.ToString().Trim());
131 | }
132 | }
133 | }
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/Unosquare.Labs.LibFprint.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | Copyright (c) 2019 - Unosquare
5 | Unosquare
6 | Unosquare.Labs.LibFprint
7 | 8.0
8 |
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Unosquare.Labs.LibFprint/fprint.h:
--------------------------------------------------------------------------------
1 | // We are keeping this file for reference only because we generated a bunch of code from this "slightly" modified version :)
2 |
3 | typedef unsigned short uint16_t;
4 | typedef unsigned long uint32_t;
5 | typedef unsigned char uint8_t;
6 | typedef int gint;
7 | typedef gint gboolean;
8 |
9 | typedef void* gpointer;
10 |
11 | struct GSList {
12 | gpointer data;
13 | GSList *next;
14 | };
15 |
16 | typedef struct libusb_device_handle { } libusb_device_handle;
17 |
18 | struct libusb_device_descriptor {
19 | /** Size of this descriptor (in bytes) */
20 | uint8_t bLength;
21 |
22 | /** Descriptor type. Will have value
23 | * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this
24 | * context. */
25 | uint8_t bDescriptorType;
26 |
27 | /** USB specification release number in binary-coded decimal. A value of
28 | * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
29 | uint16_t bcdUSB;
30 |
31 | /** USB-IF class code for the device. See \ref libusb_class_code. */
32 | uint8_t bDeviceClass;
33 |
34 | /** USB-IF subclass code for the device, qualified by the bDeviceClass
35 | * value */
36 | uint8_t bDeviceSubClass;
37 |
38 | /** USB-IF protocol code for the device, qualified by the bDeviceClass and
39 | * bDeviceSubClass values */
40 | uint8_t bDeviceProtocol;
41 |
42 | /** Maximum packet size for endpoint 0 */
43 | uint8_t bMaxPacketSize0;
44 |
45 | /** USB-IF vendor ID */
46 | uint16_t idVendor;
47 |
48 | /** USB-IF product ID */
49 | uint16_t idProduct;
50 |
51 | /** Device release number in binary-coded decimal */
52 | uint16_t bcdDevice;
53 |
54 | /** Index of string descriptor describing manufacturer */
55 | uint8_t iManufacturer;
56 |
57 | /** Index of string descriptor describing product */
58 | uint8_t iProduct;
59 |
60 | /** Index of string descriptor containing device serial number */
61 | uint8_t iSerialNumber;
62 |
63 | /** Number of possible configurations */
64 | uint8_t bNumConfigurations;
65 | };
66 |
67 | /* structs that applications are not allowed to peek into */
68 | enum fp_dev_state {
69 | DEV_STATE_INITIAL = 0,
70 | DEV_STATE_ERROR,
71 | DEV_STATE_INITIALIZING,
72 | DEV_STATE_INITIALIZED,
73 | DEV_STATE_DEINITIALIZING,
74 | DEV_STATE_DEINITIALIZED,
75 | DEV_STATE_ENROLL_STARTING,
76 | DEV_STATE_ENROLLING,
77 | DEV_STATE_ENROLL_STOPPING,
78 | DEV_STATE_VERIFY_STARTING,
79 | DEV_STATE_VERIFYING,
80 | DEV_STATE_VERIFY_DONE,
81 | DEV_STATE_VERIFY_STOPPING,
82 | DEV_STATE_IDENTIFY_STARTING,
83 | DEV_STATE_IDENTIFYING,
84 | DEV_STATE_IDENTIFY_DONE,
85 | DEV_STATE_IDENTIFY_STOPPING,
86 | DEV_STATE_CAPTURE_STARTING,
87 | DEV_STATE_CAPTURING,
88 | DEV_STATE_CAPTURE_DONE,
89 | DEV_STATE_CAPTURE_STOPPING,
90 | };
91 |
92 | enum fp_driver_type {
93 | DRIVER_PRIMITIVE = 0,
94 | DRIVER_IMAGING = 1,
95 | };
96 |
97 | enum fp_print_data_type {
98 | PRINT_DATA_RAW = 0, /* memset-imposed default */
99 | PRINT_DATA_NBIS_MINUTIAE,
100 | };
101 |
102 |
103 | struct fp_dscv_dev {
104 | struct libusb_device *udev;
105 | struct fp_driver *drv;
106 | unsigned long driver_data;
107 | uint32_t devtype;
108 | };
109 | struct fp_dscv_print {
110 | uint16_t driver_id;
111 | uint32_t devtype;
112 | enum fp_finger finger;
113 | char *path;
114 | };
115 | struct fp_dev {
116 | struct fp_driver *drv;
117 | libusb_device_handle *udev;
118 | uint32_t devtype;
119 | void *priv;
120 |
121 | int nr_enroll_stages;
122 |
123 | /* read-only to drivers */
124 | struct fp_print_data *verify_data;
125 |
126 | /* drivers should not mess with any of the below */
127 | enum fp_dev_state state;
128 | int __enroll_stage;
129 | int unconditional_capture;
130 |
131 | /* async I/O callbacks and data */
132 | /* FIXME: convert this to generic state operational data mechanism? */
133 | fp_dev_open_cb open_cb;
134 | void *open_cb_data;
135 | fp_dev_close_cb close_cb;
136 | void *close_cb_data;
137 | fp_enroll_stage_cb enroll_stage_cb;
138 | void *enroll_stage_cb_data;
139 | fp_enroll_stop_cb enroll_stop_cb;
140 | void *enroll_stop_cb_data;
141 | fp_verify_cb verify_cb;
142 | void *verify_cb_data;
143 | fp_verify_stop_cb verify_stop_cb;
144 | void *verify_stop_cb_data;
145 | fp_identify_cb identify_cb;
146 | void *identify_cb_data;
147 | fp_identify_stop_cb identify_stop_cb;
148 | void *identify_stop_cb_data;
149 | fp_capture_cb capture_cb;
150 | void *capture_cb_data;
151 | fp_capture_stop_cb capture_stop_cb;
152 | void *capture_stop_cb_data;
153 |
154 | /* FIXME: better place to put this? */
155 | struct fp_print_data **identify_gallery;
156 | };
157 | struct fp_driver {
158 | const uint16_t id;
159 | const char *name;
160 | const char *full_name;
161 | const struct usb_id * const id_table;
162 | enum fp_driver_type type;
163 | enum fp_scan_type scan_type;
164 |
165 | void *priv;
166 |
167 | /* Device operations */
168 | int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype);
169 | int (*open)(struct fp_dev *dev, unsigned long driver_data);
170 | void (*close)(struct fp_dev *dev);
171 | int (*enroll_start)(struct fp_dev *dev);
172 | int (*enroll_stop)(struct fp_dev *dev);
173 | int (*verify_start)(struct fp_dev *dev);
174 | int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
175 | int (*identify_start)(struct fp_dev *dev);
176 | int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
177 | int (*capture_start)(struct fp_dev *dev);
178 | int (*capture_stop)(struct fp_dev *dev);
179 | };
180 | struct fp_print_data {
181 | uint16_t driver_id;
182 | uint32_t devtype;
183 | enum fp_print_data_type type;
184 | GSList *prints;
185 | };
186 | struct fp_img {
187 | int width;
188 | int height;
189 | size_t length;
190 | uint16_t flags;
191 | struct fp_minutiae *minutiae;
192 | unsigned char *binarized;
193 | unsigned char data[0];
194 | };
195 |
196 | /* misc/general stuff */
197 |
198 | /** \ingroup print_data
199 | * Numeric codes used to refer to fingers (and thumbs) of a human. These are
200 | * purposely not available as strings, to avoid getting the library tangled up
201 | * in localization efforts.
202 | */
203 | enum fp_finger {
204 | LEFT_THUMB = 1, /** thumb (left hand) */
205 | LEFT_INDEX, /** index finger (left hand) */
206 | LEFT_MIDDLE, /** middle finger (left hand) */
207 | LEFT_RING, /** ring finger (left hand) */
208 | LEFT_LITTLE, /** little finger (left hand) */
209 | RIGHT_THUMB, /** thumb (right hand) */
210 | RIGHT_INDEX, /** index finger (right hand) */
211 | RIGHT_MIDDLE, /** middle finger (right hand) */
212 | RIGHT_RING, /** ring finger (right hand) */
213 | RIGHT_LITTLE, /** little finger (right hand) */
214 | };
215 |
216 | /** \ingroup dev
217 | * Numeric codes used to refer to the scan type of the device. Devices require
218 | * either swiping or pressing the finger on the device. This is useful for
219 | * front-ends.
220 | */
221 | enum fp_scan_type {
222 | FP_SCAN_TYPE_PRESS = 0, /** press */
223 | FP_SCAN_TYPE_SWIPE, /** swipe */
224 | };
225 |
226 | /* Drivers */
227 | const char *fp_driver_get_name(struct fp_driver *drv);
228 | const char *fp_driver_get_full_name(struct fp_driver *drv);
229 | uint16_t fp_driver_get_driver_id(struct fp_driver *drv);
230 | enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv);
231 |
232 | /* Device discovery */
233 | struct fp_dscv_dev **fp_discover_devs(void);
234 | void fp_dscv_devs_free(struct fp_dscv_dev **devs);
235 | struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev);
236 | uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev);
237 | int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
238 | struct fp_print_data *print);
239 | int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
240 | struct fp_dscv_print *print);
241 | struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
242 | struct fp_print_data *print);
243 | struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs,
244 | struct fp_dscv_print *print);
245 |
246 | static inline uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev);
247 |
248 | /* Print discovery */
249 | struct fp_dscv_print **fp_discover_prints(void);
250 | void fp_dscv_prints_free(struct fp_dscv_print **prints);
251 | uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print);
252 | uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print);
253 | enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print);
254 | int fp_dscv_print_delete(struct fp_dscv_print *print);
255 |
256 | /* Device handling */
257 | struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev);
258 | void fp_dev_close(struct fp_dev *dev);
259 | struct fp_driver *fp_dev_get_driver(struct fp_dev *dev);
260 | int fp_dev_get_nr_enroll_stages(struct fp_dev *dev);
261 | uint32_t fp_dev_get_devtype(struct fp_dev *dev);
262 | int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data);
263 | int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print);
264 |
265 | /** \ingroup dev
266 | * Image capture result codes returned from fp_dev_img_capture().
267 | */
268 | enum fp_capture_result {
269 | /** Capture completed successfully, the capture data has been
270 | * returned to the caller. */
271 | FP_CAPTURE_COMPLETE = 0,
272 | /** Capture failed for some reason */
273 | FP_CAPTURE_FAIL,
274 | };
275 |
276 | int fp_dev_supports_imaging(struct fp_dev *dev);
277 | int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
278 | struct fp_img **image);
279 | int fp_dev_get_img_width(struct fp_dev *dev);
280 | int fp_dev_get_img_height(struct fp_dev *dev);
281 |
282 | /** \ingroup dev
283 | * Enrollment result codes returned from fp_enroll_finger().
284 | * Result codes with RETRY in the name suggest that the scan failed due to
285 | * user error. Applications will generally want to inform the user of the
286 | * problem and then retry the enrollment stage. For more info on the semantics
287 | * of interpreting these result codes and tracking enrollment process, see
288 | * \ref enrolling.
289 | */
290 | enum fp_enroll_result {
291 | /** Enrollment completed successfully, the enrollment data has been
292 | * returned to the caller. */
293 | FP_ENROLL_COMPLETE = 1,
294 | /** Enrollment failed due to incomprehensible data; this may occur when
295 | * the user scans a different finger on each enroll stage. */
296 | FP_ENROLL_FAIL,
297 | /** Enroll stage passed; more stages are need to complete the process. */
298 | FP_ENROLL_PASS,
299 | /** The enrollment scan did not succeed due to poor scan quality or
300 | * other general user scanning problem. */
301 | FP_ENROLL_RETRY = 100,
302 | /** The enrollment scan did not succeed because the finger swipe was
303 | * too short. */
304 | FP_ENROLL_RETRY_TOO_SHORT,
305 | /** The enrollment scan did not succeed because the finger was not
306 | * centered on the scanner. */
307 | FP_ENROLL_RETRY_CENTER_FINGER,
308 | /** The verification scan did not succeed due to quality or pressure
309 | * problems; the user should remove their finger from the scanner before
310 | * retrying. */
311 | FP_ENROLL_RETRY_REMOVE_FINGER,
312 | };
313 |
314 | int fp_enroll_finger_img(struct fp_dev *dev, struct fp_print_data **print_data,
315 | struct fp_img **img);
316 |
317 | /** \ingroup dev
318 | * Performs an enroll stage. See \ref enrolling for an explanation of enroll
319 | * stages. This function is just a shortcut to calling fp_enroll_finger_img()
320 | * with a NULL image parameter. Be sure to read the description of
321 | * fp_enroll_finger_img() in order to understand its behaviour.
322 | *
323 | * \param dev the device
324 | * \param print_data a location to return the resultant enrollment data from
325 | * the final stage. Must be freed with fp_print_data_free() after use.
326 | * \return negative code on error, otherwise a code from #fp_enroll_result
327 | */
328 | static inline int fp_enroll_finger(struct fp_dev *dev,
329 | struct fp_print_data **print_data);
330 |
331 | /** \ingroup dev
332 | * Verification result codes returned from fp_verify_finger(). Return codes
333 | * are also shared with fp_identify_finger().
334 | * Result codes with RETRY in the name suggest that the scan failed due to
335 | * user error. Applications will generally want to inform the user of the
336 | * problem and then retry the verify operation.
337 | */
338 | enum fp_verify_result {
339 | /** The scan completed successfully, but the newly scanned fingerprint
340 | * does not match the fingerprint being verified against.
341 | * In the case of identification, this return code indicates that the
342 | * scanned finger could not be found in the print gallery. */
343 | FP_VERIFY_NO_MATCH = 0,
344 | /** The scan completed successfully and the newly scanned fingerprint does
345 | * match the fingerprint being verified, or in the case of identification,
346 | * the scanned fingerprint was found in the print gallery. */
347 | FP_VERIFY_MATCH = 1,
348 | /** The scan did not succeed due to poor scan quality or other general
349 | * user scanning problem. */
350 | FP_VERIFY_RETRY = FP_ENROLL_RETRY,
351 | /** The scan did not succeed because the finger swipe was too short. */
352 | FP_VERIFY_RETRY_TOO_SHORT = FP_ENROLL_RETRY_TOO_SHORT,
353 | /** The scan did not succeed because the finger was not centered on the
354 | * scanner. */
355 | FP_VERIFY_RETRY_CENTER_FINGER = FP_ENROLL_RETRY_CENTER_FINGER,
356 | /** The scan did not succeed due to quality or pressure problems; the user
357 | * should remove their finger from the scanner before retrying. */
358 | FP_VERIFY_RETRY_REMOVE_FINGER = FP_ENROLL_RETRY_REMOVE_FINGER,
359 | };
360 |
361 | int fp_verify_finger_img(struct fp_dev *dev,
362 | struct fp_print_data *enrolled_print, struct fp_img **img);
363 |
364 | /** \ingroup dev
365 | * Performs a new scan and verify it against a previously enrolled print. This
366 | * function is just a shortcut to calling fp_verify_finger_img() with a NULL
367 | * image output parameter.
368 | * \param dev the device to perform the scan.
369 | * \param enrolled_print the print to verify against. Must have been previously
370 | * enrolled with a device compatible to the device selected to perform the scan.
371 | * \return negative code on error, otherwise a code from #fp_verify_result
372 | * \sa fp_verify_finger_img()
373 | */
374 | static inline int fp_verify_finger(struct fp_dev *dev,
375 | struct fp_print_data *enrolled_print);
376 |
377 | int fp_dev_supports_identification(struct fp_dev *dev);
378 | int fp_identify_finger_img(struct fp_dev *dev,
379 | struct fp_print_data **print_gallery, size_t *match_offset,
380 | struct fp_img **img);
381 |
382 | /** \ingroup dev
383 | * Performs a new scan and attempts to identify the scanned finger against a
384 | * collection of previously enrolled fingerprints. This function is just a
385 | * shortcut to calling fp_identify_finger_img() with a NULL image output
386 | * parameter.
387 | * \param dev the device to perform the scan.
388 | * \param print_gallery NULL-terminated array of pointers to the prints to
389 | * identify against. Each one must have been previously enrolled with a device
390 | * compatible to the device selected to perform the scan.
391 | * \param match_offset output location to store the array index of the matched
392 | * gallery print (if any was found). Only valid if FP_VERIFY_MATCH was
393 | * returned.
394 | * \return negative code on error, otherwise a code from #fp_verify_result
395 | * \sa fp_identify_finger_img()
396 | */
397 | static inline int fp_identify_finger(struct fp_dev *dev,
398 | struct fp_print_data **print_gallery, size_t *match_offset);
399 |
400 | /* Data handling */
401 | int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger,
402 | struct fp_print_data **data);
403 | int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
404 | struct fp_print_data **data);
405 | int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger);
406 | int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger);
407 | void fp_print_data_free(struct fp_print_data *data);
408 | size_t fp_print_data_get_data(struct fp_print_data *data, unsigned char **ret);
409 | struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
410 | size_t buflen);
411 | uint16_t fp_print_data_get_driver_id(struct fp_print_data *data);
412 | uint32_t fp_print_data_get_devtype(struct fp_print_data *data);
413 |
414 | /* Image handling */
415 |
416 | /** \ingroup img */
417 | struct fp_minutia {
418 | int x;
419 | int y;
420 | int ex;
421 | int ey;
422 | int direction;
423 | double reliability;
424 | int type;
425 | int appearing;
426 | int feature_id;
427 | int *nbrs;
428 | int *ridge_counts;
429 | int num_nbrs;
430 | };
431 |
432 | int fp_img_get_height(struct fp_img *img);
433 | int fp_img_get_width(struct fp_img *img);
434 | unsigned char *fp_img_get_data(struct fp_img *img);
435 | int fp_img_save_to_file(struct fp_img *img, char *path);
436 | void fp_img_standardize(struct fp_img *img);
437 | struct fp_img *fp_img_binarize(struct fp_img *img);
438 | struct fp_minutia **fp_img_get_minutiae(struct fp_img *img, int *nr_minutiae);
439 | void fp_img_free(struct fp_img *img);
440 |
441 | /* Polling and timing */
442 |
443 | struct fp_pollfd {
444 | int fd;
445 | short events;
446 | };
447 |
448 | int fp_handle_events_timeout(struct timeval *timeout);
449 | int fp_handle_events(void);
450 | size_t fp_get_pollfds(struct fp_pollfd **pollfds);
451 | int fp_get_next_timeout(struct timeval *tv);
452 |
453 | typedef void (*fp_pollfd_added_cb)(int fd, short events);
454 | typedef void (*fp_pollfd_removed_cb)(int fd);
455 | void fp_set_pollfd_notifiers(fp_pollfd_added_cb added_cb,
456 | fp_pollfd_removed_cb removed_cb);
457 |
458 | /* Library */
459 | int fp_init(void);
460 | void fp_exit(void);
461 | void fp_set_debug(int level);
462 |
463 | /* Asynchronous I/O */
464 |
465 | typedef void (*fp_dev_open_cb)(struct fp_dev *dev, int status, void *user_data);
466 | int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb callback,
467 | void *user_data);
468 |
469 | typedef void (*fp_dev_close_cb)(struct fp_dev *dev, void *user_data);
470 | void fp_async_dev_close(struct fp_dev *dev, fp_dev_close_cb callback,
471 | void *user_data);
472 |
473 | typedef void (*fp_enroll_stage_cb)(struct fp_dev *dev, int result,
474 | struct fp_print_data *print, struct fp_img *img, void *user_data);
475 | int fp_async_enroll_start(struct fp_dev *dev, fp_enroll_stage_cb callback,
476 | void *user_data);
477 |
478 | typedef void (*fp_enroll_stop_cb)(struct fp_dev *dev, void *user_data);
479 | int fp_async_enroll_stop(struct fp_dev *dev, fp_enroll_stop_cb callback,
480 | void *user_data);
481 |
482 | typedef void (*fp_verify_cb)(struct fp_dev *dev, int result,
483 | struct fp_img *img, void *user_data);
484 | int fp_async_verify_start(struct fp_dev *dev, struct fp_print_data *data,
485 | fp_verify_cb callback, void *user_data);
486 |
487 | typedef void (*fp_verify_stop_cb)(struct fp_dev *dev, void *user_data);
488 | int fp_async_verify_stop(struct fp_dev *dev, fp_verify_stop_cb callback,
489 | void *user_data);
490 |
491 | typedef void (*fp_identify_cb)(struct fp_dev *dev, int result,
492 | size_t match_offset, struct fp_img *img, void *user_data);
493 | int fp_async_identify_start(struct fp_dev *dev, struct fp_print_data **gallery,
494 | fp_identify_cb callback, void *user_data);
495 |
496 | typedef void (*fp_identify_stop_cb)(struct fp_dev *dev, void *user_data);
497 | int fp_async_identify_stop(struct fp_dev *dev, fp_identify_stop_cb callback,
498 | void *user_data);
499 |
500 | typedef void (*fp_capture_cb)(struct fp_dev *dev, int result,
501 | struct fp_img *img, void *user_data);
502 | int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_capture_cb callback, void *user_data);
503 |
504 | typedef void (*fp_capture_stop_cb)(struct fp_dev *dev, void *user_data);
505 | int fp_async_capture_stop(struct fp_dev *dev, fp_capture_stop_cb callback, void *user_data);
506 |
507 | #endif
508 |
509 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '1.0.{build}'
2 | image: Visual Studio 2019
3 | configuration:Release
4 | platform: Any CPU
5 | notifications:
6 | - provider: Slack
7 | auth_token:
8 | secure: Q+xg4/yU5OR9BVF14cw4yZ+3qlhMeYDsAhUQyOIszmF1mHvq44tIvQpWByBJCd/cgUIZk3SwBpk4hh1MrkQIk6rnaOZ2LNBTev4zrq36oXk=
9 | channel: '#builds'
10 | environment:
11 | op_build_user: "Geo Perez"
12 | op_build_user_email: "geovanni.perez@gmail.com"
13 | access_token:
14 | secure: HzWdswNyfQbQ0vLk9IQyO+Ei9mxoPYp9rvv6HPhtC9J/Fm7EHRzyV953pbPRXI9I
15 | before_build:
16 | - ps: |
17 | if(-Not $env:APPVEYOR_PULL_REQUEST_TITLE -And $isWindows)
18 | {
19 | git checkout $env:APPVEYOR_REPO_BRANCH -q
20 | cinst docfx -y
21 | }
22 | after_build:
23 | - ps: |
24 | if(-Not $env:APPVEYOR_PULL_REQUEST_TITLE -And $isWindows)
25 | {
26 | docfx docfx.json
27 | git config --global credential.helper store
28 | Add-Content "$env:USERPROFILE\.git-credentials" "https://$($env:access_token):x-oauth-basic@github.com`n"
29 | git config --global core.autocrlf false
30 | git config --global user.email $env:op_build_user_email
31 | git config --global user.name $env:op_build_user
32 |
33 | git clone https://github.com/unosquare/libfprint-cs.git -b gh-pages origin_site -q
34 | git clone -b documentation https://github.com/unosquare/best-practices.git -q
35 | docfx docfx.json --logLevel Error
36 | Copy-Item origin_site/.git _site -recurse
37 | CD _site
38 | Copy-Item README.html index.html -force
39 | git add -A 2>&1
40 | git commit -m "Documentation update" -q
41 | git push origin gh-pages -q
42 | CD ..
43 | }
44 |
--------------------------------------------------------------------------------
/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": [
3 | {
4 | "src": [
5 | {
6 | "files": [ "Unosquare.Labs.LibFprint/**/*.cs" ],
7 | "exclude": [ "**/bin/**", "**/obj/**" ]
8 | }
9 | ],
10 | "dest": "obj/api"
11 | }
12 | ],
13 | "build": {
14 | "template": [
15 | "best-practices/templates/default"
16 | ],
17 | "content": [
18 | {
19 | "files": [ "**/*.yml" ],
20 | "cwd": "obj/api",
21 | "dest": "api"
22 | },
23 | {
24 | "files": [ "*.md", "toc.yml" ]
25 | }
26 | ],
27 | "resource": [
28 | {
29 | "files": [ "best-practices/resources/**" ]
30 | }
31 | ],
32 | "globalMetadata": {
33 | "_appTitle": "libfprint-cs",
34 | "_enableSearch": true,
35 | "_appLogoPath": "best-practices/resources/images/logo.png",
36 | "_docLogo": "best-practices/resources/images/transparent.gif"
37 | },
38 | "dest": "_site"
39 | }
40 | }
--------------------------------------------------------------------------------
/toc.yml:
--------------------------------------------------------------------------------
1 | - name: API Documentation
2 | href: obj/api/
--------------------------------------------------------------------------------