Compare commits

..

1 Commits

Author SHA1 Message Date
Benjamin Berg
cb56ddba5b virtual-image: Open window for race during deactivation
This is in order to test corner cases in fprintd.
2020-10-01 14:16:22 +02:00
111 changed files with 1725 additions and 18585 deletions

View File

@@ -1,10 +0,0 @@
# The commits that did automated reformatting. You can ignore them
# during git-blame with `--ignore-rev` or `--ignore-revs-file`.
#
# $ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
#
d1fb1e26f3b79e54febc94496c1184763cf2af3d
e4f9935706be4c0e3253afe251c182019ff7ccef
65e602d8c72baa7020efb62d10bf28e621feb05d
4115ae7ced77d392ee11ea55212206d9404356f0

View File

@@ -63,7 +63,7 @@ test:
script:
- meson --werror -Ddrivers=all -Db_coverage=true . _build
- ninja -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
- ninja -C _build coverage
- cat _build/meson-logs/coverage.txt
artifacts:
@@ -80,7 +80,7 @@ test_valgrind:
script:
- meson -Ddrivers=all . _build
- ninja -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
- meson test -C _build --verbose --no-stdsplit --setup=valgrind
test_scan_build:
stage: test
@@ -109,15 +109,6 @@ test_indent:
- git diff
- "! git status -s | grep -q ."
test_unsupported_list:
stage: check-source
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
allow_failure: true
script:
- tests/hwdb-check-unsupported.py
flatpak:
stage: flatpak
extends: .flatpak

59
NEWS
View File

@@ -1,65 +1,6 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2020-12-01: v1.90.7 release
Highlights:
* vfs5011: Fix possible use-after-free
* goodixmoc: Add two new PIDs (0x63AC, 0x639C)
* goodixmoc: Support finger status API
* synaptics: Only identify within provided prints
* synaptics: Reject devices with old firmware during probe (#239)
2020-12-01: v1.90.6 release
This release is primarily a bugfix release for some older issues.
The major change is that fp_print_deserialize will now correctly return a
sunken reference rather than a floating one. Most API users will have
assumed this was true, and issues could happen at a later point.
If any API user worked around this libfprint bug, they will now leak the
returned print.
Highlights:
* Object reference management fixes for FpPrint and identify
* Fixed issues that caused problem on non-x86 machines (#236)
* Fix building with older GLib versions
* synaptics: Support PID 00e7
* goodix: Fix issue with long USB packages
2020-12-01: v1.90.5 release
The 1.90.4 release caused a major regression, as it included a USB hub in
UDEV the autosupend rule list.
Highlights:
* Remove USB hub from udev autosupend rules
* synaptics: Add PID 0x00c9 which is used in some HP laptops
2020-11-27: v1.90.4 release
This release contains a number of important bugfixes. On the feature side,
the USB hotplug support was improved. A lot of drivers received fixes and
improvements.
Highlights:
* Work around GUsb cancellation issue
* Redefine internal image device state machine for more robustness
* Add public finger-status reporting to FpDevice
* Rework device removal API to be convenient (#330)
* Enable powersave for unsupported USB devices
* Improvements to examples
* synaptics: Support identify operation
* synaptics: Fix possible crash when the interrupt transfer is resubmitted
* synaptics: Add support for PIDs 0x00f9, 0x00fc and 0x00c2
* elan: Add PID 0x0c4d to supported device list
* aes3k: Fix driver and add CI test (#306)
* uru4000: Fix reference counting of image transfer
* vfs301: Fix driver and add CI test (#320)
2020-06-08: v1.90.3 release
This release mostly contains support for a number of new match-on-chip

View File

@@ -1,277 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# This file has been generated using fprint-list-udev-hwdb with all drivers enabled
# Supported by libfprint driver aes1610
usb:v08FFp1600*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes1660
usb:v08FFp1660*
usb:v08FFp1680*
usb:v08FFp1681*
usb:v08FFp1682*
usb:v08FFp1683*
usb:v08FFp1684*
usb:v08FFp1685*
usb:v08FFp1686*
usb:v08FFp1687*
usb:v08FFp1688*
usb:v08FFp1689*
usb:v08FFp168A*
usb:v08FFp168B*
usb:v08FFp168C*
usb:v08FFp168D*
usb:v08FFp168E*
usb:v08FFp168F*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes2501
usb:v08FFp2500*
usb:v08FFp2580*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes2550
usb:v08FFp2550*
usb:v08FFp2810*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes2660
usb:v08FFp2660*
usb:v08FFp2680*
usb:v08FFp2681*
usb:v08FFp2682*
usb:v08FFp2683*
usb:v08FFp2684*
usb:v08FFp2685*
usb:v08FFp2686*
usb:v08FFp2687*
usb:v08FFp2688*
usb:v08FFp2689*
usb:v08FFp268A*
usb:v08FFp268B*
usb:v08FFp268C*
usb:v08FFp268D*
usb:v08FFp268E*
usb:v08FFp268F*
usb:v08FFp2691*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes3500
usb:v08FFp5731*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes4000
usb:v5501p08FF*
ID_AUTOSUSPEND=1
# Supported by libfprint driver elan
usb:v04F3p0903*
usb:v04F3p0907*
usb:v04F3p0C01*
usb:v04F3p0C02*
usb:v04F3p0C03*
usb:v04F3p0C04*
usb:v04F3p0C05*
usb:v04F3p0C06*
usb:v04F3p0C07*
usb:v04F3p0C08*
usb:v04F3p0C09*
usb:v04F3p0C0A*
usb:v04F3p0C0B*
usb:v04F3p0C0C*
usb:v04F3p0C0D*
usb:v04F3p0C0E*
usb:v04F3p0C0F*
usb:v04F3p0C10*
usb:v04F3p0C11*
usb:v04F3p0C12*
usb:v04F3p0C13*
usb:v04F3p0C14*
usb:v04F3p0C15*
usb:v04F3p0C16*
usb:v04F3p0C17*
usb:v04F3p0C18*
usb:v04F3p0C19*
usb:v04F3p0C1A*
usb:v04F3p0C1B*
usb:v04F3p0C1C*
usb:v04F3p0C1D*
usb:v04F3p0C1E*
usb:v04F3p0C1F*
usb:v04F3p0C20*
usb:v04F3p0C21*
usb:v04F3p0C22*
usb:v04F3p0C23*
usb:v04F3p0C24*
usb:v04F3p0C25*
usb:v04F3p0C26*
usb:v04F3p0C27*
usb:v04F3p0C28*
usb:v04F3p0C29*
usb:v04F3p0C2A*
usb:v04F3p0C2B*
usb:v04F3p0C2C*
usb:v04F3p0C2D*
usb:v04F3p0C2E*
usb:v04F3p0C2F*
usb:v04F3p0C30*
usb:v04F3p0C31*
usb:v04F3p0C32*
usb:v04F3p0C33*
usb:v04F3p0C42*
usb:v04F3p0C4D*
ID_AUTOSUSPEND=1
# Supported by libfprint driver etes603
usb:v1C7Ap0603*
ID_AUTOSUSPEND=1
# Supported by libfprint driver goodixmoc
usb:v27C6p5840*
usb:v27C6p6496*
usb:v27C6p60A2*
usb:v27C6p63AC*
usb:v27C6p639C*
usb:v27C6p6594*
ID_AUTOSUSPEND=1
# Supported by libfprint driver nb1010
usb:v298Dp1010*
ID_AUTOSUSPEND=1
# Supported by libfprint driver synaptics
usb:v06CBp00BD*
usb:v06CBp00E9*
usb:v06CBp00DF*
usb:v06CBp00F9*
usb:v06CBp00FC*
usb:v06CBp00C2*
usb:v06CBp00C9*
usb:v06CBp0100*
ID_AUTOSUSPEND=1
# Supported by libfprint driver upeksonly
usb:v147Ep2016*
usb:v147Ep1000*
usb:v147Ep1001*
ID_AUTOSUSPEND=1
# Supported by libfprint driver upektc
usb:v0483p2015*
usb:v147Ep3001*
ID_AUTOSUSPEND=1
# Supported by libfprint driver upektc_img
usb:v147Ep2020*
ID_AUTOSUSPEND=1
# Supported by libfprint driver uru4000
usb:v045Ep00BC*
usb:v045Ep00BD*
usb:v045Ep00CA*
usb:v05BAp0007*
usb:v05BAp0008*
usb:v05BAp000A*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vcom5s
usb:v061Ap0110*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vfs0050
usb:v138Ap0050*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vfs101
usb:v138Ap0001*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vfs301
usb:v138Ap0005*
usb:v138Ap0008*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vfs5011
usb:v138Ap0010*
usb:v138Ap0011*
usb:v138Ap0015*
usb:v138Ap0017*
usb:v138Ap0018*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vfs7552
usb:v138Ap0091*
ID_AUTOSUSPEND=1
# Known unsupported devices
usb:v04F3p036B*
usb:v04F3p0C00*
usb:v04F3p0C4B*
usb:v04F3p0C4C*
usb:v04F3p0C4F*
usb:v04F3p0C57*
usb:v04F3p0C5E*
usb:v04F3p2706*
usb:v06CBp0081*
usb:v06CBp0088*
usb:v06CBp008A*
usb:v06CBp009A*
usb:v06CBp009B*
usb:v06CBp00A2*
usb:v06CBp00B7*
usb:v06CBp00BB*
usb:v06CBp00BE*
usb:v06CBp00C4*
usb:v06CBp00CB*
usb:v06CBp00D8*
usb:v06CBp00DA*
usb:v0A5Cp5801*
usb:v0A5Cp5805*
usb:v0A5Cp5834*
usb:v0A5Cp5840*
usb:v0A5Cp5841*
usb:v0A5Cp5842*
usb:v0A5Cp5843*
usb:v0A5Cp5845*
usb:v10A5p0007*
usb:v1188p9545*
usb:v138Ap0007*
usb:v138Ap003A*
usb:v138Ap003C*
usb:v138Ap003D*
usb:v138Ap003F*
usb:v138Ap0090*
usb:v138Ap0092*
usb:v138Ap0094*
usb:v138Ap0097*
usb:v138Ap009D*
usb:v138Ap00AB*
usb:v147Ep1002*
usb:v1491p0088*
usb:v16D1p1027*
usb:v1C7Ap0300*
usb:v1C7Ap0570*
usb:v1C7Ap0575*
usb:v27C6p5042*
usb:v27C6p5110*
usb:v27C6p5117*
usb:v27C6p5201*
usb:v27C6p521D*
usb:v27C6p5301*
usb:v27C6p530C*
usb:v27C6p532D*
usb:v27C6p533C*
usb:v27C6p5381*
usb:v27C6p5385*
usb:v27C6p538C*
usb:v27C6p538D*
usb:v27C6p5395*
usb:v27C6p5584*
usb:v27C6p55A2*
usb:v27C6p55A4*
usb:v27C6p55B4*
usb:v27C6p5740*
usb:v2808p9338*
usb:v298Dp2033*
usb:v3538p0930*
ID_AUTOSUSPEND=1

View File

@@ -1,11 +0,0 @@
if udev_hwdb_dir != ''
# This file has to be updated using
# ninja -C <builddir> libfprint/sync-udev-hwdb
# Note that the unsupported device list needs to be manually synced from
# the wiki. See comment in libfprint/fprint-list-uev-hwdb.c
install_data('autosuspend.hwdb',
rename: '60-autosuspend-@0@.hwdb'.format(versioned_libname),
install_dir: udev_hwdb_dir,
)
endif

View File

@@ -50,7 +50,7 @@
{
"name": "libfprint",
"buildsystem": "meson",
"config-opts": [ "-Dudev_hwdb=disabled", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
"config-opts": [ "-Dudev_rules=false", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
"sources": [
{
"type": "git",

View File

@@ -32,11 +32,9 @@ fp_device_get_device_id
fp_device_get_name
fp_device_get_scan_type
fp_device_get_nr_enroll_stages
fp_device_get_finger_status
fp_device_has_storage
fp_device_supports_identify
fp_device_supports_capture
fp_device_is_open
fp_device_open
fp_device_close
fp_device_enroll
@@ -93,6 +91,8 @@ FP_TYPE_PRINT
FpFinger
FpPrint
fp_print_new
fp_print_new_from_data
fp_print_to_data
fp_print_get_driver
fp_print_get_device_id
fp_print_get_device_stored
@@ -131,11 +131,8 @@ fpi_get_driver_types
FpDeviceClass
FpTimeoutFunc
FpiDeviceAction
FpiDeviceFeature
FpIdEntry
FpiDeviceUdevSubtypeFlags
fpi_device_get_usb_device
fpi_device_get_udev_data
fpi_device_get_virtual_env
fpi_device_get_current_action
fpi_device_retry_new
@@ -153,9 +150,6 @@ fpi_device_action_is_cancelled
fpi_device_add_timeout
fpi_device_set_nr_enroll_stages
fpi_device_set_scan_type
fpi_device_remove
fpi_device_report_finger_status
fpi_device_report_finger_status_changes
fpi_device_action_error
fpi_device_probe_complete
fpi_device_open_complete
@@ -168,8 +162,6 @@ fpi_device_delete_complete
fpi_device_enroll_progress
fpi_device_verify_report
fpi_device_identify_report
fpi_device_list_complete
fpi_device_class_auto_initialize_features
</SECTION>
<SECTION>
@@ -194,7 +186,6 @@ fpi_image_device_deactivate_complete
fpi_image_device_report_finger_status
fpi_image_device_image_captured
fpi_image_device_retry_scan
fpi_image_device_set_bz3_threshold
</SECTION>
<SECTION>
@@ -238,10 +229,10 @@ fpi_ssm_mark_completed
fpi_ssm_mark_failed
fpi_ssm_set_data
fpi_ssm_get_data
fpi_ssm_get_device
fpi_ssm_get_error
fpi_ssm_dup_error
fpi_ssm_get_cur_state
fpi_ssm_next_state_timeout_cb
fpi_ssm_usb_transfer_cb
FpiSsm
</SECTION>

View File

@@ -1,8 +0,0 @@
#include <libfprint-2/fprint.h>
#include <libfprint-2/fp-image-device.h>
fp_context_get_type
fp_device_get_type
fp_image_device_get_type
fp_image_get_type
fp_print_get_type

View File

@@ -30,7 +30,6 @@ gnome.gtkdoc(versioned_libname,
content_files: content_files,
expand_content_files: expand_content_files,
ignore_headers: private_headers,
gobject_typesfile: 'libfprint-2.types',
fixxref_args: [
'--html-dir=@0@'.format(docpath),
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),

View File

@@ -76,19 +76,15 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
enroll_data->ret_value = EXIT_SUCCESS;
if (fp_device_has_storage (dev))
g_debug ("Device has storage, saving a print reference locally");
else
g_debug ("Device has not storage, saving print only locally");
/* Even if the device has storage, it may not be able to save all the
* metadata that the print contains, so we can always save a local copy
* containing the handle to the device print */
int r = print_data_save (print, enroll_data->finger);
if (r < 0)
if (!fp_device_has_storage (dev))
{
g_warning ("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
g_debug ("Device has not storage, saving locally");
int r = print_data_save (print, enroll_data->finger);
if (r < 0)
{
g_warning ("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
}
}
}
else

View File

@@ -1,319 +0,0 @@
/*
* Example fingerprint verification program, which verifies the
* finger which has been previously enrolled to disk.
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "example-identify"
#include <stdio.h>
#include <libfprint/fprint.h>
#include <glib-unix.h>
#include "storage.h"
#include "utilities.h"
typedef struct _IdentifyData
{
GMainLoop *loop;
GCancellable *cancellable;
unsigned int sigint_handler;
int ret_value;
} IdentifyData;
static void
identify_data_free (IdentifyData *identify_data)
{
g_clear_handle_id (&identify_data->sigint_handler, g_source_remove);
g_clear_object (&identify_data->cancellable);
g_main_loop_unref (identify_data->loop);
g_free (identify_data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdentifyData, identify_data_free)
static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(GError) error = NULL;
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (identify_data->loop);
}
static void
identify_quit (FpDevice *dev,
IdentifyData *identify_data)
{
if (!fp_device_is_open (dev))
{
g_main_loop_quit (identify_data->loop);
return;
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, identify_data);
}
static void start_identification (FpDevice *dev,
IdentifyData *identify_data);
static void
on_identify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) match = NULL;
g_autoptr(GError) error = NULL;
char buffer[20];
if (!fp_device_identify_finish (dev, res, &match, &print, &error))
{
g_warning ("Failed to identify print: %s", error->message);
identify_data->ret_value = EXIT_FAILURE;
if (error->domain != FP_DEVICE_RETRY)
{
identify_quit (dev, identify_data);
return;
}
}
g_print ("Identify again? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y' || buffer[0] == '\n'))
{
start_identification (dev, identify_data);
return;
}
identify_quit (dev, identify_data);
}
static FpPrint *
get_stored_print (FpDevice *dev, FpPrint *print)
{
g_autoptr(GPtrArray) gallery = gallery_data_load (dev);
guint index;
if (g_ptr_array_find_with_equal_func (gallery, print,
(GEqualFunc) fp_print_equal,
&index))
return g_object_ref (g_ptr_array_index (gallery, index));
return NULL;
}
static void
on_identify_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
gpointer user_data, GError *error)
{
IdentifyData *identify_data = user_data;
if (error)
{
g_warning ("Identify report: No finger matched, retry error reported: %s",
error->message);
return;
}
if (print && fp_print_get_image (print) &&
print_image_save (print, "identify.pgm"))
g_print ("Print image saved as identify.pgm\n");
if (match)
{
g_autoptr(FpPrint) matched_print = g_object_ref (match);
char date_str[128] = {};
identify_data->ret_value = EXIT_SUCCESS;
if (fp_print_get_device_stored (match))
{
FpPrint *stored_print = get_stored_print (dev, match);
if (stored_print)
matched_print = g_steal_pointer (&stored_print);
}
if (fp_print_get_enroll_date (matched_print))
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
fp_print_get_enroll_date (matched_print));
else
strcpy (date_str, "<unknown>");
g_debug ("Identify report: device %s matched finger %s successfully "
"with print '%s', enrolled on date %s by user %s",
fp_device_get_name (dev),
finger_to_string (fp_print_get_finger (matched_print)),
fp_print_get_description (matched_print), date_str,
fp_print_get_username (matched_print));
g_print ("IDENTIFIED!\n");
}
else
{
g_debug ("Identification report: No finger matched");
g_print ("NOT IDENTIFIED!\n");
}
}
static void
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(GPtrArray) gallery = NULL;
g_autoptr(GError) error = NULL;
gallery = fp_device_list_prints_finish (dev, res, &error);
if (!error)
{
if (!gallery->len)
{
g_warning ("No prints saved on device");
identify_quit (dev, identify_data);
return;
}
g_debug ("Identifying with %u prints in gallery", gallery->len);
fp_device_identify (dev, gallery, identify_data->cancellable,
on_identify_cb, identify_data, NULL,
(GAsyncReadyCallback) on_identify_completed,
identify_data);
}
else
{
g_warning ("Loading prints failed with error %s", error->message);
identify_quit (dev, identify_data);
}
}
static void
start_identification (FpDevice *dev, IdentifyData *identify_data)
{
if (fp_device_has_storage (dev))
{
g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL,
(GAsyncReadyCallback) on_list_completed,
identify_data);
}
else
{
g_autoptr(GPtrArray) gallery = gallery_data_load (dev);
if (!gallery)
{
identify_quit (dev, identify_data);
return;
}
g_print ("Gallery loaded. Time to identify!\n");
fp_device_identify (dev, gallery, identify_data->cancellable,
on_identify_cb, identify_data, NULL,
(GAsyncReadyCallback) on_identify_completed,
identify_data);
}
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(GError) error = NULL;
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
identify_quit (dev, identify_data);
return;
}
g_print ("Opened device. ");
start_identification (dev, identify_data);
}
static gboolean
sigint_cb (void *user_data)
{
IdentifyData *identify_data = user_data;
g_cancellable_cancel (identify_data->cancellable);
return G_SOURCE_CONTINUE;
}
int
main (void)
{
g_autoptr(FpContext) ctx = NULL;
g_autoptr(IdentifyData) identify_data = NULL;
GPtrArray *devices;
FpDevice *dev;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
ctx = fp_context_new ();
devices = fp_context_get_devices (ctx);
if (!devices)
{
g_warning ("Impossible to get devices");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev)
{
g_warning ("No devices detected.");
return EXIT_FAILURE;
}
if (!fp_device_supports_identify (dev))
{
g_warning ("Device %s does not support identification.",
fp_device_get_name (dev));
return EXIT_FAILURE;
}
identify_data = g_new0 (IdentifyData, 1);
identify_data->ret_value = EXIT_FAILURE;
identify_data->loop = g_main_loop_new (NULL, FALSE);
identify_data->cancellable = g_cancellable_new ();
identify_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
SIGINT,
sigint_cb,
identify_data,
NULL);
fp_device_open (dev, identify_data->cancellable,
(GAsyncReadyCallback) on_device_opened,
identify_data);
g_main_loop_run (identify_data->loop);
return identify_data->ret_value;
}

View File

@@ -1,12 +1,5 @@
examples = [
'enroll',
'identify',
'img-capture',
'manage-prints',
'verify',
]
examples = [ 'enroll', 'verify', 'manage-prints', 'img-capture' ]
foreach example: examples
executable(example,
[ example + '.c', 'storage.c', 'utilities.c' ],

View File

@@ -2,7 +2,7 @@
* Trivial storage driver for example programs
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019-2020 Marco Trevisan <marco.trevisan@canonical.com>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -160,52 +160,6 @@ print_data_load (FpDevice *dev, FpFinger finger)
return NULL;
}
GPtrArray *
gallery_data_load (FpDevice *dev)
{
g_autoptr(GVariantDict) dict = NULL;
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *gallery;
const char *driver;
const char *dev_id;
GVariantIter iter;
GVariant *value;
gchar *key;
gallery = g_ptr_array_new_with_free_func (g_object_unref);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
dev_prefix = g_strdup_printf ("%s/%s/", driver, dev_id);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
{
FpPrint *print;
const guchar *stored_data;
g_autoptr(GError) error = NULL;
gsize stored_len;
if (!g_str_has_prefix (key, dev_prefix))
continue;
stored_data = (const guchar *) g_variant_get_fixed_array (value, &stored_len, 1);
print = fp_print_deserialize (stored_data, stored_len, &error);
if (error)
{
g_warning ("Error deserializing data: %s", error->message);
continue;
}
g_ptr_array_add (gallery, print);
}
return gallery;
}
FpPrint *
print_create_template (FpDevice *dev, FpFinger finger)
{

View File

@@ -24,7 +24,6 @@ int print_data_save (FpPrint *print,
FpFinger finger);
FpPrint * print_data_load (FpDevice *dev,
FpFinger finger);
GPtrArray * gallery_data_load (FpDevice *dev);
FpPrint * print_create_template (FpDevice *dev,
FpFinger finger);
gboolean print_image_save (FpPrint *print,

View File

@@ -152,26 +152,6 @@ on_match_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
}
}
static FpPrint *
get_stored_print (FpDevice *dev, VerifyData *verify_data)
{
FpPrint *verify_print;
g_print ("Loading previously enrolled %s finger data...\n",
finger_to_string (verify_data->finger));
verify_print = print_data_load (dev, verify_data->finger);
if (!verify_print)
{
g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger));
}
return verify_print;
}
static void
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{
@@ -185,27 +165,15 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
if (!error)
{
FpPrint *verify_print = NULL;
g_autoptr(FpPrint) stored_print = NULL;
guint i;
if (!prints->len)
{
g_warning ("No prints saved on device");
verify_quit (dev, verify_data);
return;
}
stored_print = get_stored_print (dev, verify_data);
g_warning ("No prints saved on device");
for (i = 0; i < prints->len; ++i)
{
FpPrint *print = prints->pdata[i];
if (stored_print && fp_print_equal (stored_print, print))
/* If the private print data matches, let's use the stored print
* as it contains more metadata to show */
print = stored_print;
if (fp_print_get_finger (print) == verify_data->finger &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
{
@@ -223,6 +191,8 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
if (!verify_print)
{
g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger));
verify_quit (dev, verify_data);
return;
}
@@ -269,10 +239,17 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
}
else
{
g_autoptr(FpPrint) verify_print = get_stored_print (dev, verify_data);
g_print ("Loading previously enrolled %s finger data...\n",
finger_to_string (verify_data->finger));
g_autoptr(FpPrint) verify_print = NULL;
verify_print = print_data_load (dev, verify_data->finger);
if (!verify_print)
{
g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger));
verify_quit (dev, verify_data);
return;
}

View File

@@ -135,8 +135,10 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
size_t bytes)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
unsigned char *data;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
data = g_malloc (bytes);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, g_free);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,

View File

@@ -22,8 +22,6 @@
#define AES1660_FRAME_SIZE 0x244
/* *INDENT-OFF* */
/* First init sequence, 0x07 cmd returns following before INIT1:
* { 0x07, 0x05, 0x00, 0x8f, 0x16, 0x25, 0x01, 0x00 }
*/

View File

@@ -21,8 +21,6 @@
#define AES2660_FRAME_SIZE 0x354
/* *INDENT-OFF* */
/* First init sequence, 0x07 cmd returns following before INIT1:
* { 0x07, 0x05, 0x00, 0x91, 0x26, 0x21, 0x00, 0x00 }
*/

View File

@@ -106,9 +106,7 @@ static struct aes_regwrite init_reqs[] = {
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
};
static struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
@@ -157,6 +155,4 @@ fpi_device_aes3500_class_init (FpiDeviceAes3500Class *klass)
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
aes_class->capture_reqs = capture_reqs;
aes_class->capture_reqs_len = G_N_ELEMENTS (capture_reqs);
}

View File

@@ -42,10 +42,7 @@
typedef struct
{
/* This is used both as a flag that we are in a capture operation
* and for cancellation.
*/
GCancellable *img_capture_cancel;
GCancellable *img_trf_cancel;
} FpiDeviceAes3kPrivate;
#define CTRL_TIMEOUT 1000
@@ -86,9 +83,6 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
FpImage *img;
int i;
/* Image capture operation is finished (error/completed) */
g_clear_object (&priv->img_capture_cancel);
if (error)
{
if (g_error_matches (error,
@@ -97,11 +91,13 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
{
/* Cancellation implies we are deactivating. */
g_error_free (error);
g_clear_object (&priv->img_trf_cancel);
fpi_image_device_deactivate_complete (dev, NULL);
return;
}
fpi_image_device_session_error (dev, error);
g_clear_object (&priv->img_trf_cancel);
return;
}
@@ -126,10 +122,11 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_image_captured (dev, img);
/* FIXME: rather than assuming finger has gone, we should poll regs until
* it really has. */
* it really has, then restart the capture */
fpi_image_device_report_finger_status (dev, FALSE);
/* Note: The transfer is re-started when we switch to the AWAIT_FINGER_ON state. */
/* Note: We always restart the transfer, it may already be cancelled though. */
do_capture (dev);
}
static void
@@ -144,51 +141,31 @@ do_capture (FpImageDevice *dev)
fpi_usb_transfer_fill_bulk (img_trf, EP_IN, cls->data_buflen);
img_trf->short_is_error = TRUE;
fpi_usb_transfer_submit (g_steal_pointer (&img_trf), 0,
priv->img_capture_cancel,
priv->img_trf_cancel,
img_cb, NULL);
}
static void
capture_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
if (result)
{
g_clear_object (&priv->img_capture_cancel);
fpi_image_device_session_error (dev, result);
return;
}
/* FIXME: we never cancel a pending capture. So we are likely leaving the
* hardware in a bad state should we abort the capture operation and the
* user does not touch the device.
* But, we don't know how we might cancel, so just leave it as is. */
do_capture (dev);
}
static void
do_capture_start (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
aes_write_regv (dev, cls->capture_reqs, cls->capture_reqs_len, capture_reqs_cb, NULL);
}
static void
init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (FPI_DEVICE_AES3K (dev));
fpi_image_device_activate_complete (dev, result);
if (!result)
{
priv->img_trf_cancel = g_cancellable_new ();
do_capture (dev);
}
}
static void
aes3k_dev_activate (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
g_assert (!priv->img_trf_cancel);
aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
}
@@ -198,28 +175,13 @@ aes3k_dev_deactivate (FpImageDevice *dev)
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
/* If a capture is running, then deactivation finishes from the cancellation handler */
if (priv->img_capture_cancel)
g_cancellable_cancel (priv->img_capture_cancel);
/* Deactivation finishes from the cancellation handler */
if (priv->img_trf_cancel)
g_cancellable_cancel (priv->img_trf_cancel);
else
fpi_image_device_deactivate_complete (dev, NULL);
}
static void
aes3k_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
g_assert (!priv->img_capture_cancel);
priv->img_capture_cancel = g_cancellable_new ();
do_capture_start (dev);
}
}
static void
fpi_device_aes3k_init (FpiDeviceAes3k *self)
{
@@ -262,7 +224,6 @@ fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass)
img_class->img_open = aes3k_dev_init;
img_class->img_close = aes3k_dev_deinit;
img_class->activate = aes3k_dev_activate;
img_class->change_state = aes3k_dev_change_state;
img_class->deactivate = aes3k_dev_deactivate;
/* Extremely low due to low image quality. */

View File

@@ -57,6 +57,4 @@ struct _FpiDeviceAes3kClass
gsize data_buflen; /* buffer length of usb bulk transfer */
struct aes_regwrite *init_reqs; /* initial values sent to device */
gsize init_reqs_len;
struct aes_regwrite *capture_reqs; /* capture values sent to device */
gsize capture_reqs_len;
};

View File

@@ -103,9 +103,7 @@ static struct aes_regwrite init_reqs[] = {
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
};
static struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
@@ -154,6 +152,4 @@ fpi_device_aes4000_class_init (FpiDeviceAes4000Class *klass)
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
aes_class->capture_reqs = capture_reqs;
aes_class->capture_reqs_len = G_N_ELEMENTS (capture_reqs);
}

View File

@@ -54,7 +54,6 @@ static void complete_deactivation (FpImageDevice *dev);
#define CALIBRATE_DATA_LEN 4
#define FINGER_DET_DATA_LEN 4
FP_GNUC_ACCESS (read_only, 3, 4)
static void
aesX660_send_cmd_timeout (FpiSsm *ssm,
FpDevice *_dev,
@@ -71,7 +70,6 @@ aesX660_send_cmd_timeout (FpiSsm *ssm,
fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
}
FP_GNUC_ACCESS (read_only, 3, 4)
static void
aesX660_send_cmd (FpiSsm *ssm,
FpDevice *dev,
@@ -91,12 +89,13 @@ aesX660_read_response (FpiSsm *ssm,
FpiUsbTransferCallback callback)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
unsigned char *data;
GCancellable *cancel = NULL;
if (cancellable)
cancel = fpi_device_get_cancellable (_dev);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, buf_len);
data = g_malloc (buf_len);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, buf_len, NULL);
transfer->ssm = ssm;
transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);

View File

@@ -73,19 +73,22 @@ struct _FpiDeviceElan
/* end commands */
/* state */
gboolean active;
gboolean deactivating;
unsigned char *last_read;
unsigned char calib_atts_left;
unsigned char calib_status;
unsigned short *background;
unsigned char frame_width;
unsigned char frame_height;
unsigned char raw_frame_height;
int num_frames;
GSList *frames;
gboolean deactivating;
FpiImageDeviceState dev_state;
FpiImageDeviceState dev_state_next;
unsigned char *last_read;
unsigned char calib_atts_left;
unsigned char calib_status;
unsigned short *background;
unsigned char frame_width;
unsigned char frame_height;
unsigned char raw_frame_height;
int num_frames;
GSList *frames;
/* end state */
};
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
FpImageDevice);
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
static int
@@ -484,7 +487,7 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
/* The device is inactive at this point. */
self->active = FALSE;
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
if (self->deactivating)
{
@@ -502,14 +505,16 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
}
static void
elan_stop_capture (FpiDeviceElan *self)
elan_stop_capture (FpDevice *dev)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
elan_dev_reset_state (self);
FpiSsm *ssm =
fpi_ssm_new (FP_DEVICE (self), stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
fpi_ssm_new (dev, stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
fpi_ssm_start (ssm, stop_capture_complete);
}
@@ -540,6 +545,8 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
break;
case CAPTURE_READ_DATA:
self->dev_state = FPI_IMAGE_DEVICE_STATE_CAPTURE;
/* 0x55 - finger present
* 0xff - device not calibrated (probably) */
if (self->last_read && self->last_read[0] == 0x55)
@@ -607,21 +614,18 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fpi_image_device_session_error (dev, error);
}
/* Note: We always stop capturing even if that may not be needed always.
* Doing this between captures appears to make it at least less likely for
* devices to end up in a bad state.
*/
elan_stop_capture (self);
}
static void
elan_capture (FpiDeviceElan *self)
elan_capture (FpDevice *dev)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
elan_dev_reset_state (self);
FpiSsm *ssm =
fpi_ssm_new (FP_DEVICE (self), capture_run_state, CAPTURE_NUM_STATES);
fpi_ssm_new (dev, capture_run_state, CAPTURE_NUM_STATES);
fpi_ssm_start (ssm, capture_complete);
}
@@ -773,31 +777,33 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
static void
calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
if (error)
{
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
elan_stop_capture (FPI_DEVICE_ELAN (dev));
}
else
{
elan_capture (FPI_DEVICE_ELAN (dev));
elan_capture (dev);
}
}
static void
elan_calibrate (FpiDeviceElan *self)
elan_calibrate (FpDevice *dev)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
elan_dev_reset_state (self);
g_return_if_fail (!self->active);
self->active = TRUE;
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS;
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (self), calibrate_run_state,
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), calibrate_run_state,
CALIBRATE_NUM_STATES);
fpi_ssm_start (ssm, calibrate_complete);
@@ -952,19 +958,98 @@ dev_activate (FpImageDevice *dev)
elan_activate (dev);
}
static void
elan_change_state (FpImageDevice *idev)
{
FpDevice *dev = FP_DEVICE (idev);
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
FpiImageDeviceState next_state = self->dev_state_next;
if (self->dev_state == next_state)
{
fp_dbg ("already in %d", next_state);
return;
}
else
{
fp_dbg ("changing to %d", next_state);
}
switch (next_state)
{
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
/* activation completed or another enroll stage started */
self->dev_state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
elan_calibrate (dev);
break;
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
/* not used */
break;
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
elan_stop_capture (dev);
break;
}
}
static void
elan_change_state_async (FpDevice *dev,
void *data)
{
fp_dbg ("state change dev: %p", dev);
elan_change_state (FP_IMAGE_DEVICE (dev));
}
static void
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
GSource *timeout;
G_DEBUG_HERE ();
/* Note: We always calibrate even if that may not be needed always.
* Doing this for each capture appears to make it at least less likely for
* devices to end up in a bad state.
*/
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
elan_calibrate (self);
/* Inactive and await finger off are equivalent for the elan driver. */
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
if (self->dev_state_next == state)
{
fp_dbg ("change to state %d already queued", state);
return;
}
switch (state)
{
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: {
char *name;
/* schedule state change instead of calling it directly to allow all actions
* related to the previous state to complete */
self->dev_state_next = state;
timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10,
elan_change_state_async,
NULL, NULL);
name = g_strdup_printf ("dev_change_state to %d", state);
g_source_set_name (timeout, name);
g_free (name);
break;
}
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
/* TODO MAYBE: split capture ssm into smaller ssms and use this state */
self->dev_state = state;
self->dev_state_next = state;
break;
default:
g_assert_not_reached ();
}
}
static void
@@ -974,14 +1059,19 @@ dev_deactivate (FpImageDevice *dev)
G_DEBUG_HERE ();
if (!self->active)
/* The device is inactive already, complete the operation immediately. */
fpi_image_device_deactivate_complete (dev, NULL);
if (self->dev_state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* The device is inactive already, complete the operation immediately. */
fpi_image_device_deactivate_complete (dev, NULL);
}
else
/* The device is not yet inactive, flag that we are deactivating (and
* need to signal back deactivation).
* Note that any running capture will be cancelled already if needed. */
self->deactivating = TRUE;
{
/* The device is not yet inactive, flag that we are deactivating (and
* need to signal back deactivation) and then ensure we will change
* to the inactive state eventually. */
self->deactivating = TRUE;
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
}
}
static void

View File

@@ -70,9 +70,6 @@
#define ELAN_CMD_TIMEOUT 10000
#define ELAN_FINGER_TIMEOUT 200
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
FpImageDevice);
struct elan_cmd
{
unsigned char cmd[ELAN_CMD_LEN];
@@ -214,7 +211,6 @@ static const FpIdEntry elan_id_table[] = {
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
{.vid = ELAN_VEND_ID, .pid = 0x0c4d, .driver_data = ELAN_ALL_DEV},
{.vid = 0, .pid = 0, .driver_data = 0},
};
@@ -222,8 +218,8 @@ static void elan_cmd_done (FpiSsm *ssm);
static void elan_cmd_read (FpiSsm *ssm,
FpDevice *dev);
static void elan_calibrate (FpiDeviceElan *self);
static void elan_capture (FpiDeviceElan *self);
static void elan_calibrate (FpDevice *dev);
static void elan_capture (FpDevice *dev);
static void dev_change_state (FpImageDevice *dev,
FpiImageDeviceState state);

View File

@@ -53,12 +53,10 @@ struct _FpiDeviceGoodixMoc
pgxfp_sensor_cfg_t sensorcfg;
gint enroll_stage;
gint max_enroll_stage;
gint max_stored_prints;
GCancellable *cancellable;
GPtrArray *list_result;
guint8 template_id[TEMPLATE_ID_SIZE];
gboolean is_enroll_identify;
gboolean is_power_button_shield_on;
};
@@ -128,7 +126,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
}
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)))
if(crc32_calc != *(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len))
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -310,35 +308,6 @@ goodix_sensor_cmd (FpiDeviceGoodixMoc *self,
}
/******************************************************************************
*
* fp_pwr_btn_shield_cb Function
*
*****************************************************************************/
static void
fp_pwr_btn_shield_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
if (resp->result >= GX_FAILED)
{
fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result);
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
return;
}
if (resp->power_button_shield_resp.resp_cmd1 == MOC_CMD1_PWR_BTN_SHIELD_ON)
self->is_power_button_shield_on = true;
else
self->is_power_button_shield_on = false;
fpi_ssm_next_state (self->task_ssm);
}
/******************************************************************************
*
* fp_verify_xxxx Function
@@ -361,9 +330,7 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
if (resp->capture_data_resp.img_quality == 0)
{
fpi_ssm_mark_failed (self->task_ssm,
@@ -374,7 +341,6 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
{
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
return;
}
fpi_ssm_next_state (self->task_ssm);
}
@@ -384,9 +350,9 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
g_autoptr(GPtrArray) templates = NULL;
FpDevice *device = FP_DEVICE (self);
FpPrint *print = NULL;
GPtrArray *templates = NULL;
gint cnt = 0;
gboolean find = false;
@@ -399,14 +365,15 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
{
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
{
templates = g_ptr_array_sized_new (1);
templates = g_ptr_array_new_with_free_func (g_object_unref);
fpi_device_get_verify_data (device, &print);
g_ptr_array_add (templates, print);
g_ptr_array_add (templates, g_object_ref_sink (print));
}
else
{
fpi_device_get_identify_data (device, &templates);
g_ptr_array_ref (templates);
}
for (cnt = 0; cnt < templates->len; cnt++)
{
@@ -449,7 +416,7 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
fpi_device_identify_report (device, NULL, NULL, error);
}
fpi_ssm_next_state (self->task_ssm);
fpi_ssm_mark_completed (self->task_ssm);
}
@@ -466,18 +433,7 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
case FP_VERIFY_PWR_BTN_SHIELD_ON:
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
false,
NULL,
0,
fp_pwr_btn_shield_cb);
break;
case FP_VERIFY_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
goodix_sensor_cmd (self, MOC_CMD0_CAPTURE_DATA, MOC_CMD1_DEFAULT,
true,
(const guint8 *) &param,
@@ -492,14 +448,6 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
TEMPLATE_ID_SIZE,
fp_verify_cb);
break;
case FP_VERIFY_PWR_BTN_SHIELD_OFF:
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
false,
NULL,
0,
fp_pwr_btn_shield_cb);
break;
}
}
@@ -514,9 +462,9 @@ fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
if (error && error->domain == FP_DEVICE_RETRY)
{
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, error);
else
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
fpi_device_identify_report (dev, NULL, NULL, error);
}
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
@@ -613,13 +561,6 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self,
resp->result));
return;
}
if (resp->finger_list_resp.finger_num >= self->max_stored_prints)
{
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL));
return;
}
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
}
@@ -680,9 +621,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
(resp->capture_data_resp.img_coverage < self->sensorcfg->config[5]))
{
@@ -804,7 +743,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
/* if reach max timeout(5sec) finger not up, switch to finger up again */
/* if reach max timeout(5sec) finger not up, swtich to finger up again */
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
{
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_WAIT_FINGER_UP);
@@ -817,9 +756,6 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
"Switch finger mode failed"));
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (self->enroll_stage < self->max_enroll_stage)
{
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
@@ -858,16 +794,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
}
break;
case FP_ENROLL_PWR_BTN_SHIELD_ON:
{
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
false,
NULL,
0,
fp_pwr_btn_shield_cb);
}
break;
case FP_ENROLL_IDENTIFY:
{
dummy[0] = 0x01;
@@ -892,9 +818,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
break;
case FP_ENROLL_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
goodix_sensor_cmd (self, MOC_CMD0_CAPTURE_DATA, MOC_CMD1_DEFAULT,
true,
(const guint8 *) &dummy,
@@ -982,17 +905,9 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
}
break;
case FP_ENROLL_PWR_BTN_SHIELD_OFF:
{
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
false,
NULL,
0,
fp_pwr_btn_shield_cb);
}
break;
}
}
static void
@@ -1061,7 +976,7 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
self->max_stored_prints = resp->finger_config.max_stored_prints;
fpi_ssm_next_state (self->task_ssm);
}
@@ -1345,9 +1260,6 @@ gx_fp_init (FpDevice *device)
GError *error = NULL;
int ret = 0;
self->max_stored_prints = FP_MAX_FINGERNUM;
self->is_power_button_shield_on = false;
self->cancellable = g_cancellable_new ();
self->sensorcfg = g_new0 (gxfp_sensor_cfg_t, 1);
@@ -1382,59 +1294,20 @@ gx_fp_init (FpDevice *device)
}
static void
gx_fp_release_interface (FpiDeviceGoodixMoc *self,
GError *error)
gx_fp_exit (FpDevice *device)
{
g_autoptr(GError) release_error = NULL;
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
GError *error = NULL;
g_clear_object (&self->cancellable);
g_clear_pointer (&self->sensorcfg, g_free);
/* Release usb interface */
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)),
0, 0, &release_error);
/* Retain passed error if set, otherwise propagate error from release. */
if (error == NULL)
error = g_steal_pointer (&release_error);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)),
0, 0, &error);
/* Notify close complete */
fpi_device_close_complete (FP_DEVICE (self), error);
}
static void
gx_fp_exit_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (resp->result >= GX_FAILED)
fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result);
self->is_power_button_shield_on = false;
gx_fp_release_interface (self, error);
}
static void
gx_fp_exit (FpDevice *device)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
if (self->is_power_button_shield_on)
{
goodix_sensor_cmd (self,
MOC_CMD0_PWR_BTN_SHIELD,
MOC_CMD1_PWR_BTN_SHIELD_OFF,
false,
NULL,
0,
gx_fp_exit_cb);
}
else
{
gx_fp_release_interface (self, NULL);
}
}
@@ -1536,6 +1409,7 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
static void
gx_fp_cancel (FpDevice *device)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
/* Cancel any current interrupt transfer (resulting us to go into
@@ -1551,9 +1425,6 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x5840, },
{ .vid = 0x27c6, .pid = 0x6496, },
{ .vid = 0x27c6, .pid = 0x60A2, },
{ .vid = 0x27c6, .pid = 0x63AC, },
{ .vid = 0x27c6, .pid = 0x639C, },
{ .vid = 0x27c6, .pid = 0x6594, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -1579,7 +1450,4 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass)
dev_class->cancel = gx_fp_cancel;
dev_class->verify = gx_fp_verify_identify;
dev_class->identify = gx_fp_verify_identify;
fpi_device_class_auto_initialize_features (dev_class);
dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK;
}

View File

@@ -40,8 +40,7 @@ typedef enum {
typedef enum {
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
FP_ENROLL_ENUM,
FP_ENROLL_ENUM = 0,
FP_ENROLL_IDENTIFY,
FP_ENROLL_CREATE,
FP_ENROLL_CAPTURE,
@@ -49,14 +48,11 @@ typedef enum {
FP_ENROLL_WAIT_FINGER_UP,
FP_ENROLL_CHECK_DUPLICATE,
FP_ENROLL_COMMIT,
FP_ENROLL_PWR_BTN_SHIELD_OFF,
FP_ENROLL_NUM_STATES,
} FpEnrollState;
typedef enum {
FP_VERIFY_PWR_BTN_SHIELD_ON = 0,
FP_VERIFY_CAPTURE,
FP_VERIFY_CAPTURE = 0,
FP_VERIFY_IDENTIFY,
FP_VERIFY_PWR_BTN_SHIELD_OFF,
FP_VERIFY_NUM_STATES,
} FpVerifyState;

View File

@@ -141,11 +141,8 @@ crc32_update (gf_crc32_context *ctx, const uint8_t *message, uint32_t n_bytes)
static void
crc32_final (gf_crc32_context *ctx, uint8_t *md)
{
uint32_t crc = 0;
ctx->crc = (REFLECT_REMAINDER (ctx->crc) ^ FINAL_XOR_VALUE);
crc = GUINT32_TO_LE (ctx->crc);
memcpy (md, &crc, 4);
memcpy (md, &ctx->crc, 4);
}
uint8_t
@@ -187,7 +184,7 @@ init_pack_header (
pheader->cmd1 = LOBYTE (cmd);
pheader->packagenum = packagenum;
pheader->reserved = dump_seq++;
pheader->len = GUINT16_TO_LE (len + PACKAGE_CRC_SIZE);
pheader->len = len + PACKAGE_CRC_SIZE;
pheader->crc8 = gx_proto_crc8_calc ((uint8_t *) pheader, 6);
pheader->rev_crc8 = ~pheader->crc8;
}
@@ -227,14 +224,14 @@ gx_proto_parse_header (
{
if (!buffer || !pheader)
return -1;
if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
if (buffer_len < PACKAGE_HEADER_SIZE)
return -1;
memcpy (pheader, buffer, sizeof (pack_header));
pheader->len = GUINT16_FROM_LE (pheader->len);
if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
return -1;
pheader->len = GUINT16_FROM_LE (*(buffer + 4));
pheader->len -= PACKAGE_CRC_SIZE;
return 0;
}
@@ -251,7 +248,7 @@ gx_proto_parse_fingerid (
if (!template || !fid_buffer)
return -1;
if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
if (fid_buffer_size < 70)
return -1;
buffer = fid_buffer;
@@ -259,30 +256,28 @@ gx_proto_parse_fingerid (
if (buffer[Offset++] != 67)
return -1;
fid_buffer_size--;
template->type = buffer[Offset++];
fid_buffer_size--;
template->finger_index = buffer[Offset++];
fid_buffer_size--;
Offset++;
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
Offset += sizeof (template->accountid);
memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
Offset += sizeof (template->tid); // Offset == 68
memcpy (template->accountid, &buffer[Offset], 32);
Offset += 32;
memcpy (template->tid, &buffer[Offset], 32);
Offset += 32; // Offset == 68
template->payload.size = buffer[Offset++];
if (template->payload.size > sizeof (template->payload.data))
return -1;
memset (template->payload.data, 0, template->payload.size);
memset (template->payload.data, 0, 56);
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
return 0;
}
int
gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp)
gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_cmd_response_t presp)
{
uint16_t offset = 0;
uint32_t offset = 0;
uint8_t *fingerlist = NULL;
if (!buffer || !presp)
@@ -294,65 +289,33 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
{
case RESPONSE_PACKAGE_CMD:
{
if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
return -1;
presp->parse_msg.ack_cmd = buffer[1];
}
break;
case MOC_CMD0_UPDATE_CONFIG:
{
presp->finger_config.status = buffer[0];
if (buffer_len >= 3)
presp->finger_config.max_stored_prints = buffer[2];
else
/* to compatiable old version firmware */
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
}
break;
case MOC_CMD0_COMMITENROLLMENT:
case MOC_CMD0_DELETETEMPLATE:
/* just check result */
break;
case MOC_CMD0_PWR_BTN_SHIELD:
presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd);
if (buffer_len >= 2)
{
uint8_t support_pwr_shield = buffer[1];
if (support_pwr_shield == 0xFF)
g_debug ("Power button shield feature not supported!\n");
}
break;
case MOC_CMD0_GET_VERSION:
if (buffer_len < sizeof (gxfp_version_info_t) + 1)
return -1;
memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
break;
case MOC_CMD0_CAPTURE_DATA:
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT)
{
if (buffer_len < sizeof (gxfp_capturedata_t) + 1)
return -1;
presp->capture_data_resp.img_quality = buffer[1];
presp->capture_data_resp.img_coverage = buffer[2];
}
break;
case MOC_CMD0_ENROLL_INIT:
if (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
return -1;
if (presp->result == GX_SUCCESS)
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
break;
case MOC_CMD0_ENROLL:
if (buffer_len < sizeof (gxfp_enroll_update_t))
return -1;
presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true;
presp->enroll_update.img_overlay = buffer[1];
presp->enroll_update.img_preoverlay = buffer[2];
@@ -362,11 +325,7 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
if (presp->check_duplicate_resp.duplicate)
{
if (buffer_len < 3)
return -1;
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
if ((buffer_len < tid_size + 3) || (buffer_len > sizeof (template_format_t)) + 3)
return -1;
uint16_t tid_size = GUINT16_FROM_LE (*(buffer + 1));
memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size);
}
break;
@@ -374,16 +333,18 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
case MOC_CMD0_GETFINGERLIST:
if (presp->result != GX_SUCCESS)
break;
if (buffer_len < 2)
return -1;
presp->finger_list_resp.finger_num = buffer[1];
if (presp->finger_list_resp.finger_num > FP_MAX_FINGERNUM)
{
presp->finger_list_resp.finger_num = 0;
presp->result = GX_ERROR_NO_AVAILABLE_SPACE;
break;
}
fingerlist = buffer + 2;
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
{
uint16_t fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
uint16_t fingerid_length = GUINT16_FROM_LE (*(fingerlist + offset));
offset += 2;
if (buffer_len < fingerid_length + offset + 2)
return -1;
if (gx_proto_parse_fingerid (fingerlist + offset,
fingerid_length,
&presp->finger_list_resp.finger_list[num]) != 0)
@@ -405,16 +366,14 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
presp->verify.match = (buffer[0] == 0) ? true : false;
if (presp->verify.match)
{
if (buffer_len < sizeof (template_format_t) + 10)
return -1;
offset += 1;
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
presp->verify.rejectdetail = GUINT16_FROM_LE (*(buffer + offset));
offset += 2;
score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
score = GUINT32_FROM_LE (*(buffer + offset));
offset += 4;
study = buffer[offset];
study = GUINT16_FROM_LE (*(buffer + offset));
offset += 1;
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
fingerid_size = GUINT16_FROM_LE (*(buffer + offset));
offset += 2;
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
{
@@ -452,7 +411,7 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
memset (pconfig, 0, sizeof (*pconfig));
//NOTICE: Do not change any value!
memcpy (&pconfig->config, sensor_config, G_N_ELEMENTS (sensor_config));
memcpy (&pconfig->config, sensor_config, 26);
pconfig->reserved[0] = 1;
gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, (uint8_t *) &crc32_calc);

View File

@@ -25,7 +25,7 @@
#define PACKAGE_CRC_SIZE (4)
#define PACKAGE_HEADER_SIZE (8)
#define FP_MAX_FINGERNUM (20)
#define FP_MAX_FINGERNUM (10)
#define TEMPLATE_ID_SIZE (32)
@@ -75,11 +75,6 @@
#define MOC_CMD1_GET_FINGER_MODE 0x00
#define MOC_CMD1_SET_FINGER_DOWN 0x01
#define MOC_CMD1_SET_FINGER_UP 0x02
#define MOC_CMD0_PWR_BTN_SHIELD 0xE0
#define MOC_CMD1_PWR_BTN_SHIELD_OFF 0x00
#define MOC_CMD1_PWR_BTN_SHIELD_ON 0x01
/* */
typedef struct _gxfp_version_info
@@ -94,7 +89,7 @@ typedef struct _gxfp_version_info
uint8_t interface[GX_VERSION_LEN];
uint8_t protocol[GX_VERSION_LEN];
uint8_t flashVersion[GX_VERSION_LEN];
uint8_t reserved[38];
uint8_t reserved[62];
} gxfp_version_info_t, *pgxfp_version_info_t;
@@ -172,16 +167,6 @@ typedef struct _fp_finger_status
uint8_t status;
} fp_finger_status_t, *pfp_finger_status_t;
typedef struct _fp_finger_config
{
uint8_t status;
uint8_t max_stored_prints;
} fp_finger_config_t, *pfp_finger_config_t;
typedef struct _fp_pwr_btn_shield
{
uint8_t resp_cmd1;
} fp_pwr_btn_shield_t, *pfp_pwr_btn_shield_t;
typedef struct _fp_cmd_response
{
@@ -198,8 +183,6 @@ typedef struct _fp_cmd_response
gxfp_enum_fingerlist_t finger_list_resp;
gxfp_version_info_t version_info;
fp_finger_status_t finger_status;
fp_finger_config_t finger_config;
fp_pwr_btn_shield_t power_button_shield_resp;
};
} gxfp_cmd_response_t, *pgxfp_cmd_response_t;
@@ -236,7 +219,7 @@ int gx_proto_parse_header (uint8_t *buffer,
int gx_proto_parse_body (uint16_t cmd,
uint8_t *buffer,
uint16_t buffer_len,
uint32_t buffer_len,
pgxfp_cmd_response_t presponse);
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);

View File

@@ -1,445 +0,0 @@
/*
* Next Biometrics driver for libfprint
*
* Copyright (C) 2021 Huan Wang <fredwanghuan@gmail.com>
* Copyright (C) 2011-2012 Andrej Krutak <dev@andree.sk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "nb1010"
#include "fpi-log.h"
#include "drivers_api.h"
#define FRAME_HEIGHT 180
#define FRAME_WIDTH 256
#define NB1010_EP_OUT 0x02 | FPI_USB_ENDPOINT_OUT
#define NB1010_EP_IN 0x03 | FPI_USB_ENDPOINT_IN
#define NB1010_SENSITIVITY_BIT 12
#define NB1010_CMD_RECV_LEN 16
#define NB1010_CAPTURE_RECV_LEN 540
#define NB1010_CAPTURE_HEADER_LEN 25
#define NB1010_LINE_PER_PARTIAL 2
#define NB1010_N_PARTIAL (FRAME_HEIGHT / NB1010_LINE_PER_PARTIAL)
#define NB1010_DEFAULT_TIMEOUT 500
#define NB1010_TRANSITION_DELAY 50
/* Loop ssm states */
enum {
M_WAIT_PRINT,
M_REQUEST_PRINT,
M_CHECK_PRINT,
M_READ_PRINT_PRESTART,
M_READ_PRINT_START,
M_READ_PRINT_POLL,
M_SUBMIT_PRINT,
/* Number of states */
M_LOOP_NUM_STATES,
};
/*
* The Follow Commands are obtained by decoding the usbcap, so it does not expose all the command available to the device.
* Known:
* 1. every command starts with 0x80
* 2. second byte is the comand, third byte is the seqence nubmer, init with rand, gets incremented
* everytime a new instruction is sent to the device. However device does not care or check the sequence, just echo back
* whatever chosen by the host.
* 3. cmd: 0x07 check, expect [0x80, 0x29...] as response
* 4. cmd: 0x16 ???, expect [0x80, 0x20...] as response. Happens during device init.
* 5. cmd: 0x13 print device, expect [0x80, 0x23...] as response. Response contains the device string
* 6. cmd: 0x38 check finger, expect [0x80, 0x37...] as response. The 14th byte indicate whether finger present [0-255]
* 7. cmd: 0x0d ???, expect [0x80, 0x20...] as response. Happens before capture.
* 8. cmd: 0x12 capture, expect [0x80, 0x20...] as response. After capture read 90 times in sequence to get all the frame.
*/
static guint8 nb1010_cmd_check_finger[] = {
0x80, 0x38, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
};
/* pre capture, dont know what does it do, but appears everytime a capture begins */
static guint8 nb1010_cmd_precapture[] = {
0x80, 0x0d, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
};
static guint8 nb1010_cmd_capture[] = {
0x80, 0x12, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
};
struct _FpiDeviceNb1010
{
FpImageDevice parent;
FpiSsm *ssm;
guint8 *scanline_buf;
gboolean deactivating;
int partial_received;
};
G_DECLARE_FINAL_TYPE (FpiDeviceNb1010, fpi_device_nb1010, FPI, DEVICE_NB1010, FpImageDevice);
G_DEFINE_TYPE (FpiDeviceNb1010, fpi_device_nb1010, FP_TYPE_IMAGE_DEVICE);
static void
nb1010_dev_init (FpImageDevice *dev)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
GError *error = NULL;
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
self->scanline_buf = g_malloc0 (FRAME_WIDTH * FRAME_HEIGHT);
fpi_image_device_open_complete (dev, error);
fp_dbg ("nb1010 Initialized");
}
static void
nb1010_dev_deinit (FpImageDevice *dev)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
GError *error = NULL;
g_clear_pointer (&self->scanline_buf, g_free);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
fpi_image_device_close_complete (dev, error);
fp_dbg ("nb1010 Deinitialized");
}
static void
nb1010_dev_activate (FpImageDevice *dev)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
self->deactivating = FALSE;
fpi_image_device_activate_complete (dev, NULL);
fp_dbg ("nb1010 Activated");
}
static void
nb1010_dev_deactivated (FpImageDevice *dev, GError * err)
{
fpi_image_device_deactivate_complete (dev, err);
fp_dbg ("nb1010 Deactivated");
}
static void
nb1010_dev_deactivate (FpImageDevice *dev)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
self->deactivating = TRUE;
if (self->ssm == NULL)
nb1010_dev_deactivated (dev, NULL);
}
static void
nb1010_request_fingerprint (FpiDeviceNb1010 *dev)
{
FpiUsbTransfer *transfer = NULL;
transfer = fpi_usb_transfer_new (FP_DEVICE ( dev));
transfer->short_is_error = TRUE;
transfer->ssm = dev->ssm;
fpi_usb_transfer_fill_bulk_full (transfer, NB1010_EP_OUT,
nb1010_cmd_check_finger, G_N_ELEMENTS (nb1010_cmd_check_finger),
NULL);
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
fpi_ssm_usb_transfer_cb, NULL);
}
static void
nb1010_check_fingerprint_cb (FpiUsbTransfer *transfer, FpDevice *dev,
gpointer unused_data, GError *error)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (self->deactivating)
{
fpi_ssm_mark_completed (transfer->ssm);
return;
}
if (transfer->buffer[NB1010_SENSITIVITY_BIT] > 0x30)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_jump_to_state (transfer->ssm, M_WAIT_PRINT);
}
static void
nb1010_cmd_check_fingerprint (FpiDeviceNb1010 *dev)
{
FpiUsbTransfer *transfer = NULL;
transfer = fpi_usb_transfer_new (FP_DEVICE ( dev));
transfer->short_is_error = TRUE;
transfer->ssm = dev->ssm;
fpi_usb_transfer_fill_bulk (transfer, NB1010_EP_IN, NB1010_CMD_RECV_LEN);
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
nb1010_check_fingerprint_cb, NULL);
}
static void
nb1010_read_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *dev,
gpointer unused_data, GError *error)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
FpiUsbTransfer *new_transfer = NULL;
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (self->deactivating)
{
fpi_ssm_mark_completed (transfer->ssm);
return;
}
new_transfer = fpi_usb_transfer_new ( dev );
new_transfer->short_is_error = TRUE;
new_transfer->ssm = transfer->ssm;
fpi_usb_transfer_fill_bulk (new_transfer, NB1010_EP_IN, NB1010_CMD_RECV_LEN);
fpi_usb_transfer_submit (new_transfer, NB1010_DEFAULT_TIMEOUT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
fpi_ssm_usb_transfer_cb, NULL);
}
static void
nb1010_write_ignore_read (FpiDeviceNb1010 *dev, guint8 *buf, gsize len)
{
FpiUsbTransfer *transfer = NULL;
transfer = fpi_usb_transfer_new (FP_DEVICE ( dev));
transfer->short_is_error = TRUE;
transfer->ssm = dev->ssm;
fpi_usb_transfer_fill_bulk_full (transfer, NB1010_EP_OUT, buf, len, NULL);
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
nb1010_read_ignore_data_cb, NULL);
}
static void
nb1010_read_capture_cb (FpiUsbTransfer *transfer, FpDevice *dev,
gpointer unused_data, GError *error)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (self->deactivating)
{
fpi_ssm_mark_completed (transfer->ssm);
return;
}
g_assert (transfer->actual_length == NB1010_CAPTURE_RECV_LEN);
size_t offset = self->partial_received * NB1010_LINE_PER_PARTIAL * FRAME_WIDTH;
memcpy (self->scanline_buf + offset,
transfer->buffer + NB1010_CAPTURE_HEADER_LEN, NB1010_LINE_PER_PARTIAL * FRAME_WIDTH);
self->partial_received++;
if (self->partial_received == NB1010_N_PARTIAL)
{
fpi_ssm_next_state (transfer->ssm);
return;
}
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer), NB1010_DEFAULT_TIMEOUT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
nb1010_read_capture_cb, NULL);
}
static void
nb1010_read_capture (FpiDeviceNb1010 *dev)
{
FpiUsbTransfer *transfer = NULL;
transfer = fpi_usb_transfer_new ( FP_DEVICE ( dev));
transfer->short_is_error = TRUE;
transfer->ssm = dev->ssm;
fpi_usb_transfer_fill_bulk (transfer, NB1010_EP_IN, NB1010_CAPTURE_RECV_LEN);
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
nb1010_read_capture_cb, NULL);
}
static int
submit_image (FpiSsm *ssm,
FpImageDevice *dev)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
FpImage *img;
img = fp_image_new (FRAME_WIDTH, FRAME_HEIGHT);
if (img == NULL)
return 0;
memcpy (img->data, self->scanline_buf, FRAME_WIDTH * FRAME_HEIGHT);
fpi_image_device_image_captured (dev, img);
return 1;
}
static void
m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
fp_dbg ("nb1010 ssm complete cb");
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (_dev);
self->ssm = NULL;
if (self->deactivating)
nb1010_dev_deactivated (dev, error);
else if (error != NULL)
fpi_image_device_session_error (dev, error);
}
static void
m_loop_state (FpiSsm *ssm, FpDevice *_dev)
{
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (_dev);
if (self->deactivating)
{
fp_dbg ("deactivating, marking completed");
fpi_ssm_mark_completed (ssm);
return;
}
switch (fpi_ssm_get_cur_state (ssm))
{
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
fpi_ssm_next_state_delayed (ssm, NB1010_TRANSITION_DELAY, NULL);
break;
case M_REQUEST_PRINT:
nb1010_request_fingerprint (self);
break;
case M_CHECK_PRINT:
nb1010_cmd_check_fingerprint (self);
break;
case M_READ_PRINT_PRESTART:
fpi_image_device_report_finger_status (dev, TRUE);
nb1010_write_ignore_read (self, nb1010_cmd_precapture, G_N_ELEMENTS (nb1010_cmd_precapture));
break;
case M_READ_PRINT_START:
self->partial_received = 0;
nb1010_write_ignore_read (self, nb1010_cmd_capture, G_N_ELEMENTS (nb1010_cmd_capture));
break;
case M_READ_PRINT_POLL:
nb1010_read_capture (self);
break;
case M_SUBMIT_PRINT:
if (submit_image (ssm, dev))
{
fpi_ssm_mark_completed (ssm);
fpi_image_device_report_finger_status (dev, FALSE);
}
else
{
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
}
break;
default:
g_assert_not_reached ();
}
}
static void
nb1010_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
FpiSsm *ssm_loop;
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
ssm_loop = fpi_ssm_new (FP_DEVICE (dev), m_loop_state, M_LOOP_NUM_STATES);
self->ssm = ssm_loop;
fpi_ssm_start (ssm_loop, m_loop_complete);
}
}
static const FpIdEntry id_table[] = {
{ .vid = 0x298d, .pid = 0x1010, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void
fpi_device_nb1010_init (FpiDeviceNb1010 *self)
{
}
static void
fpi_device_nb1010_class_init (FpiDeviceNb1010Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = FP_COMPONENT;
dev_class->full_name = "NextBiometrics NB-1010-U";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
img_class->img_height = FRAME_HEIGHT;
img_class->img_width = FRAME_WIDTH;
img_class->bz3_threshold = 24;
img_class->img_open = nb1010_dev_init;
img_class->img_close = nb1010_dev_deinit;
img_class->activate = nb1010_dev_activate;
img_class->deactivate = nb1010_dev_deactivate;
img_class->change_state = nb1010_dev_change_state;
}

View File

@@ -27,18 +27,10 @@
G_DEFINE_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE)
static void init_identify_msg (FpDevice *device);
static void compose_and_send_identify_msg (FpDevice *device);
static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00BD, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00E9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xDF, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -87,17 +79,10 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
if (msg_resp.payload[0] == 0x01)
{
self->finger_on_sensor = TRUE;
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
}
else
{
self->finger_on_sensor = FALSE;
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (self->cmd_complete_on_removal)
{
fpi_ssm_mark_completed (transfer->ssm);
@@ -124,7 +109,7 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
{
if (resp.response_id == BMKT_RSP_CANCEL_OP_OK)
{
fp_dbg ("Received cancellation success response");
fp_dbg ("Received cancellation success resonse");
fpi_ssm_mark_failed (transfer->ssm,
g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
@@ -209,19 +194,12 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
g_clear_pointer (&error, g_error_free);
if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING)
{
fpi_ssm_next_state (transfer->ssm);
}
if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING || error)
fpi_ssm_next_state (transfer->ssm);
else
{
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
0,
NULL,
cmd_interrupt_cb,
NULL);
}
fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_interrupt_cb, NULL);
}
static void
@@ -348,7 +326,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
* may only be a cancellation currently). */
if (seq_num <= 0)
{
self->last_seq_num = MAX (1, (self->last_seq_num + 1) & 0xff);
self->last_seq_num = MAX (1, self->last_seq_num + 1);
real_seq_num = self->last_seq_num;
if (seq_num == 0)
self->cmd_seq_num = self->last_seq_num;
@@ -454,37 +432,6 @@ parse_print_data (GVariant *data,
return TRUE;
}
static FpPrint *
create_print (FpiDeviceSynaptics *self,
guint8 *user_id,
guint8 finger_id)
{
FpPrint *print;
g_autofree gchar *user_id_safe;
GVariant *data = NULL;
GVariant *uid = NULL;
user_id_safe = g_strndup ((char *) user_id, BMKT_MAX_USER_ID_LEN);
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
user_id_safe,
strlen (user_id_safe),
1);
data = g_variant_new ("(y@ay)",
finger_id,
uid);
fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE);
g_object_set (print, "fpi-data", data, NULL);
g_object_set (print, "description", user_id_safe, NULL);
fpi_print_fill_from_user_id (print, user_id_safe);
return print;
}
static void
list_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
@@ -537,7 +484,10 @@ list_msg_cb (FpiDeviceSynaptics *self,
for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
{
GVariant *data = NULL;
GVariant *uid = NULL;
FpPrint *print;
gchar *userid;
if (get_enroll_templates_resp->templates[n].user_id_len == 0)
continue;
@@ -550,9 +500,23 @@ list_msg_cb (FpiDeviceSynaptics *self,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
print = create_print (self,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
userid = (gchar *) get_enroll_templates_resp->templates[n].user_id;
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].user_id_len,
1);
data = g_variant_new ("(y@ay)",
get_enroll_templates_resp->templates[n].finger_id,
uid);
fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE);
g_object_set (print, "fpi-data", data, NULL);
g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL);
fpi_print_fill_from_user_id (print, userid);
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
}
@@ -622,9 +586,6 @@ verify_msg_cb (FpiDeviceSynaptics *self,
switch (resp->response_id)
{
case BMKT_RSP_VERIFY_READY:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
fp_info ("Place Finger on the Sensor!");
break;
@@ -666,7 +627,7 @@ verify_msg_cb (FpiDeviceSynaptics *self,
fp_info ("Verify was successful! for user: %s finger: %d score: %f",
verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result);
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, NULL);
verify_complete_after_finger_removal (self);
fpi_device_verify_complete (device, NULL);
break;
}
}
@@ -698,212 +659,6 @@ verify (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
}
static void
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
{
FpDevice *device = FP_DEVICE (self);
if (self->finger_on_sensor)
{
fp_dbg ("delaying identify report until after finger removal!");
self->cmd_complete_on_removal = TRUE;
}
else
{
fpi_device_identify_complete (device, NULL);
}
}
static void
identify_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
FpDevice *device = FP_DEVICE (self);
if (error)
{
fpi_device_identify_complete (device, error);
return;
}
if (resp == NULL && self->cmd_complete_on_removal)
{
fpi_device_identify_complete (device, NULL);
return;
}
g_assert (resp != NULL);
switch (resp->response_id)
{
case BMKT_RSP_ID_READY:
fp_info ("Place Finger on the Sensor!");
break;
case BMKT_RSP_SEND_NEXT_USER_ID:
{
compose_and_send_identify_msg (device);
break;
}
case BMKT_RSP_ID_FAIL:
if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
{
fp_info ("Match error occurred");
fpi_device_identify_report (device, NULL, NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_info ("Print didn't match");
fpi_device_identify_report (device, NULL, NULL, NULL);
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
{
fp_info ("Print is not in database");
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
else
{
fp_warn ("identify has failed: %d", resp->result);
fpi_device_identify_complete (device,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected result from device %d",
resp->result));
}
break;
case BMKT_RSP_ID_OK:
{
FpPrint *print = NULL;
GPtrArray *prints = NULL;
g_autoptr(GVariant) data = NULL;
gboolean found = FALSE;
guint index;
print = create_print (self,
resp->response.id_resp.user_id,
resp->response.id_resp.finger_id);
fpi_device_get_identify_data (device, &prints);
found = g_ptr_array_find_with_equal_func (prints,
print,
(GEqualFunc) fp_print_equal,
&index);
if (found)
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
else
fpi_device_identify_report (device, NULL, print, NULL);
identify_complete_after_finger_removal (self);
}
}
}
static void
identify (FpDevice *device)
{
init_identify_msg (device);
compose_and_send_identify_msg (device);
}
static void
init_identify_msg (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
self->id_idx = 0;
}
static void
compose_and_send_identify_msg (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
FpPrint *print = NULL;
GPtrArray *prints = NULL;
g_autoptr(GVariant) data = NULL;
guint8 finger;
const guint8 *user_id;
gsize user_id_len = 0;
g_autofree guint8 *payload = NULL;
guint8 payload_len = 0;
guint8 payloadOffset = 0;
fpi_device_get_identify_data (device, &prints);
if (prints->len > UINT8_MAX)
{
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return;
}
if(self->id_idx >= prints->len)
{
fp_warn ("Device asked for more prints than we are providing.");
fpi_device_identify_complete (device,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected index"));
return;
}
print = g_ptr_array_index (prints, self->id_idx);
g_object_get (print, "fpi-data", &data, NULL);
g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return;
}
if(self->id_idx == 0)
{
/*
* Construct payload.
* 1st byte is total number of IDs in list.
* 2nd byte is number of IDs in list.
* 1 byte for each ID length, maximum id length is 100.
* user_id_len bytes of each ID
*/
payload_len = 2 + 1 + user_id_len;
payload = g_malloc0 (payload_len);
payload[payloadOffset] = prints->len;
payloadOffset += 1;
payload[payloadOffset] = 1; /* send one id per message */
payloadOffset += 1;
payload[payloadOffset] = user_id_len;
payloadOffset += 1;
memcpy (&payload[payloadOffset], user_id, user_id_len);
payloadOffset += user_id_len;
G_DEBUG_HERE ();
synaptics_sensor_cmd (self, 0, BMKT_CMD_ID_USER_IN_ORDER, payload, payloadOffset, identify_msg_cb);
}
else
{
/*
* 1st byte is the number of IDs
* 1 byte for each ID length
* id_length bytes for each ID
*/
payload_len = 1 + 1 + user_id_len;
payload = g_malloc0 (payload_len);
payload[payloadOffset] = 1; /* send one id per message */
payloadOffset += 1;
payload[payloadOffset] = user_id_len;
payloadOffset += 1;
memcpy (&payload[payloadOffset], user_id, user_id_len);
payloadOffset += user_id_len;
synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_ID_NEXT_USER, payload, payloadOffset, NULL);
}
self->id_idx++;
}
static void
enroll_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
@@ -925,9 +680,6 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
case BMKT_RSP_ENROLL_READY:
{
self->enroll_stage = 0;
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
fp_info ("Place Finger on the Sensor!");
break;
}
@@ -1133,45 +885,6 @@ delete_print (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
}
static void
prob_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
GUsbDevice *usb_dev = NULL;
g_autofree gchar *serial = NULL;
usb_dev = fpi_device_get_usb_device (FP_DEVICE (self));
if (error)
{
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version"));
return;
}
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
serial = g_strdup ("emulated-device");
else
serial = g_usb_device_get_string_descriptor (usb_dev,
g_usb_device_get_serial_number_index (usb_dev),
&error);
/* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */
if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED)
{
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, error);
}
else
{
g_warning ("Probe fingerprint sensor failed with %d!", resp->result);
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
}
}
static void
dev_probe (FpDevice *device)
{
@@ -1197,6 +910,9 @@ dev_probe (FpDevice *device)
return;
}
if (!g_usb_device_reset (usb_dev, &error))
goto err_close;
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
goto err_close;
@@ -1269,7 +985,40 @@ dev_probe (FpDevice *device)
fp_dbg ("Target: %d", self->mis_version.target);
fp_dbg ("Product: %d", self->mis_version.product);
synaptics_sensor_cmd (self, 0, BMKT_CMD_FPS_INIT, NULL, 0, prob_msg_cb);
/* We need at least firmware version 10.1, and for 10.1 build 2989158 */
if (self->mis_version.version_major < 10 ||
self->mis_version.version_minor < 1 ||
(self->mis_version.version_major == 10 &&
self->mis_version.version_minor == 1 &&
self->mis_version.build_num < 2989158))
{
fp_warn ("Firmware version %d.%d with build number %d is unsupported",
self->mis_version.version_major,
self->mis_version.version_minor,
self->mis_version.build_num);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Unsupported firmware version "
"(%d.%d with build number %d)",
self->mis_version.version_major,
self->mis_version.version_minor,
self->mis_version.build_num);
goto err_close;
}
/* This is the same as the serial_number from above, hex encoded and somewhat reordered */
/* Should we add in more, e.g. the chip revision? */
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
serial = g_strdup ("emulated-device");
else
serial = g_usb_device_get_string_descriptor (usb_dev,
g_usb_device_get_serial_number_index (usb_dev),
&error);
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (device, serial, NULL, error);
return;
@@ -1340,6 +1089,9 @@ dev_init (FpDevice *device)
self->interrupt_cancellable = g_cancellable_new ();
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
goto error;
/* Claim usb interface */
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
goto error;
@@ -1400,11 +1152,8 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
dev_class->close = dev_exit;
dev_class->probe = dev_probe;
dev_class->verify = verify;
dev_class->identify = identify;
dev_class->enroll = enroll;
dev_class->delete = delete_print;
dev_class->cancel = cancel;
dev_class->list = list;
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -110,7 +110,6 @@ struct _FpiDeviceSynaptics
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_pending_transfer;
gboolean cmd_complete_on_removal;
guint8 id_idx;
bmkt_sensor_version_t mis_version;

View File

@@ -693,6 +693,8 @@ sm_read_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_dbg ("read reg result = %02x", self->read_reg_result);
fpi_ssm_next_state (transfer->ssm);
}
g_free (transfer->buffer);
}
static void
@@ -729,6 +731,7 @@ sm_await_intr_cb (FpiUsbTransfer *transfer, FpDevice *device,
if (error)
{
g_free (transfer->buffer);
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
@@ -736,6 +739,7 @@ sm_await_intr_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_dbg ("interrupt received: %02x %02x %02x %02x",
transfer->buffer[0], transfer->buffer[1],
transfer->buffer[2], transfer->buffer[3]);
g_free (transfer->buffer);
self->finger_state = FINGER_DETECTED;
fpi_image_device_report_finger_status (dev, TRUE);

View File

@@ -19,8 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* *INDENT-OFF* */
#pragma once
#define UPEKTC_CMD_LEN 0x40

View File

@@ -78,7 +78,6 @@ upektc_img_cmd_update_crc (unsigned char *cmd_buf, size_t size)
cmd_buf[size - 1] = (crc & 0xff00) >> 8;
}
FP_GNUC_ACCESS (read_only, 3, 4)
static void
upektc_img_submit_req (FpiSsm *ssm,
FpImageDevice *dev,

View File

@@ -527,6 +527,15 @@ initsm_read_msg_response_cb (FpiSsm *ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected response subcommand"));
}
else if (seq != upekdev->seq)
{
fp_err ("expected response to cmd seq=%02x, got response to %02x "
"in state %d", upekdev->seq, seq,
fpi_ssm_get_cur_state (ssm));
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected sequence number in response"));
}
else
{
fpi_ssm_next_state (ssm);
@@ -1555,6 +1564,4 @@ fpi_device_upekts_class_init (FpiDeviceUpektsClass *klass)
dev_class->verify = verify;
dev_class->enroll = enroll;
/* dev_class->cancel = cancel; */
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -375,10 +375,6 @@ stop_irq_handler (FpImageDevice *dev, irqs_stopped_cb_fn cb)
g_cancellable_cancel (self->irq_cancellable);
self->irqs_stopped_cb = cb;
}
else
{
cb (dev);
}
}
/***** STATE CHANGING *****/
@@ -416,6 +412,18 @@ dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
switch (state)
{
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
break;
default:
g_assert_not_reached ();
}
self->activate_state = state;
if (self->img_transfer != NULL)
return;
@@ -655,11 +663,7 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
case IMAGING_CAPTURE:
self->img_lines_done = 0;
self->img_block = 0;
fpi_usb_transfer_submit (fpi_usb_transfer_ref (self->img_transfer),
0,
NULL,
image_transfer_cb,
NULL);
fpi_usb_transfer_submit (self->img_transfer, 0, NULL, image_transfer_cb, NULL);
break;
@@ -795,7 +799,8 @@ imaging_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (error)
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
g_clear_pointer (&self->img_transfer, fpi_usb_transfer_unref);
/* Freed by callback or cancellation */
self->img_transfer = NULL;
g_free (self->img_data);
self->img_data = NULL;
@@ -1177,10 +1182,7 @@ deactivate_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *dev,
static void
dev_deactivate (FpImageDevice *dev)
{
/* This is started/handled by execute_state_change in order to delay the
* action until after the image transfer has completed.
* We just need to override the function so that the complete handler is
* not called automatically. */
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
}
static void
@@ -1191,7 +1193,7 @@ execute_state_change (FpImageDevice *dev)
switch (self->activate_state)
{
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
fp_dbg ("deactivating");
self->irq_cb = NULL;
self->irq_cb_data = NULL;
@@ -1246,12 +1248,6 @@ execute_state_change (FpImageDevice *dev)
write_reg (dev, REG_MODE, MODE_AWAIT_FINGER_OFF,
change_state_write_reg_cb, NULL);
break;
/* Ignored states */
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
break;
}
}

View File

@@ -42,7 +42,6 @@ async_write_callback (FpiUsbTransfer *transfer, FpDevice *device,
}
/* Send data to EP1, the only out endpoint */
FP_GNUC_ACCESS (read_only, 3, 4)
static void
async_write (FpiSsm *ssm,
FpDevice *dev,

View File

@@ -147,6 +147,18 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
}
}
/* Complete loop sequential state machine */
static void
m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
if (error)
{
g_warning ("State machine completed with an error: %s", error->message);
g_error_free (error);
}
/* Free sequential state machine */
}
/* Exec init sequential state machine */
static void
m_init_state (FpiSsm *ssm, FpDevice *_dev)
@@ -164,7 +176,19 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
static void
m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpiSsm *ssm_loop;
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
if (!error)
{
/* Notify activate complete */
/* Start loop ssm */
ssm_loop = fpi_ssm_new (dev, m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_start (ssm_loop, m_loop_complete);
}
/* Free sequential state machine */
}
/* Activate device */
@@ -189,19 +213,6 @@ dev_deactivate (FpImageDevice *dev)
fpi_image_device_deactivate_complete (dev, NULL);
}
static void
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiSsm *ssm_loop;
if (state != FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
return;
/* Start a capture operation. */
ssm_loop = fpi_ssm_new (FP_DEVICE (dev), m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_start (ssm_loop, NULL);
}
static void
dev_open (FpImageDevice *dev)
{
@@ -262,7 +273,6 @@ fpi_device_vfs301_class_init (FpDeviceVfs301Class *klass)
img_class->img_close = dev_close;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->change_state = dev_change_state;
img_class->bz3_threshold = 24;

View File

@@ -93,7 +93,6 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
*out = g_steal_pointer (&transfer);
}
FP_GNUC_ACCESS (read_only, 2, 3)
static void
usb_send (FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error)
{
@@ -213,9 +212,11 @@ vfs301_proto_generate (int type, int subtype, gssize *len)
*len = 1;
return data;
}
break;
case 0x0B:
return vfs301_proto_generate_0B (subtype, len);
break;
case 0x02D0:
{
@@ -231,18 +232,22 @@ vfs301_proto_generate (int type, int subtype, gssize *len)
g_assert ((int) subtype <= G_N_ELEMENTS (dataLs));
return translate_str (dataLs[subtype - 1], len);
}
break;
case 0x0220:
switch (subtype)
{
case 1:
return translate_str (vfs301_0220_01, len);
break;
case 2:
return translate_str (vfs301_0220_02, len);
break;
case 3:
return translate_str (vfs301_0220_03, len);
break;
case 0xFA00:
case 0x2C01:
@@ -265,6 +270,7 @@ vfs301_proto_generate (int type, int subtype, gssize *len)
field[3] = field[1];
return data;
break;
}
default:
@@ -502,30 +508,30 @@ vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
FpDevice *device,
gpointer user_data, GError *error)
{
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (device);
FpDeviceVfs301 *dev = user_data;
if (error)
{
g_warning ("Error receiving data: %s", error->message);
g_error_free (error);
self->recv_progress = VFS301_FAILURE;
dev->recv_progress = VFS301_FAILURE;
return;
}
else if (transfer->actual_length < transfer->length)
{
/* TODO: process the data anyway? */
self->recv_progress = VFS301_ENDED;
dev->recv_progress = VFS301_ENDED;
return;
}
else
{
FpiUsbTransfer *new;
if (!vfs301_proto_process_data (self,
if (!vfs301_proto_process_data (dev,
transfer->length == VFS301_FP_RECV_LEN_1,
transfer->buffer,
transfer->actual_length))
{
self->recv_progress = VFS301_ENDED;
dev->recv_progress = VFS301_ENDED;
return;
}

View File

@@ -19,8 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* *INDENT-OFF* */
/* There are many similar blocks in the data below, also the data are
* self-similar (looks like some config blocks? pokes like in vfs101?) */
@@ -1623,56 +1621,56 @@ static const unsigned char vfs301_24[] = { /* 119 B */
#define vfs301_02D0_ALIGNED_BLOB \
PACKET ("0200", "8005", \
"FF830720" "5F820720" "FF830720" \
"5F820720" "FF830720" "5F820720" "FF830720" \
"5F820720" "FF830720" "5F820720" "FF8B0720" \
"608A0720" "FF930720" "61920720" "FF9B0720" \
"629A0720" "FFA30720" "63A20720" "FFAB0720" \
"64AA0720" "FFB30720" "65B20720" "FFBB0720" \
"66BA0720" "FFC30720" "67C20720" "FFCB0720" \
"68CA0720" "FFD30720" "69D20720" "FFDB0720" \
"6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \
"6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \
"6EFA0720" "FF850720" "6F840720" "FF8D0720" \
"708C0720" "FF950720" "71940720" "FF9D0720" \
"729C0720" "FFA50720" "73A40720" "FFAD0720" \
"74AC0720" "FFB50720" "75B40720" "FFBD0720" \
"76BC0720" "FFC50720" "77C40720" "FFCD0720" \
"78CC0720" "FFD50720" "79D40720" "FFDD0720" \
"7ADC0720" "FFE50720" "7BE40720" "FFED0720" \
"7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \
"7EFC0720" "FF870720" "7F860720" "FF8F0720" \
"808E0720" "FF970720" "81960720" "FF9F0720" \
"829E0720" "FFA70720" "83A60720" "FFAF0720" \
"84AE0720" "FFB70720" "85B60720" "FFBF0720" \
"86BE0720" "FFC70720" "87C60720" "FFCF0720" \
"88CE0720" "FFD70720" "89D60720" "FFDF0720" \
"8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \
"8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \
"8EFE0720" \
"FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \
"FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \
"FFDF0720" "8ADE0720" "FFD70720" "89D60720" \
"FFCF0720" "88CE0720" "FFC70720" "87C60720" \
"FFBF0720" "86BE0720" "FFB70720" "85B60720" \
"FFAF0720" "84AE0720" "FFA70720" "83A60720" \
"FF9F0720" "829E0720" "FF970720" "81960720" \
"FF8F0720" "808E0720" "FF870720" "7F860720" \
"FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \
"FFED0720" "7CEC0720" "FFE50720" "7BE40720" \
"FFDD0720" "7ADC0720" "FFD50720" "79D40720" \
"FFCD0720" "78CC0720" "FFC50720" "77C40720" \
"FFBD0720" "76BC0720" "FFB50720" "75B40720" \
"FFAD0720" "74AC0720" "FFA50720" "73A40720" \
"FF9D0720" "729C0720" "FF950720" "71940720" \
"FF8D0720" "708C0720" "FF850720" "6F840720" \
"FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \
"FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \
"FFDB0720" "6ADA0720" "FFD30720" "69D20720" \
"FFCB0720" "68CA0720" "FFC30720" "67C20720" \
"FFBB0720" "66BA0720" "FFB30720" "65B20720" \
"FFAB0720" "64AA0720" "FFA30720" "63A20720" \
"FF9B0720" "629A0720" "FF930720" "61920720" \
"FF8B0720" "608A0720" "FF830720" "5F820720" \
"5F820720" "FF830720" "5F820720" "FF830720" \
"5F820720" "FF830720" "5F820720" "FF8B0720" \
"608A0720" "FF930720" "61920720" "FF9B0720" \
"629A0720" "FFA30720" "63A20720" "FFAB0720" \
"64AA0720" "FFB30720" "65B20720" "FFBB0720" \
"66BA0720" "FFC30720" "67C20720" "FFCB0720" \
"68CA0720" "FFD30720" "69D20720" "FFDB0720" \
"6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \
"6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \
"6EFA0720" "FF850720" "6F840720" "FF8D0720" \
"708C0720" "FF950720" "71940720" "FF9D0720" \
"729C0720" "FFA50720" "73A40720" "FFAD0720" \
"74AC0720" "FFB50720" "75B40720" "FFBD0720" \
"76BC0720" "FFC50720" "77C40720" "FFCD0720" \
"78CC0720" "FFD50720" "79D40720" "FFDD0720" \
"7ADC0720" "FFE50720" "7BE40720" "FFED0720" \
"7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \
"7EFC0720" "FF870720" "7F860720" "FF8F0720" \
"808E0720" "FF970720" "81960720" "FF9F0720" \
"829E0720" "FFA70720" "83A60720" "FFAF0720" \
"84AE0720" "FFB70720" "85B60720" "FFBF0720" \
"86BE0720" "FFC70720" "87C60720" "FFCF0720" \
"88CE0720" "FFD70720" "89D60720" "FFDF0720" \
"8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \
"8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \
"8EFE0720" \
"FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \
"FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \
"FFDF0720" "8ADE0720" "FFD70720" "89D60720" \
"FFCF0720" "88CE0720" "FFC70720" "87C60720" \
"FFBF0720" "86BE0720" "FFB70720" "85B60720" \
"FFAF0720" "84AE0720" "FFA70720" "83A60720" \
"FF9F0720" "829E0720" "FF970720" "81960720" \
"FF8F0720" "808E0720" "FF870720" "7F860720" \
"FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \
"FFED0720" "7CEC0720" "FFE50720" "7BE40720" \
"FFDD0720" "7ADC0720" "FFD50720" "79D40720" \
"FFCD0720" "78CC0720" "FFC50720" "77C40720" \
"FFBD0720" "76BC0720" "FFB50720" "75B40720" \
"FFAD0720" "74AC0720" "FFA50720" "73A40720" \
"FF9D0720" "729C0720" "FF950720" "71940720" \
"FF8D0720" "708C0720" "FF850720" "6F840720" \
"FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \
"FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \
"FFDB0720" "6ADA0720" "FFD30720" "69D20720" \
"FFCB0720" "68CA0720" "FFC30720" "67C20720" \
"FFBB0720" "66BA0720" "FFB30720" "65B20720" \
"FFAB0720" "64AA0720" "FFA30720" "63A20720" \
"FF9B0720" "629A0720" "FF930720" "61920720" \
"FF8B0720" "608A0720" "FF830720" "5F820720" \
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \
@@ -1873,49 +1871,49 @@ const char *vfs301_0220_01[] = {
"A46C0420"
"A46C0400"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420" "83688420" "83688420"
"83688420" "83688420"
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
@@ -2270,55 +2268,55 @@ const char *vfs301_02D0_04[] = {
* any troubles. */
PACKET ("0200", "8005",
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
"FFF30720" "80F20720" "FFF30720" "80F20720"
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
@@ -2439,55 +2437,55 @@ const char *vfs301_02D0_05[] = {
* any troubles. */
PACKET ("0200", "8005",
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
"FFF34720" "80F24720" "FFF34720" "80F24720"
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()
Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()

View File

@@ -815,11 +815,13 @@ dev_close (FpImageDevice *dev)
GError *error = NULL;
FpDeviceVfs5011 *self = FPI_DEVICE_VFS5011 (dev);
;
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
g_free (self->capture_buffer);
g_slist_free_full (g_steal_pointer (&self->rows), g_free);
g_slist_free_full (self->rows, g_free);
fpi_image_device_close_complete (dev, error);
}

View File

@@ -1,7 +1,5 @@
#pragma once
/* *INDENT-OFF* */
#define VFS5011_LINE_SIZE 240
#define VFS5011_IMAGE_WIDTH 160

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,355 +0,0 @@
/*
* Socket utilities for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "virtual_device_connection"
#include "fpi-log.h"
#include <glib/gstdio.h>
#include <gio/gunixsocketaddress.h>
#include "virtual-device-private.h"
struct _FpiDeviceVirtualListener
{
GSocketListener parent_instance;
GSocketConnection *connection;
GCancellable *cancellable;
guint cancellable_id;
FpiDeviceVirtualListenerConnectionCb ready_cb;
gpointer ready_cb_data;
gint socket_fd;
gint client_fd;
};
G_DEFINE_TYPE (FpiDeviceVirtualListener, fpi_device_virtual_listener, G_TYPE_SOCKET_LISTENER)
static void start_listen (FpiDeviceVirtualListener *self);
FpiDeviceVirtualListener *
fpi_device_virtual_listener_new (void)
{
return g_object_new (fpi_device_virtual_listener_get_type (), NULL);
}
static void
fpi_device_virtual_listener_dispose (GObject *object)
{
FpiDeviceVirtualListener *self = FPI_DEVICE_VIRTUAL_LISTENER (object);
if (self->cancellable_id)
{
g_cancellable_disconnect (self->cancellable, self->cancellable_id);
self->cancellable_id = 0;
}
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->connection);
self->ready_cb = NULL;
G_OBJECT_CLASS (fpi_device_virtual_listener_parent_class)->dispose (object);
}
static void
fpi_device_virtual_listener_class_init (FpiDeviceVirtualListenerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = fpi_device_virtual_listener_dispose;
}
static void
fpi_device_virtual_listener_init (FpiDeviceVirtualListener *self)
{
}
static void
new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
FpiDeviceVirtualListener *self = user_data;
GSocketConnection *connection;
connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object),
res,
NULL,
&error);
if (!connection)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Error accepting a new connection: %s", error->message);
start_listen (self);
return;
}
/* Always allow further connections.
* If we get a new one, we generally just close the old connection. */
start_listen (self);
if (self->connection)
{
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
}
self->connection = connection;
fp_dbg ("Got a new connection!");
self->ready_cb (self, self->ready_cb_data);
}
static void
start_listen (FpiDeviceVirtualListener *self)
{
g_socket_listener_accept_async (G_SOCKET_LISTENER (self),
self->cancellable,
new_connection_cb,
self);
}
static void
on_cancelled (GCancellable *cancellable,
FpiDeviceVirtualListener *self)
{
fpi_device_virtual_listener_connection_close (self);
g_socket_listener_close (G_SOCKET_LISTENER (self));
g_clear_object (&self->cancellable);
self->ready_cb = NULL;
}
gboolean
fpi_device_virtual_listener_start (FpiDeviceVirtualListener *self,
const char *address,
GCancellable *cancellable,
FpiDeviceVirtualListenerConnectionCb cb,
gpointer user_data,
GError **error)
{
g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE ();
g_return_val_if_fail (FPI_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE);
g_return_val_if_fail (cb != NULL, FALSE);
g_return_val_if_fail (self->ready_cb == NULL, FALSE);
self->client_fd = -1;
g_socket_listener_set_backlog (G_SOCKET_LISTENER (self), 1);
/* Remove any left over socket. */
g_unlink (address);
addr = g_unix_socket_address_new (address);
if (!g_socket_listener_add_address (G_SOCKET_LISTENER (self),
addr,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
NULL,
NULL,
error))
{
g_warning ("Could not listen on unix socket: %s", (*error)->message);
return FALSE;
}
self->ready_cb = cb;
self->ready_cb_data = user_data;
self->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
if (self->cancellable)
self->cancellable_id = g_cancellable_connect (self->cancellable,
G_CALLBACK (on_cancelled), self, NULL);
start_listen (self);
return TRUE;
}
gboolean
fpi_device_virtual_listener_connection_close (FpiDeviceVirtualListener *self)
{
g_return_val_if_fail (FPI_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE);
if (!self->connection)
return FALSE;
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
return TRUE;
}
static void
on_stream_read_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
g_autoptr(GTask) task = user_data;
FpiDeviceVirtualListener *self = g_task_get_source_object (task);
gboolean all;
gboolean success;
gsize bytes;
all = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "all"));
if (all)
{
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
}
else
{
gssize sbytes;
sbytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
bytes = sbytes;
success = (sbytes >= 0);
}
if (g_task_return_error_if_cancelled (task))
return;
/* If we are cancelled, just return immediately. */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
{
g_task_return_int (task, 0);
return;
}
/* If this error is for an old connection (that should be closed already),
* then just give up immediately with a CLOSED error.
*/
if (self->connection &&
g_io_stream_get_input_stream (G_IO_STREAM (self->connection)) != G_INPUT_STREAM (source_object))
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CLOSED,
"Error on old connection, ignoring.");
return;
}
if (!success || bytes == 0)
{
/* We accept it if someone tries to read twice and just return that error. */
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
{
if (self->connection)
{
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
}
}
if (error)
{
g_task_return_error (task, g_steal_pointer (&error));
return;
}
else
{
// g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data");
return;
}
}
g_task_return_int (task, bytes);
}
void
fpi_device_virtual_listener_read (FpiDeviceVirtualListener *self,
gboolean all,
void *buffer,
gsize count,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
GInputStream *stream;
g_return_if_fail (FPI_IS_DEVICE_VIRTUAL_LISTENER (self));
task = g_task_new (self, self->cancellable, callback, user_data);
g_object_set_data (G_OBJECT (task), "all", GINT_TO_POINTER (all));
if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection)))
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED,
"Listener not connected to any stream");
return;
}
stream = g_io_stream_get_input_stream (G_IO_STREAM (self->connection));
if (all)
{
g_input_stream_read_all_async (stream, buffer, count,
G_PRIORITY_DEFAULT,
self->cancellable,
on_stream_read_cb,
g_steal_pointer (&task));
}
else
{
g_input_stream_read_async (stream, buffer, count,
G_PRIORITY_DEFAULT,
self->cancellable,
on_stream_read_cb,
g_steal_pointer (&task));
}
}
gsize
fpi_device_virtual_listener_read_finish (FpiDeviceVirtualListener *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, self), 0);
return g_task_propagate_int (G_TASK (result), error);
}
gboolean
fpi_device_virtual_listener_write_sync (FpiDeviceVirtualListener *self,
const char *buffer,
gsize count,
GError **error)
{
if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection)))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED,
"Listener not connected to any stream");
return FALSE;
}
return g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (self->connection)),
buffer,
count,
NULL,
self->cancellable,
error);
}

View File

@@ -1,109 +0,0 @@
/*
* Virtual driver for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* This is a virtual driver to debug the non-image based drivers. A small
* python script is provided to connect to it via a socket, allowing
* prints to registered programmatically.
* Using this, it is possible to test libfprint and fprintd.
*/
#include <gio/gio.h>
#include "fpi-device.h"
#define MAX_LINE_LEN 1024
G_DECLARE_FINAL_TYPE (FpiDeviceVirtualListener, fpi_device_virtual_listener, FPI, DEVICE_VIRTUAL_LISTENER, GSocketListener)
typedef void (*FpiDeviceVirtualListenerConnectionCb) (FpiDeviceVirtualListener *listener,
gpointer user_data);
FpiDeviceVirtualListener * fpi_device_virtual_listener_new (void);
gboolean fpi_device_virtual_listener_start (FpiDeviceVirtualListener *listener,
const char *address,
GCancellable *cancellable,
FpiDeviceVirtualListenerConnectionCb cb,
gpointer user_data,
GError **error);
gboolean fpi_device_virtual_listener_connection_close (FpiDeviceVirtualListener *listener);
void fpi_device_virtual_listener_read (FpiDeviceVirtualListener *listener,
gboolean all,
void *buffer,
gsize count,
GAsyncReadyCallback callback,
gpointer user_data);
gsize fpi_device_virtual_listener_read_finish (FpiDeviceVirtualListener *listener,
GAsyncResult *result,
GError **error);
gboolean fpi_device_virtual_listener_write_sync (FpiDeviceVirtualListener *self,
const char *buffer,
gsize count,
GError **error);
struct _FpDeviceVirtualDevice
{
FpDevice parent;
FpiDeviceVirtualListener *listener;
GCancellable *cancellable;
char recv_buf[MAX_LINE_LEN];
GPtrArray *pending_commands;
GHashTable *prints_storage;
guint wait_command_id;
guint sleep_timeout_id;
guint enroll_stages_passed;
gboolean match_reported;
gboolean supports_cancellation;
gboolean injected_synthetic_cmd;
gboolean ignore_wait;
gboolean keep_alive;
};
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice
* contents without having to use a shared private struct instead. */
G_DECLARE_FINAL_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP, DEVICE_VIRTUAL_DEVICE, FpDevice)
struct _FpDeviceVirtualDeviceStorage
{
FpDeviceVirtualDevice parent;
};
G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, FP, DEVICE_VIRTUAL_DEVICE_STORAGE, FpDeviceVirtualDevice)
char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error);
char * start_scan_command (FpDeviceVirtualDevice *self,
GError **error);
gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error);
gboolean should_wait_to_sleep (FpDeviceVirtualDevice *self,
const char *scan_id,
GError *error);

View File

@@ -1,250 +0,0 @@
/*
* Virtual driver for "simple" device debugging with storage
*
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* This is a virtual driver to debug the non-image based drivers. A small
* python script is provided to connect to it via a socket, allowing
* prints to registered programmatically.
* Using this, it is possible to test libfprint and fprintd.
*/
#define FP_COMPONENT "virtual_device_storage"
#include "virtual-device-private.h"
#include "fpi-log.h"
G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, fpi_device_virtual_device_get_type ())
static GPtrArray * get_stored_prints (FpDeviceVirtualDevice * self);
static void
dev_identify (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
g_autofree char *scan_id = NULL;
scan_id = start_scan_command (self, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
return;
if (scan_id)
{
g_autoptr(GPtrArray) stored = get_stored_prints (self);
GPtrArray *prints;
GVariant *data = NULL;
FpPrint *new_scan;
FpPrint *match = NULL;
guint idx;
new_scan = fp_print_new (dev);
fpi_print_set_type (new_scan, FPI_PRINT_RAW);
fpi_print_set_device_stored (new_scan, TRUE);
data = g_variant_new_string (scan_id);
g_object_set (new_scan, "fpi-data", data, NULL);
fpi_device_get_identify_data (dev, &prints);
g_debug ("Trying to identify print '%s' against a gallery of %u prints", scan_id, prints->len);
if (!g_ptr_array_find_with_equal_func (stored,
new_scan,
(GEqualFunc) fp_print_equal,
NULL))
error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND);
else if (g_ptr_array_find_with_equal_func (prints,
new_scan,
(GEqualFunc) fp_print_equal,
&idx))
match = g_ptr_array_index (prints, idx);
if (!self->match_reported)
{
self->match_reported = TRUE;
fpi_device_identify_report (dev,
match,
new_scan,
NULL);
}
}
else if (error && error->domain == FP_DEVICE_RETRY)
{
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (should_wait_to_sleep (self, scan_id, error))
return;
self->match_reported = FALSE;
fpi_device_identify_complete (dev, g_steal_pointer (&error));
}
struct ListData
{
FpDevice *dev;
GPtrArray *res;
};
static void
dev_list_insert_print (gpointer key,
gpointer value,
gpointer user_data)
{
struct ListData *data = user_data;
FpPrint *print = fp_print_new (data->dev);
GVariant *var = NULL;
fpi_print_fill_from_user_id (print, key);
fpi_print_set_type (print, FPI_PRINT_RAW);
var = g_variant_new_string (key);
g_object_set (print, "fpi-data", var, NULL);
g_object_ref_sink (print);
g_ptr_array_add (data->res, print);
}
static GPtrArray *
get_stored_prints (FpDeviceVirtualDevice *self)
{
GPtrArray * prints_list;
struct ListData data;
prints_list = g_ptr_array_new_full (g_hash_table_size (self->prints_storage),
g_object_unref);
data.dev = FP_DEVICE (self);
data.res = prints_list;
g_hash_table_foreach (self->prints_storage, dev_list_insert_print, &data);
return prints_list;
}
static void
dev_list (FpDevice *dev)
{
g_autoptr(GPtrArray) prints_list = NULL;
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
process_cmds (vdev, FALSE, &error);
if (should_wait_for_command (vdev, error))
return;
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
fpi_device_list_complete (dev, NULL, g_steal_pointer (&error));
return;
}
fpi_device_list_complete (dev, get_stored_prints (vdev), NULL);
}
static void
dev_delete (FpDevice *dev)
{
g_autoptr(GVariant) data = NULL;
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
FpPrint *print = NULL;
const char *id = NULL;
process_cmds (vdev, FALSE, &error);
if (should_wait_for_command (vdev, error))
return;
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
fpi_device_delete_complete (dev, g_steal_pointer (&error));
return;
}
fpi_device_get_delete_data (dev, &print);
g_object_get (print, "fpi-data", &data, NULL);
if (data == NULL)
{
fpi_device_delete_complete (dev,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return;
}
id = g_variant_get_string (data, NULL);
fp_dbg ("Deleting print %s for user %s",
id,
fp_print_get_username (print));
if (g_hash_table_remove (vdev->prints_storage, id))
fpi_device_delete_complete (dev, NULL);
else
fpi_device_delete_complete (dev,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
static void
fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self)
{
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (self);
vdev->prints_storage = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
NULL);
}
static void
fpi_device_virtual_device_storage_finalize (GObject *object)
{
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (object);
G_DEBUG_HERE ();
g_clear_pointer (&vdev->prints_storage, g_hash_table_destroy);
G_OBJECT_CLASS (fpi_device_virtual_device_storage_parent_class)->finalize (object);
}
static const FpIdEntry driver_ids[] = {
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE" },
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT" },
{ .virtual_envvar = NULL }
};
static void
fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = fpi_device_virtual_device_storage_finalize;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual device with storage and identification for debugging";
dev_class->id_table = driver_ids;
dev_class->identify = dev_identify;
dev_class->list = dev_list;
dev_class->delete = dev_delete;
fpi_device_class_auto_initialize_features (dev_class);
dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK;
}

View File

@@ -1,781 +0,0 @@
/*
* Virtual driver for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* This is a virtual driver to debug the non-image based drivers. A small
* python script is provided to connect to it via a socket, allowing
* prints to registered programmatically.
* Using this, it is possible to test libfprint and fprintd.
*/
#define FP_COMPONENT "virtual_device"
#include "virtual-device-private.h"
#include "fpi-log.h"
G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
#define INSERT_CMD_PREFIX "INSERT "
#define REMOVE_CMD_PREFIX "REMOVE "
#define SCAN_CMD_PREFIX "SCAN "
#define ERROR_CMD_PREFIX "ERROR "
#define RETRY_CMD_PREFIX "RETRY "
#define FINGER_CMD_PREFIX "FINGER "
#define SLEEP_CMD_PREFIX "SLEEP "
#define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES "
#define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE "
#define SET_CANCELLATION_PREFIX "SET_CANCELLATION_ENABLED "
#define SET_KEEP_ALIVE_PREFIX "SET_KEEP_ALIVE "
#define LIST_CMD "LIST"
#define UNPLUG_CMD "UNPLUG"
static void
maybe_continue_current_action (FpDeviceVirtualDevice *self)
{
FpDevice *dev = FP_DEVICE (self);
if (self->sleep_timeout_id)
return;
switch (fpi_device_get_current_action (dev))
{
case FPI_DEVICE_ACTION_ENROLL:
FP_DEVICE_GET_CLASS (self)->enroll (dev);
break;
case FPI_DEVICE_ACTION_VERIFY:
FP_DEVICE_GET_CLASS (self)->verify (dev);
break;
case FPI_DEVICE_ACTION_IDENTIFY:
FP_DEVICE_GET_CLASS (self)->identify (dev);
break;
case FPI_DEVICE_ACTION_LIST:
FP_DEVICE_GET_CLASS (self)->list (dev);
break;
case FPI_DEVICE_ACTION_DELETE:
FP_DEVICE_GET_CLASS (self)->delete (dev);
break;
case FPI_DEVICE_ACTION_OPEN:
FP_DEVICE_GET_CLASS (self)->open (dev);
break;
case FPI_DEVICE_ACTION_CLOSE:
FP_DEVICE_GET_CLASS (self)->close (dev);
break;
default:
break;
}
}
static gboolean
sleep_timeout_cb (gpointer data)
{
FpDeviceVirtualDevice *self = data;
self->sleep_timeout_id = 0;
if (g_cancellable_is_cancelled (self->cancellable))
return FALSE;
g_debug ("Sleeping completed");
maybe_continue_current_action (self);
return FALSE;
}
char *
process_cmds (FpDeviceVirtualDevice * self,
gboolean scan,
GError **error)
{
if (g_cancellable_is_cancelled (self->cancellable) ||
(fpi_device_get_current_action (FP_DEVICE (self)) != FPI_DEVICE_ACTION_NONE &&
g_cancellable_is_cancelled (fpi_device_get_cancellable (FP_DEVICE (self)))))
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
"Operation was cancelled");
return NULL;
}
while (self->pending_commands->len > 0)
{
gchar *cmd = g_ptr_array_index (self->pending_commands, 0);
g_debug ("Processing command %s", cmd);
/* These are always processed. */
if (g_str_has_prefix (cmd, INSERT_CMD_PREFIX))
{
g_assert (self->prints_storage);
g_hash_table_add (self->prints_storage,
g_strdup (cmd + strlen (INSERT_CMD_PREFIX)));
g_ptr_array_remove_index (self->pending_commands, 0);
continue;
}
else if (g_str_has_prefix (cmd, REMOVE_CMD_PREFIX))
{
g_assert (self->prints_storage);
if (!g_hash_table_remove (self->prints_storage,
cmd + strlen (REMOVE_CMD_PREFIX)))
g_warning ("ID %s was not found in storage", cmd + strlen (REMOVE_CMD_PREFIX));
g_ptr_array_remove_index (self->pending_commands, 0);
continue;
}
else if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
{
guint64 sleep_ms = g_ascii_strtoull (cmd + strlen (SLEEP_CMD_PREFIX), NULL, 10);
g_debug ("Sleeping %lums", sleep_ms);
self->sleep_timeout_id = g_timeout_add (sleep_ms, sleep_timeout_cb, self);
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
}
else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX))
{
g_propagate_error (error,
fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10)));
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
}
/* If we are not scanning, then we have to stop here. */
if (!scan)
{
g_warning ("Could not process command: %s", cmd);
g_ptr_array_remove_index (self->pending_commands, 0);
break;
}
if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX))
{
char *res = g_strdup (cmd + strlen (SCAN_CMD_PREFIX));
g_ptr_array_remove_index (self->pending_commands, 0);
return res;
}
else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX))
{
g_propagate_error (error,
fpi_device_retry_new (g_ascii_strtoull (cmd + strlen (RETRY_CMD_PREFIX), NULL, 10)));
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
}
else if (g_str_has_prefix (cmd, FINGER_CMD_PREFIX))
{
gboolean finger_present;
finger_present = g_ascii_strtoull (cmd + strlen (FINGER_CMD_PREFIX), NULL, 10) != 0;
fpi_device_report_finger_status_changes (FP_DEVICE (self),
finger_present ? FP_FINGER_STATUS_PRESENT : FP_FINGER_STATUS_NONE,
finger_present ? FP_FINGER_STATUS_NONE : FP_FINGER_STATUS_PRESENT);
g_ptr_array_remove_index (self->pending_commands, 0);
continue;
}
else
{
g_warning ("Could not process command: %s", cmd);
g_ptr_array_remove_index (self->pending_commands, 0);
}
}
/* No commands left, throw a timeout error. */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No commands left that can be run!");
return NULL;
}
static void
write_key_to_listener (void *key, void *val, void *user_data)
{
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (user_data);
if (!fpi_device_virtual_listener_write_sync (listener, key, strlen (key), NULL) ||
!fpi_device_virtual_listener_write_sync (listener, "\n", 1, NULL))
g_warning ("Error writing reply to LIST command");
}
static void
recv_instruction_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (source_object);
gsize bytes;
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
fp_dbg ("Got instructions of length %ld", bytes);
if (error)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Error receiving instruction data: %s", error->message);
return;
}
if (bytes > 0)
{
FpDeviceVirtualDevice *self;
g_autofree char *cmd = NULL;
self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
cmd = g_strndup (self->recv_buf, bytes);
fp_dbg ("Received command %s", cmd);
if (g_str_has_prefix (cmd, LIST_CMD))
{
if (self->prints_storage)
g_hash_table_foreach (self->prints_storage, write_key_to_listener, listener);
}
else if (g_str_has_prefix (cmd, UNPLUG_CMD))
{
fpi_device_remove (FP_DEVICE (self));
}
else if (g_str_has_prefix (cmd, SET_ENROLL_STAGES_PREFIX))
{
guint stages;
stages = g_ascii_strtoull (cmd + strlen (SET_ENROLL_STAGES_PREFIX), NULL, 10);
fpi_device_set_nr_enroll_stages (FP_DEVICE (self), stages);
}
else if (g_str_has_prefix (cmd, SET_SCAN_TYPE_PREFIX))
{
const char *scan_type = cmd + strlen (SET_SCAN_TYPE_PREFIX);
g_autoptr(GEnumClass) scan_types = g_type_class_ref (fp_scan_type_get_type ());
GEnumValue *value = g_enum_get_value_by_nick (scan_types, scan_type);
if (value)
fpi_device_set_scan_type (FP_DEVICE (self), value->value);
else
g_warning ("Scan type '%s' not found", scan_type);
}
else if (g_str_has_prefix (cmd, SET_CANCELLATION_PREFIX))
{
self->supports_cancellation = g_ascii_strtoull (
cmd + strlen (SET_CANCELLATION_PREFIX), NULL, 10) != 0;
g_debug ("Cancellation support toggled: %d",
self->supports_cancellation);
}
else if (g_str_has_prefix (cmd, SET_KEEP_ALIVE_PREFIX))
{
self->keep_alive = g_ascii_strtoull (
cmd + strlen (SET_KEEP_ALIVE_PREFIX), NULL, 10) != 0;
g_debug ("Keep alive toggled: %d", self->keep_alive);
}
else
{
g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd));
g_clear_handle_id (&self->wait_command_id, g_source_remove);
maybe_continue_current_action (self);
}
}
fpi_device_virtual_listener_connection_close (listener);
}
static void
recv_instruction (FpDeviceVirtualDevice *self)
{
fpi_device_virtual_listener_read (self->listener,
FALSE,
self->recv_buf,
sizeof (self->recv_buf),
recv_instruction_cb,
self);
}
static void
on_listener_connected (FpiDeviceVirtualListener *listener,
gpointer user_data)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
recv_instruction (self);
}
static void
dev_init (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
g_autoptr(GCancellable) cancellable = NULL;
g_autoptr(FpiDeviceVirtualListener) listener = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
G_DEBUG_HERE ();
process_cmds (self, FALSE, &error);
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
fpi_device_open_complete (dev, g_steal_pointer (&error));
return;
}
else if (self->sleep_timeout_id)
{
return;
}
else if (self->listener)
{
fpi_device_open_complete (dev, NULL);
return;
}
listener = fpi_device_virtual_listener_new ();
cancellable = g_cancellable_new ();
if (!fpi_device_virtual_listener_start (listener,
fpi_device_get_virtual_env (FP_DEVICE (self)),
cancellable,
on_listener_connected,
self,
&error))
{
fpi_device_open_complete (dev, g_steal_pointer (&error));
return;
}
self->listener = g_steal_pointer (&listener);
self->cancellable = g_steal_pointer (&cancellable);
fpi_device_open_complete (dev, NULL);
}
static gboolean
wait_for_command_timeout (gpointer data)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data);
GError *error = NULL;
self->wait_command_id = 0;
switch (fpi_device_get_current_action (FP_DEVICE (self)))
{
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_DELETE:
self->ignore_wait = TRUE;
maybe_continue_current_action (self);
self->ignore_wait = FALSE;
return FALSE;
default:
break;
}
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
fpi_device_action_error (FP_DEVICE (self), error);
return FALSE;
}
gboolean
should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error)
{
if (!error && self->sleep_timeout_id)
return TRUE;
if (self->ignore_wait)
return FALSE;
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return FALSE;
if (self->wait_command_id)
return FALSE;
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
return TRUE;
}
char *
start_scan_command (FpDeviceVirtualDevice *self,
GError **error)
{
g_autoptr(GError) local_error = NULL;
g_autofree char *scan_id = NULL;
if (fp_device_get_finger_status (FP_DEVICE (self)) == FP_FINGER_STATUS_NONE)
self->injected_synthetic_cmd = FALSE;
scan_id = process_cmds (self, TRUE, &local_error);
if (!self->sleep_timeout_id)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
}
if (should_wait_for_command (self, local_error))
{
g_assert (!scan_id);
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
"Still waiting for command");
return NULL;
}
if (local_error)
g_propagate_error (error, g_steal_pointer (&local_error));
else
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
return g_steal_pointer (&scan_id);
}
gboolean
should_wait_to_sleep (FpDeviceVirtualDevice *self,
const char *scan_id,
GError *error)
{
const gchar *cmd;
if (self->sleep_timeout_id)
return TRUE;
if (!self->pending_commands->len)
return FALSE;
cmd = g_ptr_array_index (self->pending_commands, 0);
if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
{
g_autoptr(GError) local_error = NULL;
g_free (process_cmds (self, FALSE, &local_error));
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return FALSE;
g_assert (!self->injected_synthetic_cmd);
g_assert (self->sleep_timeout_id != 0);
if (!self->pending_commands->len)
{
g_autofree char *injected_cmd = NULL;
if (scan_id)
injected_cmd = g_strconcat (SCAN_CMD_PREFIX, scan_id, NULL);
else if (error && error->domain == FP_DEVICE_ERROR)
injected_cmd = g_strdup_printf (ERROR_CMD_PREFIX " %d", error->code);
else if (error && error->domain == FP_DEVICE_RETRY)
injected_cmd = g_strdup_printf (RETRY_CMD_PREFIX " %d", error->code);
else
return TRUE;
g_debug ("Sleeping now, command queued for later: %s", injected_cmd);
g_ptr_array_insert (self->pending_commands, 0, g_steal_pointer (&injected_cmd));
self->injected_synthetic_cmd = TRUE;
}
}
return self->sleep_timeout_id != 0;
}
static void
dev_verify (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
g_autofree char *scan_id = NULL;
scan_id = start_scan_command (self, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
return;
if (scan_id)
{
GVariant *data = NULL;
FpPrint *new_scan;
FpPrint *print;
gboolean success;
g_debug ("Virtual device scanned print %s", scan_id);
fpi_device_get_verify_data (dev, &print);
new_scan = fp_print_new (dev);
fpi_print_set_type (new_scan, FPI_PRINT_RAW);
if (self->prints_storage)
fpi_print_set_device_stored (new_scan, TRUE);
data = g_variant_new_string (scan_id);
g_object_set (new_scan, "fpi-data", data, NULL);
if (self->prints_storage && !g_hash_table_contains (self->prints_storage, scan_id))
{
error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND);
success = FALSE;
}
else
{
success = fp_print_equal (print, new_scan);
}
if (!self->match_reported)
{
self->match_reported = TRUE;
fpi_device_verify_report (dev,
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
new_scan,
NULL);
}
}
else if (error)
{
g_debug ("Virtual device scan failed with error: %s", error->message);
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (error && error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
if (should_wait_to_sleep (self, scan_id, error))
return;
self->match_reported = FALSE;
fpi_device_verify_complete (dev, g_steal_pointer (&error));
}
static void
dev_enroll (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
FpPrint *print = NULL;
g_autofree char *id = NULL;
id = start_scan_command (self, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
return;
fpi_device_get_enroll_data (dev, &print);
if (id)
{
GVariant *data;
gboolean completed;
if (self->prints_storage && g_hash_table_contains (self->prints_storage, id))
{
if (should_wait_to_sleep (self, id, error))
return;
fpi_device_enroll_complete (dev, NULL,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_DUPLICATE));
return;
}
if (self->enroll_stages_passed == 0)
{
fpi_print_set_type (print, FPI_PRINT_RAW);
data = g_variant_new_string (id);
g_object_set (print, "fpi-data", data, NULL);
}
else
{
gboolean changed;
g_object_get (print, "fpi-data", &data, NULL);
changed = !g_str_equal (id, g_variant_get_string (data, NULL));
g_variant_unref (data);
if (changed)
{
g_set_error (&error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL, "ID Mismatch");
fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL,
g_steal_pointer (&error));
if (!should_wait_to_sleep (self, id, error))
self->sleep_timeout_id = g_idle_add (sleep_timeout_cb, self);
return;
}
}
self->enroll_stages_passed++;
completed = self->enroll_stages_passed == fp_device_get_nr_enroll_stages (FP_DEVICE (self));
fpi_device_report_finger_status_changes (FP_DEVICE (self),
completed ?
FP_FINGER_STATUS_NEEDED :
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
fpi_device_enroll_progress (dev, self->enroll_stages_passed, print, NULL);
if (completed)
{
if (self->prints_storage)
{
fpi_print_set_device_stored (print, TRUE);
g_hash_table_add (self->prints_storage, g_strdup (id));
}
fpi_device_enroll_complete (dev, g_object_ref (print), NULL);
self->enroll_stages_passed = 0;
}
else if (!should_wait_to_sleep (self, id, error))
{
self->sleep_timeout_id = g_idle_add (sleep_timeout_cb, self);
}
}
else
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (error && error->domain == FP_DEVICE_RETRY)
{
fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, g_steal_pointer (&error));
if (!should_wait_to_sleep (self, id, error))
self->sleep_timeout_id = g_idle_add (sleep_timeout_cb, self);
}
else
{
if (should_wait_to_sleep (self, id, error))
return;
self->enroll_stages_passed = 0;
fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error));
}
}
}
static void
dev_cancel (FpDevice *dev)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
if (self->injected_synthetic_cmd)
{
self->injected_synthetic_cmd = FALSE;
g_ptr_array_remove_index (self->pending_commands, 0);
}
if (!self->supports_cancellation)
return;
g_debug ("Got cancellation!");
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
maybe_continue_current_action (self);
}
static void
stop_listener (FpDeviceVirtualDevice *self)
{
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listener);
}
static void
dev_deinit (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
process_cmds (self, FALSE, &error);
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
fpi_device_close_complete (dev, g_steal_pointer (&error));
return;
}
else if (self->sleep_timeout_id)
{
return;
}
g_clear_handle_id (&self->wait_command_id, g_source_remove);
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
if (!self->keep_alive)
stop_listener (self);
fpi_device_close_complete (dev, NULL);
}
static void
fpi_device_virtual_device_finalize (GObject *object)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (object);
G_DEBUG_HERE ();
stop_listener (self);
g_clear_pointer (&self->pending_commands, g_ptr_array_unref);
G_OBJECT_CLASS (fpi_device_virtual_device_parent_class)->finalize (object);
}
static void
fpi_device_virtual_device_init (FpDeviceVirtualDevice *self)
{
self->supports_cancellation = TRUE;
self->pending_commands = g_ptr_array_new_with_free_func (g_free);
}
static const FpIdEntry driver_ids[] = {
{ .virtual_envvar = "FP_VIRTUAL_DEVICE", },
{ .virtual_envvar = NULL }
};
static void
fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = fpi_device_virtual_device_finalize;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual device for debugging";
dev_class->type = FP_DEVICE_TYPE_VIRTUAL;
dev_class->id_table = driver_ids;
dev_class->nr_enroll_stages = 5;
dev_class->open = dev_init;
dev_class->close = dev_deinit;
dev_class->verify = dev_verify;
dev_class->enroll = dev_enroll;
dev_class->cancel = dev_cancel;
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -29,27 +29,35 @@
#include "fpi-log.h"
#include "virtual-device-private.h"
#include "../fpi-image.h"
#include "../fpi-image-device.h"
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <gio/gunixsocketaddress.h>
struct _FpDeviceVirtualImage
{
FpImageDevice parent;
FpImageDevice parent;
FpiDeviceVirtualListener *listener;
GCancellable *cancellable;
GSocketListener *listener;
GSocketConnection *connection;
GCancellable *cancellable;
gboolean automatic_finger;
FpImage *recv_img;
gint recv_img_hdr[2];
gint socket_fd;
gint client_fd;
gboolean automatic_finger;
FpImage *recv_img;
gint recv_img_hdr[2];
};
G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVICE_VIRTUAL_IMAGE, FpImageDevice)
G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE)
static void recv_image (FpDeviceVirtualImage *self);
static void start_listen (FpDeviceVirtualImage *dev);
static void recv_image (FpDeviceVirtualImage *dev,
GInputStream *stream);
static void
recv_image_img_recv_cb (GObject *source_object,
@@ -57,16 +65,27 @@ recv_image_img_recv_cb (GObject *source_object,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (source_object);
FpDeviceVirtualImage *self;
FpImageDevice *device;
gsize bytes;
gboolean success;
gsize bytes = 0;
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
if (!bytes || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
return;
if (!success || bytes == 0)
{
if (!success)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Error receiving header for image data: %s", error->message);
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self);
@@ -78,7 +97,7 @@ recv_image_img_recv_cb (GObject *source_object,
fpi_image_device_report_finger_status (device, FALSE);
/* And, listen for more images from the same client. */
recv_image (self);
recv_image (self, G_INPUT_STREAM (source_object));
}
static void
@@ -88,30 +107,33 @@ recv_image_hdr_recv_cb (GObject *source_object,
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (source_object);
gboolean success;
gsize bytes;
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
if (error)
if (!success || bytes == 0)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
return;
if (!success)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
return;
g_warning ("Error receiving header for image data: %s", error->message);
}
g_warning ("Error receiving header for image data: %s", error->message);
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
return;
}
if (!bytes)
return;
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000)
{
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
fpi_device_virtual_listener_connection_close (listener);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
}
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
@@ -140,94 +162,131 @@ recv_image_hdr_recv_cb (GObject *source_object,
!!self->recv_img_hdr[1]);
break;
case -5:
/* -5 causes the device to disappear (no further data) */
fpi_device_remove (FP_DEVICE (self));
break;
default:
/* disconnect client, it didn't play fair */
fpi_device_virtual_listener_connection_close (listener);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
}
/* And, listen for more images from the same client. */
recv_image (self);
recv_image (self, G_INPUT_STREAM (source_object));
return;
}
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
g_debug ("image data: %p", self->recv_img->data);
fpi_device_virtual_listener_read (listener,
TRUE,
(guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height,
recv_image_img_recv_cb,
self);
g_input_stream_read_all_async (G_INPUT_STREAM (source_object),
(guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_img_recv_cb,
self);
}
static void
recv_image (FpDeviceVirtualImage *self)
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
{
fpi_device_virtual_listener_read (self->listener,
TRUE,
self->recv_img_hdr,
sizeof (self->recv_img_hdr),
recv_image_hdr_recv_cb,
self);
g_input_stream_read_all_async (stream,
dev->recv_img_hdr,
sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
}
static void
on_listener_connected (FpiDeviceVirtualListener *listener,
gpointer user_data)
new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
FpiImageDeviceState state;
g_autoptr(GError) error = NULL;
GSocketConnection *connection;
GInputStream *stream;
FpDeviceVirtualImage *dev = user_data;
self->automatic_finger = TRUE;
g_object_get (self,
"fpi-image-device-state", &state,
NULL);
switch (state)
connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object),
res,
NULL,
&error);
if (!connection)
{
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
recv_image (self);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
default:
break;
g_warning ("Error accepting a new connection: %s", error->message);
start_listen (dev);
}
/* Always further connections (but we disconnect them immediately
* if we already have a connection). */
start_listen (dev);
if (dev->connection)
{
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
return;
}
dev->connection = connection;
dev->automatic_finger = TRUE;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
recv_image (dev, stream);
fp_dbg ("Got a new connection!");
}
static void
start_listen (FpDeviceVirtualImage *dev)
{
g_socket_listener_accept_async (dev->listener,
dev->cancellable,
new_connection_cb,
dev);
}
static void
dev_init (FpImageDevice *dev)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpiDeviceVirtualListener) listener = NULL;
g_autoptr(GCancellable) cancellable = NULL;
g_autoptr(GSocketListener) listener = NULL;
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
const char *env;
g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE ();
listener = fpi_device_virtual_listener_new ();
cancellable = g_cancellable_new ();
self->client_fd = -1;
if (!fpi_device_virtual_listener_start (listener,
fpi_device_get_virtual_env (FP_DEVICE (self)),
cancellable,
on_listener_connected,
self,
&error))
env = fpi_device_get_virtual_env (FP_DEVICE (self));
listener = g_socket_listener_new ();
g_socket_listener_set_backlog (listener, 1);
/* Remove any left over socket. */
g_unlink (env);
addr = g_unix_socket_address_new (env);
if (!g_socket_listener_add_address (listener,
addr,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
NULL,
NULL,
&error))
{
fpi_image_device_open_complete (dev, g_steal_pointer (&error));
g_warning ("Could not listen on unix socket: %s", error->message);
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), g_steal_pointer (&error));
return;
}
self->listener = g_steal_pointer (&listener);
self->cancellable = g_steal_pointer (&cancellable);
self->cancellable = g_cancellable_new ();
start_listen (self);
/* Delay result to open up the possibility of testing race conditions. */
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_open_complete, NULL, NULL);
@@ -243,58 +302,24 @@ dev_deinit (FpImageDevice *dev)
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listener);
g_clear_object (&self->connection);
/* Delay result to open up the possibility of testing race conditions. */
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_close_complete, NULL, NULL);
}
static void
dev_activate (FpImageDevice *dev)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
/* Start reading (again). */
recv_image (self);
fpi_image_device_activate_complete (dev, NULL);
}
static void
dev_deactivate (FpImageDevice *dev)
{
fpi_image_device_deactivate_complete (dev, NULL);
}
G_DEBUG_HERE ();
static void
dev_notify_removed_cb (FpDevice *dev)
{
FpiImageDeviceState state;
gboolean removed;
g_object_get (dev,
"fpi-image-device-state", &state,
"removed", &removed,
NULL);
if (!removed || state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
return;
/* This error will be converted to an FP_DEVICE_ERROR_REMOVED by the
* surrounding layers. */
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev),
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
/* Delay result to open up the possibility of testing race conditions. */
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_deactivate_complete, NULL, NULL);
}
static void
fpi_device_virtual_image_init (FpDeviceVirtualImage *self)
{
/* NOTE: This is not nice, but we can generally rely on the underlying
* system to throw errors on the transport layer.
*/
g_signal_connect (self,
"notify::removed",
G_CALLBACK (dev_notify_removed_cb),
NULL);
}
static const FpIdEntry driver_ids[] = {
@@ -316,6 +341,5 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
}

View File

@@ -29,5 +29,4 @@
#include "fpi-log.h"
#include "fpi-print.h"
#include "fpi-usb-transfer.h"
#include "fpi-spi-transfer.h"
#include "fpi-ssm.h"

View File

@@ -24,18 +24,6 @@
#include "fpi-device.h"
#include <gusb.h>
#include <config.h>
#ifdef HAVE_UDEV
#include <sys/ioctl.h>
#include <sys/unistd.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <linux/hidraw.h>
#include <gudev/gudev.h>
#endif
/**
* SECTION: fp-context
* @title: FpContext
@@ -98,60 +86,6 @@ is_driver_allowed (const gchar *driver)
return FALSE;
}
typedef struct
{
FpContext *context;
FpDevice *device;
} RemoveDeviceData;
static gboolean
remove_device_idle_cb (RemoveDeviceData *data)
{
FpContextPrivate *priv = fp_context_get_instance_private (data->context);
guint idx = 0;
g_return_val_if_fail (g_ptr_array_find (priv->devices, data->device, &idx), G_SOURCE_REMOVE);
g_signal_emit (data->context, signals[DEVICE_REMOVED_SIGNAL], 0, data->device);
g_ptr_array_remove_index_fast (priv->devices, idx);
g_free (data);
return G_SOURCE_REMOVE;
}
static void
remove_device (FpContext *context, FpDevice *device)
{
RemoveDeviceData *data;
data = g_new (RemoveDeviceData, 1);
data->context = context;
data->device = device;
g_idle_add ((GSourceFunc) remove_device_idle_cb, data);
}
static void
device_remove_on_notify_open_cb (FpContext *context, GParamSpec *pspec, FpDevice *device)
{
remove_device (context, device);
}
static void
device_removed_cb (FpContext *context, FpDevice *device)
{
gboolean open = FALSE;
g_object_get (device, "open", &open, NULL);
/* Wait for device close if the device is currently still open. */
if (open)
g_signal_connect_swapped (device, "notify::open", (GCallback) device_remove_on_notify_open_cb, context);
else
remove_device (context, device);
}
static void
async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
@@ -176,9 +110,6 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u
}
g_ptr_array_add (priv->devices, device);
g_signal_connect_swapped (device, "removed", (GCallback) device_removed_cb, context);
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
}
@@ -258,7 +189,12 @@ usb_device_removed_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx
continue;
if (fpi_device_get_usb_device (dev) == device)
fpi_device_remove (dev);
{
g_signal_emit (self, signals[DEVICE_REMOVED_SIGNAL], 0, dev);
g_ptr_array_remove_index_fast (priv->devices, i);
return;
}
}
}
@@ -312,10 +248,6 @@ fp_context_class_init (FpContextClass *klass)
* @device: A #FpDevice
*
* This signal is emitted when a fingerprint reader is removed.
*
* It is guaranteed that the device has been closed before this signal
* is emitted. See the #FpDevice removed signal documentation for more
* information.
**/
signals[DEVICE_REMOVED_SIGNAL] = g_signal_new ("device-removed",
G_TYPE_FROM_CLASS (klass),
@@ -446,103 +378,6 @@ fp_context_enumerate (FpContext *context)
}
}
#ifdef HAVE_UDEV
{
g_autoptr(GUdevClient) udev_client = g_udev_client_new (NULL);
/* This uses a very simple algorithm to allocate devices to drivers and assumes that no two drivers will want the same device. Future improvements
* could add a usb_discover style udev_discover that returns a score, however for internal devices the potential overlap should be very low between
* separate drivers.
*/
g_autoptr(GList) spidev_devices = g_udev_client_query_by_subsystem (udev_client, "spidev");
g_autoptr(GList) hidraw_devices = g_udev_client_query_by_subsystem (udev_client, "hidraw");
/* for each potential driver, try to match all requested resources. */
for (i = 0; i < priv->drivers->len; i++)
{
GType driver = g_array_index (priv->drivers, GType, i);
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_UDEV)
continue;
for (entry = cls->id_table; entry->udev_types; entry++)
{
GList *matched_spidev = NULL, *matched_hidraw = NULL;
if (entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_SPIDEV)
{
for (matched_spidev = spidev_devices; matched_spidev; matched_spidev = matched_spidev->next)
{
const gchar * sysfs = g_udev_device_get_sysfs_path (matched_spidev->data);
if (!sysfs)
continue;
if (strstr (sysfs, entry->spi_acpi_id))
break;
}
/* If match was not found exit */
if (matched_spidev == NULL)
continue;
}
if (entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_HIDRAW)
{
for (matched_hidraw = hidraw_devices; matched_hidraw; matched_hidraw = matched_hidraw->next)
{
const gchar * devnode = g_udev_device_get_device_file (matched_hidraw->data);
int temp_hid = -1, res;
struct hidraw_devinfo info;
if (!devnode)
continue;
temp_hid = open (devnode, O_RDWR);
if (temp_hid < 0)
continue;
res = ioctl (temp_hid, HIDIOCGRAWINFO, &info);
close (temp_hid);
if (res < 0)
continue;
if (info.vendor == entry->hid_id.vid && info.product == entry->hid_id.pid)
break;
}
/* If match was not found exit */
if (matched_hidraw == NULL)
continue;
}
priv->pending_devices++;
g_async_initable_new_async (driver,
G_PRIORITY_LOW,
priv->cancellable,
async_device_init_done_cb,
context,
"fpi-driver-data", entry->driver_data,
"fpi-udev-data-spidev", (matched_spidev ? g_udev_device_get_device_file (matched_spidev->data) : NULL),
"fpi-udev-data-hidraw", (matched_hidraw ? g_udev_device_get_device_file (matched_hidraw->data) : NULL),
NULL);
/* remove entries from list to avoid conflicts */
if (matched_spidev)
{
g_object_unref (matched_spidev->data);
spidev_devices = g_list_delete_link (spidev_devices, matched_spidev);
}
if (matched_hidraw)
{
g_object_unref (matched_hidraw->data);
hidraw_devices = g_list_delete_link (hidraw_devices, matched_hidraw);
}
}
}
/* free all unused elemnts in both lists */
g_list_foreach (spidev_devices, (GFunc) g_object_unref, NULL);
g_list_foreach (hidraw_devices, (GFunc) g_object_unref, NULL);
}
#endif
while (priv->pending_devices)
g_main_context_iteration (NULL, TRUE);
}

View File

@@ -28,23 +28,17 @@ typedef struct
GUsbDevice *usb_device;
const gchar *virtual_env;
struct
{
gchar *spidev_path;
gchar *hidraw_path;
} udev_data;
gboolean is_removed;
gboolean is_open;
gboolean is_open;
gchar *device_id;
gchar *device_name;
FpScanType scan_type;
gchar *device_id;
gchar *device_name;
FpScanType scan_type;
guint64 driver_data;
guint64 driver_data;
gint nr_enroll_stages;
GSList *sources;
gint nr_enroll_stages;
GSList *sources;
/* We always make sure that only one task is run at a time. */
FpiDeviceAction current_action;
@@ -55,8 +49,7 @@ typedef struct
GSource *current_task_idle_return_source;
/* State for tasks */
gboolean wait_for_finger;
FpFingerStatusFlags finger_status;
gboolean wait_for_finger;
} FpDevicePrivate;

View File

@@ -44,27 +44,16 @@ enum {
PROP_DEVICE_ID,
PROP_NAME,
PROP_OPEN,
PROP_REMOVED,
PROP_NR_ENROLL_STAGES,
PROP_SCAN_TYPE,
PROP_FINGER_STATUS,
PROP_FPI_ENVIRON,
PROP_FPI_USB_DEVICE,
PROP_FPI_UDEV_DATA_SPIDEV,
PROP_FPI_UDEV_DATA_HIDRAW,
PROP_FPI_DRIVER_DATA,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
enum {
REMOVED_SIGNAL,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0, };
/**
* fp_device_retry_quark:
*
@@ -95,8 +84,6 @@ fp_device_cancel_in_idle_cb (gpointer user_data)
cls->cancel (self);
fpi_device_report_finger_status (self, FP_FINGER_STATUS_NONE);
return G_SOURCE_REMOVE;
}
@@ -140,8 +127,6 @@ fp_device_constructed (GObject *object)
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
FpDevicePrivate *priv = fp_device_get_instance_private (self);
g_assert (cls->features != FPI_DEVICE_FEATURE_NONE);
priv->type = cls->type;
if (cls->nr_enroll_stages)
priv->nr_enroll_stages = cls->nr_enroll_stages;
@@ -173,8 +158,6 @@ fp_device_finalize (GObject *object)
g_clear_object (&priv->usb_device);
g_clear_pointer (&priv->virtual_env, g_free);
g_clear_pointer (&priv->udev_data.spidev_path, g_free);
g_clear_pointer (&priv->udev_data.hidraw_path, g_free);
G_OBJECT_CLASS (fp_device_parent_class)->finalize (object);
}
@@ -191,19 +174,15 @@ fp_device_get_property (GObject *object,
switch (prop_id)
{
case PROP_NR_ENROLL_STAGES:
g_value_set_uint (value, priv->nr_enroll_stages);
g_value_set_int (value, priv->nr_enroll_stages);
break;
case PROP_SCAN_TYPE:
g_value_set_enum (value, priv->scan_type);
break;
case PROP_FINGER_STATUS:
g_value_set_flags (value, priv->finger_status);
break;
case PROP_DRIVER:
g_value_set_static_string (value, FP_DEVICE_GET_CLASS (self)->id);
g_value_set_static_string (value, FP_DEVICE_GET_CLASS (priv)->id);
break;
case PROP_DEVICE_ID:
@@ -218,10 +197,6 @@ fp_device_get_property (GObject *object,
g_value_set_boolean (value, priv->is_open);
break;
case PROP_REMOVED:
g_value_set_boolean (value, priv->is_removed);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -254,20 +229,6 @@ fp_device_set_property (GObject *object,
g_assert (g_value_get_object (value) == NULL);
break;
case PROP_FPI_UDEV_DATA_SPIDEV:
if (cls->type == FP_DEVICE_TYPE_UDEV)
priv->udev_data.spidev_path = g_value_dup_string (value);
else
g_assert (g_value_get_string (value) == NULL);
break;
case PROP_FPI_UDEV_DATA_HIDRAW:
if (cls->type == FP_DEVICE_TYPE_UDEV)
priv->udev_data.hidraw_path = g_value_dup_string (value);
else
g_assert (g_value_get_string (value) == NULL);
break;
case PROP_FPI_DRIVER_DATA:
priv->driver_data = g_value_get_uint64 (value);
break;
@@ -349,13 +310,6 @@ fp_device_class_init (FpDeviceClass *klass)
FP_TYPE_SCAN_TYPE, FP_SCAN_TYPE_SWIPE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_FINGER_STATUS] =
g_param_spec_flags ("finger-status",
"FingerStatus",
"The status of the finger",
FP_TYPE_FINGER_STATUS_FLAGS, FP_FINGER_STATUS_NONE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_DRIVER] =
g_param_spec_string ("driver",
"Driver",
@@ -383,41 +337,6 @@ fp_device_class_init (FpDeviceClass *klass)
"Whether the device is open or not", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_REMOVED] =
g_param_spec_boolean ("removed",
"Removed",
"Whether the device has been removed from the system", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
/**
* FpDevice::removed:
* @device: the #FpDevice instance that emitted the signal
*
* This signal is emitted after the device has been removed and no operation
* is pending anymore.
*
* The API user is still required to close a removed device. The above
* guarantee means that the call to close the device can be made immediately
* from the signal handler.
*
* The close operation will return FP_DEVICE_ERROR_REMOVED, but the device
* will still be considered closed afterwards.
*
* The device will only be removed from the #FpContext after it has been
* closed by the API user.
**/
signals[REMOVED_SIGNAL] = g_signal_new ("removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/* Private properties */
/**
* FpDevice::fpi-environ: (skip)
*
@@ -445,32 +364,6 @@ fp_device_class_init (FpDeviceClass *klass)
"Private: The USB device for the device",
G_USB_TYPE_DEVICE,
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
/**
* FpDevice::fpi-udev-data-spidev: (skip)
*
* This property is only for internal purposes.
*
* Stability: private
*/
properties[PROP_FPI_UDEV_DATA_SPIDEV] =
g_param_spec_string ("fpi-udev-data-spidev",
"Udev data: spidev path",
"Private: The path to /dev/spidevN.M",
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
/**
* FpDevice::fpi-udev-data-hidraw: (skip)
*
* This property is only for internal purposes.
*
* Stability: private
*/
properties[PROP_FPI_UDEV_DATA_HIDRAW] =
g_param_spec_string ("fpi-udev-data-hidraw",
"Udev data: hidraw path",
"Private: The path to /dev/hidrawN",
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
/**
* FpDevice::fpi-driver-data: (skip)
@@ -576,26 +469,6 @@ fp_device_get_scan_type (FpDevice *device)
return priv->scan_type;
}
/**
* fp_device_get_finger_status:
* @device: A #FpDevice
*
* Retrieves the finger status flags for the device.
* This can be used by the UI to present the relevant feedback, although it
* is not guaranteed to be a relevant value when not performing any action.
*
* Returns: The current #FpFingerStatusFlags
*/
FpFingerStatusFlags
fp_device_get_finger_status (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FP_FINGER_STATUS_NONE);
return priv->finger_status;
}
/**
* fp_device_get_nr_enroll_stages:
* @device: A #FpDevice
@@ -629,7 +502,7 @@ fp_device_supports_identify (FpDevice *device)
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
return cls->identify && !!(cls->features & FPI_DEVICE_FEATURE_IDENTIFY);
return cls->identify != NULL;
}
/**
@@ -647,7 +520,7 @@ fp_device_supports_capture (FpDevice *device)
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
return cls->capture && !!(cls->features & FPI_DEVICE_FEATURE_CAPTURE);
return cls->capture != NULL;
}
/**
@@ -666,7 +539,7 @@ fp_device_has_storage (FpDevice *device)
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
return !!(cls->features & FPI_DEVICE_FEATURE_STORAGE);
return cls->list != NULL;
}
/**
@@ -719,7 +592,6 @@ fp_device_open (FpDevice *device,
break;
case FP_DEVICE_TYPE_VIRTUAL:
case FP_DEVICE_TYPE_UDEV:
break;
default:
@@ -731,7 +603,6 @@ fp_device_open (FpDevice *device,
priv->current_action = FPI_DEVICE_ACTION_OPEN;
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
FP_DEVICE_GET_CLASS (device)->open (device);
}
@@ -839,7 +710,7 @@ fp_device_close_finish (FpDevice *device,
* in. The driver may make use of this metadata, when e.g. storing the print on
* device memory. It is undefined whether this print is filled in by the driver
* and returned, or whether the driver will return a newly created print after
* enrollment succeeded.
* enrollment successed.
*/
void
fp_device_enroll (FpDevice *device,
@@ -955,7 +826,6 @@ fp_device_verify (FpDevice *device,
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
FpMatchData *data;
task = g_task_new (device, cancellable, callback, user_data);
@@ -976,14 +846,6 @@ fp_device_verify (FpDevice *device,
return;
}
if (!cls->verify || !(cls->features & FPI_DEVICE_FEATURE_VERIFY))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
"Device has no verification support"));
return;
}
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
@@ -997,7 +859,7 @@ fp_device_verify (FpDevice *device,
// Attach the match data as task data so that it is destroyed
g_task_set_task_data (priv->current_task, data, (GDestroyNotify) match_data_free);
cls->verify (device);
FP_DEVICE_GET_CLASS (device)->verify (device);
}
/**
@@ -1035,7 +897,7 @@ fp_device_verify_finish (FpDevice *device,
data = g_task_get_task_data (G_TASK (result));
*print = data ? data->print : NULL;
*print = data->print;
if (*print)
g_object_ref (*print);
}
@@ -1074,7 +936,6 @@ fp_device_identify (FpDevice *device,
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpMatchData *data;
int i;
task = g_task_new (device, cancellable, callback, user_data);
if (g_task_return_error_if_cancelled (task))
@@ -1094,26 +955,12 @@ fp_device_identify (FpDevice *device,
return;
}
if (!fp_device_supports_identify (device))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
"Device has not identification support"));
return;
}
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
data = g_new0 (FpMatchData, 1);
/* We cannot store the gallery directly, because the ptr array may not own
* a reference to each print. Also, the caller could in principle modify the
* GPtrArray afterwards.
*/
data->gallery = g_ptr_array_new_full (prints->len, g_object_unref);
for (i = 0; i < prints->len; i++)
g_ptr_array_add (data->gallery, g_object_ref (g_ptr_array_index (prints, i)));
data->gallery = g_ptr_array_ref (prints);
data->match_cb = match_cb;
data->match_data = match_data;
data->match_destroy = match_destroy;
@@ -1156,13 +1003,13 @@ fp_device_identify_finish (FpDevice *device,
if (print)
{
*print = data ? data->print : NULL;
*print = data->print;
if (*print)
g_object_ref (*print);
}
if (match)
{
*match = data ? data->match : NULL;
*match = data->match;
if (*match)
g_object_ref (*match);
}
@@ -1191,7 +1038,6 @@ fp_device_capture (FpDevice *device,
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
task = g_task_new (device, cancellable, callback, user_data);
if (g_task_return_error_if_cancelled (task))
@@ -1211,21 +1057,13 @@ fp_device_capture (FpDevice *device,
return;
}
if (!cls->capture || !(cls->features & FPI_DEVICE_FEATURE_CAPTURE))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
"Device has no verification support"));
return;
}
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
priv->wait_for_finger = wait_for_finger;
cls->capture (device);
FP_DEVICE_GET_CLASS (device)->capture (device);
}
/**
@@ -1274,7 +1112,6 @@ fp_device_delete_print (FpDevice *device,
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
task = g_task_new (device, cancellable, callback, user_data);
if (g_task_return_error_if_cancelled (task))
@@ -1295,7 +1132,7 @@ fp_device_delete_print (FpDevice *device,
}
/* Succeed immediately if delete is not implemented. */
if (!cls->delete || !(cls->features & FPI_DEVICE_FEATURE_STORAGE_DELETE))
if (!FP_DEVICE_GET_CLASS (device)->delete)
{
g_task_return_boolean (task, TRUE);
return;
@@ -1309,7 +1146,7 @@ fp_device_delete_print (FpDevice *device,
g_object_ref (enrolled_print),
g_object_unref);
cls->delete (device);
FP_DEVICE_GET_CLASS (device)->delete (device);
}
/**

View File

@@ -38,12 +38,10 @@ G_DECLARE_DERIVABLE_TYPE (FpDevice, fp_device, FP, DEVICE, GObject)
/**
* FpDeviceType:
* @FP_DEVICE_TYPE_VIRTUAL: The device is a virtual device
* @FP_DEVICE_TYPE_UDEV: The device is a udev device
* @FP_DEVICE_TYPE_USB: The device is a USB device
*/
typedef enum {
FP_DEVICE_TYPE_VIRTUAL,
FP_DEVICE_TYPE_UDEV,
FP_DEVICE_TYPE_USB,
} FpDeviceType;
@@ -93,7 +91,6 @@ typedef enum {
* @FP_DEVICE_ERROR_DATA_NOT_FOUND: Requested print was not found on device
* @FP_DEVICE_ERROR_DATA_FULL: No space on device available for operation
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
*
* Error codes for device operations. More specific errors from other domains
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
@@ -109,8 +106,6 @@ typedef enum {
FP_DEVICE_ERROR_DATA_NOT_FOUND,
FP_DEVICE_ERROR_DATA_FULL,
FP_DEVICE_ERROR_DATA_DUPLICATE,
/* Leave some room to add more DATA related errors */
FP_DEVICE_ERROR_REMOVED = 0x100,
} FpDeviceError;
GQuark fp_device_retry_quark (void);
@@ -175,7 +170,6 @@ const gchar *fp_device_get_device_id (FpDevice *device);
const gchar *fp_device_get_name (FpDevice *device);
gboolean fp_device_is_open (FpDevice *device);
FpScanType fp_device_get_scan_type (FpDevice *device);
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
gint fp_device_get_nr_enroll_stages (FpDevice *device);
gboolean fp_device_supports_identify (FpDevice *device);

View File

@@ -27,19 +27,17 @@ typedef struct
{
FpiImageDeviceState state;
gboolean active;
gboolean cancelling;
gboolean finger_present;
gboolean enroll_await_on_pending;
gint enroll_stage;
gboolean minutiae_scan_active;
GError *action_error;
FpImage *capture_image;
guint pending_activation_timeout_id;
gboolean pending_activation_timeout_waiting_finger_off;
gint bz3_threshold;
} FpImageDevicePrivate;
void fpi_image_device_activate (FpImageDevice *image_device);
void fpi_image_device_deactivate (FpImageDevice *image_device,
gboolean cancelling);
void fpi_image_device_deactivate (FpImageDevice *image_device);

View File

@@ -56,6 +56,44 @@ static guint signals[LAST_SIGNAL] = { 0 };
* - sanitize_image seems a bit odd, in particular the sizing stuff.
**/
/* Static helper functions */
static gboolean
pending_activation_timeout (gpointer user_data)
{
FpImageDevice *self = FP_IMAGE_DEVICE (user_data);
FpDevice *device = FP_DEVICE (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action = fpi_device_get_current_action (device);
GError *error;
priv->pending_activation_timeout_id = 0;
if (priv->pending_activation_timeout_waiting_finger_off)
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_REMOVE_FINGER,
"Remove finger before requesting another scan operation");
else
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL, error);
fpi_device_verify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_report (device, NULL, NULL, error);
fpi_device_identify_complete (device, NULL);
}
else
{
/* Can this happen for enroll? */
fpi_device_action_error (device, error);
}
return G_SOURCE_REMOVE;
}
/* Callbacks/vfuncs */
static void
fp_image_device_open (FpDevice *device)
@@ -74,14 +112,26 @@ fp_image_device_close (FpDevice *device)
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE);
cls->img_close (self);
/* In the close case we may need to wait/force deactivation first.
* Three possible cases:
* 1. We are inactive
* -> immediately close
* 2. We are waiting for finger off
* -> immediately deactivate
* 3. We are deactivating
* -> handled by deactivate_complete */
if (!priv->active)
cls->img_close (self);
else if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE)
fpi_image_device_deactivate (self);
}
static void
fp_image_device_cancel_action (FpDevice *device)
{
FpImageDevice *self = FP_IMAGE_DEVICE (device);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action;
action = fpi_device_get_current_action (device);
@@ -92,7 +142,17 @@ fp_image_device_cancel_action (FpDevice *device)
action == FPI_DEVICE_ACTION_VERIFY ||
action == FPI_DEVICE_ACTION_IDENTIFY ||
action == FPI_DEVICE_ACTION_CAPTURE)
fpi_image_device_deactivate (self, TRUE);
{
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
/* XXX: Some nicer way of doing this would be good. */
fpi_device_action_error (FP_DEVICE (self),
g_error_new (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Device operation was cancelled"));
}
}
static void
@@ -128,9 +188,27 @@ fp_image_device_start_capture_action (FpDevice *device)
}
priv->enroll_stage = 0;
/* The internal state machine guarantees both of these. */
g_assert (!priv->finger_present);
g_assert (!priv->minutiae_scan_active);
priv->enroll_await_on_pending = FALSE;
/* The device might still be deactivating from a previous call.
* In that situation, try to wait for a bit before reporting back an
* error (which will usually say that the user should remove the
* finger).
*/
if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE || priv->active)
{
g_debug ("Got a new request while the device was still active");
g_assert (priv->pending_activation_timeout_id == 0);
priv->pending_activation_timeout_id =
g_timeout_add (100, pending_activation_timeout, device);
if (priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
priv->pending_activation_timeout_waiting_finger_off = TRUE;
else
priv->pending_activation_timeout_waiting_finger_off = FALSE;
return;
}
/* And activate the device; we rely on fpi_image_device_activate_complete()
* to be called when done (or immediately). */
@@ -147,6 +225,7 @@ fp_image_device_finalize (GObject *object)
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE);
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
G_OBJECT_CLASS (fp_image_device_parent_class)->finalize (object);
}
@@ -190,7 +269,9 @@ fp_image_device_constructed (GObject *obj)
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
/* Set default threshold. */
/* Set default values. */
fpi_device_set_nr_enroll_stages (FP_DEVICE (self), IMG_ENROLL_STAGES);
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
if (cls->bz3_threshold > 0)
priv->bz3_threshold = cls->bz3_threshold;
@@ -208,9 +289,6 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
object_class->get_property = fp_image_device_get_property;
object_class->constructed = fp_image_device_constructed;
/* Set default enroll stage count. */
fp_device_class->nr_enroll_stages = IMG_ENROLL_STAGES;
fp_device_class->open = fp_image_device_open;
fp_device_class->close = fp_image_device_close;
fp_device_class->enroll = fp_image_device_start_capture_action;
@@ -220,8 +298,6 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
fp_device_class->cancel = fp_image_device_cancel_action;
fpi_device_class_auto_initialize_features (fp_device_class);
/* Default implementations */
klass->activate = fp_image_device_default_activate;
klass->deactivate = fp_image_device_default_deactivate;

View File

@@ -281,7 +281,7 @@ fp_image_detect_minutiae_thread_func (GTask *task,
gint map_w, map_h;
gint bw, bh, bd;
gint r;
g_autofree LFSPARMS *lfsparms = NULL;
g_autofree LFSPARMS *lfsparms;
/* Normalize the image first */
if (data->flags & FPI_IMAGE_H_FLIPPED)

View File

@@ -667,25 +667,36 @@ fp_print_serialize (FpPrint *print,
for (i = 0; i < print->prints->len; i++)
{
struct xyt_struct *xyt = g_ptr_array_index (print->prints, i);
gint j;
gint32 *col = g_new (gint32, xyt->nrows);
g_variant_builder_open (&nested, G_VARIANT_TYPE ("(aiaiai)"));
for (j = 0; j < xyt->nrows; j++)
col[j] = GINT32_TO_LE (xyt->xcol[j]);
g_variant_builder_add_value (&nested,
g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
xyt->xcol,
col,
xyt->nrows,
sizeof (xyt->xcol[0])));
sizeof (col[0])));
for (j = 0; j < xyt->nrows; j++)
col[j] = GINT32_TO_LE (xyt->ycol[j]);
g_variant_builder_add_value (&nested,
g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
xyt->ycol,
col,
xyt->nrows,
sizeof (xyt->ycol[0])));
sizeof (col[0])));
for (j = 0; j < xyt->nrows; j++)
col[j] = GINT32_TO_LE (xyt->thetacol[j]);
g_variant_builder_add_value (&nested,
g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
xyt->thetacol,
col,
xyt->nrows,
sizeof (xyt->thetacol[0])));
sizeof (col[0])));
g_variant_builder_close (&nested);
g_free (col);
}
g_variant_builder_close (&nested);
@@ -808,7 +819,6 @@ fp_print_deserialize (const guchar *data,
"device-id", device_id,
"device-stored", device_stored,
NULL);
g_object_ref_sink (result);
fpi_print_set_type (result, FPI_PRINT_NBIS);
for (i = 0; i < g_variant_n_children (prints); i++)
{
@@ -858,7 +868,6 @@ fp_print_deserialize (const guchar *data,
"device-stored", device_stored,
"fpi-data", fp_data,
NULL);
g_object_ref_sink (result);
}
else
{
@@ -877,7 +886,8 @@ fp_print_deserialize (const guchar *data,
return g_steal_pointer (&result);
invalid_format:
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"Data could not be parsed");
return NULL;
*error = g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"Data could not be parsed");
return FALSE;
}

View File

@@ -66,20 +66,13 @@ typedef enum {
FP_FINGER_LAST = FP_FINGER_RIGHT_LITTLE,
} FpFinger;
/**
* FpFingerStatusFlags:
* @FP_FINGER_STATUS_NONE: Sensor has not the finger on it, nor requires it
* @FP_FINGER_STATUS_NEEDED: Sensor waits for the finger
* @FP_FINGER_STATUS_PRESENT: Sensor has the finger on it
*/
typedef enum {
FP_FINGER_STATUS_NONE = 0,
FP_FINGER_STATUS_NEEDED = 1 << 0,
FP_FINGER_STATUS_PRESENT = 1 << 1,
} FpFingerStatusFlags;
FpPrint *fp_print_new (FpDevice *device);
FpPrint *fp_print_new_from_data (guchar *data,
gsize length);
gboolean fp_print_to_data (guchar **data,
gsize length);
const gchar *fp_print_get_driver (FpPrint *print);
const gchar *fp_print_get_device_id (FpPrint *print);
FpImage *fp_print_get_image (FpPrint *print);

View File

@@ -19,7 +19,7 @@
#pragma once
#include "fp-image.h"
#include <fprint.h>
/**
* fpi_frame:

View File

@@ -23,7 +23,6 @@
#if !GLIB_CHECK_VERSION (2, 57, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GTypeClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GParamSpec, g_param_spec_unref);
#else
/* Re-define G_SOURCE_FUNC as we are technically not allowed to use it with
@@ -38,9 +37,3 @@ typedef struct _FpDeviceClass FpDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
#endif
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
#else
#define FP_GNUC_ACCESS(m, p, s)
#endif

View File

@@ -46,40 +46,6 @@ fp_device_get_instance_private (FpDevice *self)
g_type_class_get_instance_private_offset (dev_class));
}
/**
* fpi_device_class_auto_initialize_features:
*
* Initializes the #FpDeviceClass @features flags checking what device vfuncs
* are implemented.
* Drivers should call this at the end of the class initialization.
*/
void
fpi_device_class_auto_initialize_features (FpDeviceClass *device_class)
{
g_return_if_fail (FP_IS_DEVICE_CLASS (device_class));
if (device_class->capture)
device_class->features |= FPI_DEVICE_FEATURE_CAPTURE;
if (device_class->verify)
device_class->features |= FPI_DEVICE_FEATURE_VERIFY;
if (device_class->identify)
device_class->features |= FPI_DEVICE_FEATURE_IDENTIFY;
if (device_class->list)
{
device_class->features |= FPI_DEVICE_FEATURE_STORAGE;
device_class->features |= FPI_DEVICE_FEATURE_STORAGE_LIST;
}
if (device_class->delete)
{
device_class->features |= FPI_DEVICE_FEATURE_STORAGE;
device_class->features |= FPI_DEVICE_FEATURE_STORAGE_DELETE;
}
}
/**
* fpi_device_retry_new:
* @error: The #FpDeviceRetry error value describing the issue
@@ -173,10 +139,6 @@ fpi_device_error_new (FpDeviceError error)
msg = "This finger has already enrolled, please try a different finger";
break;
case FP_DEVICE_ERROR_REMOVED:
msg = "This device has been removed from the system.";
break;
default:
g_warning ("Unsupported error, returning general error instead!");
error = FP_DEVICE_ERROR_GENERAL;
@@ -250,7 +212,6 @@ fpi_device_set_nr_enroll_stages (FpDevice *device,
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_if_fail (FP_IS_DEVICE (device));
g_return_if_fail (enroll_stages > 0);
priv->nr_enroll_stages = enroll_stages;
g_object_notify (G_OBJECT (device), "nr-enroll-stages");
@@ -369,38 +330,6 @@ fpi_device_get_usb_device (FpDevice *device)
return priv->usb_device;
}
/**
* fpi_device_get_udev_data:
* @device: The #FpDevice
* @subtype: Which subtype to get information about
*
* Get a subtype-specific hardware resource for this #FpDevice. Only permissible to call if the
* #FpDevice is of type %FP_DEVICE_TYPE_UDEV.
*
* Returns: Depends on @subtype; for SPIDEV/HIDRAW returns a path to the relevant device.
*/
gpointer
fpi_device_get_udev_data (FpDevice *device, FpiDeviceUdevSubtypeFlags subtype)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
g_return_val_if_fail (priv->type == FP_DEVICE_TYPE_UDEV, NULL);
switch (subtype)
{
case FPI_DEVICE_UDEV_SUBTYPE_HIDRAW:
return priv->udev_data.hidraw_path;
case FPI_DEVICE_UDEV_SUBTYPE_SPIDEV:
return priv->udev_data.spidev_path;
default:
g_return_val_if_reached (NULL);
return NULL;
}
}
/**
* fpi_device_get_virtual_env:
* @device: The #FpDevice
@@ -647,49 +576,6 @@ fpi_device_get_cancellable (FpDevice *device)
return g_task_get_cancellable (priv->current_task);
}
static void
emit_removed_on_task_completed (FpDevice *device)
{
g_signal_emit_by_name (device, "removed");
}
/**
* fpi_device_remove:
* @device: The #FpDevice
*
* Called to signal to the #FpDevice that it has been unplugged (physically
* removed from the system).
*
* For USB devices, this API is called automatically by #FpContext.
*/
void
fpi_device_remove (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_if_fail (FP_IS_DEVICE (device));
g_return_if_fail (!priv->is_removed);
priv->is_removed = TRUE;
g_object_notify (G_OBJECT (device), "removed");
/* If there is a pending action, we wait for it to fail, otherwise we
* immediately emit the "removed" signal. */
if (priv->current_task)
{
g_signal_connect_object (priv->current_task,
"notify::completed",
(GCallback) emit_removed_on_task_completed,
device,
G_CONNECT_SWAPPED);
}
else
{
g_signal_emit_by_name (device, "removed");
}
}
/**
* fpi_device_action_error:
* @device: The #FpDevice
@@ -805,7 +691,6 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
FpDeviceTaskReturnData *data = user_data;
FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
g_autofree char *action_str = NULL;
FpiDeviceAction action;
g_autoptr(GTask) task = NULL;
@@ -814,39 +699,9 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
g_debug ("Completing action %s in idle!", action_str);
task = g_steal_pointer (&priv->current_task);
action = priv->current_action;
priv->current_action = FPI_DEVICE_ACTION_NONE;
priv->current_task_idle_return_source = NULL;
if (action == FPI_DEVICE_ACTION_OPEN &&
data->type != FP_DEVICE_TASK_RETURN_ERROR)
{
priv->is_open = TRUE;
g_object_notify (G_OBJECT (data->device), "open");
}
else if (action == FPI_DEVICE_ACTION_CLOSE)
{
/* Always consider the device closed. Drivers should try hard to close the
* device. Generally, e.g. cancellations should be ignored.
*/
priv->is_open = FALSE;
g_object_notify (G_OBJECT (data->device), "open");
}
/* Return FP_DEVICE_ERROR_REMOVED if the device is removed,
* with the exception of a successful open, which is an odd corner case. */
if (priv->is_removed &&
((action != FPI_DEVICE_ACTION_OPEN) ||
(action == FPI_DEVICE_ACTION_OPEN && data->type == FP_DEVICE_TASK_RETURN_ERROR)))
{
g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_REMOVED));
/* NOTE: The removed signal will be emitted from the GTask
* notify::completed if that is necessary. */
return G_SOURCE_REMOVE;
}
switch (data->type)
{
case FP_DEVICE_TASK_RETURN_INT:
@@ -858,17 +713,16 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
break;
case FP_DEVICE_TASK_RETURN_OBJECT:
g_task_return_pointer (task, g_steal_pointer (&data->result),
g_object_unref);
g_task_return_pointer (task, data->result, g_object_unref);
break;
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
g_task_return_pointer (task, g_steal_pointer (&data->result),
g_task_return_pointer (task, data->result,
(GDestroyNotify) g_ptr_array_unref);
break;
case FP_DEVICE_TASK_RETURN_ERROR:
g_task_return_error (task, g_steal_pointer (&data->result));
g_task_return_error (task, data->result);
break;
default:
@@ -881,30 +735,6 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
static void
fpi_device_task_return_data_free (FpDeviceTaskReturnData *data)
{
if (data->result)
{
switch (data->type)
{
case FP_DEVICE_TASK_RETURN_INT:
case FP_DEVICE_TASK_RETURN_BOOL:
break;
case FP_DEVICE_TASK_RETURN_OBJECT:
g_clear_object ((GObject **) &data->result);
break;
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
break;
case FP_DEVICE_TASK_RETURN_ERROR:
g_clear_error ((GError **) &data->result);
break;
default:
g_assert_not_reached ();
}
}
g_object_unref (data->device);
g_free (data);
}
@@ -957,7 +787,6 @@ fpi_device_probe_complete (FpDevice *device,
g_debug ("Device reported probe completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1000,7 +829,12 @@ fpi_device_open_complete (FpDevice *device, GError *error)
g_debug ("Device reported open completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
priv->is_open = TRUE;
g_object_notify (G_OBJECT (device), "open");
}
if (!error)
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
@@ -1028,7 +862,6 @@ fpi_device_close_complete (FpDevice *device, GError *error)
g_debug ("Device reported close completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
switch (priv->type)
{
@@ -1043,7 +876,6 @@ fpi_device_close_complete (FpDevice *device, GError *error)
break;
case FP_DEVICE_TYPE_VIRTUAL:
case FP_DEVICE_TYPE_UDEV:
break;
default:
@@ -1054,10 +886,16 @@ fpi_device_close_complete (FpDevice *device, GError *error)
}
if (!error)
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
GUINT_TO_POINTER (TRUE));
{
priv->is_open = FALSE;
g_object_notify (G_OBJECT (device), "open");
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
GUINT_TO_POINTER (TRUE));
}
else
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
{
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
}
}
/**
@@ -1080,14 +918,12 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
g_debug ("Device reported enroll completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
if (FP_IS_PRINT (print))
{
FpiPrintType print_type;
g_autofree char *finger_str = NULL;
g_object_get (print, "fpi-type", &print_type, NULL);
if (print_type == FPI_PRINT_UNDEFINED)
@@ -1101,9 +937,6 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
return;
}
finger_str = g_enum_to_string (FP_TYPE_FINGER, fp_print_get_finger (print));
g_debug ("Print for finger %s enrolled", finger_str);
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
}
else
@@ -1152,7 +985,6 @@ fpi_device_verify_complete (FpDevice *device,
data = g_task_get_task_data (priv->current_task);
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1212,7 +1044,6 @@ fpi_device_identify_complete (FpDevice *device,
data = g_task_get_task_data (priv->current_task);
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1228,7 +1059,7 @@ fpi_device_identify_complete (FpDevice *device,
}
else
{
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, GUINT_TO_POINTER (TRUE));
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT, GINT_TO_POINTER (TRUE));
}
}
else
@@ -1269,7 +1100,6 @@ fpi_device_capture_complete (FpDevice *device,
g_debug ("Device reported capture completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1315,7 +1145,6 @@ fpi_device_delete_complete (FpDevice *device,
g_debug ("Device reported deletion completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
@@ -1350,7 +1179,6 @@ fpi_device_list_complete (FpDevice *device,
g_debug ("Device reported listing completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (prints && error)
{
@@ -1566,59 +1394,3 @@ fpi_device_identify_report (FpDevice *device,
if (call_cb && data->match_cb)
data->match_cb (device, data->match, data->print, data->match_data, data->error);
}
/**
* fpi_device_report_finger_status:
* @device: The #FpDevice
* @finger_status: The current #FpFingerStatusFlags to report
*
* Report the finger status for the @device.
* This can be used by UI to give a feedback
*
* Returns: %TRUE if changed
*/
gboolean
fpi_device_report_finger_status (FpDevice *device,
FpFingerStatusFlags finger_status)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_autofree char *status_string = NULL;
if (priv->finger_status == finger_status)
return FALSE;
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
fp_dbg ("Device reported finger status change: %s", status_string);
priv->finger_status = finger_status;
g_object_notify (G_OBJECT (device), "finger-status");
return TRUE;
}
/**
* fpi_device_report_finger_status_changes:
* @device: The #FpDevice
* @added_status: The #FpFingerStatusFlags to add
* @removed_status: The #FpFingerStatusFlags to remove
*
* Report the finger status for the @device adding the @added_status flags
* and removing the @removed_status flags.
*
* This can be used by UI to give a feedback
*
* Returns: %TRUE if changed
*/
gboolean
fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpFingerStatusFlags finger_status = priv->finger_status;
finger_status |= added_status;
finger_status &= ~removed_status;
return fpi_device_report_finger_status (device, finger_status);
}

View File

@@ -24,18 +24,6 @@
#include "fp-image.h"
#include "fpi-print.h"
#include <config.h>
/**
* FpiDeviceUdevSubtype:
* @FPI_DEVICE_UDEV_SUBTYPE_SPIDEV: The device requires an spidev node
* @FPI_DEVICE_UDEV_SUBTYPE_HIDRAW: The device requires a hidraw node
*/
typedef enum {
FPI_DEVICE_UDEV_SUBTYPE_SPIDEV = 1 << 0,
FPI_DEVICE_UDEV_SUBTYPE_HIDRAW = 1 << 1,
} FpiDeviceUdevSubtypeFlags;
/**
* FpIdEntry:
*
@@ -55,44 +43,10 @@ struct _FpIdEntry
guint vid;
};
const gchar *virtual_envvar;
struct
{
FpiDeviceUdevSubtypeFlags udev_types;
const gchar *spi_acpi_id;
struct
{
guint pid;
guint vid;
} hid_id;
};
};
guint64 driver_data;
};
/**
* FpiDeviceFeature:
* @FPI_DEVICE_FEATURE_NONE: Device does not support any feature
* @FPI_DEVICE_FEATURE_CAPTURE: Supports image capture
* @FPI_DEVICE_FEATURE_IDENTIFY: Supports finger identification
* @FPI_DEVICE_FEATURE_VERIFY: Supports finger verification
* @FPI_DEVICE_FEATURE_STORAGE: Device has a persistent storage
* @FPI_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates
* @FPI_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates
* @FPI_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage
* @FPI_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection
*/
typedef enum /*< flags >*/ {
FPI_DEVICE_FEATURE_NONE = 0,
FPI_DEVICE_FEATURE_CAPTURE = 1 << 0,
FPI_DEVICE_FEATURE_IDENTIFY = 1 << 1,
FPI_DEVICE_FEATURE_VERIFY = 1 << 2,
FPI_DEVICE_FEATURE_STORAGE = 1 << 3,
FPI_DEVICE_FEATURE_STORAGE_LIST = 1 << 4,
FPI_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5,
FPI_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6,
FPI_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7,
} FpiDeviceFeature;
/**
* FpDeviceClass:
* @id: ID string for the driver. Should be a valid C identifier and should
@@ -100,8 +54,6 @@ typedef enum /*< flags >*/ {
* @full_name: Human readable description of the driver
* @type: The type of driver
* @id_table: The table of IDs to bind the driver to
* @features: The features the device supports, it can be initialized using
* fpi_device_class_auto_initialize_features() on @class_init.
* @nr_enroll_stages: The number of enroll stages supported devices need; use
* fpi_device_set_nr_enroll_stages() from @probe if this is dynamic.
* @scan_type: The scan type of supported devices; use
@@ -159,7 +111,6 @@ struct _FpDeviceClass
const gchar *full_name;
FpDeviceType type;
const FpIdEntry *id_table;
FpiDeviceFeature features;
/* Defaults for device properties */
gint nr_enroll_stages;
@@ -180,8 +131,6 @@ struct _FpDeviceClass
void (*cancel) (FpDevice *device);
};
void fpi_device_class_auto_initialize_features (FpDeviceClass *device_class);
/**
* FpTimeoutFunc:
* @device: The #FpDevice passed to fpi_device_add_timeout()
@@ -222,8 +171,6 @@ typedef enum {
GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
const gchar *fpi_device_get_virtual_env (FpDevice *device);
gpointer fpi_device_get_udev_data (FpDevice *device,
FpiDeviceUdevSubtypeFlags subtype);
//const gchar *fpi_device_get_spi_dev (FpDevice *device);
@@ -255,7 +202,6 @@ void fpi_device_get_delete_data (FpDevice *device,
FpPrint **print);
GCancellable *fpi_device_get_cancellable (FpDevice *device);
void fpi_device_remove (FpDevice *device);
GSource * fpi_device_add_timeout (FpDevice *device,
gint interval,
@@ -309,10 +255,4 @@ void fpi_device_identify_report (FpDevice *device,
FpPrint *print,
GError *error);
gboolean fpi_device_report_finger_status (FpDevice *device,
FpFingerStatusFlags finger_status);
gboolean fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status);
G_END_DECLS

View File

@@ -41,9 +41,6 @@ fp_image_device_get_instance_private (FpImageDevice *self)
g_type_class_get_instance_private_offset (img_class));
}
static void fp_image_device_change_state (FpImageDevice *self,
FpiImageDeviceState state);
/* Private shared functions */
void
@@ -54,105 +51,67 @@ fpi_image_device_activate (FpImageDevice *self)
g_assert (!priv->active);
/* We don't have a neutral ACTIVE state, but we always will
* go into WAIT_FINGER_ON afterwards. */
priv->state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
/* We might have been waiting for deactivation to finish before
* starting the next operation. */
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
fp_dbg ("Activating image device");
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_ACTIVATING);
cls->activate (self);
}
void
fpi_image_device_deactivate (FpImageDevice *self, gboolean cancelling)
fpi_image_device_deactivate (FpImageDevice *self)
{
FpDevice *device = FP_DEVICE (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device);
if (!priv->active || priv->state == FPI_IMAGE_DEVICE_STATE_DEACTIVATING)
if (!priv->active || priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* XXX: We currently deactivate both from minutiae scan result
* and finger off report. */
fp_dbg ("Already deactivated, ignoring request.");
return;
}
if (!cancelling && priv->state != FPI_IMAGE_DEVICE_STATE_IDLE)
g_warning ("Deactivating image device while it is not idle, this should not happen.");
if (!priv->cancelling && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
g_warning ("Deactivating image device while waiting for finger, this should not happen.");
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
fp_dbg ("Deactivating image device");
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_DEACTIVATING);
cls->deactivate (self);
}
/* Static helper functions */
/* This should not be called directly to activate/deactivate the device! */
static void
fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_autofree char *prev_state_str = NULL;
g_autofree char *state_str = NULL;
gboolean transition_is_valid = FALSE;
gint i;
struct
{
FpiImageDeviceState from;
FpiImageDeviceState to;
} valid_transitions[] = {
{ FPI_IMAGE_DEVICE_STATE_INACTIVE, FPI_IMAGE_DEVICE_STATE_ACTIVATING },
/* Cannot change to inactive using this function. */
g_assert (state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
{ FPI_IMAGE_DEVICE_STATE_ACTIVATING, FPI_IMAGE_DEVICE_STATE_IDLE },
{ FPI_IMAGE_DEVICE_STATE_ACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
{ FPI_IMAGE_DEVICE_STATE_IDLE, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON },
{ FPI_IMAGE_DEVICE_STATE_IDLE, FPI_IMAGE_DEVICE_STATE_CAPTURE }, /* raw mode -- currently not supported */
{ FPI_IMAGE_DEVICE_STATE_IDLE, FPI_IMAGE_DEVICE_STATE_DEACTIVATING },
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON, FPI_IMAGE_DEVICE_STATE_CAPTURE },
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON, FPI_IMAGE_DEVICE_STATE_DEACTIVATING }, /* cancellation */
{ FPI_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF },
{ FPI_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_IDLE }, /* raw mode -- currently not supported */
{ FPI_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_DEACTIVATING }, /* cancellation */
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF, FPI_IMAGE_DEVICE_STATE_IDLE },
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF, FPI_IMAGE_DEVICE_STATE_DEACTIVATING }, /* cancellation */
{ FPI_IMAGE_DEVICE_STATE_DEACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
};
/* We might have been waiting for the finger to go OFF to start the
* next operation. */
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
fp_dbg ("Image device internal state change from %s to %s",
prev_state_str, state_str);
for (i = 0; i < G_N_ELEMENTS (valid_transitions); i++)
{
if (valid_transitions[i].from == priv->state && valid_transitions[i].to == state)
{
transition_is_valid = TRUE;
break;
}
}
if (!transition_is_valid)
g_warning ("Internal state machine issue: transition from %s to %s should not happen!",
prev_state_str, state_str);
priv->state = state;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
g_signal_emit_by_name (self, "fpi-image-device-state-changed", priv->state);
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
}
else if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_NEEDED);
}
}
static void
@@ -160,75 +119,15 @@ fp_image_device_enroll_maybe_await_finger_on (FpImageDevice *self)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
/* We wait for both the minutiae scan to complete and the finger to
* be removed before we switch to AWAIT_FINGER_ON. */
if (priv->minutiae_scan_active || priv->finger_present)
return;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
static void
fp_image_device_maybe_complete_action (FpImageDevice *self, GError *error)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpDevice *device = FP_DEVICE (self);
FpiDeviceAction action;
if (error)
if (priv->enroll_await_on_pending)
{
/* Keep the first error we encountered, but not if it is of type retry */
if (priv->action_error && !(priv->action_error->domain == FP_DEVICE_RETRY))
{
g_warning ("Will complete with first error, new error was: %s", error->message);
g_clear_error (&error);
}
else
{
g_clear_error (&priv->action_error);
priv->action_error = error;
}
}
/* Do not complete if the device is still active or a minutiae scan is pending. */
if (priv->active || priv->minutiae_scan_active)
return;
if (!priv->action_error)
g_cancellable_set_error_if_cancelled (fpi_device_get_cancellable (device), &priv->action_error);
if (priv->action_error)
{
fpi_device_action_error (device, g_steal_pointer (&priv->action_error));
g_clear_object (&priv->capture_image);
return;
}
/* We are done, report the result. */
action = fpi_device_get_current_action (FP_DEVICE (self));
if (action == FPI_DEVICE_ACTION_ENROLL)
{
FpPrint *enroll_print;
fpi_device_get_enroll_data (device, &enroll_print);
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
}
else if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_CAPTURE)
{
fpi_device_capture_complete (device, g_steal_pointer (&priv->capture_image), NULL);
priv->enroll_await_on_pending = FALSE;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
else
{
g_assert_not_reached ();
fp_dbg ("Awaiting finger on");
priv->enroll_await_on_pending = TRUE;
}
}
@@ -244,16 +143,14 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
FpiDeviceAction action;
/* Note: We rely on the device to not disappear during an operation. */
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
priv->minutiae_scan_active = FALSE;
if (!fp_image_detect_minutiae_finish (image, res, &error))
{
/* Cancel operation . */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_image_device_deactivate (self, TRUE);
fpi_device_action_error (device, g_steal_pointer (&error));
fpi_image_device_deactivate (self);
return;
}
@@ -264,12 +161,13 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_GENERAL, "Minutiae detection failed, please retry");
}
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
action = fpi_device_get_current_action (device);
if (action == FPI_DEVICE_ACTION_CAPTURE)
{
priv->capture_image = g_steal_pointer (&image);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_device_capture_complete (device, g_steal_pointer (&image), error);
fpi_image_device_deactivate (self);
return;
}
@@ -283,9 +181,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (error->domain != FP_DEVICE_RETRY)
{
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
/* We might not yet be deactivating, if we are enrolling. */
fpi_image_device_deactivate (self, TRUE);
fpi_device_action_error (device, error);
fpi_image_device_deactivate (self);
return;
}
}
@@ -306,10 +203,10 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
g_steal_pointer (&print), error);
/* Start another scan or deactivate. */
if (priv->enroll_stage == fp_device_get_nr_enroll_stages (device))
if (priv->enroll_stage == IMG_ENROLL_STAGES)
{
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_image_device_deactivate (self, FALSE);
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
fpi_image_device_deactivate (self);
}
else
{
@@ -329,8 +226,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_device_verify_complete (device, error);
fpi_image_device_deactivate (self);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
@@ -352,8 +249,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_identify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_device_identify_complete (device, error);
fpi_image_device_deactivate (self);
}
else
{
@@ -408,19 +305,6 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action;
if (present)
{
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
}
else
{
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
}
if (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* Do we really want to always ignore such reports? We could
@@ -439,23 +323,27 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
g_debug ("Image device reported finger status: %s", present ? "on" : "off");
priv->finger_present = present;
if (present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_CAPTURE);
}
else if (!present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
{
/* If we are in the non-enroll case, we always deactivate.
*
* In the enroll case, the decision can only be made after minutiae
* detection has finished.
*/
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_IDLE);
/* We need to deactivate or continue to await finger */
/* There are three possible situations:
* 1. We are deactivating the device and the action is still in progress
* (minutiae detection).
* 2. We are still deactivating the device after an action completed
* 3. We were waiting for finger removal to start the new action
* Either way, we always end up deactivating except for the enroll case.
*
* The enroll case is special as AWAIT_FINGER_ON should only happen after
* minutiae detection to prevent deactivation (without cancellation)
* from the AWAIT_FINGER_ON state.
*/
if (action != FPI_DEVICE_ACTION_ENROLL)
fpi_image_device_deactivate (self, FALSE);
fpi_image_device_deactivate (self);
else
fp_image_device_enroll_maybe_await_finger_on (self);
}
@@ -490,9 +378,9 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
action == FPI_DEVICE_ACTION_IDENTIFY ||
action == FPI_DEVICE_ACTION_CAPTURE);
g_debug ("Image device captured an image");
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
priv->minutiae_scan_active = TRUE;
g_debug ("Image device captured an image");
/* XXX: We also detect minutiae in capture mode, we solely do this
* to normalize the image which will happen as a by-product. */
@@ -500,9 +388,6 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
fpi_device_get_cancellable (FP_DEVICE (self)),
fpi_image_device_minutiae_detected,
self);
/* XXX: This is wrong if we add support for raw capture mode. */
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
}
/**
@@ -538,27 +423,36 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
g_debug ("Reporting retry during enroll");
fpi_device_enroll_progress (FP_DEVICE (self), priv->enroll_stage, NULL, error);
/* Wait for finger removal and re-touch.
* TODO: Do we need to check that the finger is already off? */
priv->enroll_await_on_pending = TRUE;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
}
else if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
fp_image_device_maybe_complete_action (self, NULL);
fpi_image_device_deactivate (self, TRUE);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_verify_complete (FP_DEVICE (self), NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
fp_image_device_maybe_complete_action (self, NULL);
fpi_image_device_deactivate (self, TRUE);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_identify_complete (FP_DEVICE (self), NULL);
}
else
{
/* The capture case where there is no early reporting. */
g_debug ("Abort current operation due to retry (no early-reporting)");
fp_image_device_maybe_complete_action (self, error);
fpi_image_device_deactivate (self, TRUE);
/* We abort the operation and let the surrounding code retry in the
* non-enroll case (this is identical to a session error). */
g_debug ("Abort current operation due to retry (non-enroll case)");
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_action_error (FP_DEVICE (self), error);
}
}
@@ -617,8 +511,10 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
if (error->domain == FP_DEVICE_RETRY)
g_warning ("Driver should report retries using fpi_image_device_retry_scan!");
fp_image_device_maybe_complete_action (self, error);
fpi_image_device_deactivate (self, TRUE);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_action_error (FP_DEVICE (self), error);
}
/**
@@ -637,7 +533,6 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
action = fpi_device_get_current_action (FP_DEVICE (self));
g_return_if_fail (priv->active == FALSE);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_ACTIVATING);
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
action == FPI_DEVICE_ACTION_VERIFY ||
action == FPI_DEVICE_ACTION_IDENTIFY ||
@@ -656,7 +551,6 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
/* We always want to capture at this point, move to AWAIT_FINGER
* state. */
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_IDLE);
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
@@ -671,20 +565,36 @@ void
fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
FpiDeviceAction action;
g_return_if_fail (priv->active == TRUE);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_DEACTIVATING);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE);
g_debug ("Image device deactivation completed");
priv->active = FALSE;
/* Assume finger was removed. */
priv->finger_present = FALSE;
/* Deactivation completed. As we deactivate in the background
* there may already be a new task pending. Check whether we
* need to do anything. */
action = fpi_device_get_current_action (FP_DEVICE (self));
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_INACTIVE);
/* Special case, if we should be closing, but didn't due to a running
* deactivation, then do so now. */
if (action == FPI_DEVICE_ACTION_CLOSE)
{
cls->img_close (self);
return;
}
fp_image_device_maybe_complete_action (self, error);
/* We might be waiting to be able to activate again. */
if (priv->pending_activation_timeout_id)
{
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
priv->pending_activation_timeout_id =
g_idle_add ((GSourceFunc) fpi_image_device_activate, self);
}
}
/**
@@ -710,8 +620,6 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
fpi_device_report_finger_status (FP_DEVICE (self), FP_FINGER_STATUS_NONE);
fpi_device_open_complete (FP_DEVICE (self), error);
}

View File

@@ -25,9 +25,6 @@
/**
* FpiImageDeviceState:
* @FPI_IMAGE_DEVICE_STATE_INACTIVE: inactive
* @FPI_IMAGE_DEVICE_STATE_ACTIVATING: State during activate callback
* @FPI_IMAGE_DEVICE_STATE_IDLE: Activated but idle
* @FPI_IMAGE_DEVICE_STATE_DEACTIVATING: State during deactivate callback
* @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
* @FPI_IMAGE_DEVICE_STATE_CAPTURE: capturing an image
* @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed
@@ -38,33 +35,9 @@
* The driver needs to call fpi_image_device_report_finger_status() to move
* between the different states. Note that the capture state might be entered
* unconditionally if the device supports raw capturing.
*
* A usual run would look like:
* - inactive -> activating: activate vfunc is called
* - activating -> idle: fpi_image_device_activate_complete()
* - idle -> await-finger-on
* - await-finger-on -> capture: fpi_image_device_report_finger_status()
* - capture -> await-finger-off: fpi_image_device_image_captured()
* - await-finger-off -> idle: fpi_image_device_report_finger_status()
* - idle -> deactivating: deactivate vfunc is called
* - deactivating -> inactive: fpi_image_device_deactivate_complete()
*
* Raw mode is currently not supported (not waiting for finger), but in that
* case the following transitions are valid:
* - idle -> capture
* - capture -> idle
*
* Also valid are these transitions in case of errors or cancellations:
* - activating -> inactive: fpi_image_device_activate_complete()
* - await-finger-on -> deactivating: deactivate vfunc is called
* - capture -> deactivating: deactivate vfunc is called
* - await-finger-off -> deactivating: deactivate vfunc is called
*/
typedef enum {
FPI_IMAGE_DEVICE_STATE_INACTIVE,
FPI_IMAGE_DEVICE_STATE_ACTIVATING,
FPI_IMAGE_DEVICE_STATE_DEACTIVATING,
FPI_IMAGE_DEVICE_STATE_IDLE,
FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON,
FPI_IMAGE_DEVICE_STATE_CAPTURE,
FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF,
@@ -85,6 +58,11 @@ typedef enum {
* finger or image capture). Implementing this is optional, it can e.g. be
* used to flash an LED when waiting for a finger.
*
* These are the main entry points for image based drivers. For all but the
* change_state vfunc, implementations *must* eventually call the corresponding
* function to finish the operation. It is also acceptable to call the generic
*
*
* These are the main entry points for drivers to implement. Drivers may not
* implement all of these entry points if they do not support the operation
* (or a default implementation is sufficient).

View File

@@ -1,432 +0,0 @@
/*
* FPrint SPI transfer handling
* Copyright (C) 2019-2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fpi-spi-transfer.h"
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <errno.h>
/**
* SECTION:fpi-spi-transfer
* @title: SPI transfer helpers
* @short_description: Helpers to ease SPI transfers
*
* #FpiSpiTransfer is a structure to simplify the SPI transfer handling
* for the linux spidev device. The main goal are to ease memory management
* and provide a usable asynchronous API to libfprint drivers.
*
* Currently only transfers with a write and subsequent read are supported.
*
* Drivers should always use this API rather than calling read/write/ioctl on
* the spidev device.
*
* Setting G_MESSAGES_DEBUG and FP_DEBUG_TRANSFER will result in the message
* content to be dumped.
*/
G_DEFINE_BOXED_TYPE (FpiSpiTransfer, fpi_spi_transfer, fpi_spi_transfer_ref, fpi_spi_transfer_unref)
static void
dump_buffer (guchar *buf, gssize dump_len)
{
g_autoptr(GString) line = NULL;
line = g_string_new ("");
/* Dump the buffer. */
for (gssize i = 0; i < dump_len; i++)
{
g_string_append_printf (line, "%02x ", buf[i]);
if ((i + 1) % 16 == 0)
{
g_debug ("%s", line->str);
g_string_set_size (line, 0);
}
}
if (line->len)
g_debug ("%s", line->str);
}
static void
log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
{
if (g_getenv ("FP_DEBUG_TRANSFER"))
{
if (submit)
{
g_debug ("Transfer %p submitted, write length %zd, read length %zd",
transfer,
transfer->length_wr,
transfer->length_rd);
if (transfer->buffer_wr)
dump_buffer (transfer->buffer_wr, transfer->length_wr);
}
else
{
g_autofree gchar *error_str = NULL;
if (error)
error_str = g_strdup_printf ("with error (%s)", error->message);
else
error_str = g_strdup ("successfully");
g_debug ("Transfer %p completed %s, write length %zd, read length %zd",
transfer,
error_str,
transfer->length_wr,
transfer->length_rd);
if (transfer->buffer_rd)
dump_buffer (transfer->buffer_rd, transfer->length_rd);
}
}
}
/**
* fpi_spi_transfer_new:
* @device: The #FpDevice the transfer is for
* @spidev_fd: The file descriptor for the spidev device
*
* Creates a new #FpiSpiTransfer.
*
* Returns: (transfer full): A newly created #FpiSpiTransfer
*/
FpiSpiTransfer *
fpi_spi_transfer_new (FpDevice * device, int spidev_fd)
{
FpiSpiTransfer *self;
g_assert (FP_IS_DEVICE (device));
self = g_slice_new0 (FpiSpiTransfer);
self->ref_count = 1;
/* Purely to enhance the debug log output. */
self->length_wr = -1;
self->length_rd = -1;
self->device = device;
self->spidev_fd = spidev_fd;
return self;
}
static void
fpi_spi_transfer_free (FpiSpiTransfer *self)
{
g_assert (self);
g_assert_cmpint (self->ref_count, ==, 0);
if (self->free_buffer_wr && self->buffer_wr)
self->free_buffer_wr (self->buffer_wr);
if (self->free_buffer_rd && self->buffer_rd)
self->free_buffer_rd (self->buffer_rd);
self->buffer_wr = NULL;
self->buffer_rd = NULL;
g_slice_free (FpiSpiTransfer, self);
}
/**
* fpi_spi_transfer_ref:
* @self: A #FpiSpiTransfer
*
* Increments the reference count of @self by one.
*
* Returns: (transfer full): @self
*/
FpiSpiTransfer *
fpi_spi_transfer_ref (FpiSpiTransfer *self)
{
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (self->ref_count, NULL);
g_atomic_int_inc (&self->ref_count);
return self;
}
/**
* fpi_spi_transfer_unref:
* @self: A #FpiSpiTransfer
*
* Decrements the reference count of @self by one, freeing the structure when
* the reference count reaches zero.
*/
void
fpi_spi_transfer_unref (FpiSpiTransfer *self)
{
g_return_if_fail (self);
g_return_if_fail (self->ref_count);
if (g_atomic_int_dec_and_test (&self->ref_count))
fpi_spi_transfer_free (self);
}
/**
* fpi_spi_transfer_write:
* @transfer: The #FpiSpiTransfer
* @length: The buffer size to allocate
*
* Prepare the write part of an SPI transfer allocating a new buffer
* internally that will be free'ed automatically.
*/
void
fpi_spi_transfer_write (FpiSpiTransfer *transfer,
gsize length)
{
fpi_spi_transfer_write_full (transfer,
g_malloc0 (length),
length,
g_free);
}
/**
* fpi_spi_transfer_write_full:
* @transfer: The #FpiSpiTransfer
* @buffer: The data to write.
* @length: The size of @buffer
* @free_func: (destroy buffer): Destroy notify for @buffer
*
* Prepare the write part of an SPI transfer.
*/
void
fpi_spi_transfer_write_full (FpiSpiTransfer *transfer,
guint8 *buffer,
gsize length,
GDestroyNotify free_func)
{
g_assert (buffer != NULL);
g_return_if_fail (transfer);
/* Write is always before read, so ensure both are NULL. */
g_return_if_fail (transfer->buffer_wr == NULL);
g_return_if_fail (transfer->buffer_rd == NULL);
transfer->buffer_wr = buffer;
transfer->length_wr = length;
transfer->free_buffer_wr = free_func;
}
/**
* fpi_spi_transfer_read:
* @transfer: The #FpiSpiTransfer
* @length: The buffer size to allocate
*
* Prepare the read part of an SPI transfer allocating a new buffer
* internally that will be free'ed automatically.
*/
void
fpi_spi_transfer_read (FpiSpiTransfer *transfer,
gsize length)
{
fpi_spi_transfer_read_full (transfer,
g_malloc0 (length),
length,
g_free);
}
/**
* fpi_spi_transfer_read_full:
* @transfer: The #FpiSpiTransfer
* @buffer: Buffer to read data into.
* @length: The size of @buffer
* @free_func: (destroy buffer): Destroy notify for @buffer
*
* Prepare the read part of an SPI transfer.
*/
void
fpi_spi_transfer_read_full (FpiSpiTransfer *transfer,
guint8 *buffer,
gsize length,
GDestroyNotify free_func)
{
g_assert (buffer != NULL);
g_return_if_fail (transfer);
g_return_if_fail (transfer->buffer_rd == NULL);
transfer->buffer_rd = buffer;
transfer->length_rd = length;
transfer->free_buffer_rd = free_func;
}
static void
transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GTask *task = G_TASK (res);
FpiSpiTransfer *transfer = g_task_get_task_data (task);
GError *error = NULL;
FpiSpiTransferCallback callback;
g_task_propagate_boolean (task, &error);
log_transfer (transfer, FALSE, error);
callback = transfer->callback;
transfer->callback = NULL;
callback (transfer, transfer->device, transfer->user_data, error);
}
static void
transfer_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
FpiSpiTransfer *transfer = (FpiSpiTransfer *) task_data;
struct spi_ioc_transfer xfer[2];
int transfers = 0;
int status;
if (transfer->buffer_wr == NULL && transfer->buffer_rd == NULL)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
"Transfer with neither write or read!");
return;
}
memset (xfer, 0, sizeof (xfer));
if (transfer->buffer_wr)
{
xfer[transfers].tx_buf = (guint64) transfer->buffer_wr;
xfer[transfers].len = transfer->length_wr;
transfers += 1;
}
if (transfer->buffer_rd)
{
xfer[transfers].rx_buf = (guint64) transfer->buffer_rd;
xfer[transfers].len = transfer->length_rd;
transfers += 1;
}
/* This ioctl cannot be interrupted. */
status = ioctl (transfer->spidev_fd, SPI_IOC_MESSAGE (transfers), xfer);
if (status < 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
g_io_error_from_errno (errno),
"Error invoking ioctl for SPI transfer (%d)",
errno);
}
else
{
g_task_return_boolean (task, TRUE);
}
}
/**
* fpi_spi_transfer_submit:
* @transfer: (transfer full): The transfer to submit, must have been filled.
* @cancellable: Cancellable to use, e.g. fpi_device_get_cancellable()
* @callback: Callback on completion or error
* @user_data: Data to pass to callback
*
* Submit an SPI transfer with a specific timeout and callback functions.
*
* The underlying transfer cannot be cancelled. The current implementation
* will only call @callback after the transfer has been completed.
*
* Note that #FpiSpiTransfer will be stolen when this function is called.
* So that all associated data will be free'ed automatically, after the
* callback ran unless fpi_usb_transfer_ref() is explicitly called.
*/
void
fpi_spi_transfer_submit (FpiSpiTransfer *transfer,
GCancellable *cancellable,
FpiSpiTransferCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_return_if_fail (transfer);
g_return_if_fail (callback);
/* Recycling is allowed, but not two at the same time. */
g_return_if_fail (transfer->callback == NULL);
transfer->callback = callback;
transfer->user_data = user_data;
log_transfer (transfer, TRUE, NULL);
task = g_task_new (transfer->device,
cancellable,
transfer_finish_cb,
NULL);
g_task_set_task_data (task,
g_steal_pointer (&transfer),
(GDestroyNotify) fpi_spi_transfer_unref);
g_task_run_in_thread (task, transfer_thread_func);
}
/**
* fpi_spi_transfer_submit_sync:
* @transfer: The transfer to submit, must have been filled.
* @error: Location to store #GError to
*
* Synchronously submit an SPI transfer. Use of this function is discouraged
* as it will block all other operations in the application.
*
* Note that you still need to fpi_spi_transfer_unref() the
* #FpiSpiTransfer afterwards.
*
* Returns: #TRUE on success, otherwise #FALSE and @error will be set
*/
gboolean
fpi_spi_transfer_submit_sync (FpiSpiTransfer *transfer,
GError **error)
{
g_autoptr(GTask) task = NULL;
GError *err = NULL;
gboolean res;
g_return_val_if_fail (transfer, FALSE);
/* Recycling is allowed, but not two at the same time. */
g_return_val_if_fail (transfer->callback == NULL, FALSE);
log_transfer (transfer, TRUE, NULL);
task = g_task_new (transfer->device,
NULL,
NULL,
NULL);
g_task_set_task_data (task,
fpi_spi_transfer_ref (transfer),
(GDestroyNotify) fpi_spi_transfer_unref);
g_task_run_in_thread_sync (task, transfer_thread_func);
res = g_task_propagate_boolean (task, &err);
log_transfer (transfer, FALSE, err);
g_propagate_error (error, err);
return res;
}

View File

@@ -1,113 +0,0 @@
/*
* FPrint spidev transfer handling
* Copyright (C) 2019-2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-compat.h"
#include "fpi-device.h"
G_BEGIN_DECLS
#define FPI_TYPE_SPI_TRANSFER (fpi_spi_transfer_get_type ())
typedef struct _FpiSpiTransfer FpiSpiTransfer;
typedef struct _FpiSsm FpiSsm;
typedef void (*FpiSpiTransferCallback)(FpiSpiTransfer *transfer,
FpDevice *dev,
gpointer user_data,
GError *error);
/**
* FpiSpiTransfer:
* @device: The #FpDevice that the transfer belongs to.
* @ssm: Storage slot to associate the transfer with a state machine.
* Used by fpi_ssm_spi_transfer_cb() to modify the given state machine.
* @length_wr: The length of the write buffer
* @length_rd: The length of the read buffer
* @buffer_wr: The write buffer.
* @buffer_rd: The read buffer.
*
* Helper for handling SPI transfers. Currently transfers can either be pure
* write/read transfers or a write followed by a read (full duplex support
* can easily be added if desired).
*/
struct _FpiSpiTransfer
{
/*< public >*/
FpDevice *device;
FpiSsm *ssm;
gssize length_wr;
gssize length_rd;
guchar *buffer_wr;
guchar *buffer_rd;
/*< private >*/
guint ref_count;
int spidev_fd;
/* Callbacks */
gpointer user_data;
FpiSpiTransferCallback callback;
/* Data free function */
GDestroyNotify free_buffer_wr;
GDestroyNotify free_buffer_rd;
};
GType fpi_spi_transfer_get_type (void) G_GNUC_CONST;
FpiSpiTransfer *fpi_spi_transfer_new (FpDevice *device,
int spidev_fd);
FpiSpiTransfer *fpi_spi_transfer_ref (FpiSpiTransfer *self);
void fpi_spi_transfer_unref (FpiSpiTransfer *self);
void fpi_spi_transfer_write (FpiSpiTransfer *transfer,
gsize length);
FP_GNUC_ACCESS (read_only, 2, 3)
void fpi_spi_transfer_write_full (FpiSpiTransfer *transfer,
guint8 *buffer,
gsize length,
GDestroyNotify free_func);
void fpi_spi_transfer_read (FpiSpiTransfer *transfer,
gsize length);
FP_GNUC_ACCESS (write_only, 2, 3)
void fpi_spi_transfer_read_full (FpiSpiTransfer *transfer,
guint8 *buffer,
gsize length,
GDestroyNotify free_func);
void fpi_spi_transfer_submit (FpiSpiTransfer *transfer,
GCancellable *cancellable,
FpiSpiTransferCallback callback,
gpointer user_data);
gboolean fpi_spi_transfer_submit_sync (FpiSpiTransfer *transfer,
GError **error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiSpiTransfer, fpi_spi_transfer_unref)
G_END_DECLS

View File

@@ -74,7 +74,7 @@
* upon success (or fails).
*
* Your completion callback should examine the return value of
* fpi_ssm_get_error() in order to determine whether the #FpiSsm completed or
* fpi_ssm_get_error() in ordater to determine whether the #FpiSsm completed or
* failed. An error code of zero indicates successful completion.
*/
@@ -130,7 +130,6 @@ fpi_ssm_new_full (FpDevice *dev,
{
FpiSsm *machine;
BUG_ON (dev == NULL);
BUG_ON (nr_states < 1);
BUG_ON (handler == NULL);
@@ -156,8 +155,6 @@ fpi_ssm_set_data (FpiSsm *machine,
gpointer ssm_data,
GDestroyNotify ssm_data_destroy)
{
g_return_if_fail (machine);
if (machine->ssm_data_destroy && machine->ssm_data)
machine->ssm_data_destroy (machine->ssm_data);
@@ -176,32 +173,12 @@ fpi_ssm_set_data (FpiSsm *machine,
void *
fpi_ssm_get_data (FpiSsm *machine)
{
g_return_val_if_fail (machine, NULL);
return machine->ssm_data;
}
/**
* fpi_ssm_get_device:
* @machine: an #FpiSsm state machine
*
* Retrieve the device that the SSM is for.
*
* Returns: #FpDevice
*/
FpDevice *
fpi_ssm_get_device (FpiSsm *machine)
{
g_return_val_if_fail (machine, NULL);
return machine->dev;
}
static void
fpi_ssm_clear_delayed_action (FpiSsm *machine)
{
g_return_if_fail (machine);
if (machine->cancellable_id)
{
g_cancellable_disconnect (machine->cancellable, machine->cancellable_id);
@@ -258,8 +235,6 @@ fpi_ssm_set_delayed_action_timeout (FpiSsm *machine,
gpointer user_data,
GDestroyNotify destroy_func)
{
g_return_if_fail (machine);
BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
@@ -327,8 +302,6 @@ __ssm_call_handler (FpiSsm *machine)
void
fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback)
{
g_return_if_fail (ssm != NULL);
BUG_ON (!ssm->completed);
ssm->callback = callback;
ssm->cur_state = 0;
@@ -363,9 +336,6 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
void
fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
{
g_return_if_fail (parent != NULL);
g_return_if_fail (child != NULL);
BUG_ON (parent->timeout);
child->parentsm = parent;
@@ -385,8 +355,6 @@ fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
void
fpi_ssm_mark_completed (FpiSsm *machine)
{
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
@@ -459,7 +427,6 @@ fpi_ssm_mark_completed_delayed (FpiSsm *machine,
void
fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
{
g_return_if_fail (machine != NULL);
g_assert (error);
if (machine->error)
{
@@ -567,8 +534,6 @@ fpi_ssm_next_state_delayed (FpiSsm *machine,
void
fpi_ssm_jump_to_state (FpiSsm *machine, int state)
{
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
BUG_ON (state < 0 || state >= machine->nr_states);
BUG_ON (machine->timeout != NULL);
@@ -645,8 +610,6 @@ fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
int
fpi_ssm_get_cur_state (FpiSsm *machine)
{
g_return_val_if_fail (machine != NULL, 0);
return machine->cur_state;
}
@@ -661,8 +624,6 @@ fpi_ssm_get_cur_state (FpiSsm *machine)
GError *
fpi_ssm_get_error (FpiSsm *machine)
{
g_return_val_if_fail (machine != NULL, NULL);
return machine->error;
}
@@ -677,8 +638,6 @@ fpi_ssm_get_error (FpiSsm *machine)
GError *
fpi_ssm_dup_error (FpiSsm *machine)
{
g_return_val_if_fail (machine != NULL, NULL);
if (machine->error)
return g_error_copy (machine->error);
@@ -737,56 +696,3 @@ fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, error);
}
/**
* fpi_ssm_spi_transfer_cb:
* @transfer: a #FpiSpiTransfer
* @device: a #FpDevice
* @unused_data: User data (unused)
* @error: The #GError or %NULL
*
* Can be used in as a #FpiSpiTransfer callback handler to automatically
* advance or fail a statemachine on transfer completion.
*
* Make sure to set the #FpiSsm on the transfer.
*/
void
fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer, FpDevice *device,
gpointer unused_data, GError *error)
{
g_return_if_fail (transfer->ssm);
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
/**
* fpi_ssm_spi_transfer_with_weak_pointer_cb:
* @transfer: a #FpiSpiTransfer
* @device: a #FpDevice
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
* #gpointer to nullify when the callback is completed. I.e a
* pointer to the current #FpiSpiTransfer.
* @error: The #GError or %NULL
*
* Can be used in as a #FpiSpiTransfer callback handler to automatically
* advance or fail a statemachine on transfer completion.
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
* with the transfer.
*
* Make sure to set the #FpiSsm on the transfer.
*/
void
fpi_ssm_spi_transfer_with_weak_pointer_cb (FpiSpiTransfer *transfer,
FpDevice *device, gpointer weak_ptr,
GError *error)
{
g_return_if_fail (transfer->ssm);
if (weak_ptr)
g_nullify_pointer ((gpointer *) weak_ptr);
fpi_ssm_spi_transfer_cb (transfer, device, weak_ptr, error);
}

View File

@@ -93,7 +93,6 @@ void fpi_ssm_set_data (FpiSsm *machine,
gpointer ssm_data,
GDestroyNotify ssm_data_destroy);
gpointer fpi_ssm_get_data (FpiSsm *machine);
FpDevice * fpi_ssm_get_device (FpiSsm *machine);
GError * fpi_ssm_get_error (FpiSsm *machine);
GError * fpi_ssm_dup_error (FpiSsm *machine);
int fpi_ssm_get_cur_state (FpiSsm *machine);
@@ -112,15 +111,4 @@ void fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
gpointer weak_ptr,
GError *error);
typedef struct _FpiSpiTransfer FpiSpiTransfer;
void fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer,
FpDevice *device,
gpointer unused_data,
GError *error);
void fpi_ssm_spi_transfer_with_weak_pointer_cb (FpiSpiTransfer *transfer,
FpDevice *device,
gpointer weak_ptr,
GError *error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiSsm, fpi_ssm_free)

View File

@@ -187,7 +187,7 @@ fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer,
* fpi_usb_transfer_fill_bulk_full:
* @transfer: The #FpiUsbTransfer
* @endpoint: The endpoint to send the transfer to
* @buffer: The data to send.
* @buffer: The data to send. A buffer will be created and managed for you if you pass NULL.
* @length: The size of @buffer
* @free_func: (destroy buffer): Destroy notify for @buffer
*
@@ -275,7 +275,7 @@ fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer,
* fpi_usb_transfer_fill_interrupt_full:
* @transfer: The #FpiUsbTransfer
* @endpoint: The endpoint to send the transfer to
* @buffer: The data to send.
* @buffer: The data to send. A buffer will be created and managed for you if you pass NULL.
* @length: The size of @buffer
* @free_func: (destroy buffer): Destroy notify for @buffer
*
@@ -354,24 +354,6 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
fpi_usb_transfer_unref (transfer);
}
static gboolean
transfer_cancel_cb (FpiUsbTransfer *transfer)
{
GError *error;
FpiUsbTransferCallback callback;
error = g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Transfer was cancelled before being started");
callback = transfer->callback;
transfer->callback = NULL;
transfer->actual_length = -1;
callback (transfer, transfer->device, transfer->user_data, error);
fpi_usb_transfer_unref (transfer);
return G_SOURCE_REMOVE;
}
/**
* fpi_usb_transfer_submit:
@@ -405,18 +387,6 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
log_transfer (transfer, TRUE, NULL);
/* Work around libgusb cancellation issue, see
* https://github.com/hughsie/libgusb/pull/42
* should be fixed with libgusb 0.3.7.
* Note that this is not race free, we rely on libfprint and API users
* not cancelling from a different thread here.
*/
if (cancellable && g_cancellable_is_cancelled (cancellable))
{
g_idle_add ((GSourceFunc) transfer_cancel_cb, transfer);
return;
}
switch (transfer->type)
{
case FP_TRANSFER_BULK:

View File

@@ -20,7 +20,6 @@
#pragma once
#include <gusb.h>
#include "fpi-compat.h"
#include "fpi-device.h"
G_BEGIN_DECLS
@@ -116,7 +115,6 @@ void fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer,
guint8 endpoint,
gsize length);
FP_GNUC_ACCESS (read_only, 3, 4)
void fpi_usb_transfer_fill_bulk_full (FpiUsbTransfer *transfer,
guint8 endpoint,
guint8 *buffer,
@@ -136,7 +134,6 @@ void fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer,
guint8 endpoint,
gsize length);
FP_GNUC_ACCESS (read_only, 3, 4)
void fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
guint8 endpoint,
guint8 *buffer,

View File

@@ -1,213 +0,0 @@
/*
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include "fpi-context.h"
#include "fpi-device.h"
static const FpIdEntry whitelist_id_table[] = {
/* Currently known and unsupported devices.
* You can generate this list from the wiki page using e.g.:
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
*/
{ .vid = 0x04f3, .pid = 0x036b },
{ .vid = 0x04f3, .pid = 0x0c00 },
{ .vid = 0x04f3, .pid = 0x0c4b },
{ .vid = 0x04f3, .pid = 0x0c4c },
{ .vid = 0x04f3, .pid = 0x0c4f },
{ .vid = 0x04f3, .pid = 0x0c57 },
{ .vid = 0x04f3, .pid = 0x0c5e },
{ .vid = 0x04f3, .pid = 0x2706 },
{ .vid = 0x06cb, .pid = 0x0081 },
{ .vid = 0x06cb, .pid = 0x0088 },
{ .vid = 0x06cb, .pid = 0x008a },
{ .vid = 0x06cb, .pid = 0x009a },
{ .vid = 0x06cb, .pid = 0x009b },
{ .vid = 0x06cb, .pid = 0x00a2 },
{ .vid = 0x06cb, .pid = 0x00b7 },
{ .vid = 0x06cb, .pid = 0x00bb },
{ .vid = 0x06cb, .pid = 0x00be },
{ .vid = 0x06cb, .pid = 0x00c4 },
{ .vid = 0x06cb, .pid = 0x00cb },
{ .vid = 0x06cb, .pid = 0x00d8 },
{ .vid = 0x06cb, .pid = 0x00da },
{ .vid = 0x0a5c, .pid = 0x5801 },
{ .vid = 0x0a5c, .pid = 0x5805 },
{ .vid = 0x0a5c, .pid = 0x5834 },
{ .vid = 0x0a5c, .pid = 0x5840 },
{ .vid = 0x0a5c, .pid = 0x5841 },
{ .vid = 0x0a5c, .pid = 0x5842 },
{ .vid = 0x0a5c, .pid = 0x5843 },
{ .vid = 0x0a5c, .pid = 0x5845 },
{ .vid = 0x10a5, .pid = 0x0007 },
{ .vid = 0x1188, .pid = 0x9545 },
{ .vid = 0x138a, .pid = 0x0007 },
{ .vid = 0x138a, .pid = 0x003a },
{ .vid = 0x138a, .pid = 0x003c },
{ .vid = 0x138a, .pid = 0x003d },
{ .vid = 0x138a, .pid = 0x003f },
{ .vid = 0x138a, .pid = 0x0090 },
{ .vid = 0x138a, .pid = 0x0092 },
{ .vid = 0x138a, .pid = 0x0094 },
{ .vid = 0x138a, .pid = 0x0097 },
{ .vid = 0x138a, .pid = 0x009d },
{ .vid = 0x138a, .pid = 0x00ab },
{ .vid = 0x147e, .pid = 0x1002 },
{ .vid = 0x1491, .pid = 0x0088 },
{ .vid = 0x16d1, .pid = 0x1027 },
{ .vid = 0x1c7a, .pid = 0x0300 },
{ .vid = 0x1c7a, .pid = 0x0570 },
{ .vid = 0x1c7a, .pid = 0x0575 },
{ .vid = 0x27c6, .pid = 0x5042 },
{ .vid = 0x27c6, .pid = 0x5110 },
{ .vid = 0x27c6, .pid = 0x5117 },
{ .vid = 0x27c6, .pid = 0x5201 },
{ .vid = 0x27c6, .pid = 0x521d },
{ .vid = 0x27c6, .pid = 0x5301 },
{ .vid = 0x27c6, .pid = 0x530c },
{ .vid = 0x27c6, .pid = 0x532d },
{ .vid = 0x27c6, .pid = 0x533c },
{ .vid = 0x27c6, .pid = 0x5381 },
{ .vid = 0x27c6, .pid = 0x5385 },
{ .vid = 0x27c6, .pid = 0x538c },
{ .vid = 0x27c6, .pid = 0x538d },
{ .vid = 0x27c6, .pid = 0x5395 },
{ .vid = 0x27c6, .pid = 0x5584 },
{ .vid = 0x27c6, .pid = 0x55a2 },
{ .vid = 0x27c6, .pid = 0x55a4 },
{ .vid = 0x27c6, .pid = 0x55b4 },
{ .vid = 0x27c6, .pid = 0x5740 },
{ .vid = 0x2808, .pid = 0x9338 },
{ .vid = 0x298d, .pid = 0x2033 },
{ .vid = 0x3538, .pid = 0x0930 },
{ .vid = 0 },
};
static const FpIdEntry blacklist_id_table[] = {
{ .vid = 0x0483, .pid = 0x2016 },
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
{ .vid = 0x045e, .pid = 0x00bb },
{ .vid = 0 },
};
static const FpDeviceClass whitelist = {
.type = FP_DEVICE_TYPE_USB,
.id_table = whitelist_id_table,
.id = "whitelist",
.full_name = "Hardcoded whitelist"
};
GHashTable *printed = NULL;
static void
print_driver (const FpDeviceClass *cls)
{
const FpIdEntry *entry;
gint num_printed = 0;
if (cls->type != FP_DEVICE_TYPE_USB)
return;
for (entry = cls->id_table; entry->vid != 0; entry++)
{
const FpIdEntry *bl_entry;
char *key;
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++)
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
break;
if (bl_entry->vid != 0)
continue;
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
if (g_hash_table_lookup (printed, key) != NULL)
{
if (cls == &whitelist)
g_warning ("%s implemented by driver %s",
key, (const char *) g_hash_table_lookup (printed, key));
g_free (key);
continue;
}
g_hash_table_insert (printed, key, (void *) cls->id);
if (num_printed == 0)
{
if (cls != &whitelist)
g_print ("\n# Supported by libfprint driver %s\n", cls->id);
else
g_print ("\n# Known unsupported devices\n");
}
g_print ("usb:v%04Xp%04X*\n",
entry->vid, entry->pid);
num_printed++;
}
if (num_printed > 0)
g_print (" ID_AUTOSUSPEND=1\n");
}
static int
driver_compare (gconstpointer p1, gconstpointer p2)
{
g_autoptr(FpDeviceClass) cls1 = g_type_class_ref (*(GType *) p1);
g_autoptr(FpDeviceClass) cls2 = g_type_class_ref (*(GType *) p2);
return g_strcmp0 (cls1->id, cls2->id);
}
int
main (int argc, char **argv)
{
g_autoptr(GArray) drivers = fpi_get_driver_types ();
g_autofree char *program_name = NULL;
guint i;
program_name = g_path_get_basename (argv[0]);
g_print ("# SPDX-License-Identifier: LGPL-2.1-or-later\n");
g_print ("# This file has been generated using %s with all drivers enabled\n",
program_name);
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_array_sort (drivers, driver_compare);
for (i = 0; i < drivers->len; i++)
{
GType driver = g_array_index (drivers, GType, i);
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
if (cls->type != FP_DEVICE_TYPE_USB)
continue;
print_driver (cls);
}
print_driver (&whitelist);
g_hash_table_destroy (printed);
return 0;
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include "fpi-context.h"
#include "fpi-device.h"
static const FpIdEntry whitelist_id_table[] = {
/* Unsupported (for now) Validity Sensors finger print readers */
{ .vid = 0x138a, .pid = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vid = 0x138a, .pid = 0x0091 },
{ .vid = 0x138a, .pid = 0x0094 },
{ .vid = 0x138a, .pid = 0x0097 }, /* Found on e.g. Lenovo T470s */
{ .vid = 0 },
};
static const FpIdEntry blacklist_id_table[] = {
{ .vid = 0x0483, .pid = 0x2016 },
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
{ .vid = 0x045e, .pid = 0x00bb },
{ .vid = 0 },
};
static const FpDeviceClass whitelist = {
.type = FP_DEVICE_TYPE_USB,
.id_table = whitelist_id_table,
.full_name = "Hardcoded whitelist"
};
GHashTable *printed = NULL;
static void
print_driver (const FpDeviceClass *cls)
{
const FpIdEntry *entry;
gint num_printed = 0;
if (cls->type != FP_DEVICE_TYPE_USB)
return;
for (entry = cls->id_table; entry->vid != 0; entry++)
{
const FpIdEntry *bl_entry;
char *key;
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++)
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
break;
if (bl_entry->vid != 0)
continue;
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
if (g_hash_table_lookup (printed, key) != NULL)
{
g_free (key);
continue;
}
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
if (num_printed == 0)
g_print ("# %s\n", cls->full_name);
g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n",
entry->vid, entry->pid);
g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n",
entry->vid, entry->pid, cls->full_name);
num_printed++;
}
if (num_printed > 0)
g_print ("\n");
}
int
main (int argc, char **argv)
{
g_autoptr(GArray) drivers = fpi_get_driver_types ();
guint i;
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < drivers->len; i++)
{
GType driver = g_array_index (drivers, GType, i);
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
if (cls->type != FP_DEVICE_TYPE_USB)
continue;
print_driver (cls);
}
print_driver (&whitelist);
g_hash_table_destroy (printed);
return 0;
}

View File

@@ -16,7 +16,6 @@ libfprint_private_sources = [
'fpi-print.c',
'fpi-ssm.c',
'fpi-usb-transfer.c',
'fpi-spi-transfer.c',
]
libfprint_public_headers = [
@@ -41,7 +40,6 @@ libfprint_private_headers = [
'fpi-minutiae.h',
'fpi-print.h',
'fpi-usb-transfer.h',
'fpi-spi-transfer.h',
'fpi-ssm.h',
]
@@ -142,9 +140,6 @@ foreach driver: drivers
if driver == 'vfs5011'
drivers_sources += [ 'drivers/vfs5011.c' ]
endif
if driver == 'vfs7552'
drivers_sources += [ 'drivers/vfs7552.c' ]
endif
if driver == 'upektc_img'
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upek_proto.c' ]
endif
@@ -160,15 +155,6 @@ foreach driver: drivers
if driver == 'virtual_image'
drivers_sources += [ 'drivers/virtual-image.c' ]
endif
if driver == 'virtual_device'
drivers_sources += [ 'drivers/virtual-device.c' ]
endif
if driver == 'virtual_device_storage'
drivers_sources += [ 'drivers/virtual-device-storage.c' ]
endif
if driver.startswith('virtual_')
drivers_sources += [ 'drivers/virtual-device-listener.c' ]
endif
if driver == 'synaptics'
drivers_sources += [
'drivers/synaptics/synaptics.c',
@@ -181,11 +167,6 @@ foreach driver: drivers
'drivers/goodixmoc/goodix_proto.c',
]
endif
if driver == 'nb1010'
drivers_sources += [
'drivers/nb1010.c',
]
endif
endforeach
if aeslib
@@ -231,7 +212,6 @@ deps = [
glib_dep,
gobject_dep,
gusb_dep,
gudev_dep,
imaging_dep,
mathlib_dep,
nss_dep,
@@ -254,8 +234,6 @@ libnbis = static_library('nbis',
'-Wno-error=redundant-decls',
'-Wno-redundant-decls',
'-Wno-discarded-qualifiers',
'-Wno-array-bounds',
'-Wno-array-parameter',
]),
install: false)
@@ -278,7 +256,7 @@ libfprint_drivers = static_library('fprint-drivers',
mapfile = files('libfprint.ver')
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0])
libfprint = shared_library(versioned_libname.split('lib')[1],
libfprint = library(versioned_libname.split('lib')[1],
sources: [
fp_enums,
libfprint_sources,
@@ -315,30 +293,20 @@ libfprint_private_dep = declare_dependency(
]
)
udev_hwdb = executable('fprint-list-udev-hwdb',
'fprint-list-udev-hwdb.c',
udev_rules = executable('fprint-list-udev-rules',
'fprint-list-udev-rules.c',
dependencies: libfprint_private_dep,
link_with: libfprint_drivers,
install: false)
udev_hwdb_generator = custom_target('udev-hwdb',
output: 'autosuspend.hwdb',
depend_files: drivers_sources,
capture: true,
command: [ udev_hwdb ],
install: false,
)
custom_target('sync-udev-hwdb',
depends: udev_hwdb_generator,
output: 'sync-udev-hwdb',
install: false,
command: [
'cp', '-v',
udev_hwdb_generator.full_path(),
meson.source_root() / 'data'
]
)
if get_option('udev_rules')
custom_target('udev-rules',
output: '60-@0@-autosuspend.rules'.format(versioned_libname),
capture: true,
command: [ udev_rules ],
install: true,
install_dir: udev_rules_dir)
endif
supported_devices = executable('fprint-list-supported-devices',
'fprint-list-supported-devices.c',

View File

@@ -1,5 +1,5 @@
project('libfprint', [ 'c', 'cpp' ],
version: '1.90.7',
version: '1.90.3',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',
@@ -88,19 +88,10 @@ cairo_dep = dependency('cairo', required: false)
# Drivers
drivers = get_option('drivers').split(',')
virtual_drivers = [
'virtual_image',
'virtual_device',
'virtual_device_storage',
]
udev_drivers = [
]
virtual_drivers = [ 'virtual_image' ]
default_drivers = [
'upektc_img',
'vfs5011',
'vfs7552',
'aes3500',
'aes4000',
'aes1610',
@@ -120,17 +111,9 @@ default_drivers = [
'upeksonly',
'upekts',
'goodixmoc',
'nb1010'
]
# FIXME: All the drivers should be fixed by adjusting the byte order.
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
endian_independent_drivers = virtual_drivers + [
'aes3500',
'synaptics',
]
all_drivers = default_drivers + virtual_drivers + udev_drivers
all_drivers = default_drivers + virtual_drivers
if drivers == [ 'all' ]
drivers = all_drivers
@@ -144,21 +127,8 @@ if drivers.length() == 0 or drivers[0] == ''
error('Cannot build libfprint without drivers, please specify a valid value for the drivers option')
endif
if drivers == all_drivers or drivers == default_drivers
default_drivers_are_enabled = true
else
default_drivers_are_enabled = true
foreach driver: default_drivers
if driver not in drivers
default_drivers_are_enabled = false
break
endif
endforeach
endif
nss_dep = dependency('', required: false)
imaging_dep = dependency('', required: false)
gudev_dep = dependency('', required: false)
libfprint_conf.set10('HAVE_PIXMAN', false)
foreach driver: drivers
if driver == 'uru4000'
@@ -175,33 +145,11 @@ foreach driver: drivers
libfprint_conf.set10('HAVE_PIXMAN', true)
endif
if udev_drivers.contains(driver)
gudev_dep = dependency('gudev-1.0', required: false)
if not gudev_dep.found()
error('udev is required for SPI support')
endif
libfprint_conf.set10('HAVE_UDEV', true)
endif
if not all_drivers.contains(driver)
error('Invalid driver \'' + driver + '\'')
endif
endforeach
supported_drivers = []
foreach driver: drivers
if build_machine.endian() == 'little' or driver in endian_independent_drivers
supported_drivers += driver
else
warning('Driver @0@ is not supported by big endian cpu @1@. Please, fix it!'.format(
driver, build_machine.cpu()))
endif
endforeach
if default_drivers_are_enabled and supported_drivers != drivers
default_drivers_are_enabled = false
endif
# Export the drivers' types to the core code
drivers_type_list = []
drivers_type_func = []
@@ -214,7 +162,7 @@ drivers_type_func += '{'
drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));'
drivers_type_func += ' GType t;'
drivers_type_func += ''
foreach driver: supported_drivers
foreach driver: drivers
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();'
drivers_type_func += ' g_array_append_val (drivers, t);'
@@ -226,27 +174,13 @@ drivers_type_func += '}'
root_inc = include_directories('.')
udev_hwdb = get_option('udev_hwdb')
if not udev_hwdb.disabled()
# systemd v248 includes our autosuspend rules
udev_versioned_dep = dependency('udev', version: '>= 248', required: false)
udev_hwdb_dir = get_option('udev_hwdb_dir')
if udev_hwdb.auto()
if udev_versioned_dep.found()
udev_hwdb_dir = ''
endif
else
if udev_versioned_dep.found()
warning('udev hwdb will be installed by both systemd and libfprint')
endif
endif
if get_option('udev_rules')
udev_rules_dir = get_option('udev_rules_dir')
if udev_hwdb_dir == 'auto'
if udev_rules_dir == 'auto'
udev_dep = dependency('udev')
udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d'
udev_rules_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/rules.d'
endif
else
udev_hwdb_dir = ''
endif
if get_option('gtk-examples')
@@ -270,7 +204,6 @@ if get_option('gtk-examples')
subdir('demo')
endif
subdir('data')
subdir('tests')
pkgconfig = import('pkgconfig')

View File

@@ -6,12 +6,12 @@ option('introspection',
description: 'Build GObject Introspection repository',
type: 'boolean',
value: true)
option('udev_hwdb',
description: 'Whether to create a udev hwdb',
type: 'feature',
value: 'auto')
option('udev_hwdb_dir',
description: 'Installation path for udev hwdb',
option('udev_rules',
description: 'Whether to create a udev rules file',
type: 'boolean',
value: true)
option('udev_rules_dir',
description: 'Installation path for udev rules',
type: 'string',
value: 'auto')
option('gtk-examples',

53
tests/README-umockdev Normal file
View File

@@ -0,0 +1,53 @@
To create a new umockdev test, you should:
1. Decide on what to test, the easiest case is just using the existing
capture test case.
2. Find the USB device you are testing with lsusb, e.g.:
Bus 001 Device 005: ID 138a:0090 Validity Sensors, Inc. VFS7500 Touch Fingerprint Sensor
This means we need to record USB device /dev/bus/usb/001/005
3. Run "umockdev-record /dev/bus/usb/001/005 >device"
This records the information about device, it should be placed into test/DRIVER/device
4. Run the test, for a capture test this would be:
umockdev-record -i /dev/bus/usb/001/005=capture.ioctl -- ./capture.py capture.png
This will create a capture.ioctl and capture.png file.
Please set the FP_DEVICE_EMULATION=1 environment variable. You may need
to adjust the driver to adapt to the emulated environment (mainly if it
uses random numbers, see synaptics.c for an example).
5. Place all files into the driver subdirectory test/DRIVER,
i.e. device, capture.ioctl, capture.png
6. Add glue to meson.build
7. Test whether everything works as expected
Please note, there is no need to use a real finger print in this case. If
you would like to avoid submitting your own fingerprint then please just
use e.g. the side of your finger, arm, or anything else that will produce
an image with the device.
Note that umockdev-record groups URBs aggressively. In most cases, manual
intervention is unfortunately required. In most cases, drivers do a chain
of commands like e.g. A then B each with a different reply. Umockdev will
create a file like:
A
reply 1
reply 2
B
reply 1
reply 2
which then needs to be re-ordered to be:
A
reply 1
B
reply 1
A
reply 2
B
reply 2
Other changes may be needed to get everything working. For example the elan
driver relies on a timeout that is not reported correctly. In this case the
driver works around it by interpreting the protocol error differently in
the virtual environment.

View File

@@ -27,7 +27,7 @@ A new 'capture' test is created by means of `capture.py` script:
- `export LD_PRELOAD=<meson-build-dir>/libfprint/libfprint-2.so`
- `export GI_TYPELIB_PATH=<meson-build-dir>/libfprint`
Also, sometimes the driver must be adapted to the emulated environment
Also, sometimes the driver must be adopted to the emulated environment
(mainly if it uses random numbers, see `synaptics.c` for an example).
Set the following environment variable to enable this adaptation:
- `export FP_DEVICE_EMULATION=1`
@@ -41,11 +41,6 @@ A new 'capture' test is created by means of `capture.py` script:
The following USB device is used in the example above:
`/dev/bus/usb/001/005`.
For the following commands, it is assumed that the user that's
running the commands has full access to the device node, whether
by running the commands as `root`, or changing the permissions for
that device node.
4. Record information about this device:
`umockdev-record /dev/bus/usb/001/005 > DRIVER/device`

View File

@@ -35,11 +35,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0000
A: bmAttributes=80
A: busnum=3\n
A: busnum=3
A: configuration=
H: descriptors=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000
A: dev=189:259
A: devnum=4\n
A: devnum=4
A: devpath=1.1.3
L: driver=../../../../../../../../../../bus/usb/drivers/usb
A: idProduct=5731
@@ -106,11 +106,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=9100
A: bmAttributes=e0
A: busnum=3\n
A: busnum=3
A: configuration=
H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
A: dev=189:258
A: devnum=3\n
A: devnum=3
A: devpath=1.1
L: driver=../../../../../../../../../bus/usb/drivers/usb
A: idProduct=0006
@@ -186,11 +186,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=9100
A: bmAttributes=e0
A: busnum=3\n
A: busnum=3
A: configuration=
H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
A: dev=189:257
A: devnum=2\n
A: devnum=2
A: devpath=1
L: driver=../../../../../../../../bus/usb/drivers/usb
A: idProduct=0006
@@ -270,11 +270,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0415
A: bmAttributes=e0
A: busnum=3\n
A: busnum=3
A: configuration=
H: descriptors=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C
A: dev=189:256
A: devnum=1\n
A: devnum=1
A: devpath=0
L: driver=../../../../../../../bus/usb/drivers/usb
A: idProduct=0002

View File

@@ -36,11 +36,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0140
A: bmAttributes=80
A: busnum=1\n
A: busnum=1
A: configuration=
H: descriptors=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001
A: dev=189:93
A: devnum=94\n
A: devnum=94
A: devpath=4.4
L: driver=../../../../../../bus/usb/drivers/usb
A: idProduct=0c26
@@ -107,11 +107,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=5284
A: bmAttributes=e0
A: busnum=1\n
A: busnum=1
A: configuration=
H: descriptors=1201100209000140EF17181084520102000109021900010100E0000904000001090000000705810301000C
A: dev=189:82
A: devnum=83\n
A: devnum=83
A: devpath=4
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=1018
@@ -189,11 +189,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0503
A: bmAttributes=e0
A: busnum=1\n
A: busnum=1
A: configuration=
H: descriptors=12010002090001406B1D020003050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0
A: devnum=1\n
A: devnum=1
A: devpath=0
L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002

View File

@@ -1,217 +1,307 @@
@DEV /dev/bus/usb/003/008
@DEV /dev/bus/usb/001/003
USBDEVFS_GET_CAPABILITIES 0 FD010000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 D00000000500BA4500611A297F
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000008009D6200D00000239572F5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000008009D6200D00001B5A57582000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 D0000001850067980002FE4150500000000000303130303032343744454C4C00000000474D3138384230004746353238380000312E30342E30352E31302E3530000000000000000000000000000000000000005553420000000000564253000000000030303030303030330000000000000000000000000000000000000000000000000000000000003B5CB43C000000000000555342000000000056425300000000003030303030303033000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 140 140 0 C001000184008E71000064500F41080A1800002300000101000101010100010105050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B737316F0558B152
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 D0000001850067980001FE415050000000000030313030303232384C454E4F564F0000474D3138384230004746333230360000312E30322E30310055534200000000005642530000000000303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051239DE6303030303033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 140 140 0 C001000184008E71000064500F410C0A1800002300000101000101010100010105050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B737316F3EB36C6A
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000208004BB400C001005F5A6B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000208004BB400C00101C96A6C6B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 C00100030700D12E0014140342C8AE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E00100020400BE41BBC7BACE
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 C00100030500FB040093B3ED01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A6000002050049B600C27E4B39
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000004080036C900E00101C26FC596000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000004080036C900A60001F1AFC9FB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E0010005080054AB00141441240D0ECF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A6000003050022DD00CA3B9C30
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A60000050600609F000094D6C40E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000030700AC53000F411A349263
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000060800E01F00A60001BCF2ED17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000060800E01F00A20001605AE410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A60000070600B64900007A6860130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000040700BA45000F41625785F3
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A2000007070007F8005564FA6B157100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A50000042400F40B000000000000000000000000000000000000000000000000000000000000000095D4A28A
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000080800CC3300A20001BA8679AC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000080800CC3300A500013F9036A9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000090C00BC430054640027004D0084CD5EED0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A500000524009F60000000000000000000000000000000000000000000000000000000000000000048D9D8CB
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A50000090500DE2103D6515435000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A10000050500807F007BE269C4
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000A08001AE500A5000172CD1245000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000A08001AE500A10001AE651B42000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A500000B050008F703C6DBFA26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A100000605003DC200632D10DE
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A100000B250002FD00B786B17D6A044D24C1651C2B1A76F6396D790639F58CA6D62DDDB8E179A9BD4A6C5C6C9200000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000607006C93000F41A33C2AB4
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000C0800679800A100014526FF87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000C0800679800A200011C98B985000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A100000D25007F8000D7843025CC713EA1543DF81EBAAF6BE244543EB9F4BC6FA74E8F246A711CD8C3EA54665F00000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000007070007F8000F41630A457A
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200000D0700807F0059643EDA283F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000007070055AA016450891085EC
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000E0800B14E00A2000151C59D69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000E0800B14E00A000013F11196A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200000F0C00C13E003E620027005900101FD1980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000008070012ED016450F8E6B5D9
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000000F070004FB000000E0109A2200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200080500629D004A354747
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001008003FC000A0000187F37724000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001008003FC000B002017532670A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000001107008A7500000002FCFB4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020009050009F6004270904E
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200114500A15E008E0091009E006F0083007C006D00690079008800000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000000000000000000000988D37C39E006F0083007C006D00690079008800000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000907002BD4000F41D2CA1A81
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000120800E91600B00201386F43E6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000120800E91600A20001A47AD7CB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002001345007788008A009C009400880008009A0099008B00080008009100850000000000000000008F00A4009B0090008F00A100A000940088009A0097008D000000000000000000BEDDBBB29400880008009A0099008B00080008009100850000000000000000008F00A4009B0090008F00A100A000940088009A0097008D
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000A07009669000F41D397DA08
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001307000EF1004B640F46BD2D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000A0700C43B016450398D1A9E
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000140800946B00A200014F39330E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000140800946B00A0000121EDB70D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000150C00E41B004E640027004F00755632510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000B0700AF50016450F9BB7550
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A0000015070021DE0000007BC22C5100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000B0500DF200052FA3E5D
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000016080042BD00A000016CB093E1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000016080042BD00B002019E7183CF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000170700F708000000BAA9831600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000C0500C93600FFA00844
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200174500DC23008200A200AA0093009F009800A90087009A009100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000000000000000000000F1B14CECAA0093009F009800A90087009A009100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000C0700EB14000F416BC2A256
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001808006E9100B0020144AD1E73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001808006E9100A20001D8B88A5E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200194500F00F008C009C009600080086009D0097008E00810092009100850000000000000000008F00A4009A008F008E00A1009F00920087009A0096008C000000000000000000E3A1F2A19600080086009D0097008E00810092009100850000000000000000008F00A4009A008F008E00A1009F00920087009A0096008C
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000D0700807F000F41ABF4CD98
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001907008976005664DBD4593000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000D0700D22D01645041EE0D0E
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001A0800B84700A2000195E5AEB2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001A0800B84700A00001FB312AB1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001B0C00C8370048640027005A00021B15CE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000E07006F9001645040B3CD87
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000001B07000DF2000000CA0273AA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000E05001FE000EF2AA657
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001C0800C53A00A000011072CE74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001C0800C53A00B00201E2B3DE5A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000001D0700708F003A000B89A2D100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000F0500748B00E76F715E
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002001D45005BA400A8009100AB0071008B008F009100920093009100000000000000000000000000AF00A500AD00A000B100A300AA00A200A3009C000000000000000000000000008A57E0B3AB0071008B008F009100920093009100000000000000000000000000AF00A500AD00A000B100A300AA00A200A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000F070056A9000F416A9F62DF
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001E080013EC00B00201AFEEFAB6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001E080013EC00A2000133FB6E9B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002001F45008D720008009900920086008800960097008D007F0091008D00850000000000000000008F00A4009B0090008F00A100A000930087009A0096008D00000000000000000069C4E77C920086008800960097008D007F0091008D00850000000000000000008F00A4009B0090008F00A100A000930087009A0096008D
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000100700B34C000F4148456C7B
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001F0700F40B005A625A6BF72B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000100700E11E016450A25FACED
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000200800DE2100A2000173C16EC1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000200800DE2100A000011D15EAC2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000210C00AE510048640027005500DD002B870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001107008A750164506269C323
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002107006B94002900A6F807F200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200110500FA0500438F0629
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000022080008F700A000015048CE2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000022080008F700B00201A289DE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000230700BD420000008C0CEEF100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020012050047B8005B407F33
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200234500966900870088008800700085009600940070001A001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D0000000000000000000000000074CA825A8800700085009600940070001A001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000120700659A000F41892EC33C
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000240800758A00B0020149CA3AC5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000240800758A00A20001D5DFAEE8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200254500EB14008D00A100900087000800980099008C00080008000800080000000000000000008F00A3009A008F008E00A0009F00930087009A0096008C0000000000000000000F8D1061900087000800980099008C00080008000800080000000000000000008F00A3009A008F008E00A0009F00930087009A0096008C
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001307000EF1000F414918ACF2
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000250700926D00556427B73E5900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001307005CA3016450A3026C64
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000260800A35C00A2000198828A04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000260800A35C00A00001F6560E07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000270C00D32C0057640027004E0017D2351D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001407004AB5016450DB617BF4
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A0000027070016E90058265460564800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001405003AC500FE5F9E23
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002808008F7000A000012C8A93BB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002808008F7000B00201DE4B8395000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002907003AC500000044F2661300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020015050051AE00F61A492A
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B0020029450011EE007B00950097006E0084008A007400720078008000000000000000000000000000AE00A500AD00A000B100A200AA00A300A3009D000000000000000000000000007AB44F7697006E0084008A007400720078008000000000000000000000000000AE00A500AD00A000B100A200AA00A300A3009D00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000150700738C000F41F14DD4AC
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002A080059A600B002019316A779000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002A080059A600A200010F033354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002002B4500C7380089009C00920008008A00990098008A007F0093008E00860000000000000000008F00A4009A008F008E00A100A000930087009A0096008D000000000000000000A0269EE8920008008A00990098008A007F0093008E00860000000000000000008F00A4009A008F008E00A100A000930087009A0096008D
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000160700CE31000F41F0101425
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200002B0700BE4100566455244C8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001607009C630164501A0AD4B3
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002C080024DB00A20001E440D791000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002C080024DB00A000018A945392000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200002D0C0054AB004A64002700590057B20D220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000170700F708016450DA3CBB7D
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002D0700916E005F2DD3D14D7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200170500877800E690E739
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002E0800F20D00A00001C7C9777E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002E0800F20D00B0020135086750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002F070047B8004C4C4EAAB86E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200180500C03F00B4605C02
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002002F45006C9300A80083008A006D00870082008900940074001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000000000000000000000DD3369188A006D00870082008900940074001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000180700E21D000F4141D04BDE
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003008007C8300B002018DEA091E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003008007C8300A2000111FF9D33000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200314500E21D00080008000800080088009A0096008F00820092009000080000000000000000008F00A3009A008F008E00A000A000930087009A0096008C000000000000000000E0BA753D0800080088009A0096008F00820092009000080000000000000000008F00A3009A008F008E00A000A000930087009A0096008C
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001907008976000F4181E62410
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200003107009B6400586440DB796400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000190700DB240164506BFCE486
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000320800AA5500A200015CA2B9DF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000320800AA5500A0000132763DDC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000330C00DA25005464002700500088A694DC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001A070066990164506AA1240F
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003307001FE072635FE0E8A18200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001A050016E900A4EAF211
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000340800D72800A00001D935D919000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000340800D72800B002012BF4C937000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000350700629D0000006775A83E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001B05007D8200ACAF2518
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B0020035450049B6007D00920094008C009A008B008400890094006D00000000000000000000000000AE00A500AD00A000B100A300AA00A200A3009D00000000000000000000000000520A47F394008C009A008B008400890094006D00000000000000000000000000AE00A500AD00A000B100A300AA00A200A3009D00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001B07005FA0000F41408D8B57
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000036080001FE00B0020166A9EDDB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000036080001FE00A20001FABC79F6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002003745009F600008000800080008008600970095000800830090008D00880000000000000000008F00A3009A008F008E00A100A000930087009A0096008C000000000000000000F054EC42080008008600970095000800830090008D00880000000000000000008F00A3009A008F008E00A100A000930087009A0096008C
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001C070049B6000F4138EE9CC7
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000370700E619005964B9BF1A2300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001C07001BE4016450D2F45C51
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003808002DD200A200012060E44A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003808002DD200A000014EB46049000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000390C005DA2004A640027004F005D569D1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001D0700708F01645012C2339F
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003907009867725F526A136B6D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001D050000FF0009B0C408
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003A0800FB0400A0000103E944A5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003A0800FB0400B00201F128548B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003B07004EB1000000D6B5F7C500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A300001E0700B649000F41F8F75650
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002003B4500659A0084007D008B0099009C006A009A007B0089008300000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000000000000000000000BAEEF1FA8B0099009C006A009A007B0089008300000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001E07009F60000F41F9853380
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003C0800867900A30001B114E662000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003C0800867900A20001867E2463000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A300003D0500629D009DDA98C4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 A400001F6A001EE1640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900E6F6BD05
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200003D0700619E005864307089D800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001F0700A659016450D3A99CD8
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003E080050AF00A40001795F8D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003E080050AF00A00001A5F7848C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A400003F05006B940099962233000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E0000020040049B6AEA0E8AB
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003F0700E51A0063324BE2275A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200200500708F00DCB5EECB
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004008001BE400E00001D5F1C38E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004008001BE400B00201E7BD49D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E000004108001BE400000000315A099D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A60000210500B74800B39B168D
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200414500857A0078006F0074009200A6008C0071006C008E009400000000000000000000000000AF00A500AD00A000B100A300A900A200A3009C0000000000000000000000000079DB6FC674009200A6008C0071006C008E009400000000000000000000000000AF00A500AD00A000B100A300A900A200A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000021070039C6000F41C7E8B94B
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000420800CD3200A60001EA5DF016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000420800CD3200A2000136F5F911000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 A60000436C00EC130001640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900FA60A49A000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E00100220400FD0253E4FA3B
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200004307002AD5005A647427533000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000220700D6290164502CAFB954
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000440800B04F00E0010132DE18BE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000440800B04F00A00001B36299D7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E00100450800D22D000000002B1189D3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000230700EF100100238AF5F029
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A0000045070005FA0061447F5F4C1200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200230500CD3200C47A97D1
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000460800669900A2000190EB3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000460800669900B002010CFEAD15000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000470C0016E9004C640027004D005C10F4310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A50000242400B7480000000000000000000000000000000000000000000000000000000000000000664B5D3F
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200474500F807009500860087008D00A3006D007D0081009C007C00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C0000000000000000000000000074D7CC3787008D00A3006D007D0081009C007C00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000240700F906000F417EE0019C
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004808004AB500A50001CF21EB81000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004808004AB500A200014A37A484000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A50000499200D22D004C642A00000000640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04D4A2B430F0D25BF63D97E631EC0F0F86A6A3DCDEF50C82BB7E8C2D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E000002504008976203A9633
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000490700AD52005764F1A7756700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000250700C03F01645054CCAEC4
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004A08009C6300E00001A9339E1B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004A08009C6300A0000169BE046B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E000004B08009C63004C642A9C8BFEAB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E0010026040056A9D15D8DC2
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000004B070029D60041281F96933800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002605000DF20079AA0FDB
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004C0800E11E00E00101034161C7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004C0800E11E00B00201703CF080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E001004D0800837C004C642ACB9D5A09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000027070044BB010023F3CB2730
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002004D45007F80009E008E008E007E00AB00840096007F0092008100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000000000000000000000D393E7738E007E00AB00840096007F0092008100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000027070044BB000F417FBDC115
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004E080037C800A20001A1744041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200004F0C0047B80052640027004D00E19CE96F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A500002824004DB200000000000000000000000000000000000000000000000000000000000000003DB8032C
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200004F0700D02F005964C7DF8EA700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000028070051AE016450E45131B6
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000500800B94600A500019C80610A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000500800B94600A000017742AA0C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A5000051920021DE0052642A00000000640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04D4A2B430F0D25BF63D97E631EC0F0F86A6A3DCDEF50CCC7D08E82D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E00000290400738C14C55D45
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000005107000CF300624F1EC75A2600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002905004AB5002B5AB4E0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005208006F9000E00001FA921490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005208006F9000B00201C8DE9ECE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E000005308006F900052642AB5A4CC36000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 A700002A6A0044BB640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479001CF66539
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200534500F10E0077007A00720083007500930073007E006E008200000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C00000000000000000000000000C5190965720083007500930073007E006E008200000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200002A0700D52A000F41CF205E67
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000054080012ED00A70001544A2520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000054080012ED00A20001BF88EE26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A7000055050052AD00C5D5FE86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000550700F50A0058641D3C23CD00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000002B0700EC13016450E50CF13F
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000560800C43B00A000019C014EC9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000570700718E726054F685049700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002C05008A7500968A2CEA
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000580800E81700B00201B41CC35B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002005945007689008C007100780072007A009500A10088009C008F00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000000000000000000000D98A26F0780072007A009500A10088009C008F00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200002D0700C33C000F41B74349F7
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005A08003EC100A200016554739A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200005B0700D926005964EDCD672F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000002E07002CD30164505C0449E8
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005C080043BC00A00001E0C3135C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000005D0700F609725F58291DE42400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002F050037C8008E4555F0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005E0800956A00B002015F5F279E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002005F45000BF400A30088009D008D00A80071007F0092006F006100000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C000000000000000000000000001A1438ED9D008D00A80071007F0092006F006100000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000300700F00F000F4154F2E814
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000060080058A700A200018370B3E9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000610700BF400059646AA8553300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000310700C9360164507EDE474C
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006208008E7100A00001A0F91306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000006307003BC4006432979DA1E700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020032050004FB00326A5B9D
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000640800F30C00B00201B97BE7ED000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002006545006D92008D008F008A00750083008D0092008B0071007A00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000000000000000000000394AB8458A00750083008D0092008B0071007A00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200003307004DB2000F4155AF289D
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000066080025DA00A200016833572C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000670700C23D0057645CD0AEF300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000034070009F6016450C7D6FF9B
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000068080009F600A00001DC3B4E93000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000690700BC43002E00509568C700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A3000035070019E6000F41EC883513
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006A0800DF2000A30001C8D82C7D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A300006B05003BC40055C25B16000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 A40000366A006798640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900B5C8699F
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006C0800A25D00A40001A68D87BD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A400006D0500996600E41BAEE2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A60000370500689700E8D1ECD8
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006E0800748B00A6000185042752000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 A600006F6C0055AA0001640043010107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479006EA4C362000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000380700A15E010023D1112994
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000700800FA0500A20001E14E401B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200007107001DE2005A635942221700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A50000392400847B000000000000000000000000000000000000000000000000000000000000000038910386
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00007208002CD300A5000129052BF2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A50000739300A15E005A632900000000640043010107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A21C0F44B08232229E7F2E5DBFA70A5CEF58A3966ED710002FF9938030303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A2
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 a200003a07007788010023107a86d3
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000700800FA0500A20001E14E401B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200007107001DE2005A635942221700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 a500003b240052ad0000000000000000000000000000000000000000000000000000000000000000828af704
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00007208002CD300A5000129052BF2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A50000739300A15E005A632900000000640043010107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A21C0F44B08232229E7F2E5DBFA70A5CEF58A3966ED710002FF9938030303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A2
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 a700003c6a009b64640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4650312d30303030303030302d302d30303030303030302d6e6f626f647900473c9b29
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000074080051AE00A70001AC924B34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A7000075050011EE00ACFFDA28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

View File

@@ -20,21 +20,11 @@ d.open_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# List, enroll, list, verify, identify, delete
print("enrolling")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
print("listing")
@@ -43,31 +33,17 @@ print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
del p
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("identifying")
identify_match, identify_print = d.identify_sync(stored)
print("identify done")
assert identify_match.equal(identify_print)
print("deleting")
d.delete_print_sync(p)
print("delete done")
d.close_sync()
del d

View File

@@ -1,30 +1,30 @@
P: /devices/pci0000:00/0000:00:14.0/usb3/3-2
N: bus/usb/003/008=12010002EF000040C627405800010102030109022000010103A0320904000002FF0000040705830240000007050102400000
E: DEVNAME=/dev/bus/usb/003/008
P: /devices/pci0000:00/0000:00:14.0/usb1/1-8
N: bus/usb/001/003=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000
E: DEVNAME=/dev/bus/usb/001/003
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=27c6/5840/100
E: PRODUCT=27c6/60a2/100
E: TYPE=239/0/0
E: BUSNUM=003
E: DEVNUM=008
E: BUSNUM=001
E: DEVNUM=003
E: MAJOR=189
E: MINOR=263
E: MINOR=2
E: SUBSYSTEM=usb
E: ID_VENDOR=Goodix_Technology_Co.__Ltd.
E: ID_VENDOR_ENC=Goodix\x20Technology\x20Co.\x2c\x20Ltd.
E: ID_VENDOR_ID=27c6
E: ID_MODEL=Goodix_USB2.0_MISC
E: ID_MODEL_ENC=Goodix\x20USB2.0\x20MISC
E: ID_MODEL_ID=5840
E: ID_MODEL_ID=60a2
E: ID_REVISION=0100
E: ID_SERIAL=Goodix_Technology_Co.__Ltd._Goodix_USB2.0_MISC_UIDE1AD5CBA_XXXX_MOC_B0
E: ID_SERIAL_SHORT=UIDE1AD5CBA_XXXX_MOC_B0
E: ID_SERIAL=Goodix_Technology_Co.__Ltd._Goodix_USB2.0_MISC_UIDCBEE4D7B_XXXX_MOC_B0
E: ID_SERIAL_SHORT=UIDCBEE4D7B_XXXX_MOC_B0
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=Shenzhen Goodix Technology Co.,Ltd.
E: ID_PATH=pci-0000:00:14.0-usb-0:2
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2
E: LIBFPRINT_DRIVER=Goodix MOC Fingerprint Sensor
E: ID_PATH=pci-0000:00:14.0-usb-0:8
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_8
E: LIBFPRINT_DRIVER=AuthenTec AES1610
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
@@ -37,32 +37,32 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0100
A: bmAttributes=a0
A: busnum=3\n
A: configuration=UIDE1AD5CBA_XXXX_MOC_B0
H: descriptors=12010002EF000040C627405800010102030109022000010103A0320904000002FF0000040705830240000007050102400000
A: dev=189:263
A: devnum=8\n
A: devpath=2
A: busnum=1
A: configuration=UIDCBEE4D7B_XXXX_MOC_B0
H: descriptors=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000
A: dev=189:2
A: devnum=3
A: devpath=8
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=5840
A: idProduct=60a2
A: idVendor=27c6
A: ltm_capable=no
A: manufacturer=Goodix Technology Co., Ltd.
A: maxchild=0
L: port=../3-0:1.0/usb3-port2
A: power/active_duration=2684
L: port=../1-0:1.0/usb1-port8
A: power/active_duration=324448
A: power/async=enabled
A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000
A: power/connected_duration=54348
A: power/connected_duration=5916532
A: power/control=auto
A: power/level=auto
A: power/persist=1
A: power/runtime_active_kids=0
A: power/runtime_active_time=2518
A: power/runtime_active_time=327268
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=51550
A: power/runtime_suspended_time=5588987
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
@@ -75,39 +75,38 @@ A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=Goodix USB2.0 MISC
A: quirks=0x0
A: removable=removable
A: removable=fixed
A: rx_lanes=1
A: serial=UIDE1AD5CBA_XXXX_MOC_B0
A: serial=UIDCBEE4D7B_XXXX_MOC_B0
A: speed=12
A: tx_lanes=1
A: urbnum=15
A: urbnum=2180
A: version= 2.00
P: /devices/pci0000:00/0000:00:14.0/usb3
N: bus/usb/003/001=12010002090001406B1D020008050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/003/001
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/508
E: PRODUCT=1d6b/2/504
E: TYPE=9/0/1
E: BUSNUM=003
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=256
E: MINOR=0
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.8.0-38-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.8.0-38-generic\x20xhci-hcd
E: ID_VENDOR=Linux_5.4.0-29-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.4.0-29-generic\x20xhci-hcd
E: ID_VENDOR_ID=1d6b
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_ID=0002
E: ID_REVISION=0508
E: ID_SERIAL=Linux_5.8.0-38-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_REVISION=0504
E: ID_SERIAL=Linux_5.4.0-29-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
@@ -124,33 +123,33 @@ A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0508
A: bcdDevice=0504
A: bmAttributes=e0
A: busnum=3\n
A: busnum=1
A: configuration=
H: descriptors=12010002090001406B1D020008050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:256
A: devnum=1\n
H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0
A: devnum=1
A: devpath=0
L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002
A: idVendor=1d6b
A: interface_authorized_default=1
A: ltm_capable=no
A: manufacturer=Linux 5.8.0-38-generic xhci-hcd
A: maxchild=4
A: power/active_duration=2790916
A: manufacturer=Linux 5.4.0-29-generic xhci-hcd
A: maxchild=12
A: power/active_duration=5879432
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=15607832
A: power/connected_duration=5916912
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=1
A: power/runtime_active_time=2790874
A: power/runtime_active_kids=2
A: power/runtime_active_time=5879430
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=12816956
A: power/runtime_suspended_time=37481
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
@@ -168,7 +167,5 @@ A: rx_lanes=1
A: serial=0000:00:14.0
A: speed=480
A: tx_lanes=1
A: urbnum=584
A: urbnum=1319
A: version= 2.00

View File

@@ -1,54 +0,0 @@
#!/usr/bin/env python3
import os
import sys
import urllib
import urllib.request
import re
error = False
try:
response = urllib.request.urlopen('https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md')
except:
print("Could not download current list of unsupported devices, skipping test.")
sys.exit(77)
data = response.read().decode('utf-8')
devices = []
devices_re = re.compile(r'^.*([0-9a-fA-F]{4}):([0-9a-fA-F]{4}).*$', re.MULTILINE)
for m in devices_re.finditer(data):
vid = m.group(1)
pid = m.group(2)
devices.append((vid, pid))
generator = open(os.path.join(os.path.dirname(__file__), '..', 'libfprint', 'fprint-list-udev-hwdb.c')).read()
id_re = re.compile(' { .vid = 0x([a-fA-F0-9]*), .pid = 0x([a-fA-F0-9]*) }')
# Check everything is the same
started = False
for l in generator.split('\n'):
m = id_re.match(l)
if m is None:
# Stop on the first line that does not match anymore
if started:
break
continue
else:
started = True
vid_pid = (m.group(1), m.group(2))
try:
devices.remove(vid_pid)
except ValueError:
print("Generator has entry that is not on wiki: {}:{}".format(*vid_pid))
error = True
for vid_pid in devices:
print("New entry from wiki is missing: {}:{}".format(*vid_pid))
error = True
if error:
sys.exit(1)
else:
sys.exit(0)

View File

@@ -5,7 +5,6 @@ envs.set('G_MESSAGES_DEBUG', 'all')
# Setup paths
envs.set('MESON_SOURCE_ROOT', meson.source_root())
envs.set('MESON_BUILD_ROOT', meson.build_root())
envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint'))
# Set FP_DEVICE_EMULATION so that drivers can adapt (e.g. to use fixed
@@ -13,11 +12,7 @@ envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint'))
envs.set('FP_DEVICE_EMULATION', '1')
# Set a colon-separated list of native drivers we enable in tests
envs.set('FP_DRIVERS_WHITELIST', ':'.join([
'virtual_image',
'virtual_device',
'virtual_device_storage',
]))
envs.set('FP_DRIVERS_WHITELIST', 'virtual_image')
envs.set('NO_AT_BRIDGE', '1')
@@ -26,67 +21,55 @@ drivers_tests = [
'elan',
'synaptics',
'vfs0050',
'vfs301',
'vfs5011',
'vfs7552',
'goodixmoc',
'nb1010',
]
if get_option('introspection')
envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint'))
virtual_devices_tests = [
'virtual-image',
'virtual-device',
]
unittest_inspector = find_program('unittest_inspector.py')
if 'virtual_image' in drivers
python3 = find_program('python3')
unittest_inspector = find_program('unittest_inspector.py')
base_args = files('virtual-image.py')
suite = []
foreach vdtest: virtual_devices_tests
driver_name = '_'.join(vdtest.split('-'))
if driver_name in drivers
python3 = find_program('python3')
base_args = files(vdtest + '.py')
suite = ['virtual-driver']
r = run_command(unittest_inspector, files('virtual-image.py'))
unit_tests = r.stdout().strip().split('\n')
r = run_command(unittest_inspector, files(vdtest + '.py'))
unit_tests = r.stdout().strip().split('\n')
if r.returncode() == 0 and unit_tests.length() > 0
suite += vdtest
else
unit_tests = [vdtest]
endif
foreach ut: unit_tests
ut_suite = suite
ut_args = base_args
if unit_tests.length() > 1
ut_args += ut
ut_suite += ut.split('.')[0]
endif
test(ut,
python3,
args: ut_args,
suite: ut_suite,
depends: libfprint_typelib,
env: envs,
)
endforeach
if r.returncode() == 0 and unit_tests.length() > 0
suite += 'virtual-image'
else
test(vdtest,
find_program('sh'),
args: ['-c', 'exit 77']
)
unit_tests = ['virtual-image']
endif
endforeach
foreach ut: unit_tests
ut_suite = suite
ut_args = base_args
if unit_tests.length() > 1
ut_args += ut
ut_suite += ut.split('.')[0]
endif
test(ut,
python3,
args: ut_args,
suite: ut_suite,
depends: libfprint_typelib,
env: envs,
)
endforeach
else
test('virtual-image',
find_program('sh'),
args: ['-c', 'exit 77']
)
endif
foreach driver_test: drivers_tests
driver_envs = envs
driver_envs.set('FP_DRIVERS_WHITELIST', driver_test)
if (driver_test in supported_drivers and
gusb_dep.version().version_compare('>= 0.3.0'))
if driver_test in drivers and gusb_dep.version().version_compare('>= 0.3.0')
test(driver_test,
find_program('umockdev-test.py'),
args: join_paths(meson.current_source_dir(), driver_test),
@@ -184,13 +167,6 @@ foreach test_name: unit_tests
)
endforeach
# Run udev rule generator with fatal warnings
envs.set('UDEV_HWDB', udev_hwdb.full_path())
envs.set('UDEV_HWDB_CHECK_CONTENTS', default_drivers_are_enabled ? '1' : '0')
test('udev-hwdb',
find_program('test-generated-hwdb.sh'),
env: envs)
gdb = find_program('gdb', required: false)
if gdb.found()
add_test_setup('gdb',
@@ -211,7 +187,6 @@ if valgrind.found()
timeout_multiplier: 10,
env: [
'G_SLICE=always-malloc',
'UNDER_VALGRIND=1',
('LIBFPRINT_TEST_WRAPPER=@0@ --tool=memcheck --leak-check=full ' +
'--suppressions=@1@ --suppressions=@2@').format(
valgrind.path(), glib_suppressions, python_suppressions)

View File

@@ -1,98 +0,0 @@
@DEV /dev/bus/usb/001/003
USBDEVFS_GET_CAPABILITIES 0 FD010000
USBDEVFS_REAPURBNDELAY 0 3 2 0 0 8 8 0 8038010008000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 16 16 0 803701001000000000000000F7000000
USBDEVFS_REAPURBNDELAY 0 3 2 0 0 12 12 0 800D03000C00000000040000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 16 16 0 80200300100000000000000000000000
USBDEVFS_REAPURBNDELAY 0 3 2 0 0 32 32 0 8012040020000000020000000000000000000000000000000000000020000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 16 16 0 80200400100000000000000003000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000010000000001000001E5E5E5E5E5E4E4E4E5E5E5E4E6E7E6E6BEE6E4E5E4E3E5E6E3E4E4E3E5E6E4E5E6E5E5E5E4E4E5E5E3E3E2E3E3E4E4E4E4E5E5E5E2E2E3C9E2E4E3E4E3E3E4E4E8E8E7E8E5E5E3E4E5E3E4E5E3E4E5E3E4E4E5E5E3E4E4E4E4E5E5E5E3E3E2E3E4E3E3E3E2E3E3E3E3E5E5E5E5E5E4E5E3E4E4E3E5E66AE3E4E5E4E5E5E4E4E5E4E2E2E3E6E5E5E4E4E3E5E3E6E6E7E6E4E4E3E2E5E5E5E6E4E6E5E2E2E3E2E3E4E3E3E4E5E3E5E5E5E3E4E4E6E4E5E5E4E3E4E2E3E5E4E4E5E6E4E5E2E3E2E3E2E3E4E4E5E4E3E3E5E6E6E6E4E4E3E3E6E5E5E6E5E5E5E6E5E5E5E5E5E4E0E4E4E3E2E3E3E3E2E4E3E4E4E5E5E4E5E6E2E3E3E2E4E4E4E3E4E2E4E6E4E5E4E4E6E6E7E7E6E7E6E7E8E6E7E7E8E8E8E8E7E6E7E6E7E5E7E7E7E7E7E6E6E4E4E6E3E4E3E4E4E3E3E4E2E3E4E3E4E3E4E5E3E5E4E5E4E4E3E2E5E5E5E4E5E6E7E6E4E5E4E5E6E7E7E8E2E3E4E4E7E5E7E6E6E3E4E5E7E7E7E8E6E5E6E6E6E5E5E6E6E5E6E4E4E5E4E4E7E7E5E5E5E6E4E7E7E6E5E6E4E4E6E6E6E6E5E5E5E5E5E5E5E4E5E6E4E5E6E6E4E4E5E4E4E6E6E6E6E6E6E5E6E7E7E6E5E7E5E5E7E6E5E7E5E5E7E5E6E4E5E6E7E6E5E7E4E5E5E5E8E6E7E0E6E6E7E7E8E8E9E9E3E5E5E4E6E5E6E7E6E5E5E6E6E5E5E6E5E4E4E3E6E6E6E6E5E4E3E4E6E7E6E5E6E7E5E5E6E6E7E7E7E7E8E6E7E5E7E5E7E6E7E8E6E6E7E5E5E5E5E5E5E2E6E5E7E6E7E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000030000000001000001E7E7E7E7E6E6E6E6E7E7E7E8E8E8E6E8E9E7E8E9E0E4E5E4E8E7E8E7E5E4E4E5E6E1E5E5E7E6E6E6E6E5E4E4E5E4E3E5E5E6E4E5E4E5E5E5E2E6E4E3E5E5E5E6E6E6E5E5E6E5E6E6E7E6E6E7E5E4E5E5E4E5E5E7E7E7E7E7E5E4E4E4E4E3E3E3E5E5E6E5E6E6E5E5E4E4E4E2E6E6E4E5E6E6E8E6E7E6E5E8E6E6E4E5E6E6E7E6E6E6E6E6E6E6E6E5E5E7E5E5E5E6E6E7E5E6E5E5E5E5E5E4E6E6E8E6E0E6E6E7E7E7E8E8E6E6E7E6E7E6E8E6E6E5E6E6E7E6E6E5E5E6E4E5E6E5E6E6E6E4E6E5E7E6E6E6E2E6E7E6E6E5E5E6E7E7E6E5E5E5E6E5E7E7E6E6E5E3E5E3DEE5E6E5E4E5E2E5E6E5E4E5E6E4E5E5E5E5E4E4E6E6E7E7E6E7E6E5E6E4E6E5E4E5E3E4E8E6E7E6E8E7E7E9E7E5E7E9E6E6E5E7E8E7E7E7E7E6E6E6E7E6E7E5E3E4E6E5E4E4E4E6E4E5E3E7DDE5E6E5E6E5E5E7E3E4E5E4E4E5E4E5E3E3DCE4E6E5E6E7E4E4E4E6E5E4E7E7E4E4E3E5E6E6E7E7E5E4E6E5E4E4E5E5E6E5E5E5E6E6E5E6E3E6E5E6E4E2E2E4E5E6E4E4E4E5E4E5E9E9E8E7E6E6E7E7E8E7E7E7E5E4E5E3E6E8E7E7E5E5E3E4E4E5E3E4E5E5E5E5E6E5E4E5E6E7E7E7E5E7E6E6E4E6E6E6E5E4E094E5E6E6E6E7E5E6E5E7E6E7E6E5E6E6E7E7E6E6E6E6E7E8E7E7E5E5E6E6E6E8E6E6E5E5E7E7E7E6E7E5E7E5E5E8E8E7E7E7E5E7E4E6E5E4E6E5E7E4E5E7E6E6E6E7E5E6E6E6E4E6E6E5E7E6E6E5E5E3E6E8E7E6E7E4E2E4E4E6E6E7E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000050000000001000001E6E6E6E6E8E7E7E7E8E6E7E8E9E8E8E8E8E8E8E9E7E6E6E9E6E7E4E6E5E5E6E5E5E6E7E6E6E5E6E6E4E5E4E4E3E5E2E4E5E4E4E5DDE3E4B5E5E7E6E5E5E6E5E1E6E7E7E7E5E6E7E5E5E5E5E5E6E5D6E5A1E4E6E6E4E5E4E3E4E4E4E5E4E5E4E5E6E6E6E6E7E7E6E7E4E4E5E4E6E5E4E6E47AE5E5E7E7E6E7E4E4E5E3E6E4E5E5E4E4E2E3E6E7E7E4E5E6E7E6E6E7E6E7E5E6E6E4E6E7E6E5D4E7E8E7E3E4E5E4E6E6E5E7E5E4E5E3E3E5E7E6E4E3E4E6E6E7E7E7E4E4E5E4E6E7E6E8E7E6E6E7E9E8E9E9E7E6E6E6E4E6E5E4E6E6E7E4E6E6E7E6E7E6E6E5E4E4E5E5E6E5E6E4E6E6E5E6E6E4E5E5E5E6E5E7E6E6E6E7E5E6E5E5E7E6E8E6E4E4E5E5E5E6E5E5E8E8E7E7E6E6E6E6E8E6E8EAE7E9E8E8E8E8E8E9E6E6E7E6E4E5E6E4E5E4E3E5E5E5E5E5E4E5E48B80E4E5E0E7E5E8E6E4E5E5E5E6E2D2E6E7E6E5E6E2E3E5E3E6E8E417D4E3E6E6E6E4E5E5E6E4E6E6E5E6E5E5E7E7E6E7E6E5E4E5E4E5E4E6E7E6E7E7E5E4E6E3E6E4E5E780E6E5E6E4E4E3E4E4E5E6E4E5E5E5E4E7E7E7E6E4E5E4E5E6E1E8E8E6E7E7E8E7E5E5E6E0E5E5D0E4E4E3E4E7E4E6E5E3E4E4E5E5E6E5E6E5E4E3E3DEE2E6E6E5E5E5E4E2E4E6E692E7E6E6E4E6E5E5E3E5E5E6E4E4E4E5E4E5E5E6E6E4E5E6E7E5E5E6E5E5E5E5E6E5E5E5E7E5E7E7E6E6E6E6E6E6E5E6E4E4E5E4E5E6E4E4E6E5E5E6E6E7E7E5E4E5E4E5E6E3E5E5E3E5E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000070000000001000001E5E5E5E5E7E7E8E7E4E8E8E9E9E7E8E8E9E8E9E8E6E8E7E659E5E5E578E5E5E4E5E4E5E5E3AFE4E2E4E0E3E5E0E3E5E5E6E6E7E6E3CDE4E3E6E400E1E3E4E6E3E8E7E6E7E4E3E5E4E5E5E5E5E5E6E5E6E6E6E5E7E4E5E4E5E5E5E4E1D8E6E719E5E7E7E6E5E5E4E6E5E4E4E5E0E7E7E7E7E7E678E6E7E7E5E4E6E6E5E6E6E5E6E4E5E4E4E6E3E6E1E5E6E5E6E4E7E6E6E6E4E5E6E7E6E5E6E7E2E6E7E4E6E6E6E7E7E5E6E6E5E7E6E6E8E7E6E5E5E3E2E4E4E5E6E6E7E4E6E6A6E4E6E5E6E5E5E7E5E6E4E4E3E4E4E7E5E5E4E4E3E5E6E7E6E5E7E4E5E5E5E6E6E6E6E4E4E5E5E7E6E5E7E3E4E3E4E8E7E6E7E5E6E4E5E4E6E5E5E6E5E4E4E7E5E7E6E4E3E5E5E6E6E7E7E7E7E7E7E8E8E8EAE8E8E7E8E9E8E8E9E9E8D8E8E7E6E6E789E3E1E4E3E390E4E5E6E5E6E4E4E5E2E6E5E7E6E7E5E5E5E1E3E5030CE1000019E4E3E3E4E5E3E5E7E5E6E6E6E7E7E6E6E6E6E5E7E6E6E5E5E6E5E7E5E69BE4E7E6E6E5E5E4E4E4E7E7E6E7E4E4E4E5E7E7E7E6E5E5E7E7E6E5E6E6E4E4E4E5E6E7E7E7E5E7E6E5E5E4E6E6E5E4E4E4D8E6E6E5E5E6E6E6E4E5E3E2E6E3E6E7E3E3E4E3E6E6E6E6E5E6E7E7E4E5E6E6E6E7E5E3E5E5E6E7E4E5E4E4E7E7BCE5E5E4E5E6E6E7E7E6D6E4E6E4E7E6DDE5E7E6E7E6E5E631E4E8E7E7E6E7E6E6E7E8E7E6E7E7E5E5E5E5E4E0E6E7E6E6E6E7E5E5E5E7E7E8E7E8E7E6E5E7E7E6E7E5E4E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000090000000001000001E5E5E6E5E5BEE1E6EAE6E8E9E7E7E6E6EAE6E9E7E6E7E6E7E5E7E3E7E4E3E2E5E5E4D8E4E4E5E4E5E4E4E44599E3E5E6E3E2E1E3E5E4E03100E100000078E5E5E4E4E5E5E6E6E5E5E3E4E5E4E6E7E4E6E7E5E4E4E5E3E3E4E42B0000D6E5E4E6E6E6E5E5E5E3E3E4E5E4E4E6E4E5E4E4E8E6E7E8E6E6E6E6E7E6E6E7E5E6E5E6E5E5E6E5E5E6E6E4E6E6E6E4E3E2E5E6E6E5B7E5E3E5E5E5E5E6E5E6E5E4E5E6E585E4E5E6E5E7E6E4E3E6E5E4E5E5E5E6E4E4E6E6E5E7E6E5E5E4E3E5E5E5E5E4E5E5E4E4E5E5E4E5E4E4E5E6E6E6E5E5E5E6E5E4E4E0E1E3E4E4E59BE3E5E5E4B5BEE5E6E5D6E5E5E6E5E4E5E6E4E6E4E5E6E5E6E5E4E7E5E5E5E5E5E4E5E2E7E6E7E6E8E7E7E8E7E6E7E7E8E9E8E8E8E7E8E7E8D2E7E7E6E5E4E6E6DDE6E22DE3E4E7E9E6E5E7E2E2E3A62278E4E7E4E4E5E4E6E7E078E08B0000001B249DB3E4E0E3E6E5E7E7E6E6E8E4E6E4E8E6E4E5E4E4E4E4E2E6E6851D00009BE4E4E6E5E6E5E5E4E3E5E8E7E7E8E6E5E6E500B7E6E5E6E5B33628E4E5E7E6E5E5E5E7E5E6E2E5E5E5E4E6E5E3E3E6E6E4E5E8E7E8E7E6E5E5E5E6E1E6E5E6E5E5E4CBE6E6E7E8E7E7E6E5E5E4E5E5E6E7E8E6E3E4E4E8E8E7E7E5E4E6E3E5E6E5E6E6E5E5E5E7E3E6E7E7E7E7E7E6E7E5E6E5E6E7E7E4E5E3E4E6E5E6E7E5E4E5E5E7E5E5E5E6E6E5E5E7E7E5E7E8E8E6E7E8E5E5E7E5E7E6E7E4E5E5E5E6E5E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000000B0000000001000001E3E4E4E4E6E7E6E6E8E6E8E7E9E2E8E8E9E9E9E8E6E7E1E6E5E4E5E5E4E5E2E47300E3E4E3E4E3E3E4E3D6E1432B0043E6E7E7E5E5E5E5DFE3E0000026000024E5E6E5E4E5E2E4E5E5E4E0E34141E3E4E4E3E3E3E6E4E4E5E4E3000000B3E5E5E5E6E5E6E8E610E4E4E5E5E5E7E8905F001D83E2E5E2E4E3E2E1A600E4E6E7E5E3E5E4E3E4E5E7E6E8E5E4E4E5E4E5E5E6E5E6E5E4E4E4E4E4E3E4E4E4E4E2E3E6E7E6E6E5E4E3E2E6E5E7E5E4E2E5E3E7E5E5E5E5E4E5E7E7E6E6E6E5E4E3E3E3E5E7E5E5E5E5E4E6E6E5E5E6E5E6E6E6E3E5E4E6E6E4E5E6E4E4E5E5E5E4E3E3E4E4E3E4E5E6E3E4E4E5E4E7E6E5E5E7E5E6E6E7E4E6E6E6E5E6E6E4E5E5E2E7E7E7E7E7E6E7E8E6E7E7E8EBEAE9E9E4E7E8E7E8E7E9E8E7E3C0E7E5E6E6E324242B89C7E5E6E5E2E473E4E5050012E5E5E2E6E59BE5E6E589000000520100D0E6E5D4E4E3E5E4E5E4E5A6031B0092E5E3E4E4E2E4E5E3E4E50022000017E3E6E7E6E6E3E10057E3E5E5E6E4E30000039F0CE3E4E4E3E3E6E05B2D05E7E6E7E6E5E5E4E9E7E6E9E1E4E4E3E6E5E5E5E6E6E6E7E6E4E5E7E6E4E6E5E6E4E4E4E7E6E7E8E5E6E4E5E7E7E8E8E6E6E4E5E6E4E6E5E4E5E5E6E7E6E6E6E7E5E6E7E7E6E6E7E5E2E6E6E6E7E6E7E7E8E7E7E97EE7E7E6E6E6E5E6E5E5E5E5E5E5E6E7E6E6E7E6E6E7E7E6E5E6E6E6E5E6E5E6E6E8E7E6E7E5AAE7E8E8E7E6E5E5E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000000D0000000001000001E3E3E3E2E6E6E7E6E8E6E6E7E6E7E7E7E3E4E4E1E5E0E0E5E6E6CBE5DEE4E1E07E002B0000DBE2E1E5E4E4E5E300001243E40001E2E1D0E0006A000024000000E5E6E7E8E4E3E3E4E2E3E3E300380000E6E4E6E5E3E2E3E2E3E30000000000E2E485E4E5E00599000EDBE3E4E4E4E3B100000000E4E6E5E5E3E400D2317AE4E1E2E1E3E3E5E4E5E5E7E6E6E5A4222BE2E1E5E4E4E600E6E6DCE4E5E4E0E3E3E3E4E5E4E3E3E1E4E3E5E4E6E6E3E3E2E3E4E5E4E4E2E2E3E2E694E5E4E2E2E3C9E6E8E6E7E5E6E4E4E3E4E5E4E5E5E4E5E4E5E5E4E4E4E2E4E4E2E2CBE5E5E7E5E5E5E5E4E5E6DDE5E5E5E2E4E3E6E4E5E3E3E4E4E6E5E6E6E4E4E5E4E4E5E5E5E7E7E6E7E7E5E6E7E6E6E7E7E9EAE9E8E8E8E8E9E5E3E0E6E3E4E3DFE1E2E2E3BC476D831720191080E4E5E5E27300260000152DE2E3E0E29FE30000007800009BE4E4E4E5E5E4E3E5E4E36F00000010DEE3E4E5E517E2E3E5E50000000083E3D0E7E4E4E2789400AF83E4E5E6E6E5E40000330041E4E4E4E3E5712FE20CE4E4E4E4E3E3E5E4E6E5E6E6E6E3CB5FE5E3E5E6E5E4E7E5E7E5E5E3E3E5E5E6E4E4E5E5E5E5E4E5E4E2E5E4E7E5E4E3E4E2E4E5E5E4B3E6E4E6E8E5E7E7E3E4E5A6E6E7E6E6E4E4E2DFE5E5E4E5E6E5E6E5E4E5E6E4E6E3E6E3E6E6E5E4E6E6E7E6E4E5DDE5E6E7E6E6E3E5E0E7E5E6E7E5E6E4E4E5E8E7E6E0E2E5E5E4E4E3E4E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000000F0000000001000001E5E4E5E5E6E6E6E6E7E7E8E8E9E7E8E6E8E090E8E6E6E5E4E5E5E3E5E5E4E5E5E2E4050001000094E1E2E3E2E3D00E4300150064E105B1DDE4DC5D0000000000E0E5E3E2E7E5E5E3E2E3E2DB2200001B01E2E2E3E4E37CE1E3E4E3240000000049E3E5E4E6CBE4BA9B459BE5E4E3E2C90020410000E7E6E5E6E03600B55BE4E5E6E3E4E3E6B1E4A8E5E5E5E4E58B3A33E3E5E5E5E5E5E4E3DFE4E4E4E6E6E5E4E4E5E6AFE2E4E4E3E5E5E5E4E6E6E5E6006AE3E7E0E4E3E3E6E5E4E4E3E4E4E3E6E6E6E7E5E5E347E2E4E4E4E4E5E7E4E4E3E5E4E6E6E4C9E3E6E6E4E5E5E5E7E6E5E5E5E5E4E5E3E4E4E2E6E2E6E7E7E7E675E4E6E8E5E8E6E5E6E3E5E4E4E4E7E7E7E7E6D8E6E5E8E8E8E8E7E6E4E5E9E9EBEAE4E5E59D1D0C266FE1E2E1E1E61B000003000C6F6DE4E5E4E0E1CB0000000C0EDF7E01E1E1E6E5D80000000000E3E4E5E4E4E4E3E4E5E1E1A6DB830E00E5E4E4E4E3E2E3E3E0E2E3870028000096E4E6DE8E00451B0C68E4E5E3E5A80000000000E3E7E4E43A003E0038E4E3E5E5E5E4E449DE4E00C9E6E5E6E0B1B7E7E5E6E7E7E6E673220000E5BAE5E6E7E5E4E0E3E46FE4E5E7E4E4E5E7E7E6E700E3E3E3E5E6E5E5E5991BC5E2E5E7E7E6E5E6E7E7E5E35F20E5E5E6E5E4E3E4E5E6E6E6E5E5E4E5DBE6E6E7E4E4E4E4E8E6E6E6E4E4E5E4E6E7E5E2E3E5E5E4E0E571E4E7E6E7E7E7E6E2E6E5E5E7E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000110000000001000001E4E4E5E2E8E7E7E9E6E6E7E8E6E7E8E4E5E7E6E6E4E4E378E29600C9E1E2E3E2B1E2000000DC003EACB5E0E3E21BE00000C20000D2E08315E3E3E3191000002B00E2E5E3E4E4E3E4E0E5E4BCE2E528004C0500E4E4E3E3B3920AE2E3E400002600BCE1E1E30500735D000000E6E5E3E7D800000066E7E7E6E4E300001968E5E4E2E3E4B5DDAC83730E03E3E3E4E3626DE5E4E4E5E5E4E3E3E2000000E3E3E2E4E3E28900E3E4E3E3D6E4E4E3E4E4E4E20CE0E0E3E5E4E2E52F07004331A8E3E3E3E3E5E3E4E4C7AFD4E3E2E4E6E4E5E6E4E4E2E1E5E4E5D4E6E0E4E6E5E4E4E5E6E6E5E4E4E5E5E5E4E3E3DCE3E5E6E5E6E3E4E7E4E5E4E6E4E4E5E6E4E4E4E4E7E6E6E8E7E6E8E7E8E7E3E7E6E7E5E7E7E7E8E7E5E37A43000000789FE3E3E3E1E44C0E000000129D0C99E3E3E1E31000000000209FDFE4E5E4E2C9003A000036E4E4E5E5E5E6BC22070A75E54E4C0E0000001DE3E4E2E3E6E6E6E60E225DB50099E3E3E68500000000000000E5E3E5E61B31007AE5E4E4E6E4260000BEE3C24EE6E8E13E80A82D01D600E5E4E319AFE8E7E5E7E5E6E6E6855900E519E0E4E4E5E6E3E3BAE4E5E5E7E6E6E6E400009D00E3E5E5E6E7E5E564A1D20A00D8E5E6E6E5E6E1CDE6E4E4E6E7E7E5E6E6E6E4E5E4E4E5E7E6E6E6E5E5E6E6E6E6E6E7E6E4E7E6E7E7E6E7E4E4E1E5E8E6EAE9E7E6E7E5DFE7E7E6E6E5E5E6E6E4E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000130000000001000001E5E5E4E5E1E6E6E6E7E7E7E7E6E6E6E7E7E7E6E6E5E5E5E51D001543DD89ACE3E59DE1E30000007E493885E1E4E5E3B30A0C004E004CE3E2E3E34CE2A40000032DE3E6E7E4E4E12F0038362BE2E3E43C00002B0059E5E6E6E6E6E5E24C000000003638E1E3E4000000079B6800E3E6E7E5E496000A1700C9E5E60000C0E4000000E2E5E650000007000000E3E5E4E1BEE72DE541C0E5E6E56A00E3E5DBB7E4E4E4E4E5E5E2D6E5E5E3E5E6E4BA00000050E5E5E3E4E5E5E4008500000012E4E4E3E5E4E4B5E4E6E6E5E5E6E4E3E5E50003E4E4E3E5E5E4E6E6E4E5E4E4E6E5E6E7E7E6E6E5E5E5E3E4E3E4E6E7E6E6E6E6E6E6E7E6E0E5E4E7E5E6E5E4E4E4E4E7E7E6E7E8CBE8E7E8E7E6E6E7E5E8E8E9E7E7E8E8E8E7E6E6993E129DE13ADCE7E4E3E35D4E000000000AB7E4E4E4E2570000000000008BDBE11BD25D07170CAFE3E3E3E6E5E007012B001028E5E638001000154EE3E4E4E5E4E2E2E2173A00000E1741E3E10110000A4CBC00A4E4E4E5E5E6000000050AE4E62D0100E4000020E6E7E7E1E2008568200C05E2E6E7E6E3E6E6000CBEE7E5E400E5E33AE4E4E6E7E5E6E6E2E2E4E3E5E6E6E5AC000000E3E6E4E5E4E6E6E5758B8050AF33E4E5E7E6E7E68BB3E4E6E5E2E5E5E6E503D2002DE2E6E6E3E6E5E7E6E8E7E6E6E5E4E6E6E5E7E6E5E5E6E5E5E5E5E5E6E6E7E5E7E6E5B7E6E6E7E6E7E6E7E5E4E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000150000000001000001E4E5E5E5E7E6E7E7E8E2E8DDE7E8E6E700CBE7E8E7E6E6E7E5E33307004E002DE4E4E4A1AC312F9DE071059BB5E4E3E2E5435D0700000028E4E3E2E4DD19000000DFE5E4E6E36F0A0000992F00E0E4E000003C0C20E1E4E2E4E3E5E2E1AFE0000115AF89E5E62B47001B00003654E4E5E1E2E2100A00126DE4E7E5E4DE000000002DD2E5E4E100000C1D9D0C43E3E6E5E6E7732207A4E4E4E39BE252A10028E4E5E4E6E3E3E1E47EE4E4E4E4E3DB3643E4E5E4E6E4E5E5E590E5E27E7EE4E4E5E4525DE5E7E6E7E7E7E3E5E4E38B000000E1E4E4E5E4E5E6E5E4E4E5E6E6E5E5E5E5E4E4E8E8E6E6E3E3E6E4E5E6E7E5E5E4C9E4E5E5E5E7E6E6E4E5E4E3E5E4E7E7E7E6E6E7E2E1EAE8E8E8E9E7DCE89DE8E8E7E6E5E6E6E4E300201B0000004728E4E4E3DD000000A1439DC0C7E5DFE6E40E000000001573E2E4E5E3125D1B00E4E3E6E6E3E42B000000000020E2CDE2201B12003ACDE1E2E3E2E4E2E4E00A00000015D6E6E322003615197C50E0E3E5E2E5010000000AE2E3E4E5E63A000C00E4E6E6E4C9014500000300DBE7E6E8E3E5E61549E2E4E5E5E5E6E600E3730AE6E4E6E08EE4920AE5E5E5E3000EBE475FE5E6E4E6E4E5DFDEE6E2E6E5E4E5E6E673E5E7E5E4E4E4E6E1E6E4000C007528E5E5E5E4E6E6E7E5E6E6E6E7E4E4E5E6E6E7E6E6E6E7E6E1E4E5E5E4E4E5E4E6E6E5E6E6E1BA07E6E7E6E5E4E5E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000170000000001000001E6E7E6E5E7E6E7E7E8E8E7E9E7E9EAE8E7E7E6E6E6E7E7E7E4E3E2070010000000B7E2E2D8DCC7590000CDE1D4E0E4E2E2E483000000002B0AE3E2DCE0450E05058BE2E150E4E3520105050320C5E2E1940107000043DCE2E4E5E5E4E3E4E320105B2094D2E4E2E0E2011252000071E3E5E6E43100000000E5E4E4E7E4E22815031D00E4E2E4D8AF002B4100E5E6D6E6E5E1E5E30E3600E5E5E3E4780A120300E3E6E7E5DDE2389DE5E4E5E00000963A2DE1E4E4E2E4DF68DC077EE5E4E4E1E43850E3E5E5E4E4E4E5E6E5E6E426DDA60AE3E4E4E1E4E6E4E5E5E478E5E5E4E6E6E5E5E5E7E6E7E6E4E4E5E6E6E4E4E5E4E5E5E4E5E4E1E5E1E4E6E4E5E5E5E6E7E7E7E7E6E7E7E6E8E8E7E8E7E8E8E8E8E992E9E7E6E7E8E4E0E5050007E33E6DE1E3DDE289E4E32F00282FE1E3E2E3E3DBE41B000000010085E5C289780000A6E2E14717B3E443490A00000064B5E5E20E003100003ADFE5E3E4E6E37E623E3C4307B3E5DEE4E00E00120C4C0CDEE5E2E1E500000E0043E3E2E4E4E5BA002B00190057E5E4E6E4000000002FDCE6E5E6E5E6E700000071E4E6E57510070152E7E8E8E8BC3AE2D2E6E5E4E60000E2AFACD0E4E2E5E2E66F3C5FE1E4E0E6E3E3666A9B339BE6E5E4E6E4E4E4E49D901BE2E4E2E3E6E7E5E7E5E2E5E2E1E4E4E4E6E7E6E7E7E6E6E7E6E6E6E7E6E6E6E5E7E7E6E7E5E5E5E6E7E7E8E7E4E4E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000190000000001000001E4E4E5E4E6E6E6E5CBE5E7E6E7E7E7E6E7E56DE6E4E6E6E5E4E3E2830C007C1564DC24E2E5E4E3E357000E01030A20E0C789B7E2C54300071BE0E0E383E324006FE4C5597E00A48500000033000085E326E30000000528996FE2E4E4A4E1E26F00100700177EE5E5E16A0000000A4E625FE2E00000000000E3E5E6E6E54C00000000001BE3E5E3E2002B012F50E1E3E4E5E0E20073000000E2E2E5E25728CD31E5E4E4E54CDFE400E3E4E4E100000A3CD8E5E3E6E4E05B5B000CE3E5E3E4E31278A4C0B3BEA8E5E7E4E4E4E2E38B3807E1E4E4E4E6E4E5E5C7BCE5E6E3E4E5E4C7E4E5E6E4E2E4E4E5E4E4E5E6E5E6E5E5E4E5E4E5E4E6E4E3E4E4E5E3D4E4E5E7E7E7E8E8E7E7E7E8E7E0E8E6E5E6E5E5BE2BE7E2E4E4E3E4E3E50020000000382062A4E2E2E1A48500050E000A0A22E3E4BE451D20D60A05E0C9E2D09D6DDC7CE1E207152B94E1315F1D261952E4E1C5D2362F0307057AE2E4E5E6E2E2E3541D0533240010DBE6E5000001001700E0E3E6E55F0C1010E57E8590E6E473240000000000E3E5E5E6E459431DBCE1E8E0E6AC570000000000E4E5E5E178943C17E2E3E5E0B1E40000E5E4E55B50E0594978E5E6E6E1904EB77300D6E6E5E3E42001A6949FE5E5E5E7E5E6E5E5E4E2789BE4E4E5E5E4E5E5B1DE8EE2E4E5E5E4E4E7E5E6E5E6E7E6E7E6E5E4E6E5E6E5E6E3E4E5E4E6E8E6E1DDE7E6E5E3E2E3E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000001B0000000001000001E5E5E5E6E8E7E7E7E5E6E7E6E8E7E9E8E7E2E4E5BCDB33C2E3E2E0E22D00000001287C9FCBE1BE940000000000016431E1E3965B00171724E2C7E0D8E0D6E14CE1E1E16A000762E233002200000CCDE1E1DF07000000000064A6E0E1E4E3E12B10280000ACE3B7E4E2000000003C0119E3DFE2680031901900000064E2E3E2AF00000052E3E3E4E1A43A070100A6C7E3E3DC228B0000000000E2E5E3E278000083E5E5E4E5E5730085E4E3E100895FAFC5E4E3E3E2457852AF28C7E4E4E2E310002641C2E5E4E4E3E296E3E3E5E4E5E2E3E3E2E4E5E0B1AC4CE3E3B1D6E6E5E5E4E2E5E4E5E5E4E3E6E5E5E5E5E5E6E5E3E6E3E5E5E3E3E4E4E4E5E3E2E3E5E3E7E7E8E8E7E6E7E7E7E5E6E6E7E7E9E8E8E8E5E400360C1749E1E4E1DF0000BA2001055252C2E44E000000002B0022685BB5D2A8102F3622C2E0E2E3E49657E5E3E4E1C0430547E4E0855D00000028E2E2E46F3E0000E20033E575E5E5E4E4E2432F1D00006D0578E11B000000190071C5E5E7CBE0E2000000000068E6E6E4C00012002D26E4E5E6E50300E4E3E6E58BE6E2C0E6E10A5D3C0000E1E5E5E6002B7A41E5E6E4E6E03E87E5E6E4E2E3E4E3E4E1E4E44159E26D5BE0E6E6E3E3E1DBE5B74E59E5E6E6E3E01DAAE3E6E5E5E5E6E5E4E6E6E592C9DC9FACE4E6E5E5E5E6E7E6E7E6E6E5E5E6E6E6E8E7E6E7E5E6E6E8E7E5E5E5E5E7E7E7E6E0E4E0E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000001D0000000001000001E5E5E5E5E6E6E6E2E8E6E7E7E6E7E7E8E8E7E6E40000000CE1E3E3E1E20E2B00052652432D31E2A6E00700006600382DE1E1E5E3002F7A00004E4536E2E35DE5E6E3876F000005AAE3E01200003A2FC9E2E5D015000000001DE46AE3E2E4D8E22F000000003A0003E4780000004E3100AAE5E4E4E4E4000000050000DDE53E00000043220026E5E6E5470045C2E2E6BE6DE4D8E2E76622E10075E2E4E5E4DBE400E2E2E5E5E4E4E5E2E3E4E2032F36E4E5E4E6E0E34EE3DEE3E4E6E5E2DB0E015D7512E5E6E6E5E6E2207AE5E4E5E5E4E6E4E5E5E4DFC0AAD845B5E3E6E6E6E5E5E3E2E5E4E5E5E3E5E4E6E6E8E7E7E7E7E5E7E7E5E4E5E6E6E5E4E6E5E5E5E4E7E7E8E6E5E6E6E6E7E7E6E615E7E7E8E6E7E60000000000AFE3E3E5E4E35F01002600150001D0E3D83A000000000C49E0E0E3D600000000001B0552E1E3E2E5E4E0150300000000E3E34300A83300D6E1E3C05D2000000000AADBE5E3E49F6FE50C00E200000C194728017A003A0000737EE4E4E3E400000000000000E7D0380049000000003AE4E4E4000500E30E00A4E4E6E5E400689D000CAFE5E20022001BE2E3E4E6E4E2E5E5E4E6E60E5900E1E6E5E4E4E5E3E4E4E1E4E5E5E6E347B54C0A83E7E6E6E7E59207E0DBE6E6E1E6E3E5E4E1E46F50DEB5E3E5E4E6E5E5E5E6E6E6E6E6E6E7E7E5E6E7E8E6E5E6E6E6E6E4E5E6E7E7E6E5E5E4E3E4E5E6E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000001F0000000001000001E3E4E4E5E7E6E5E6E7E7DFE5E7E8E7E7E9E9E5E200000000E1E2E2E0E3E3730C0015000C052DC2A67EE03C0700000C2B6820E3E4DC1922000000000162E4E5E4E0E25D0000000000B5E43E00120A36E4B3E3E3E3C90E152F7812BAE2E4A6E3D2E3100000000331E3E2E1E37A4303003600ACE3E3E8E6E400000000CDE6E6E5E700B72D94000E909DE7E38919E2E0050000C9E4E4E3874C0000B5E2E7E2D005E3DCE5E4E0E2C236103CE4E5E5E2007868E6E6E494003E0596E2E5E5E5E3E3E3E492E3E4E3E5E7E4E0545FC533BAE5E4E5E5E5E4E6E5E7E5E5E1E4E4E4E6E6E5E4E3E3E5E4E6E6E4E6E5E0E4E6E7E5E6E6E8E5E5E6E7E6E6E8E6E5E3E4E5E2E5E5E6E6E6E6E7E6E7E7E7E5E6E7E8E8E6E7E6E6E8E7D40000000000E3E3E4E0E53C001031000AB7E3E4E3E3B1920038222654A8E3E32B6F31000000000017E2E3E3E549E1450000000000E462000012AFE3E1E1E3E1E30C260A683AE1E0E3E3E4E3D6E1014E0001002212D8CD2FE10100010500E3E5E6A6E6A1280017030094E1E189E410002B00B1D2C5E5B145E2E4030000A4E4DD00E20000001DE5E5E5E5E4337AE5E7E5E67ADB4500DCE5E5000000E3E3E6E4503E9B49A8E4E4E0E30000008EE5E5E6E4E5E552E264E4E39DE5E5E6E6E5E6E5E5E2E6E7E6E7E6E6E6E5E5E5E5E7E6E8E7E5E5E6E5E7E7DEE4E6E6E6E3E6E6E6E6E5E4E5E5E0E5E5E3A6E5E4E3000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000210000000001000001E5E6E6E4E8E6E7DDE7E7E7E5E6E8E8E7E7E6E8E8E4E3E05F001280E6E3E4E390382419004CB5E2E392E080780C1D000A2D75E3DFE3BA2020013E000000E3E3E3E5DD1D000000000000BCE347006D260057E0E5C95B5F0022000000C2AAE1E3E4E6220A170C20360A00E1E4E6002F00E10000E5E5E322E4220000032250C2E0D8E4E5000000B375623EE4E5E0E5E000000003E4E4E30700C9000543E3E4E215196659E4E3E57E2D0C5BE3E44700000092E4E6E36A0015E3E1E2E4E33300A80000E4E6E4E5E3E4E6E3D675E2E0E3E3E5E5E5E6E4E4E4E3E6E5E6E4E5E6E4E5E5E5E4E4E4E4E4E7E5E6E5E6E6E7E5E7B3E5E6E5E5E5E6E6E6E5B7E445E8E4E0E2E3E7E7E7E7E7E6E7E7E8E8E7E7EAE9E9E9E7E6E6E6E7E6E5711DE2E3D2E3E5E4D4A4240E54032224E1D8E46887BE2B00071B00D8E2AFD82F00890000003AE2E4E1E1BE5D2FBE710E0031ACE49F547115070E54E5E6E249050500000000E2E0E4E4A83E00052010001D0E68E5E4E30000E000105DE6E6DEE6E6360015000001E3CDE4E41D0049310AE1E5E6E6E5E6E50000001DDEE6E50A000500260059E3D4228E508E59E7E4E5005FE2E5E520170000DCE6E6E603C74799E6E5E5E30003000000BEE7E7E4E5E22DA1E2E0E3E3E6E6E7E6E7E6E5E6E5E5E6E6E7E7E6E8E5E5E4E5E7E7E6E5E5E5E4E6E6E6E6E4E7E7E7E9E8E6E7E6E7E5E7E7E6E6E6E6E0E3E5E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000230000000001000001E4E4E5E5E7E6E5E6E8CBE8E8E9E8E7E8E8E9E9E8E7E4E4A67CC062E2E4E2E4E3E34731000019076AE0E2C964122B100000001BE1E2D264000000079FE2E2E2E3E203E1E39D00000000C0DEE2200C0015BCE4DEE4E5900A0000001000C094E4E4E3990000007A0000B7E2E4E466000300000ADEC5E6E5E6E50000003C0007E0E4E4E2DE017C57008E24E2E4E3E4E500002FE4E5E494E4B500003E0110DF470031A4000E99E287001D87E0E568220AE2E5E5E3E4E5E21099E0E6E5B7DBC5505BE2E5E5E6E4E1CD8BAA89C2E6E5E4E5E6E4786AE3E4E3E4E3E4E6E6E6E7E5E5E5E4E5E1E5E3E6E5E6E6E8E6E3E6E5E7E5E6E6E6E6E5E5E5E5E5E4E4E1E6E5E5E5E4E7E7E8E7E7E1E6E6E5E6E7E6E6E7E5E6E6E7E7E7E7BC52416FE4E296B5BEE3E0E3DC0C010000013ABEE4BC6F0000001900008589E4713601001933BCE4E4E49FE4E3C552412F1B030033E3E49600000A002FC7E6B5415949000000170E38E6E6E6BC000000000022752628E2E30C0033120564966FE5E6E32F0E000C000092E4E6E7E8331D24052DAAE5E5E4E4E4D07C0031E2E5E6E5193C2845000CDEE500E3E50578C0E345003A00E4E5570050E4E4E5E5E6A854472DE5E6E6E4E341070071E6E5E5E220C7A6DDE3B7E5E5E4E4E5E3E2C759925FE4E3E1E6E7E7E5E4E5E4E6E5E6E7E6E5E5E5C5E6E6E6E5E7E7E6E759E5CDE6E6E6CBE6E5E07A7AE5E4E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000250000000001000001E4E5C9E5E7E7E8E7E8E6E7E6E9E7E5E9E4E6E6E6E3786D57001BE1E1E2A1C2E2E1E400000000000000E0E3942600000000158026BEE2CD4500419062D0E0E18EE4E3E4DE667C0000000ADBE0E20C000000008EE4E34C92152415281D0700E1E2E5E500000000000000594EE2E224003C006603527AE2E4BE570A00102D47E3E4E5E5E562001D072054E2E1E3E4B7A817001983E4E3E54599A85BCD0C9DE422DB005D7CE4E40E280C002FE4E4D805E0E4E4E4DE7AE1E3C7E5E4E592646F318EE5E6E5E5E5D89FC09DE2E3E4E3E4E4E5BE64E3AC5F7AE4E4E4E3E3E4E3E4E3E4E4E5E5E5AFE4E5E4E6E6E6E6E6E5E5E5E6E5E5E5E6E6E4E4E5E3E4E5E6E3E4E4E3E7E7E8E7E7E6E7E4E6E6E5E5E5E7E3E7E6E5E5E4E5E0E20A0031001DD2E5E4E4E4E1AA4E000000000071E3DB622F000A36000E0CDCE0B5A63E12B3E2E3E4E2E3E6E6E6B3C73C00001536A8E36A4500100E00ACE3E4E42D3E002F000E22D4E3E4E5E4E2E37A45000000220389D099809F0017000A0EC0E4E41B010000010ACD8B00E2E5E2151B00E3E5E5E6E6E30AA67EBC572290E4E4412403750000E2E3E38B000028E5E347151231B1E4E4E5E5E6E5E3E4E58EC766C9E5E4E23E33C754E4E4E4E3E3CD1BE443BEE5E5E4E7E4E4E44EE6E0DDE4E7E6E5E5E6E4E8E7E5E3E5BCE5E6E5E7E4E4E5E3E7E7E6E8E5E1E6E5E6E6E6E7E7E6E4E6E4E3BCE6E5E5E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000270000000001000001E3E5E5E5E7E6E6E6E7E7E6E6E8E8E8E7E5E6E4E5E4E4E4AF00000000996AB5E1E1E1DE0000000101103ED6E2E14300000000031538DDE24C03003CE0CDA1579BDEE3E1A6E187070E4EE3E3E4E2E36600001952B1E2E4D40700120000017CE5B7C7E3E1E419000000000328DBE390E13E6D0000000054E6E4E42600280528000001C7E357018E0141E6E6E7E4E478002FA42D073CE3E5E000224C2800A8E5E5E47826DCE5E46D0385AF71E4E4E5E4E5E4E3E39F2B2600BEE2E5AF3826E545E5E3E5E4E69D120750AFE4E4E6E4E4E200B32FE245E1E4E5E4E0E3E2E2E2E4E4E3E2E3E4E3E4E6E6E4E5E5E6E5E5E4E3E4E5E5E4E6E5E5E5E4E6E5E6E4E1E2E4E5E1E6E7E6E7E6E6E6E6E6E6E6E6E5E6C5E5E5E6E5E7E56FE45200191D38929BB1E2E2E3686F000A000E3A4C62E4E25200000C364E00173CA178BA20009DE2102022E0E4E2E5E6527ADF17E1E2BAE4E0DE500005E1E2CBE6AC261000752400ACCDE2E3E3E49B7128261703281294E3E2E3E3A60E030000248EE4E2750000005707002217E3590A47E52FE5E3E1E4E3E222CD3C3600571DE6E31900A62057E4E4E5E27EE2E2E3E4E4E2E00071E5E5E3E5E5E4E6E36F2B0057E5E6E4E08B006A41E1E4E7E6E3E2D01DE3E4E6E6E6E6E2DC00E32B9243E6E5E4E4E5E2D0E2E3E0E3E3E3E3E2E3E4E5E3E6E6E2E5E4E6E6E6E3E5E4E6E6E7E7E6E6E5E7E7E7E8E3E5E0E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000290000000001000001E3E4E4E4E7E8E7E7E7E8E6E4E9E6E8E6E3E5E6E6E6E5E4E4E00A17000054DD9487E58BDD00002BB7202694E3D4E1360000122B00197EBCDDE27A009F520031005BD8E3CDE04E4E310020E2E5E5E1C29D0010992B5DE3E280010C0000005DD8E3D0E4E3E2E27A192D001D45B5A4E5E0BAC717007A000068E3E4500000000000000031E3C9BC000000E5E53CE3E2009B190315032F2666E3C70005668BE3E4DC0003001DE1E2E4E4E4E4E4E5E2E5E4E4E5E4E4E23E526A78E4E5E29DB100CBE5E4E5DB1089E16DE3E6E6E4E4E5E4474517E1E4E5E4E3E4D6BCE380E4E0E2E2E3E3E5E4E6E4E4E6E6E4E3E5E5E4E6E5E4E4E3E5E6E4E8E6B5E6E794E7E6E5E4E4E4E6E7E7E6E6E6E7E6E7E7E7E6E6E6E6E7C2285BE6E7E6E1E5C9380000000C5B9BE2E4E2E30A051983DBDD8BE2E371D2360000002B0054DCE2D86AE266005B2D0775E4E4E5E383BA1D0007E0E3E3E4E3AC0000003E75DBE3E3E02401051003E0E4E2E5E4E4B5AC3349000010A4E483D050201500241B0112BAC7E119123C0A000000E1E5E475380341E4E289E3E3DCE10A03226D00B3E5E3E3E5E5E6E5E55078490571E1E5E5E6E5E6E52443E4E5E5E5E4E6E7E6E59F874EB1E5E54E59B1E4E4E4E26A6464E2C7E5E6E5E4E4E483E5E04E33E5E5E7E7E5E7E5C7E3E5E6E8E4E6E5E4E5E4E4E5E6E5E4E4E3E5E6E8E6E7E5E2E1E5E5E8E6E6E6E6E5E6E0E5E6E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000002B0000000001000001E3E3E4E4E7E7E7E7E8E6E8E8E6E8E8E568101BE7E7E6E6E5AA3300002F0017E1CDE1E4E3E143003633D8A8E5B1E1A69F120105150319A8B3E56AE5450CE36419128BE2E5E47C9678000C2F7EDEE3BA620E36001033D4D2E2785D7300052D5DA1E1CDE4E4E2E026121728871750C2B7BA20001200002405413CC21D00660000003600E5E7170EE0D2E5C2E2E4E2E3E10000E3310020B5C0E2E5E5E7E5E49626E1005DA1E5E5E4E5E5DB9D8B36A8E3E3E4E4E6E2E3E5E387E1E5E6E4E2E3E4E4E4DDD80E0CE1E2E5E5E5E5E4E3B5E0E27A94E4E4E5E4E4E6E3E1C7D4E0E4E5E5E3E1E4E2E4E6E5E4E3E4E5E5E4E5E5E4E4E3E4E6E6E6E5E5E5E4E2E4E2E0E3E4E3E5E6E6E6E7E5E7E6E8E6E6E6E6E8E7E40E0119E7E6E5E3E32B943600000000E4E2E3E3B76D240019033154B7E3E1E4E0453E0A0E001003E3DDE2E2E138010024C7E1C5E3E5E1D84900000059E4E5541B0500381210127EE4E22BB13C0E071000B7E5E5E5C7CB244C00A60A004900C0E8000047006400000317E2E2E0E50E0E001220DEE5E4E3E6E728573ADCE5E5AC5F0000410C07E5C9E3E1E2E3E4E5E2009200ACE4E5E5E4E1AF03244333DBE5E6E4E3E4E5E2E5E4E6E5E4E5E3E5E1E5DFE4E30590014EE5E5E5E7E5E4E6D8E4BE3AE4E6E7E7E8E6E7C000070CDFE7E6E5E5E4E3D8E5E6E7E6E6E7E5E5E6E7E7E7E7E6E6E4E7E5E6E5E6E6E3E6E6DEE1E5E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000002D0000000001000001E3E2E4E4E6E6E5E6E7E6E7E6E8E8E8E6AFE3E5E4E4E6E190E2E19000001589C0A887D8C9920000000012478315E2E2C58926004300330087E2E4C9E1E05200003A6DE0E3E2E0D80000E100C5C7E3B72D00032F05000000E3E5E200100007000028E5E4E7E1ACE4364E2619000083ACE30A000000AF2D6D3C2FE1E4E5E6DFC7520000E4E7E6E2E5E092E185E4E645C20A4E05030700A8E443E3E5E0E4E66A94310043E5E5E4E3E3E5AC751722E6E5E4E5E4E352CDE3E0E3E5E3E5E5E2E6E4E4D2E05438AFE3E4E3E3E4E2E4C0854185A1DCE7E4E6E4E4E2660124E4E4E4E4E3E2E4E5E2E4E6E5E6E5E4E5E5E4E6E6E6E5E3E4E5E4E6E6E5E3E5E4E5E699E4E5E6E5E8E7E7E7E7E7E7E9DBE8E8EAE8E8E300050A5BE0E6BC4CE5E5D06D103A1296E16F38E2C5AF000000000080D8E4E1E3B10100000020D0E1E3E5E3B1381533261D5743DFE3E4DB0000000341D2E4E3E2121500C5002B00E4E7E34345000E00000022AFE3E5E2E1E3E2412800856880E6E2E10C00001200050EE4E5E5E3E40000000064E3E6E4CDA4E2E4DCE5E4E4E152891241500054E8E5E3E6E4E5D61B0073203EE2E5E4E4410EC7E23107E4E5E4E4E3E52D832D75E5E5E5E5E5E3E5E5BE8038C0C0E5E5E6E5E6E6E5E4E0E44562C9E6E6E4E5E2E2E19928006DE6E6E5E5E5E5E4E6D4E5E5E6E5E6E6E5E6E7E5E6E6E5E4E2E4E5E6E7E6E6E6E6E2E2E4E4E1000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000002F0000000001000001E1E5E5E4E7E7E6E6E7E6E5E5E9E7E62D00E57A12D0E0E6E6E45F00DF00190001058780E4AC1B0000000000319BE0E0E3E1010C0000432BB1E4E3E490542D0000002438E27CE1B55F0000001BE5E1E3E45D100022000000DBE3E2C2360300002D000026E4E5E3E2E3B51D3600005DE2C7E3B10300000100100022E5E4E3E0001500000041E5E59212E3E438E1E4E2DF5D45240C125D002DE5E4E6E4B1170057004373E2E4E2E2E001E0990085E6E4E2E4E4E43A6AA49BE0E4E3E4E4E4E5E5E3C215418BE3E5E4E5E6BE6D59E46433E5E6E2E6E5E1B5E3E2E2D066E2E6E4E3E5E4E5E4E5E6E5E5E5E6E5E5E5E4E3E5E4E4E6E6E6E7E2E5E4E3E6E6E7E68EE5E5E4E5E6E6D2E7E6E6E6E8E8E8E8E7E6E8332200050305E6E5E6E4DE03120000AA00001B00A8E29F20000000001B9F31E3E390E226033157E1D2E5E4E4C045052400005D38E1D4E2BE50BE2D31208EE4E3E3E15D000C0003529DD8E3E3DB17000000002DA6AFE4E396E15F5F2220EBE5E0E3E39F2F491915056415E27554E3E50500000000D2E3E46200E6E12F8EE5E5E3A8E7E600100C0700E6E2E3E4E3002D8928527AE1E2E7E778D2BE240E33C5E4E5E5E4E3DB59E0711BE0E3E5E5E5E2E3E4E4B39DE6E6E6E5E5E5E6D6E559E5E5E5E5E5E5E4E1BECBE3E2CDE5E3E5E2E3E5E3E5E4E3E4D0E690E6E6E5E5E6E7E4E6E5E6E5E4E6E7E6E8E7E4E3E5E4E2DEE4E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000310000000001000001E2E4E4E4E7E5E5E6E6E3E5E5E6E7E70000003CDD3A966DD2E2E2C90000010000001924E2E2960A0000000000003180E226E173030700CDE1E2DBAFE49B7E03000000105DDCDBAC7C3E36000C005BD0E2E77107000022007AC5B762D4D40000520000BC7CE0E2E1E0E1E07A0003E77EE2BAD65B9D00003801263C01CDE0751500002415E1E4E3E399E0E14E6FA8E6E5E6E501001B001D1043E4E5E1A6750000004C2D36E4E3E21073501B00B7E3E2E2E3E5E41228E2DBE0E1E5B7E5E4E0E2E3C0C026E2E3E4E2E4E31066E59468E3E4E3E3E1D800B18EE4ACE1E2E3E2E4E3E4E3E5E5E6E6E4E3E5E4E6E6E5E4E4E2E3E5E2E4E5E3DDE4E5E4E5E4E5E2E5CDE4E4E4E7E8E6E7E7E7E7E7E6E6E7E6E6E8000036E2B5E2E0E3E5E5E3E4E20A000000597E99E0D094C23600007107000AE05FE3B3BC00282407DCBE8936E1AF6A3100000003037EE1E5E05F200000000CC2EBEAB1030000101D5B92EA9F28D6363E000000105D2D9D7C68A6411712458EE254E3E2544E0000122B2899DF9FC5AAA61B380015E09BE3E5E5E5E3003320AFDFE4495959832649055FE2E5E3E4546410000317E4E2E4E5E4E50C0715C9E2E4E4E5E6DD317C54175DE6E5E4E0E7E0DFBAE4DFCBE5E3E0E5E5E42D6A62E2E2E4E6E4E6E389DBE5E4E0E4CDE5E4E7E3E4E3E594E4E4E4E1E3E5E5E4E5E6E5E4E4E3E4E7E6E6E6E4E4E4E4E5E5E4E7E5DEE6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000330000000001000001E2E4E3E4E7E7E6D8E5E7E6E6E6E6E61903389994E1E1CB36E068E2A11500317A1D1573E3A8DBDE33000C0000002426D2E1C9E0000000009971152D99E19B620000120C262BBCDDC0E1E6003A000EBEE5EA5D7CC900000000E5E8E9890066122D000000265DDBE0E6E478004C001500DB83E3E1BA5401005941A6E2E012E2E4870001122BE2E4E3E5E3E324E09BE1E3E4E5A800100A203C22E1E4E4E4E149030700A8E2E4E4E4E40000000068DFE3E2E3E37507472DE0E2E4E3E3E4E48E66E4E3E6E5E4E6E3E4E41B263E8ED0E3E1E3E5E4E268039FE4E2E3E3E4E4E4E3E3E4E4E3E4E3E2E3E4E4E6E4E5E4E6E5E6E6E4E5E4E5E4E4E5E4E5E6E4E7E5E4A1E4E4E5E7E7E7E6E6E5E6E7E7E8E6E0E7E8E3000000E1E4E3E0E3E3E1E1E0E07E2B01000000AF36C2DE7C0000000000000AE1D88E0043000026000000007AE00A120000000000D0E4A1E6DBE200000000D6E1E9EBE79400000000D6EAE1E580364C000000010017E6E8EBE3E215005B2D000CA4E2E3E24500002BE022000041DB90120024000043E3E5E5E4E5B5C0E6E6E6E4E5E501576F179901E4E3E4E4E33E260007CDE5E5E19F00000001E2E4E3E3E4E457000080E1D8E2E4E4E4E5E5E4923ACBE6E5E5E5E4E4E159E010C7E3E5E3E5E3E3E4E3520049E4E4E4E5E4E5E6E4E4E2E2E4E4E4E6E4E4E5E5E5E6E5E3E2E4E3E5E6E5E6E3E2E3E5E7E7E7E6E0E4E1E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000350000000001000001E1E4E4E5E7E6E7E8E7E6E3E6EAE9E7BE00070000334EBAA4DDE2E0E2C99BE11D28000052E0E29F2B00000020000000001DE2E0B7800A28150000646FE1E25B000000000000E5E1E1E2BCD800000022E2EBEBE8640E2412036F9080E7E37A00050000000028C5E094CBD499000000170089E1DCE1150000000A28962DC503430A000305006AE2E6E5E6830019E1E3E5E4E4E12B2B00000012E5E4E3E4E21200410047E5E4E2730000AC2200E1E4E4E55F0007260AE3E3E4E4E4E33EE0E1003AC0E5E5E4E4E6E55400E1E4CDC0E5E4E5E5E5E2E3E4E450E5E7E4E3E5E4E7E4C5E0E1E3E4E5E4E3E3E4E3E3E4E3E6E6E3E3E1E4E4E4E6E6E4E4E5E5E5E5E4E2E2E5E4E7E8E7E8E6E7E7E8E7E7E7E9E7AAE9E07505710057D815C9E2E3E5E4E0E2AF280E0C9D2FE47CE20700000E0000001200E4E35296E08B00001500126FE368DD00120000000059B7E0E2577E1B003871E1E8C773070A000007544E7CE48747240000000000501BDEDEE8E0000000504CBECBE2E5E96624002F1B1B433EE2E101004C000EA1E3E4E2E04E4507006ABAE6B70710156A4131004CE6E7E4520A000000E4E2E3E3000043000000E6E6E6E7E5311B0022E2E5E5E3E6DC00332400B1E4E6E7E6E4E7E51BE10007AFC9E6E5E4E5E4E38EE026E6E7E6E5E6E7E552668EE6E6E7E7E6E6E4E5E6E6E5E7E7E5E396E3E6E6E3E5E6E6E4E4E7E7E8E6E1E5E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000370000000001000001E3E5E5E5E7E7E7E6E8E8E7E5E5E8E6E8E500000010006D246F9FA4E3E3E4E3C0E33E005F1DE3E05092000000000A0373A4E3E2577AE0E10007AC000000E1CB2F6D00BA00000001C7E3DCDE661D1759DBE5E3E89900000001006FE1E1E4E4E2C7335F3A00000000198EA6A8281500284100BAE4E5EBEA62001726000017DBDB000000000015E3E5E3D05D26006AE5E1E6E4E30000000A0000E4E1E3E4E21D150000C2E0E4E4A42F002D009450E5E5E4E3002F1B4307E4E3E4E4E3E412E4E500E4E4E4E4E5E6E5E5E4003CCBE4E4E4E6E5E3E4E0664EE5E0E4E4E6E5E42BE2E1E2E2E3E6E4E4E5E5E5E4E6E5E5E6E6E7E5E6E3E4E4E6E5E5E4E6E3E6E7E3E6E0E5E5E7E7E7E5E5E6E5E6E6E5E5269FE7E7E9E4150E0A71E09678E2E1A65BCBE0E16D330C0A008BA47105000000001001004CE3E0D49BD89F0000002D1200B5E3E212000019170005E1E4E0BE1B000005B7BADBE5CD00002D000147E0E6E6E4D8243A1B73D2000000E0EB9FD052384700000041B1E5EBE99289B5000000003CC50000E5000000E0E6E5AF781759E7E6E6E7E6E5DB01002200226FE3E1E5E5A6382043E4E1E2E3E4E54147859B64E3E3E3E4CDE09DE4E4E5E4E5E6E5E6C2000000E3E6E7E3E5E8E6E5E6E6E4E5E48EE4E6E65DAC225FE4E5E5E6E6E6E5E59BE7E3E6E6E3E6E5E5E6E4E5E3E5E6E7E4E6E5E6E6E5E6E4E6E7E6E6E6E6E7E7E6E4E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000390000000001000001E0E5E3E4E4E2E7E7E6E7E9E7E5E8E7E6E7E503150000A100050085D0C9E2E2C2E180D6545DA4E2DCD02B0E0000000000008ED694E3E30001000000000E1BE0E205003112002494EBEAE03A000000000043E2E9E500000000002D15E77EE36D281507000000034389E6E5E1E3E3751D00000C4CE2CBE2AF9F781B1003781B7C000000001D2FC5E4CB070C5B643AE3E6E5E6E5E8E50096009612E5E4E45D833A246F15ACE4E5CD1017450045E4E3E2E4DF3C8E3E1BD4E4E3E6E6E6E138410738E2E6E6E6E5E685E3E4E4E4E4E3E4E2E1BA38D0857CE4E1E2E49DE5E5E2E2E4DED0E6E5E5E5E6E6E7E4E4E2E3E5E5E5E4E5E5E3E4E6E4E4E4E3E4E5E5E6E4E5E7E6E3E6E7E6E7E7E6E6E7E8E9E7000015E8E7E79F1700190100000041E3DE8E667E9FE1AC193892BA9FE17C030000000000006F24E3E5E56A680E2B22070A7EE5C2525D360A005041E2EBE0BE0000E10301E4E7E75400000028386200DF15E4E31700150000473838B3E1DBB3E3BA9F0020000092D2E7BEEAAFDCE3942633003E96004C453822E4E5E3313A283A66E4DF054C2B223E002D00332880E3E48E0000229405E7E5E6E6498B0E4105E1E3E5E5E478E0872B57E4E4E4E5E37A472D49E5E5E7E5E6C03A0307DBE6E6E6E8E5E5E5E2433C36E2E6E6E7E7E7E5E1E3CD94E4E5E5E3E2E4E6E4E6E7E5E2E5E6E8E6E7E8E6E6E6E5E7E7E6E8E6E7E5E7E5E5E4E3000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000003B0000000001000001E3E5E6E6E3E5E6E6E6E6E7E5000000C0E7E7E70000033EE500006FE1E48BE24E2D80C26FB3C24CDB5DD42800BE0012C70096E1E3D4E5E00005000000000E7ACBC71200002B0A17E0E6B5E0190000001D64E9EBBA000000000007758362EAE5DB00000000001564474CE56F1DDF0E008000000059E6E2EBC0DEE1803C004100E10A450054E2E3E459500E54DBE3E30000005D002F00E000333EE4E3E457363C00005DE2E4E5E6E5330031E0E4E5E6E5E63AC00028E5E7E6E7E2E4478B003CE3E4E6E5E46205E3AA01E3E5E6E3E5E5E2E6E37EDDE7E6E3E5E4E4E42D00B5E3E1E5E5E5E5E4E5E5E4E4E7E5E2E6E4E3E4E6E5E4E3E4E3E4E6E5E6E5E7E5E4E4E6E4E4E7E7E7E7E6E7E7E3E5E6E65B000083E6E8E8A10003001500202D8EE080E25F0585E2E3A8E15DE2DC54E2190001001B264EBCE3E3787A1900000000000517E3E390000064070C33E1A8E3E1000000009BE7E4E3050010000028504E75E9E79B242D030000121D0000D878DBE2000000150020A6E9E4E2CDE01B000036310022E400006AE1DDE4E4E29F7C38ACE300E4472247260E9D001D4CC0E3E1E20003B3000054E3E4E412000050E6E6E7E6E45743E4DE3AE3E5E5E4E2E219000041E1E5E7E6DF945D8E0C8EC9E6E5E8E5E6E6E5E6E4E5E6E4E4E3E45400E3E55FE3E3E3E5E6E4E5E4E4E5E4E6E6E6E5E5E4E4E7E7E3E6E5E4E4E6E7E5E4E4E3E5E5E5E2000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000003D0000000001000001E1E3E4E4E6E6E7E6E6E7E6E600000000E2E0E5C2593600003E288041E2C2D0A84E90877EBEE1DDE1BEE199E10000003328E1B1E2E0E0800000002400000052C2E4A68000000000005B62E4E3330000D0E2C0E4CBB5AC22E3000000000C85E7C2928017070057000000B5E58592D2000000009B68E5E3E2DBE200107CC20000E2E56A26E7E3D0E0E4E41B00E0E4E626D07A262083002B000083D4E1E1DE0000E400001DE3E4CB00A44E0A43E4E5E0E2126F3A0A0AE4E5E6E6E27868BC003EE2E2E2E1E22B28E3E1AFDEE6E6E5E5E4E6E5E2E4E5E6E6E5E3E00A12E03350E2E2E0E5E1E4E3E4E4E6E5E4E4E5E4E6E4E5E5E5E4E4E5E3E4E2E7E4E5E4E3E5E522DBE3E6E6E6E7E6E7E6E7E6E6E417006F1980E4E3E443190000000E6D718BBAE119191D660CD8E2E2E3DEE092640038663C80DBE2E4DCD8101B000000002D003E6ADC712220000000000E50E9E7E171151D0010CBE2E2991500010A00000000E1E38B332400380000000022851DDC9F170000000A8083EBE2D0E2E31B22006A1285E1E2E3EAE7E2E3E1D028283EE2E8C9070A20DBC954753C1000E5E4E5DC22226800002DE6E5C70105003349E5E4E6E5E54C2431E5E3E4E3E2E3685B6D24E1E3E3E6E5E47E5F595728E7E6E5E6E73EE1E5E5E4E5E5E5E5E5E4E0D4E317E0E5E4E5E7E5E6E6E5E6E5E6E6E7E7E6E4E3E3E4E7E5E5E5E5E4E5E5E6E6E6E6E4E4E3E0000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000003F0000000001000001E2E5E5E4E6E6E6E6E7E7E7E8E400177EDBAAE4E7ACA6000000000012C0E2E30000380E0150BC6DDBE2B3685924381D9017E2E2E5C0E0E394DD57001000000C01CBE27A5F008B380024E2E1EBE95900000000387C2B9466000010000000E1A6E4E4E300000000710000104185BCD0781000200092EBE1E3E0E0E26A000000992026C2EBC0BE49DD6D942FACD6EAE6B1E3E343E4000073288B3EE3E3E3BC3AAC00220A41E2E7E25417002BB3C2E5E5E4E08E5B17E4E4E2E5E4E5E092E5E4E4E2E4E5E5E1E226945922E0E6E7E666B1BCDEE3E4E5E4E5E5E4E3E5E3E2E4E4E5E4E6E5E5E5E5E7E6E8E5E6E6E4E7E6E4E5E4E4E4E5E5E1E5E5E5E5E4E4E5BCE4E5E5E3E4E7E6E7E7E6E7E9E8E8E8E74778E5E4C7CBE3E33E00000015000017E2C2150007008B034E204178E185E1E13E2FAC077C7EE1DCE4DDE5E1E13E00005D1768D6895931000E01246292E1EBB35D0000002B1B00456F9654071719000100BEE4E5E50E000000000000000000B1E8E245001792DCEBA8E0DFC5E28000000C909D28B3C9EBEBE2E4E5A83AC57C64E2C2AFE6C200001B00000096C9E5E4E2BAE3BA000545E7E4902062E5E43CE4E5E3E5175D1092E4E3E4E2E3E31010C2E6E5E5E6E6E7E7E5E3544CE4E6E5E4E4E2E666E4E4E5E6E6E6E6E6E5E2E5E4E4E5E5E5E4E6E6E6E3E6E6E5E6E6E6E7E8E5E5E4E5E6E6E5E6E8E1E5E5E8E7E7E77EE371E3000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000410000000001000001E3E4E5E5E6E6E4E4E8E9E8E9E77E00000041E3E7E30503000000000C00C9E3641B241B00000C104E89DE5971125D07120EE26F079DE4E4E4D0B7002B0000000036E1DF891900000005AAE5E90019000000190003E57385730075000033000000E3EB544900000000000000000087E13A000019C7E5E345E0BAE2EB64001500E2E4E0CBE0E5E1E3E2DC0EE05FE2BABE0C38120A0059593E009FDEE5E4E3E2E0E30024C0E4E5E30571C57350E7E4E3410100642F71E3E5E3D29B99CB5DE4E4E3E6E5E35D5B0EE4E5E5E4E1E2E073960E85BEE4E3E3E5E4E4E5E5E3E4E4E4E3E3E3E3E4E5E2E6E5E5E6E3E5E4E5E5E6E3E3E6E6E7E7E5E5E4DFE6E5E5E6E3E3E4B7E5E7E7E7E5E6E6E2E8E8E7E7E900000A00D0DFB7E5E1070000000000A1E2E0E200000005120C0059CDE0CBC989521003DFE1121BA12D94E4E200000005330000008EE3E2450E010000BAE2E4DE2F000000430000E8199B2D3A00000000000000E2E6E55D00000700000500229228E1A6003C00E31B45159FD8E396870003000CE4E3EBEBE8E6E4E568890ECBEAE2E4E3000000000000001B80E2E4E3E4E4E5BE171536E4E5AF100EBE2489E4E4E50E0EC0206496E4E5E6E5A817003CE4E2E4E4E6E399D6E5E6E4E5E6E5E4B766D038285DE4E3E5E4E3E2E4E7E2DEE4E1E4E5E5E5E5E4E4E4E3E6E4E5E4E6E4E5E6E5E7E4E5E4E6E6E7E4E5E5E6E5E6B1E5E2E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000430000000001000001E2E4E4E4E7E7E7E7E8E7E8EAE1B100000000BEE09B2F00000000005B9FBA2B57050000003841000062C5E2E3D07E9D196F891D00000036E2E27500000062000000E1E28BE1B5008E1722C7E3D4BA9F5F003A3E008B7C3671B5000000003C0000A1E8E93300000000AA411B00006AE17A1BE6D6E7003E49A6DBE3E792AA00000024E5E9EBEBE6E4E500001000170EA8E3E4D6360E001233C9E4E3E3E4E3E2E3E320CDE4E2A47810500C20C5E6E3E33A470000E1E6E4E5C73300AA0092E4E3E4E4E47347E2E4E56AE5E4E4E494E5E54C8BBEE3E4E2E3C50050E2E3E2D2E1E2E4E6E3E6E4E2E4E3E4E5E3E6E6E689E7E5E7E6E6E7E7E5E4E3E2E5E5E5E5E2E2E2E3E5E7E7E5E6E6E7E2E9E8E8E8E9E80503E059206AE547012B0000002D3875B54ED033000000000019005BE3E157E0E07EBE0A0015310E00CDE19D000000000003E2E1E2E2E1012600000036E1E03A9B31007A64500E28B168E500000000170000BC0001E900000000000000000096E26A001D9226190112AFD6E5E86F6F3C003305EBE1EBEBE4E3E3E3010000004390DFE3E3E50028C9E6E1E6E4E6E2E4E3E4544C7CE6E4E5E436DB3600E5E6E6E1D685159FE5E6E6E4E2960000008EE5E4E6E3E23E94AFE4E5E5E3E5E4AAC2ACAAE0D4E4E5E3E4E068E4E112DDE2E5E3E2E2E3E6E5E4E4E2E4E4E3E3E5E6E5E4E5E6E4E6E7E7E9E5E5E6E4E6E6E5E7E5E3E3E3000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000450000000001000001E2E5E5E5E5E5E5E5E4E5E5E6E7E5E7E8E03A1524E3E43A68000012100047D8E100075200000000000E8EE1E28BE185E4A8AF4CB55D002F9BA4E119000003001B3373C7E4E319006F000375DCE0C7E1102BC54920000000C0E00000000C000000030096E40000000000000000007EDBE1923EEB3819623371E0E4EBEA1B00126D0000D4EBE8E4E3E1E0101D00052B3817E4E457312F454CE4E5E6E6E2E5E7E6E7E3E2E4DFE4E3E3E0E200E3E3E5E5E5E1E5E5E4E4E6E5E6E4200001E2E5E5E46D1B0000C7E4E5E4E3E3E3E4E3E58971E4E5E5E4E2E152DC6A00D6E4E3E2E2E3E2E3E5E5E2E3E4E3E2E2E2E3E3E6E5E2E6E2E5E5E6E5E5E5E5E2E7E6E5E7E6E6E3E4E6E6E6E7E6E6E6E7E7E7E7E7E8E8E8E77E0C41E2E5E68B00030A05009D71C90A38680041000A0000AA57BCE5E4E3E5E16FE33A0C2BA1E3E0E2E2520005005F009DE3E29D1900000000E4E0E5DEE1AA6F0E050A00003AE8E6DE5B1D0000009D501BE6E9000000004107AA224C24E0E5809B3A410012000003E4EAE82B2F0000001DE3E5E3E5E7E9E5E5E000007C572BE1E29F073617009BE554E4E4E3E4E40C00339FE5E6E5E34347E4E3E4E5E3E6E6AFE3E3E2E7E7E6E70520A6E4E3E5E5A622E32807E2E5E5E6E6E685E4E45438E6E5E6E4E4E1AAE11733E2E3E3E2E48594E5E5E5E4E5E4E5E3E4E4E4E5E7E6E7E8E6E6E8E6E7E6E6E5E4E6E6E6E5E4E2E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000470000000001000001E2E4E5E5E7E7E7E6E8E7E8E7E5E6E7E7E8E7ACE6E4E6E5DE85000000002D50C000CB47002012333C490E002D7EE3C0E5E2E1105F100005E3E1D4DE41000000470000E3D4E1D40007002645E3E2E0E0E2158524DF0005A4E2E5E1360E1B00000071D4E1E94E2B20050E000A0C4C506AE2E2E5D8E74E000000E5E3E450E3E1000A00A89BE3E2E3E380E20043900026E0E3E0755B5252120C00B1D6E1E2B7E43100DB0050E3E6E7D05700AFE5E4E4E3317C20E2E5E5E3E4E69D1919E6E7E3E4E4122817520012E4E4E4E6E559902857E4E5E5E5E475AAE2DE38A4E3E5E5E4E2D896E4E5E4E5E5E4E4E3E4E4E5E4E6E5E6E6E4E5E4E5E7E4E5E6E5E5E4E5E6E4DFE5E4E6E7E7E6E7E6E6E8E7E7E7E7E7E7E7E6E4E1E0E3DFE3E4AF1700000012284592DC663E000E0000001B927AE1E4E4E4E5E1A65B0000002D52E4E46A171000000000E1E3E3800E66244771AFE2E0DDE83E503A220087E0E3E7E3E22B000100243A59C5E775AF9F313E2000000073D4AFE8E8E6DF05000003EAEBE6EBE1C0802F002B523A71E4E2660000E22F00003A6690E3B520001D0000005980E7E5E6A13EBC1771E3E5E55F45339024E5E4DC33264966E3E4E5E5E59D1D57E6E6E7A4E6E1380C7350E2E4E4E5E7E580E0D092E4E5E8E5E6E5E1E4D6E1E6E2E6E4E5E4E4E2E4E6E4E5E3E4E3E3E4E4E5E4E5E5E6E5E7E6E5E6E7E7E8E8E4E7E7E7E7E5D6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000490000000001000001E3E6E5E6E6E7E6E6E7E8E5E7E6E7E7E8E6E4E7E7E3D4E3E3DE45003C000E6A22BEE1B1010A0000870054A8B5CDE5E5E689B7E1360000000A0EBAE3DF750007001B1B05CBE2E2E0457C471D2B1285D8E7D0410031BCE1C9E5EBE4E233000000244C9D5FAF92E0BE0328000000000057E7E7EB3E000C000000CDE9EBEBB5C968107E2F38009DE5E7730028003E001900A4A6E3E3220312E6920000E1E1E2DF57A68E3328E4E4E48771E2E25DD4E6E48B785DE3E5E4E2E3030C1536E3E5E3E4E4AF9FC94783E4E5E6E6CBE0E6B5E3E4E6E5E6E6E5E689D054E2E5E5E5E4E4E4AFE3E6E3E5E6E3E5E4E5E3E5E3E4E6E6E6E6E6E5E4E4E4E7E6E6E8E5E4E5E5E4E5E6E5E7E7E7E7E7E6E7E2E5E7E6E7DBE8E803E5E7E1E1E5E4E3E3E1411B005B719DE1E0D4C91D000000001D174CE3E2E6E5CD5B5700006200001278E1E473830C0510203194D8E25BC9150E00150062E0E2AC83154E78D4E4E5EBEAE5E2E4E03600361B19AFE357890A000C0000000007E5EBE45B0ED00A0A2F26E2E8E6E2E1E1009F52102BDFE1E5C9101700193103E49F85E52836000C5B12001792E1E4E16D337E3C17DBE4E5E6BEE6E16894E2E65F1794E3E5E5E5A10000006AE1E4E5E4E33CBA5FACE2E5E6E6E4A42857BA85E5E5E5E6E6E7AFE58533E1E1E5E5E3E6BAE4D2E5E4E3E4E5E5E4E6E4E4E3E4E6E6E6E7E5E6E4E3E5E6E6E6E6E6E7E7E6E6E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000004B0000000001000001E1E5E5E5E7E7E7E6E7E1E7E6E6E6E6E6E5E5E4E29FDE49E2E1E3E1E28075B1E2E4E3E43322001200005B0068D8E3E1E2E4E319000000000000D0E2E39BB50C0100280C1252E1D4E28900000019BA96E0E2CB450300D4A6E4E5E6E6E5E0E3E08B9F190C3CC2D06D1B00000000005447E2E8E4D8000000000038E0E4E3D8E2E10C000026C9C0E2E41964000001001700E4E2E5E04100000701000A4154E1E4D06F730180E2E28BE4E3E5E52B2BE3E4E3B7E3E5E6E4E4010031004C52E3E4E4DB00310000E4E4E5E5E5899DE44EE5E6E7E8E5E4640EE3D2E2E4E3E3E4E3E2E1E0E2E2E3E3E4E3E3E3E4E6E6E4E5E5E6E5E6E7E8E6E6E4E4E6E6E6E7E6E5E6E5E5E6E3E7E7E7E8E7E5E6E7E3E7E6E7E7E7E8E557385219A628DBE2836F49A12B789675E1E03A5B12002F73AFA4E1E2E0E2E3E2E16D9400002800001D948EC7E17CA1000000173368E3E4990000850015D0E3E2AF15000C0001E0E4E0E4E5E441B1E3E20728E2E3E1E39D000041000022504CE2E531150C0300003864C9E1E5E55D524E641064DEE6E7E3122D0007E500001DE3E27AE200BE8EAC002BCBE4E6C0E57322B7E5E2E3E5E5E4E3E47300E1E4E4D6E4E4E4E5E45B00000092E2E5E6E6E40ADF3E28E1E7E6E7E2E4E79D6DE3E5E6E5E7E6E7DF5700E5E6E3E4E4E4E3E3E4E3E3E4E4E5E6DCE5E5E3E4E1E6E3E5E5E7E7E5E6E6E6E5E3E6E7E6E8E6E5E3E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000004D0000000001000001E2E6E6E6E6E5E7E6CBE6E62BE6E5E7E7E34531192003DFDED8E1BE000000102803AA5038002F00190049B189E3E3E1ACE1E3CD3C00050010001B3EBCDDB7A42F012DD236007AE2E2E03A000000013C73E1C7C222200A006250E1D0E4E3C70C1700B580E3DBD0B5E4D8000000A622C7E073D2E1A843001B28177CE2E1E3E5D6A1174741A694DBD89DE5E20000000A171592B5E1E4E2E13600A6477EE3E54CB57C201BCBE6E5E4E4E4E2E4A6171599E4E3E6E0E5E3E5DE00003AE3E4E3E5E696103A0089E3E4E2E4E0E0E5A457E5E5E5E5E6E49999E3E4E5E4E6E5E5E5E3E3E5E4E3E4E4E3E4E4E3E4E2E1E1E2E4E5E5E6E6E5E5E5E6E4E4E6E4E4E5E4E7E5E6DBE5E6E6E6E7E7E7BAE6E7E6C9E5E7E6E9E5BC004C000071E078DF50000000000A00D2A801000C003A0059629BCBDEBC73DEE3E3E32F2600000000008B45E2E09D0038E3310743DDE0DB6A000A12052443A8E26F5F0000000028E1BCDCE37C0000000000DFE6DFE0E3E0CBDB1924B7DBE5E36DE58515AC1000151B24B7E1E399C06F2620D29DE3E4E3E4D20C570010157AE7C0DCE6E3E3E3DCE2000EE4E2D85007006866E2E3E1E4E5E5C91D3115E0E3E5E5E5E6E5E43C2B542D17E4E5E3E2335F0036B3E2E3E1E6C58968D483E5E5E4E5E6E200CBA1E2E3E3E3E5E3E3BA525DE5E3E4E4E3E5E6E4E5E4E5E3E5E3E4E5E5E4E6E6E6E6E6E4E7E6E5E6E4E4E4E4E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000004F0000000001000001E3E5E7E6E7E8E7E7E3E7E5E4E6E4E7E7E3E500172B00385DE2E3411D0000002D43D8DF001038002D0E68E0C9E14C730E416AE2C7E25412000000005DE2E1835B8000000019AADEE2DEAAAA22151700E392E138000000920038E2E4E15D361500470000948BE1E1E1E1DFE1E3C2E0E2E4D87EE4E3AC170000001DC54EC0E4E3DDA133077A7CE2E4E3DD7A0A2B1D5000001BDC64E3E4E4E4E22B0041E147E43845000000AFE4DBE4E3E5E44C001DC9D0E5E3E4E4E5E5D2C7E1D4E4E6E2E4E4E1BA785068E4E3E32D640024E3E3E2E4E5E4E5E4E2E06AE0E2E4E5E4CDE3E2D2E2E2E6E3E4E6E4E0E3E3E3E2E1E4E3E3E3E5E6E6E6E7E3E5E4E6E7E6E4E5E5E5E5E4E5E7E7E7E8E7E4E7E8E8E8E6E652E6E8E8E4001500000022DEAADE0000BA570059A1E4E4265F0000009FE1E3C9782B3615C0E2E3A41D000000A10094E19BBCE3430E000000473AD089CB2F0000000E71E3DD6600000000005778E5E25D120017B7170000005FD4E4642F80E2E5E2E5E3E3E2E4E4E300260000173C03E3E4E6E550494C1B243EE5E2E28B150C00123E010EC752E5E2E5E0EA2B0000D0E57A5B1B002B01BEE4E4E2E0628B5D0038E5E5E2E3E4E5E3E5E5E5E3E4E4E3E4E6E2E3DB807CE5E5E6E5A8BC9F0033E4E4E4E3E24926008B24E3E3E5E4E322C7BEE4E5E6E5E5E5E4E4E1E3E5E4E4E4E2E5E5E6E5E5E5E4E0E8E6E6E7E7E6E5E5E6E5E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000510000000001000001E1E4E4E5E5E6E7E7E6E7E7E7E03307E7E8E8E0220000002D90E3E18B00000000003CC96D57190047ACE1DDDC9F41000E004E59E4E42800000000006AD4E1E2DB3A280000000000E380DFD0006F005422DFE27500030000005452D6E554751B000000000000338096893E00E266E1E3E1E0AC66E36200006200000A9BE4E4A4C9BC055726009DE6E5DC52013C000000006FE0E1E2D000787E830000B79BE33C5B891745E3E5E5E4783A0E012D0EAFE3E3E2E3E3E2E6E4C55FE3E4E3E4E3E4E4E1E1E4E5E4E4E35D12DC0143E3E4E4E5E5DD8EE35089E6E6E6E5E3E2B1E4E4E4E5E4E3E3E2E3E2E2D2E1E4E3E4E4E4E6E5E5E5E5E5E5E4E5E5E6E5E5E5E5E3E4E5E5E5E5E6E8E8E7E7E7E8E7E7E63E03E6E8E5E717002205667AB7E3E1000C00AFE1DEE389264C2D716F3675E1787822005D7E36E2E3AA000000000100B5E1E2E4E11B33000000363CE2E3AC5724050A9DE2E359E35F00221D4C68E0E4E18771070000960000229BE199000075786DE2E3A49B2DDBE1260000000000D0E4E6E65D8500001B38857CE3E38E00000105000C31E0E4E5E1200000000A7517E2E29DE0946619E5E0E5E1B38000AC9900E4E3E3E2E3E4E36F5F59C5E5E5E5E4E7E5E6E1E5E6E1E6E4E5D071DD17C5E4E5E5E5E37CE3E5D8D8E5E6E3E5E5E399E2E3E4E4E6E4E6E5E2E3E4E3E5E5E4E3E4E6E4E5E4E5E3E4E6E6E6E4E6E5E6E4E6E4E4E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000530000000001000001E5E7E6E6E8E7E8E7E8E8DCE6E8B1BAE6E7E6E72D002F3C1D0CE0E1E47822003C0059E4D29F994522000024E0E1475712121BACDBE2E0B5030000010A6F3AE4E178262D0100031728C073E068005B3A057ED489E3A4190C1200B3E249E6C2311500000000263C0CE05B00006A75E2ACBCE56AD6E2E0CD2B0000010012D2E4E5B3BA0A12000012A8E3E4AA003300C2000020E5E4E28B2D0000006F7A00DDE478AC68203EA8E4E3E1E3C5E33A0500E4CBE1E4E6E5C03A7538A6E6E6E6E6B5003E15E4E8E5E6E4E3E4E2E5E5E4E6E5E4E3C7DEE3E4E5E6E7E8E7E4E3E5E4E4E3E5E3E5E7E4E3E3E2E1E3E3E1E2E2E5E6E6E5E6E4E6E6E6E7E7E7E7E7E6E8E3E4E4E5E5E7E7E7E7E6E7E6E9E7E8E2E7E7C985E8E7E4E207051B1533E6E4E35D1703220E5792E06FA44100002F1B2DE28E2F2F00073E9DE2BCC0B30A00005D243671E1E08EAF030000331B00E1E5DB89E0261226E3E3E3E09462002D2F78D0DEE45B07000005000017B1DFE2071D053EE34C00E0DEE3E5E41519000000003689E5E5360500200000269BE4E5BE941D00100005E3E0E0B100410047310000E28EE6E47305124596E4E5E3E4E3E371472FE5E0E1D4E4E32F000028E287E4E4A60000001DE3E6E6E6E5E6E7E5E6E5E4E7E7E6E2E0E3E0C2E5E3E4E5E6E5E5E3E6E6E4E6E4E4E7E7E3E6E4E3E4E1E3E3E5E4E5E5E6E5E5E5E5E4E5E7E6E6E6E6E7E6E5E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000550000000001000001E4E6E5E5E6E6E7E5E7E7E7E7E605003C5BE1E2D0318900000033DEE2D050152B0533AFE3D85D153A2F0C1717C7BE522D410E3E36D6E2E2940000005900033ED6E49496380E310A3E529BE1E1B12424030159E3B39B94170000006ABCE1E4A1900500002B001712A668E27C0043337A1B2F8BE1D6E3E1E0000000001B41B1E3E2430090000017E2C5E5E310680050200A26E3E7E1A4E1000E000000E2E6E5E2C5B33AB71BDEE5E5E2E1529D26031D90E5E5E6E633006D0E9DE4E5E6E60AE10C85E6E4E5E6E68E49D4E5E6E5E6E7E4E4D092E4E5E7E5E4E4E5E3E3E3E4E3E3E4E4E5E6E5E3E6E4E4E5E5E2E3E4E6E6E5E7E5E6E4E6E6E7E5E7E6E6E6E5E6E6E6E6E5E6E6E6E8E6E7E7E7E7E6E6E300001920E2E3E2E1D000000000DFA87A0741360A1B38E3E39B00311B904E07318752220A100A7E94E1E3AF4300002B000712BAE3E12801002B3319A1BA87E0DE50001000C5E3E380A80000B7000094ACE3E0572D502824000100D00790381BD8000000002447E2E1E3E100000000000033E3E2D65000010007AFE3D0E46A0A5441170E00DFE4E5DE240500001200AAE3E4E3E23A41544703E4E3527E0312E50054D2E3E6E6E69D3E3E66E3E4E7E6E700575F015DE4E5E5E445921DA4E2E5E7E4E4E3E4BEE3E4E6E6E5E6E5E4E3E3E3E0E3E5E3E5E6E5E6E3E3E2E2E4E3E5E4E5E4E4E5DFE6E5E4E6E6E6E6E6E7E6E7E6E5E5E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000570000000001000001E5E8E7E5E2E7E8E6E8E4E5E57C00000E78C0E5E6E12F000100009BCDA40A017100003CAFE3BA0C070054000036E33A4717000015C7C0E5E12B6200032028009FE1E36F579B010E7822BE80E4CD2015E30007CBE2E2E124000000002B80D6E1A63A190000000000AAA1B3E2E3E0D000E10000001DC55BE336000000247A6285DBDBA40000000057665DE4E4C0D8000500571BBAE5E194012424490EE0C0E3E3E22400000059E1C29417500126DE80E2E3E6E6E6E6DF49E4E5E5E6E5E4E5504C01DEE4E3E45D5F5924E0E3E5E5E3E5E41B9FE5E6E5E6E7E4E5E4E5E4E5E4E4E2E3E5E5E4E4E3E1E2E1E3E5E5E5E4E3E5E4E7E6E6E2E4E6E6E7E6E6E5E5E5E5E6E5E4E7E7E6E7E6E7E4E7E5E6E500E1000000E2E4E3E100000000005BE2C5000064000524E0E3E21045000000241DB147000092000047E0E2A8A4850C1D00009BDBA4E0C5DB9F170115000C43E3E00000000000DFE1C959C90700001DC0A6E2E2D8C7AC00015D0000C9E0E1E0E1000000D0001000D0D8E2E1E3E4E2002D78B7E2E3E490151900053AA6E2E49478261505008B0185E6EA66D633336F4700CDE5E5E7E38320001BE2E2AF6F5073D287DDE3E0E1E2E53C547CDEE3E6E7E7E8E6D2A47CE3E4E4E56D201000A8E5E5E3E6E4CD68E03EE2E4E8E6E5E5E5E2E4E4E4E5E1E5E4E4E3E3E4E3E5E2E4E4E5E4E5E4E4E4E5E5E4E3E5E5E6E5E6E6E7E6E6E5E6E3000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000590000000001000001E1E5E4E1E7E6E6E6E7E7E7E7E3050010B5C783E5BC960003000A0052E14C003C00A60024D2E1DBA4C700002007475F00000000006FBC75E2E1DF26331700491BA4E1DEE000660000000071E1E03E000000334CDFB3C9801D00001D3600DD68E11B33000000003EE0E1C9E2E0D405003800000022C9E0E0E3E3E283192B50DFE2E2B11D710043005D73E3B12B000700E20003DDE7EBC257734C5062629BE2E4DF3E717A5B7CDCE2E3503E87E405E4E2E2DDE1DD33D257E5E5E3E4E3E4E4E5B57AE4E4E4E6A4311900E1E5E5E2E16AAFE3E043DDE3E4E5E4E3E2E3E5E5E3E5E4E3E3E5E5E4E5E4E3E4E3E4E5E5E4E5E5E4E5E5E5E4E3E4E5E5E5E6E5E5E6E6E7E6E4E6E8E7E7E8E8E8E7E6E6E3E7E2E76A125B4EE5B57A0000005B006FD09038000503002BE0E39D94A42B07011D75DDC9282F12002BD2E0E2DB1BB3620000001D002FE2C5AA380000410A01E1E3E03C00000117E0E3E1E1A600330C365DCDE2E1E0A105000000036ABADDC2E0E15B0031012B009673E3E1E3DEE1BC004E3EDDE2E0BC0000000300BC50AAE30A173E3CE56603E1E2E9EADCE5E2DDDCE3D8E4AF3807CB000028D4E1C007DE9D8B96E6E4E5E5E6E894AF5FE3E4E1E2E4E4E06AE5E4E5E5E5E6DBD6DB00E6E4E5E468A8E3E4E3E3E4E6E5E4E3E3E4E3E2E2E6E5E6E6E4E5E2E5E3E4E6E3E3E2E3E3E6E5E6E7E6E5E5E5E5E6E4E6E7E7E7E7E6E3E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000005B0000000001000001E3E5E4E5E6E6E5E6E6E7E5E5E8AF9F000000C9E4E5E3150000050000D8CD4E4E96123EDDE3E37131000000000075E1C07838AC0005B5B7E4E3C70E0000000000006DE0E3E3B52D00000C24E1E0D2E22B2D19129DE3BCE0E00C1B0038C5D8E1E1E15B1D0000000A1D4ECBE0E0D800002F00001959E2D0339D00003ED400009FE2E2E12F96000000200062E39D220000E4BA0047E2E6E87524A4E2E0E2DBE3D6E1E3E3E2E3E4E6E4E2E059C250383EBAE1E3E436383CCD52E2E3E4E3E4437383E3E3E5E3C0A4E3496AE4E5E5E4E7E4E5E3E2DDE5E3E3E3E3E1E2E3E2E3E4E3E4E5E4E4E2E3E2E3E4E1E6E3E4E4E4E5E5E5E5E6E4E5E6E3E4E5E4E4E6E6E4E5E4E5E5E6E7E7E7E7E6E7E7E5E5E5E9E7AC0E8E000CE0E190E25D00000000A8874C38105B31E0D0E152070E03000A008EE0E2924141100050B5E1E1E1AC07005000244141E2E5E2D62B032417073CE8DFE19600282633E1E2B3005003030A28283AE0E26D2F00000000014171E6E3A6000000000038A6737EDD280C0000E1B59B85E2E2E3E11D00001D018075E3DF3805016D0003D4E3C7D23E0C0E2249DFE0E4E6E5E4E4E4E3E5E6E6E400E0E31924E0E4E2E5B30E1700AFB5E4E5E6E519193333E1E6E6E5E13126A868E4E4E4E4E2E5E5C954E1E2E3E6E5E5E0E4E3E4E6E6E5E5E7E6E5E4E4E1E4E5E4E5E5E3E4E6E6E6E6E7E7E7E7E9E6E3E7E8E6E9E7E6E6E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000005D0000000001000001E4E685E5E7E7E7E7E8E7E7E6E9E5E53C43010A22B5E4D2780085000087E4000A01E2E0E2B3641B0054050500005233E4E36A361900008EE4E4E4D08B101B003A07A6C9C5E4891736005F2283E1E33A0000000199DBE29BB7A6050000001B0080C9DED65F0007000E2490E3E2E0DDC003000107385DE3E39F00011210E2DCE1E1E3E4E5000068800028D0E6E4DE011200730075DFE2AC0C1D0015284CE0E4E5AAE1E3E6E4E4E5E4E5E2E3001983D8E4E5E43354D62226E6E5E5E4BE00003610E4E5E5E5E4DE9F009BE6E7E0E4E59DE6E5E3E3E4E4E6E6E5E7E3E3E3E4E6E5E4E5E5E5E6E6E4E4E5E4E6E4E4E3E5E4E4E5E7E6E6E6E5E5E4E5E6E5E7E7E6E5E6E2E5E5A4E5E7E7E7E1E6E7E7E7E6E9E8310020030E17E2E3DB0500000001D200003164D6E0E0646D00000A05002B59DEE48E7A6600000017A1DCE1E252202233000052AABEE5E30E000054053A64E4DB00640000E3DDE3E1E49F17000E000CAFC0C7C21200000020DB00E37CE2E1E2A8903600003A24ACB1360000000092E2E3E1E1E4E4E30000000001C7E2E4DE26C533E1D44331C7DCA4C910A10045BEE3DC503A7EE3E4C7E3E4E5E6E5E12243E2E4E2E2E1C5000010E5E5E5E3A10A80412FE4E5E5E5629BE2A810E6E4E5E2AA6F00E1E4E3E5E5E6E5E4E4E4E2E6E4E5E4E5E5E5E5E4E4E6E7E6E5E5E6E5E3E7E5E5E7E7E5E5E5E5E6E5E5E5E5E7E7E5E2E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000005F0000000001000001E483E594E7E4E6E7E6E4E6E6E9E9E9E600203E0066E2E3E2C707000000E220265DC5E0E18389E0A605002010458BE3E3E2E1750000287C5FBECB80CD73E05D0A001B2F03D8E3625B00000000BED89B00000000D8CBE4C7968B2F000000000036D2805400001B000000BADC68B380CDDFC20000000589C7240043000000C771E3E3E2E2E3BC241000005950E3E1B3DFE1E3E41D3ECDDEC72B360000BCE3D012072D52CDBAE2E0E3E5E3E5453CB5ACE3E3E0680CE52819E3E4E3E3262400B7E0E5E4E1E3E30A12002DE6E4E3E27EA4E447E4E3E3E4E7E4E5E4E6E3E5E4E4E4E4E4E6E5E3E6E5E4E3E4E2E4E3E4E4E3E6E4E5E6E4E5E4E7E7E5E6E5E5E7E5E6E4E6E6E7C7E7E7E7E7E6E8E8E8E6E6E4E6E17319152D1DE1E396AA5F00336DA120330045E1CBC77EE4DD75000A00006FAFE4E3DB170A0000196F68DCC5E2A4BE52010019016475C9734E0E07000000E2852F0C001D1B20E1E3C0DE960007000C3ABAE0E1A41B032B2FDB31E10033A1E354E3710005000000E0CD00010C0000009971E5E5E6E5E5D80E001787E1E3E37CE1E3E1E09BC95FE3E183545920E2E2960059A6A82D71E4E4E5E3E5E3E26843D4E3E2B38BE0B14E78E6E6E4E5572283BA57E5E8E5E4907CC987E3E5E6E3E2E5B3E5E1E4E6E4E4E5E4E5E3E5E4E5E4E4E4E3E3E5E4E4E5E3E3E3E3E4E6E6E6E4E6E5E6E7E6E5E4E6E7E7E7E4E5E6E7E6E5E5E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000610000000001000001E6E6E6E6E6E1E3E5E6E7E6E6E7E5E5E4E4D60000010000C9E2E1E268DDE12D001DBE2403624CE3E1E2A63C7A208390DCE2D88000781D0036DEDCE1C0E1E1C0AF280000000000E09F1200000012CDE600004E0100D2C0E0C9A49F0000000000010000DC7A8E263AC9E194B3DFBCDC0000E10000E2000000CBAA0E01000322193EDFE2DE87000000E2007CE3DDE2DCE2E3E2E19D7A8750DBDEE3E2E2C7C75B000E000038E3E2E3E1E5E7E5E5E4E1E2CBE3E6D6411B855289E4E3E3E5416AD2E4E4E3E4E2E3E2A6E5E5E4E0A1D4E4E3E4E4E4E4E5E2E4E3E6E6E5E5E5E4E3E3E4E4E4E6E3E4E3E4E3E4E4E4E5E4E4E5E4E3E8E6E6E7E6E5E6E7E4E5E7E5E5E5E5E5E6E8E8E8E5E5E7E6E8E8E8E8E3E5E4E2E1E1000000001719BAE0E0E2E2D65D5054903C280000E2DFE1B36F2424240E24E0DBD62B00000087493CDEBCD8E49092000000A4002696E0DC0A0000009BE9E1B5000000ACA1E3B7E201000000000000004EBAE0BEE3E1DF99A4CB6800000005174E000000000087E23E590A00000A00A8BEBCB73A0E000000385FE1E4D0E5E4E43C005915AC6AC2E1E4E4E2E30515360071E3D2E2CBE8E4E3E3DEE3E3E2E4E4E6E038E49000E4E3DBE4E500009BE4E5E3E6E1E2AFC0E6E6E5E5E5E3E487E4E6E6E5E6E5E5E4B1E5E5E3E3E2E5E4E4E5E4E5E5E4E2E5E1E4E4E4E3E4E5E5E5E6E5E6E6E4E5E7E7E7E5E5E6E7E5E4E6E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000630000000001000001E3E4E5E4E7E8E7E7E8E7E6E5E6E6E4E6E400000000000049A694E17392E23A45B7470A1D714EE2E0E09F570E0010003AD8E39F0E000C0C9B90D6E1C26DE3E073000000000092E2E2D2D05B0010DFE7E72F000000002F62E0C54E00000043000000150AE00052BAE1DEBEB53A4C0000008764000000000110A805000000000000DDD2E18B9F4E2D00498EDBE1E4DBE3E5E3E34C15416DCDE338E2E17C6A6433665B80E4E1E3E6E4E4E4C2E1E4E4E5E4E9E4E2E09F8092E0E3E5E56607A110AFE1E2E6BCA8E2A4E0E3E6E7E8E5E2E2E0E3E5E4E5E4E3E3E0E2E2E2E2E2E2E2E1E0E5E6E5E5E6E6E4E4E3E5E5E5E5E5E4E5E5E5E5E4E5E3E5E5E5E5E4E5E6E4E6E5E5E7E6E7E9E7E7E7E6E7E4E522E2E5E4E2D6280C000010001538E3A6CDE3E2E0E4D010260E1B26BEE3D06D0789C700015BDEE3C5280E241B43DEE1030E7EE2835015243E284350E1E0E0E5E2E1E6E6E52000000000C201E0E3E2A10000000300000075E2C778E4E3E3E2E2A6645F000000002D6D00150024E1E205005900003C59E5E4C728001900E1E3E3DFE0E5E4E1B57A0E0012B7E3E4E3E5DED2E2E4CB6DB5DFE1E1E4E8E5E88545DDE3E5E5E2E3E6E6E6E500E0E3E4E5E454AFB515E1E0E7E6E5E4C7E4E5E7E4E5E4E2E4E5E3E6E3E5E5E5E3E2E2E4E5E4E5E2E4E1E3E3E4E5E6E5E5E5E6E6E4E7E6E6E5E4E5E4E5E6E6E6E6E6E4E8E6E6E5E4E6E4E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000650000000001000001E4E5E5E4E7E7E7E8E6E6E5E6E05FE2E9E1E4D850000000000012E1E15496E1E2E3E324010000004EE2D0000000330005A1B3E1C966380AA48B5DE1544C20E1E39B0C71003E2D0A90E1AFDFDEA875E5E2AA00000000206DE1BED2E1C0000000000712005B57DFE4E5E2E341A6DC000000009FDF380E000075E1E200000000011000E0E159D06F9D3143E4E5E5E3E4E2E29BE1E1576ABCC5D6E3E2E3B3CBB1227C7ED4E512E3E5E3E5A46F000089E4E4E3E3E1E2E4E4E3E5E1E4E4C543190EC9E4E5E4E5DBE1E1E1E3E6E5E26AE1E2E0E3E4E0E6E5E3E4E2E5E1E5E4E4E4E2E2E4E2E4E5E4E4E4E4E6E4E6E4E5E3E4E3E3E4E4E5E5E6E6E4E4E3E5E6E6E3E4E3E6E6E7E7E7E8E6E5E7E9E6E8E9E6E4E6E3E3E100DB1907E00A0036C0C9C9C9E4E3E2201B0000005DE1E3E23C00000500123AE2E3E2451B0020A6E1E0590000B3E2E10015006A201D2D6A3E2FE2E2E2E0D0A4000003103366E3E2CD269400000A120000498BACE1E2E2E2E396001B00000015D0D60E000A00B7D8E32F030700000031E3E2CBE5C91D4C73E3E3E4E7E6E4E2E3CB5250891DE0BAE1E4E3E443C06880E4E4AAD2EAE4E6E5E5D8050000DFE3E4E4E4E5E5E7E7E6E5E6E58E8747C0B1E4E6E6E5E1D057E1E4E6E6E6DBE4E1E4E3E4E5E5E5E4E1E3E4E5E6E5E6E5E3E4E2E2E5E4E6E4E5E6E5E6E7E7E6E5E4E6E5E5E5E6E5E0E5E5E5E6E6E8E6E3E3E3E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000670000000001000001E7E7E7E7E7E6E6E6E7E7E6E7E32BE4E6E4E2E03A00008700007CE0E2B3E1E3DCE2E141000000332BE3E3964E001B201252B3E1DF38240E332BE1BC5B001000DDE5C9A12D0C245B4E004CE2E19FE2E2D29B00001B005B5B71E2E18EA45B00000A5200000047E3E4E2E2E3E08B2803000020E3E2DE283A3C17DFE1AF2D00000000001DE3E0E27E31314326E4E3E5E0E0E4E4AA593C87876D31A8E3E8E3E3E3E296E1E5D4E0E6E2E3E4E11D262241E5EBE2E4E2E4E7E4E5E5E4E3E3E1A18BB3E2E4D6E0E07A49A4E4E7E6E6E5E3E3E1E6E4E3E4E6E6E6E0E1E3E2E6E6E5E3E2E3E4E6E5E6E3E3DCE5E4E4E5E5E4E5E7E5E5E3E5E5E5E6E5E6E7E6E7E8E7E6E4E5E5E7E8E6E7E6E2E6E0E8E7E9E7E4E1BAD0E6E2E4AC1D0100000033AC5BE2E3E2E1E2AA26000083005B96E2AAA612681B0E0312E4E4800AB30028E3521900000000E1E2504E000A00000000A1E17AE2E5DB41000000363C47AF68E30AAF0E00000749004C0019B3E2E2E5E3E16600681B0300E1E4E32F871B01BAE1E262002D500010A6E0E0E24500000005C2E4E4E4E2E3E2E2E20000387C2271D8E09B7AE28EDFDEE1E2E3E3E3E0E224A150DE1BE2E6E2E4E3E4E7E6E6E5E3E5E7E48BDBE2E2E2E5CB68E6E226E3E5E5E4E0CDE5E0E5E4E2E5E4E5E6E2E4E3E6E4E5E6E4E4E5E5E4E5E5E5E3E2E2E2E3E4E4E4E5E5E5E3E5E6E5E4E7E6E5E6E5E5E5E7E4E5E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000690000000001000001E5E6E5E6E6E6E5E7E6E5E6E5E645471080E4E1E4E1333E000020003ADCC7E3D68BE32800000A0078E3E2D0E09B43002B002DC2E3E107000001E42D0050800000A6E4E1434E000062000022929DDDE2C900570000000E662B49C2E0A66D3C0087000000151DE1E2E3E5E2E17C003C100C207CA4A48B3C38246FE2E40100000000007EDEE29603007100009DE3E1D8E2E3E3E3AF00A110E3D8CDD66645E02F28E3E3B1E3E3E4E2E38907B1E1B766E0E1E0E1C507E2E4E5E4E4E3E4E5E4E5C2E1E0E1E420AFE200DEE4E3E6E0E290E4E4E5E2E4E4E5E2E4E3E3E5E5E3E4E3E2E3E2E6E5E5E5E4E1E2E3E2E5E5E6E4E0E2E3E3E5E3E5E5E4E3E4E2E4E5E5E4E5E5E5E6E6E6E7E8E6E7E4E8E8E2E8E2263E28B1E2E6E4DC5D003617BC6252E0E1E062E2757C1D541962CBE3DCE4E2E4E16A050062B3E1E3B34C506FE219030000001203E2E3E2526400000000037AE0E4E2E02B38000000105D00B3D0E1CB66B10700003C20001B78E3E596E4E138152812173ADEE0DDE0C28BE2E4EBE69B000000000047E3E2E20000000000E1220CA4E4E3E5E5E441001549D280E0A4E0C7C059DCE26690E3E6E5E3E23A64E5E15DE4E4E4E29D5BC9E4E7E3E5E2E4E5E5E5E4E2E3E3E56ADB5B5DE4E3E4E13CE3E3E6E3E4E3E2E4E4E6E6E5E6E4E4E5E2E3E4E2E4E2E3E6E6E5E0E3E5E5E6E5E6E6E1E5E5E5E6E6E7E6E5E6E5E6E5E6E7E6E4E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000006B0000000001000001E7E7E8E7E7E7E3E8E4E7E6E7E58B331033ACD2E2E4E1A6D8002F0CE2E336D0E19BE3E25F0C07283E10E0DEE2E2E2C000000017E1E5D6751566E09B3C000500000ECDE1D2E028170E007E5BDDE1D6DFE08524056A000000B7D071DEE1261038000000001700E0E3E3E4E47E621700000089E1E3E375623C664CE4EBBC00002D00000089E5E2CB2F0017C9470078E0E5E4E6E6E6E50A1724319BE4E3CBAC9401E2E200AFE3E6E6EAEBBC00002D45E5E5E6E4C2C233D4E5E8E5E2E4E5E4E4E5E6E5E2E5E4E1D8AFE3E3E5E5E699E5E4E4E3E6E6E7E5E6E4E4E5E5E6E6E4E6E4E3E4E3E5E6E6E3E3E5E4E5E6E5E5E7E1E4E4E6E5E6E5E8E4E6E6E6E6E5E7E6E4E6DCE6E7E7E6E6E2E6E3E6E6E8E7E8E600000017C7E0E2E3E21500D000D626E2E2E2E1B3E2660001000105A6C5E31DC01900000000009BE1E0A4E3E1B550003E00100059E0E0E2DD62281B0C032BE3E5E2E2E2B700000000319F00961BE07AE0DE0000001B2600C5E2E0E3B51245000000000AAFE2E0BE0A00153187EBE017001533004C0ADCE5CBDFBAE6E1C07A66E5E3E2E1AFDBE7E3E02D59E0E5E4E389E1E1E0E36231E5E4E3E0B100732B1BE8E4E5E4E2C7000731E5E5E5E3E5E5E5E1E2E3E3E7E6E8E5C7B3E2E4E5E2E6E5E5E1E3E6E4E5E5E4E5E5E2E2E0E5E4E4E4E4DDE3E3E2E5E6E5E2E4E4E5E5E6E6E8E6E6E6E6E8E7E7E7E6E5E5E6E8E7E7E2E4E2E3000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000006D0000000001000001E4E4E4E5E7E6E6E6E7E7E6E5E7E67500000000E2E1E3E1280019DFDE000094C96A877E3C2417077CE1E262E16FC01700E138000100E1E2E0E3E2B7D25F1973001D0EC5E11DCDCB710026004EE2E2E3E0E3A8310000172F00001D50C28E0010000000E3E100B1E3E038AAB5592F0000330043D6DFD466A43E1BE1E9E2E4000000000010BED8E2E071DCE4B1C7E6C2E4DFE2783EAFE4E338226FAAE25B80E3E8E2030E54DBE4E4E9E017382000E8E3E3E4E6B1497A92E4E6E5E5E4E5E1E4E4E5E5E2E3E2E4E4E3D2E3E4E4E4E3E7E6E5E4E3E3E4E2E4E4E1E4E4E4E3E4E4E3E1E3E4E4E5E5E5E2E1E4E4E3E5E5E3E2E4E3E3E5E5E3E8E6E6E7E4E4E5E4E5E4E4E49FE8E8E7E6E6E5E2E7E7E7E6E4E6E500800052AF12E19BC003202800000085E08368B70000000022A8E254E2E4DF4C00000000001BE0E18BE5DFD610000003642466DCE3878E0000000000013AE1E2E1E06A71413805C9C70050CDA4E2BA52BE310A01000085E4E10031E2AFC764000E7E2BDBDBB587C96422E0EAE38B17003C002080DCD2DDE4E7E9E2E26DB568E4E2E3AA3A33E4E8E2837EAAE4DFE4E9E6AF173E54DEDFE6DEB303C5594ED0E4E5E4DDB1D2E317E6E5E6E6E5E4E4E4E5E5E5E4E4E5E5E6E6E0E1E6E5E5E6E4E5E5E3E6E4E4E4E5E5E4E4E4E4E3E7E5E5E3E1E3E4E3E6E2E2E1E3E3E5E6E5E6E2E4E5E4E5E6E7E8E5E6E4E6E6E6E8E4E4E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000006F0000000001000001E6E6E6E5E7E7E6E7E9E8E7E7E8E5E7200000005BC2E380E1852D9B0043593371E4E5E14100994100003A6A71E3E16A156400010003A6E3A1E3E3C5C503032B12001DDDDBE5E2BE410000000017C9E0E3E2E2B7CD261D28075BDEBEE2E2E0E06D2800000010E4E5E22043E1E2E224000000C0DDE3DE687A590068E3EBE4C2C510000103A6C7E14726E9E5E1949BE1E2E2E5E3E3E447B1666D52A8E290E7E5E4E47110035489E2E1C026B5BA1DE2E3E39DC9C9AC4E10E3E7E5E2E664AFE4E3E3E4E5E3E5E5E5E5E5E6E4E4E5E6E7E6E6E5E4E3E4E2E5E6E4E4E2E4E5E2E2E3DDE2E5E5E6E6E4C2E4E4E5E5E6E6E1E4E4E7E6E4E4E5E6E5E4E4E6E5E6E7E8E6E6E7E5E6E5E5E7E8E7E8E8E7E8E6E6E5E8E6E507001B2FB383E3A6B7E152000A1D836DE1D03800280E0020314CE4E0E2E0E15D240C0015D6E457E1E3E4E1C7540300001B73E2D850E3DD3A20000012E2DCE1E2E392A8313A00121B224CE1E3E20C3A0000000000BEE200008700E14E628926038EE3E5E38B002D223CE37ADBEB908E2800DFE2EBEBBA45E1CBC0000E5DBEAAE29FB30A0ACB00E4DEE2E4E487E4E3E100008EE6E6E4E5E4E46DB39DD2E4E4E4D6102478A48EE5E7E4E496E4E0E1E3E3E5E2E6E3E6E6E4E7E5E4E5E6E5E6E4E5E6E7E7E7E6E4E2E4E2E5E4E6E4E387E3E5E3E6E6E7E1CDE6E5E5E6E6E6E5E5E6E3E5E6E6E6E5E4E3E5E3E5E1E5E3E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000710000000001000001E6E7E5E5E5E6E7DDE6E6E5E5E6E6E6E6E3DD0052002F5BE1E1E4E3A42610207E80ACE2832600000A89A8227CE4E1D8D2520E003E000AE08EE3E3E1C25F120078000062E3D8E192893E001528265FA8A68EE0C7AFDE05000503479F10E0E192A6002200009BE310010087C5DB92330C00001BE3E5E2AC0C3C432BE2E2EAE871280000E2E4E9EBEBE3E4E3E21985C7E0E4E4C2661B0EE4DE4EE4E4E2E3E4E4E27C001931C5E6E4E4E2E57AD22883E3E7E5A83E49E36DE6E7E7E3E55DE3E5E4E5E6E5E4E4E3E5E2E6E8E5E6E459E6E5E4E2E4E5E6E5E5E6E4E3E5E5E5E5E3E4E4E2E7E5E6E6E4E2E0E2E6E5E8E7E6E2E5E7E3E5E5E6E6E69FE6E6E6E7E6E6ACE0E5E7E7E7E7B5E6E9E7E7E7E6E7E6E7E1E6E2E01503102DE0E0E2E3E4E0001919717333E5A61B36412B001D3807E2E4E4E33C121B1900286DE3E2D2E3E34500000CD6004CAFE5E2AFA6E1682401001264D6DFA8E0450017017C151D87E1E5E5E0AFDE0E002BACE324000000E0E3E26A26190071E0E3E3E2E01D0C4CB3E5E6A1660000000549E6EAE4E4E1E2621D5045D4E5E0C26D056401017EE3E3E3E5E6E5BE1B000500B549E5E7C7CB2DE4121DE1E3E4D8E5E5E4E3E3E4E7E5E6E5E2E4E1E4E3E6E6E4E5DDE2E5E5E4E5E4E5E6E4E6E4E3E6E4E6E5E7E5E5E3E5E5E4E4E4E2E0E4E5E7E4E6E5DCE0E3E7E7E6E5E6E4E4E4E4E7E7E7E6E4E6E7E8E7E8E4E5E5E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000730000000001000001E5E5E6E6E7E6E6E7E5E4E5E5E7E7E7CB94E326000059A1E2E2E1E2E20A000C002638E2DB382B265000120ADF87E3D2E0E22F000000002DE180BEE18E6449000100070319E3E0E03AE08B2400000A0049E0E0E3E18B80030000008BCB0CE4E2B30C20A1007AE100001701808BE4D41D15000096E3E4E2DD4E2466C9C0EBE4A40000000000DDE3E2E5E1190100001BE0E0E2D6AF223A07CDE4E3E5E2E3E3E5E2D8524C5B33E5E2E2D271714900AAE4E4E1E4E520E20047E3E4E2E4E3C5E3E3E3E5E5E2E4E3E6E0E4E7E5E4E5E6E6E4E3E4E3E4E5E5E5E4E3E2E4E6E5E5E3E4E2E1E5E7E5E5E2E5E3E3E5E4E3E4E4E4E4E3E3E5E5E4E6E6E4E6E3E5E6E6E6E4E6E7E7E7E7E7E6E5E6E7E7E7E8E6E6E2E8E6E464005022B5A1E2E0E3C03C00000005263852E3A8E17E2200002226923896E3E4620000E2000531C949E5D4D2D010002B2400007EE2C5D2C9176200000100335DE0E4E3E3E16F220000008722D0E3E045284178E350001068227AE5E28B24000031387AE9EBE33A28016D85E9E12D00E517016D9BE8E9EB501B43C90033E4E1E3E1E15B1971E2E3E4E3E4E2E6E6E6E5A194AC54E3E4E4E4D8B785E6E3E4E4E6E6E5E3D2E2A4E7E9E6E5E3DEDFD4E5E6E5E56FE4E3E6E8E6E7E5E4E6E5E5E8E7E4E6E4E6E5E2E2E3E4E5E7E6E4E5E1E4E5E7E6E7E5E5E4E5E5E4E6E6E6E6E3E6E6E6E8E7E7E6E5E5E5E5E6E6E5E5CBDF000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000750000000001000001E7E7E7E7E6E7E6E6E8E7E7E7E7E7E7E6E4645BE24101D2E2E4E2E4000000000000156DE2E4453C1710000C0E3C28E3E4BEE252000000364CAC17B7E25FC924121B2D0343E0E3E5C0A4543824002400003638E2E2E15B3C0000000000002BD6E3E19626BCB1E2000C1B1D5BE2E1E1C70003000033E6E6E0001B100019D0E3312F150A92459BE5E9B75B0E00000038E0E3E5E6E5B73CD2D4DFE4E3E3E3E6A1E3E3C72887E2E4E5E4E3E0E1E0E4E5E5E5E3E2E2E5E5E07EE4E5E5E4E5E3E1E1E4E3E7E6E5E5E2E4E6E6E7E7E4E8E6E3E5E7E4E5E5E6E6E1E1E4E3E2E3E4E5E4E2E4E4E5E4E6E4E4E6E6E4E6E7E8E4E4E4E3E5E5E6E6E5E5E5E5E7E5E7E7E5E6E5E7E7E7E6E7E7E7E2E7E6E6E7E6E9E7E8E9E4E400380145E3E5DFE1E164000000000054E0E3B3E380450024004E0592E2C99FDDA6001D100045B3E271E3E4E2E18500000E3E28DFE4E15D9F2B3300000E9F5033E3D2E3E12F00030000006AE2E2E2E53E0589E4288BE300003696E4E3BE5700000000E0DDE2570015000028E09417E2D8B3D2E1E6E6E0AF7826000015DDD2E4E349C9BAE5155BE3E3E4E3E5E0E0E8E4E37EE4E5E6E2E3E1A6CBE2E6E6E5E4E5E6E5E5E4E4E4E7E5E236E5E2E3E3E4E4E4E5E5E6E7E6E7E5E4E5E6E4E4E5E5E3E5E4E6E6E6E5E3E4E4E6E6E5E4E3E5E2E6E5E7E5E5E6E7E6E5E7E5E5E6E5E5E4E5E4E6E6E5E5E5E4E4E5E5E3E4E4E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000770000000001000001E5E6E5E6E6E7E6E4E7E7E7E6E8E4E4E7E78E073100E1DFE3E0E2E32D15000C0000002BA8E3BE8038010E20280003E2E2E2E3D426000000001D8BBEE2D0E1837C001B004E0036D4E4E299683E0A364141AADCE3E2E1E12B00000C0000005BD6D2E1E289BE5D0E1000000036B7E0A46600002F000089E4E30E0100000196DFE275505450E2DEE4E4E0AC315B00455FE6E1E0E25764E2CB03C9E4E2E4E4E6E0E1E4E5E6E3E7E6E7DDE2E3C783CDE5E5E3E4E59FE3E4E0E3E5E6E6E6D0E1E2E4E3E4E6E7E5E6E6E6E6E4E4E4E5E6E5E5E4E4E2E4E4E4E3E1E1E4E4E4E5E6E3E0E3E3E2E4E5E4E4E4E4E0E4E6E3E4E5E5E2E1E4E6E6E7E5C9E5E6E6E7E7E7E5E5E4E5E6E7E7E7E6E6E6E7E8E7E7E8E5C5DDE6E4E4592426C0E2E1E5D0D0A8BE2600070E2F4E9DD4C2733C493600280A75E5E3E2E1D22D0700031B2B5B599DE0CBA873000000000047E0E4E3E3E25705DE00753A5066E3E4E385750045001D17127359DEBEE3E3E42F4500003E0054D8E545220000190000E4E0E42D28000001E1E6D63A662B22BAE3E3E0922015000CE1E3E2E5E3E6E4D4007CC741D2E1E4E5E0E2E3E4E3E6E3E4E4E4E4D064D0E0E4E6E3E4E5E5E6E2E3E4E5E6E5E4E5E1E5E4E5DEE7E7E5E4E2E4E5E5E5E3E5E8E6E5E5E6E6E6E7E6E4E1E2E4E5E5E4E4E49DE4E3E5E5E5E5E5E5E6E5E5E6E5E5E6E6DBE3E3E5E5E5E7E5E5E4E6E8E8E7E4E3E5E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000790000000001000001E4E5E5E5E8E8E6E7E8E7E7E7001780E1E2E1AF100EE32DDFE1E3E2E2C79B68001541806AE06AE1002600150000055FA6E2E1DE33200A242DD62F99DFE3E3E0A143005D00002D80DFE1BE2D0C050A001D003AE2D4E1DE9F965D929D1B0043280054E4E2E2E4E23300000E00E0E2E3A49D0000170A89E4E4E13A5B28005285D6E3A1E2E6E0E4E1E1E1E2330A221983E3B5E6E5E4E1E1B1CD2D28A8E2E35FDFD400E38BE4E5E5E6E6E4E2BEE55BE6E4E0E2E4E4E3E3E2E3E2E4E6E5E5E4E2E3E5E7E5E5E5E2E3E6E7E7E5E4E5E5E1E6E5E7E3E4E4E3E6E5E3E3E3E5E6E5E4E2E4E3E5E5E4E6E5E4E6E4E5E5E5E5E6E6E5E6E5E4E5E6E5E6E5E5E5E5E5E6E4E3E5E1E7E7E7E6E7E7E6E6E8E7E7E7000726E0E3E4E371E2E31D0000E0E1E0E1E17A1B000141503183DD006F0E541200430EA64CDEE1CB01200012000E2FC7E1E3E4DD6F00000003B52DAFE3E10A001200780000AAE08EE273E1E02D6F1715002B3126C2E2E4E3E3E1752000010054E0E2DD3E22000000B5E4E6DF6A6D9403260094E3E5E5CBE2E3E3E5E3E23A002F0064E2E4E3E4E4E10000330094E59BE2E4E0362B0000E0E5E5E4E3E5E3E3E536E2E5CBE5E3E6E45BE2E4E5E7E7E2E3E7E4E4E6E5E7E6E6E3E3E4E6E5E7E5E6E5E3E6E8E4E4E3E6E4E6E5E5E4E3E3E5E3E2E2BCE1E6E6E5E6E5E5E6E5E6E6E7E8E5E6E3E4E3E3E6E5E7E7E6E6E7E6E5E7E6E5E785000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000007B0000000001000001E6E7E7E7E7E7E8E7E8E8E8E80038990000E3B59DE36607E30115E0A4E5E2A417001B1D22D0D2E4E46F000001000C00196FE4E683942F10071B19003347E29BE2570E00003E1268B7E3E2C0E2800000240083A8BAC2E389C0332200B5031B0000CBE4E4E4E4ACA1260000283EA6E4E3E34500100A1DE2E1D0B7850045286DE1E3E1DDE3D0E5E2E3E300006800267CE2E5E8E6E1E40000850068E4E2E4DBE2680AE200E3E4E5E2E6E5E412E5A6E5E1E1E5E3E5E3E40EE3E5E7E5E3D8E4E3E4E5E5E8E6E8E2E2E5E4E5E6E5E6E4E6E6E5E6E6E5E6E6E4E5E5E2E4E4E5E3E5E5E1E5E6E6E6E6E5E5E6E7E1E3E5E4E7E7E5E6E5E5E6E5E6E6E6E5E3E5E7E6E5D2E4E4E7E8E8E8E8CBE7E8E8E8E8E700001B000000E4E56DB10012000CA6AA47DCB39B0A0000153A83B3E7520A0E003A0E102B3A75E4E3E0430000BE0C0045E1E2DEC0AC0E000300384EE1E5DBBE83150003001DAC5DB7E2E4A4BA9090380000260000E3E0E2E2E13A00000024000099D6A64C03200019008E47E1E2872B0000005D43E1D0E3E4E6E4E6E48000001219D8E3E4E3E4DF5400002B0000E1E4E4E3E4E000002654E3E0E4E5E4E4E5E7E4E7E6E3E6E4E4E2E7E5D0E6DDE4E2E4E6E6E5E7E7E6E0E4E6E3E7E4E6E4E5E4E3E7E6E6D0E4E6E4E4E5E6E2E4E6E5E7E6E4B5E4E7E4E5E5E5E8E6E6E6E4E6E6E7E6E7E7E7E5E6E7E8E5E5E5E6E6E5E6E7E4E3E4DD000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000007D0000000001000001E4E5E6E5E7E4E7E7E7E7E7E8E7C900010000E5E5E3E40007001D906DE0E0A8B70020000A0024AFE38726001D000000000399E2E3C5E10305E483125F07E3E4A69B264C00000015DED8DDE0711B0C0064000199E0DEE3E296E1DD7133DE005F00D8E0E3E4D6E100008019000000D0E100200000000043B3A6E380C200006D030089E3DDE6E5E2E3E3E1DBD0E0E4E5E5E1E7E5E5E2BE780E0005E3E0E0E2E2E3000A00E4E2E1E4D2E3E6E3E8E7E5E1E3E4E4E4E3E3E4E2E3E1E2E5E6E5E5E5E6E5E6E5E0E3E6E6E7E7E3E3E1E3E4E4E5E7E4E6E4E5E5E4E4E6E5E4E5E0E2E4E1E4E5E6E7E5E5E4E2E3E5E6E5E5E6E4E6E7E5E6E5E7E7E6E7E7E4E7E6E7E6E5E6E5E7E8E7E7E8E7E7E7EAEAE4E9E600000000C9E4E4E2E23600003143E1D8E0E2D8000A1DAF2489A1E1E32D2F0380071905389685E3ACE083380500010A92E1AFA180BE2D000000001DE38BE3E1A496621900CDA671E2E2E4E3E8A4381D0059E9DFE0A8E3E5E0DD0000000000416A92E3000012B7000064D6DFE0D46A1B28150010E154E2E4E6E5E57E28688B41E4E3E6E5E3E6E5E371851B24DEE5E2E3E5E39D2DBAC2BCE6E4E4E7E5E4E5E7E7DDE4E6E3E0E3E4E6E7E4E5D4E6E5E3E4E2E3E6E5E6E5E7E3E5E5E5E5E7E7E5E6E5E5E3E3E5E6E6E5E4E4E6E5E6E5E5E4E5E4E6E5E6E6E5E5E7E5E5E5E5E5E6E6E7E6E7E6E6E8E8E8E8E7E7E7E5E6E6E7E7E5E7E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000007F0000000001000001E4E5E5E6E6E4E7E6E9E9E9E8DC00000000B3E4E3E3E2A8260E24006283E0E347895033E2662D5FE0E1C21B050015012D5B66B5E3E2A883192819010778B3E3E1E0DF6400669B002431E0E2A19FD0924E000000195DE3E0B3E254C53800106DE2D0E3D8E3E2D0830A000012C53C00E1E20007000000432DE4E2E3592896171957DEE0E2E5E5E2D4240000001500AFE3E3E4E4E6E5E6E0685B3CE1E3E4E2E3D66428B7C2E3E1E2E4E4E4E5E7E6E3E4E2E4E2E5E4E2E4E5E0E4E3E4E4E4E4E4E5E4E8E7E4E6E4E4E5E6E7E6E3E5E5E4E4E2E4E3E3E1E5E4E5E6E6E5E0E5E3E7E6E6E6E6E6E4E4E5E4E4E3E4E4E6DEE2E5E4E6E7E7E7E5E5E4E4E5E5E5E6E3E4E4E1E5E6E5E6E8E7E6E8E7E7E8E8E900000000E3E4E4E2E1E3A4430E2B2F47E1E1A82819D0D6E35F4141E3E147875D45192D006689D4E1E199070001000000E0E3E1E3E4470000E3000031C0E1E4E2B50000005B000015A4DFE1D69FE22003B7AAE3BEE2E1E2E59DBA940E280003BAC510AF334E0C00000E0EB3E3BA9B450E260000A4E3E3E3E5E3DC9D9201240CA6492BE6E4E01D7C7805002643E1E2E5E5E5E0CDA8E2E3E7E6E4E6E47854E4E5E4E5E4E4E5E5E5E5E6E6E6E6E6E6E5E6E5E5E5E5E6E5E4E7E5E5E6E5E5E5E2E1E6E8E2E7E4E6E4E4E4E1E6E5E4E3E3E3E1E3E3E3E5E5E5E5E1E5E6E5E5E4E6E5E5E5E0E1E4E4E4E4E5E5E6E4E7E5E8E7E6E5E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000810000000001000001E6E7E7E5E7E7E8E8E6E7E5E7E5DB000007E3B1BCE1E1DC752D0000011D94E0E39200265BC9E0E27166E29F9996170059003399E0E5B5DC19000100000031E0AFE4E4DD100000007E0E2DCDE4E1D86F00008E0000170C6FE19D78803A0A7E87E0DEEBE0DCE1E2E2E39F12000ED2C7E1E2BE6D000C000C00D2E2DD1BA6BC1B00000000E4D2E4E5E3D02817B1E40026C5ACE4E445BE7A00D0D200C5E1E4E6E4E1E4B3E3D8E6E5E3E5E59B0CE2E6E5E6E3E5E5E5E5E6E4E5E1E3E6E6E5E5E3E4E3E5E7E7E8E6E6E6E7E6E6E6E5E6E5E5E6E5E6E5E4E7E5E3E7E5E5E5E4E1E4E5E5E6E5E3E5E5E4E4E5E3E3E5E5E7E8E4E6E6E7E6E7E7E7E6E8E5E5E3E6E4E6E5E6E6E5E8E7E5E9E6E7E9E8E8E8EAE6E6E7E5E5E417BA90E0E1E03C00A82000C58BB7E0B5246A6DE2E5A666E0E1E4785B00310017AA2FBEE4DBCB26009200000E00A8E466E480476A2B5247E0E3E4E27C9F73002F285747E3E1C0C7E592B10A45B5204CE8DE80E3E4E5DB000000000EC7C7E1DEC7052F000000A8E3E1AAE1E26F5D0000E100E2E5E1E0B7002801262443DCE2E2E55D9B5422E31B00AAE3E3E5E4E2E08585A4E5E4E6E5E4E4D2E1E3E6E5E7E6E3E4E6E6E6E6E4E5E6E4E6E5E5E6E6E6E6E5E6E4E4E5E7E6E5E4E5E3E5E6E5E6E6E6E6E6E6E4E5E5E6E5E6E5E4E5E4E5E5E5E5E7E6E2E3E3E4E4E5E4E7E6E3E6E4E4E5E5E7E6E5E6E3E4E6E6E7E4E694000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000830000000001000001E6E7E7E8E7E7E8E0E9EAE9E8E6E7E8E9E3CD0C99E1E3E3E000000100001B9092E3E33E0E000062E0C5E5E3E08E7A05000010002450E1E2E27E311D0000649D83C5D8E3E32D1B05E3E2A457E1E5D2E2993C7E157C36E3E2E4EAEBE8A83126E36FC7D4DD5FE0E3E4E000008B00E2DBE0E1DE7C543126000066C2E3E2E25B4C000000C50AD0E6E3E2E0262B0033504757E4E0E6E3B74900000020E2E4E4E4E4E3CDD0C7E3E7E6E5E6E4E2E2E199E3E5E5E4E5E6E6E5E6E5E6E4E5E4E5E5E3E4E6E3E4E5E6E5E5E7E7E7E5E3E6E4E8E7E9E8E5E4E2E5E6E7E7E3E5E5E7E2E5E5E5E4E4E5E4E5E6E6E7E6E7E5E6E6E6E6E5E4E5E4E6E7E7E6E5E6E7E7E6E6E7ACE6E4E5E4DCE6E6E7E6E7E8E8E8E9E8E6E8E6E51B89E32DE2E1E3E2B1013C2219649BE2D8E0170E000390E2BAE4E3E0A84100006D0A0785B3E3E4A4963100002FC7E1E1E6C7E2D66D4C267EE3E1E2E3E4E5E4DE4E6A7A36C2E1E5EBEBEBE2178EDF90DE00008071E3E5E531000E000073E5E3E5E2E23E1931287AE2E2E3E400310000121D0C5FE4E1E05F784778D000B1E4E2E2E583E1E4543A0A0C85E6E4E5E4E4E171AFD8E5E6E3E5BEE431E5E4E6E6E5E4E7E5E6E7E5E4E4E5E8E6E6E6E2E4E5E6E6E6E7E5E7E7E8E7E6E6E6E6E5E6E8E6E6E4E5E6E8E6E4E7E6E3E5E5E5E5E6E4E7E7E5E5E8E6E6E5E5E6E5E5E5E6E6E6E6E5E6E8E6E5E6E5E6E7E7E8E7C0E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000850000000001000001E6E6E5E7E7E7E6E6E8E8E8E7E4E3E5E2E33C49E2BCE1E2A6E00A00333CD8E0D2E3E0B57100A4200AB5E2DBE2E2CD4E5B0300005771E1BEE3D6C5070C01153190B5E2E2E3457C24102F1BE2C9E4E4E4E2B77C4E28209D66E2E4EBE9EBE4E0C019009B414543E1E5E59F5B100000288BE5E5E4CB0000000071E4E5E2E3B7D615003892A6E2E4E3E1850C8B0712005FE3E2E4E4DF9FE1C7E141A8CBE4E7E1E4E3E3E4E5E3E5E3E3E4E2E4DEC7E5E6E4E4E4E3E485E4E3E4E4E7E6E6E7E5E5E4E6E5E5E2E6E8E4E5E4E6E6E4E5E6E7E5E6E5E6E6E6E7E5E4E6E5E5E5E3E6E6E5E6E5E4E5E5E5E5E5E5E5E2E3E4E4E8E5E7E5E3E6E5E6E7E5E6E5E7E6E6E7E4E5E5E5E5E6E6E6E0E5E5E0E7E7E6E8E2E4E6E6E4B34CE2E0E4E4E1DF0E220000059B54B7E0E0949903001B129BE2E2E2E2E1B524831B220A2D5DE3E371262B032D8EE0E1E3E1D8DD663E0000008080E2E5DCCB226F9D4C00E078E1E0E9EBE33C6400AF00E1E047D075E3DF006D00470000E0C06AE366000A100000E3ACE3E2E3E252031724A883E2E2E59F9B380A57004EE5E5E6E5E3E2E47C2FA1E2E3E1E5E5E5E7E580E3E2E5E6E5E7E3E6E2E3E5E6E6E4E4E3E5E4E4E3E4E6E6E2E2E6E6E4E5E6E7E6E7E6E6E5E4E5E1E6E5E6E6E7E6E5E6E2E6E4E5E6E6E6E5E6E5E5E6E7E6E6E6E5E4E4E6E8E6E6E6E5E1E6E4E6E5E5E5E5E2E6C9E6E6E6E7E6E5E6E6E3E5E4E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000870000000001000001E4E6E6E6E7E7E7E7E7E6E7E7E7E7E6E4E47C00544EE1E2E2E3890012000015CB80D6E08B31104E0000384EE4E4E0E1E2495F19001BD4C9E3E2E0640087B764D6D6E5E4E2E3E136005F2B0078ACE2E2C0BEA1050000478BDDE2EBEBE2C26A1B12E133903AA1E0E2DBD0E71D0000000000E1E0E3430026003CE0CBE2E3E1070C0C1092E2E2DCE2E0AA9FE000000C12C7E1E4E3E3E3E33336C2E5E4E5E3E5E6E5E589E3E0E6E5E5E4E2E5E3E4E4E6E4E4E4E5E7E6E6E6E4E7E6E4E6E6E6E3E4E4E4E7E5E5E6E5E4E5E7E3E4E4E6E8E6E5E6E5E6E4E5E5E1E5E4E5E5E4E5E4E4E4E4E4E4E3E6E4E3E4E2E6E5E6E6E6E5E5E6E4E4E4E6E6E6E5E5E7E6E5E6E4E4E4E2E4E6E7E6E7E7E3E7E7E7E8E7E7E6E3E5E200007A1BB1E3E3E34E52220C4C2059BE96E2E2BEBC593C005D2066E6E5E266E0470C5F1BB3E5D2E5E37C509B2D73C9E3D4E4E4C0D6D63C000087E28BE4E4E0E39F0000802B89AF2DE0EAE645DEE5E1E4E9B71010E1E2E2EBC79900E40000E0E2E6E08B002200171DE5E4E4BC0000E20033DEE4E1E4E6E3E2E317473643E1D0E4E4E4E4E571B30AE6E5E5E7E5E4E4E4E164E4E5E4E3E3E0E4E4E5E5E5E6E4E3E2E6E6E6E6E7E7E7E3E3E4E4E5E6E5E5E8E5E6E7E7E6E5E5E6E6E7E6E7E6E6E5E6E5E7E7E6E6E4E6E5E6E6E4E5E4E3E5E6E5E0E6E5E4E5E4E8E7E6E7E6E5E7E6E6E7E7E7E6E696E7E8E7E7E7E5E6E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000890000000001000001E2E7E7E4E8E8E6E8E8E7E7E7E7E6E8E6E1BE4C542F50DEE3B5D8640024E171419DC2E3E092DB3673282F3C9FE0E4E371005D99360057BEE0E4E278E4D81959AFC7E2E4E5E2E0CB6F00006AAFE2D2E3E2E18E8E034E0000599689E7E45D73E5E5E4E4789D00336AE2EAD0EB000000006AE2E15D1B2022E02036E3E4E6E21B00000049E0E1E3E2E1E5E58B8B2415AFE4E2E6E4E6E6E43C000ED4E3E4E6E4E4E3E3E3E2E3E3E6E5E5E4E3E5E7E6E9E7E6E6E4E5E4E4E6E6E6E894E7E8E7E5AAE5E5E7E6E7E8E6E4E5E5E6E5E5E6E6E6E2E7E7E6E6E6E6E7DDE5E3E6E6E7E6E4E4E4E6E7E7E7E7E7E7E6E6E6E7E7E8E6E5E6E5E6E6E6E6E6E6E4E6E5E7E8E6E6E6E5E5E8E8E7E7E7E7E7E9E9E7E8E7E6E6E7E1E1014112ACE1E3E2E05996D847572073E352E0E3DEA67A542F1B4EE3E6E5E4331D5422000515DFE5E1CBE3960A411DE375E3E3E5E2E1365B6FAF12E1B3E1E6C7E378100124000078DBAFD4DE9283E4E4BE5B1D0017ACE4E9EBE98700001BD6E6E5E149009680199268E6E38E714122711D31E5E5E4E6E6E4E4A11B24E5E7E4E6E3E6E6E252C512E4E6E7E6E3E4E3E4E79FE3E7E7E3E4E4E2E4E5E4E7E4E5E2E4E5E4E5E6E6E8E7E6E4E7E6DFE6E6E5E7E6E6E9E8E6E6E6E7E7E8E7E7E6E6E6E6E7E7E5E6E6E4E6E5E5E7E5E6E4E6E4E6E5E6E5E4E5E4E4E6E6E5E8E7E6E4E5E7E7E7E7E7E8E5E7E5E6E5E7E7E5E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000008B0000000001000001E1E5E6E5E7E3E6E6E8E8E7E8E5E5E6E6E3E20E17832675E2E4E147E3E16A280054E1E180E5E5E05D3A500E4178BAE4E57C07892B0A590000E6E1E1544C3C5283498BE3AFE6E3DCAA0112E05B49E0B5E1E1E43C000000000028E396DDE2E2E4E4E65990000000E3E5E4EBEB80002FDEE2E5E9E4E0496D0E1B2DE1E3E3E3E2007A2D3815C7E6E3E5E5E6E750010000E3E2E3E4E5E4E2E0E3ACE5E4E6E6E5E0E2E3E3E319E4E6E4E3E5E3E5E5E5E5E4E6E6E5E4E3E2E6E5E5E7E6E4E6E6E7E5E6E4E5E5E6E5E6E6E1E7E8E8E7E7E9E6E7E9E5E5E6E5E6E6E6E5E4E5E6E5E7E5E2E5E5E5E6E6E7E7E4E5E5E6E7E7E6E0E5E5E6E7E7E7E7E6E7E8E7E7E7E7E7E7E6E7E4E7E7E4E7E7E6E7E8E8E8E8E8E9E8EAE2DB280A1243DC8EE2E2E2E3E2E14C3C01B3A4E3E5D6E37831DF6F1B28E1E2E2E3504C1531E20015E1E4E3DF8745A82F45338EDEDFE4E383D2492F50A4A1BAE4E5E894E00000000C3175BAE2E4E4E5E5E4240000004949E2E4E4E5D207A1D6E5E0E4DDE4C92222000EE2E5E5E4E58B5F005210E4E4E5E4E4E7AA9F19000003E1E5E5E5E6D0E3E2E3E4CDE4E4E5E5E5E566E215E6E5E4E4E5E6E6E6E5E7E7E7E6E7E7E7E6E6E7E5E6E6E4E3E7E8E6E5E5E7E7E7E7E6E6E5E7E6E6E5E6E6E5E5E6E8E8E7E7E5E7E5E6E5E6E6E5E4DDE4E4E4E6E5E6E6E5E6E6E5E6E5E7E7E6E6E7E6E6E5E6E6E7E6E6E7E7E7E5E7E6E64C000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000008D0000000001000001E3E6E6E5E8E9E5E8E7E7E6E7E8E8E9E8E5E5C70A1DE1E2E4E3E55BE4E1DE80124322E0ACE2E2AA8B9B2B3C1920DFE4E4E2C0BC000C0033001BE5E1E5E2E173BE244E3378DEE5E4E3BE17243300E0AFE1E3E5E0D8BE712020542F41E7E2DCE3E3E46D6A00640A85E4E4E619000000E1E5E3E4E5E3E00C78E364C2E3E5E471014E00E5E3E5E4E4E5E4E4360700E3001DE5E6E4E8E1ACC7E08EE6E7E4E4E5E4E4641DE0B3E5E4E5E5E4E4E5E6E6E7E6E6E7E6E4E5E6E6E6E5E6E4E3E5E6E6E6E4E5E6E6E7E6E7E0E5E5E6E5E6E7E6E3E5E6E5E5E5E4E8E5E6E4E5E6E6E6E5E3E4E4E3E5E5E6E6E5E5E5E6E6E5E6E6E4E5E5E7E7E7E7E4E5E6E6E8E7E8E7E2E6CBE7E4E5E6E6E7E4C7E7E9E9E9E8E8E9E8E9E6E415940000A8DFE2E26D78E2E27E0131289FDDA6E5E4E3000000000136AAE2DEE4E34E07389BAA45E3E3DDE1DEE1B312002F7EBEE4E5E4544C26001B43DD64E5E4E3851DAA5F547CE031A6C0E3E4E3E6E37E173A1728E0E6E40000000028E3E4E7E2E2E003E5E743A6E3E3E45D451D00E3E4E4E5E5E4E4E5E3C205000083E4E6E6E5E6E1D8E1DCE2E6E5E6E6E4E6DD3CE5E5E5E3E5E4E2E6E4E6E5E3E4E3E4E6E7E5E6E7E6E7E6E6E7E9E8E2E3E4E5E6E7E6E8E5E6E6E6E7E6E6E6E6E4E6E6E7E7E6E6E8E7E5E7E7E6E5E7E4E3E5E5E7E6E6E8E5E3E4E5E8E8E8E9E7E6E7E5E6E6E4E6E4E6E6E8D8E7E6E6E6E5E5E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000008F0000000001000001E5E7E7E6E6E3E6E7E8E8E8E3B5E4E2E6E4E3249FB70019DF6FE2E5BAE2E2DD9B92001D3C3650E2E10C19004E0000529FE5E0E2CB785D05CDE0E1E4E4CD9BC9000000310078E4E5E1CBBEBA0000033EAFE3E3E6E49643734E3AE3E4E4E0E6E6E0E7E4D40700006AE3E6E60019E3006DD4E5E6E3E0157A7CE200B3E1E3E2C9222B0185E5E5E6E4E3E5E6E7E631004CE3E5E8E5E8E6E3E3E3E1E6E7ACE8E6E4E5E5AAE6E5E6E6E5E6E5E5E4E6E5E5E5E5E6E6E6E5E6E8E7E7E7E8E7E6E7E5E5E5E5E7E7E6E7E4E3E4E5E7E7E7E6E6E7E6E7E6E7E6E5E6E7E4E6E5E7E5E6E3E4E5E6E6E5E6E6E6E5E7E7E7E6E5E7E6E5E7E6E2E5E6E7E4E4E6E8E5E6E6E7E8E7E7E8E5E6E7E6E7E7E8E7E8E8E8E8E9E8E8E6E4E3E200001D26E18BE2E5E3DBE4E1B700E300945FDEE0D2AA57000000001547C2DCE0E52D0C1BAFAFE185E5E1CBD69D7A246F49E1E2E4E3E0E217000031906D89E3DDE3E3D2E27131CDA1C9E3E3E4E3D4E20707000E00E1E6E6000000009DE2E4E7DCE39F4538284CE6E6E6E5C57C94E4DEE4E4E7E6E6E5E5E1E3DDE7E6E7E7E6E4E6E6E4E4E36AE4E3E4E4E4E4E4E4E4E5E6E8E6E5E4E6E7E6E7E6E5E4E5E5E7E6E6E5E6E2E4AFE6E6E7E6E7E3E6E7E7E7E7E8E4E6ACE5E7E5E6E6E6E6E6E6E6E5E7E7E7E5E6E6E6E8E7E6E4E4E4E3E6E6E6E4E5E3E4E5E6E6E7E5E7E6E6E8E6E5E5E5E5E4E6E5E5E6E6E7E6E4E5E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000910000000001000001E5E6E6E6E7E8E7E7E7E5E6E6E5E4E4E4E2E3E07A430EC7E1E1E2E4E3E0B5E1C9002854386A87E1DBE349000000000028E0E2E4E0101B9B6D2FAAE3E2DCE0D62B47640AC2E3D4E2DFE7E57500000AC983E3E4E4DEE4E4E0004C9DB380E4E4E6E5DE380C00000007E2E4E6E10000107AE3E1E5DFE0E3E5AF22DBE4E5E59BE11522E4E6E7E6E6E6E5E5E5E6B7E1E4E4E6E6E4E6E5E5E2E3B17AE3E5E5E1E4E4E3E2E5E5E6E7E5E6E5E5E5E5E5E6E4E4E5E6E4E5E5E4E5E8E5E6E4E7E5E3E5C2E4E6E6E5E4E6E3E4E4E6E7E6E7E7E3E6E6E4E5E4E5E5E4E6E2E4E5E5E6E6E6E6E7E7E6E6E5E4E6E6E4E6E7E5E7E5E6CBE5E6E8E6E6B1E5E7E5E7E6E5E7E6E7E6E5E6E5E6E5E7E7E7E7E6E9E8E8E9E5E6E4E4E3E3E3E23C2087E3DEE0E2E2E2E3E4DF052D053C33A8E3E57E7E00001700000A45E0E2575F012D330CE1E5E4E3E0E1943E99242DBCE3E4E3E3D8E2A8E375B1DCDFE1E5E4E3E1E3D26492E1E0DEE2DEE4E2E31901360E5B57E6E5E5527E1B0773E4E5E5E4E1E3E51994E5E6E4E5E59236E5E5E5E6E7E7E5E5E4E4D290684CE6E6E6E6E6E5E4E4E3E5E2E3E6E5E7E5E5E6E6E6E3E8E8E7E6E8E6E5E6E5E7E6E7E9E6E5E6E5E4E5E7E7E6E6E5E5E6E5E4E6E6E7E5E4E5E3E5E6E6E6E7E7E6E6E2E7E6E5E5E7E6E6E5E5E4E4E4E4E6E5E5E6E5E5E6E6E5E4E4E6E6E5E6E6E5E5E6E7E5E5E5E5EAE6E7E8E7E7E9E7E5E5E3E4000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000930000000001000001E4E6E6E6E6E6E6E7E6E7E7E7E3E3E3E2E2E0E2E0800000808E80E0E1DCE1E2E0AC477A54263C87E39FC5470000001B2B4EAAE3E1DFE2474E19DDE2E4E0E2E14C153E3E0000648BE3E3DCE3DB7580DEE2DEE4E4E4E6E5E44719100794BAD2DBE4E4E0D047074719E3E3E5E2E02B244322BCE3E4E2E3E0000012C5E3E4E4E443DBD0E587CBE7E6E5E4E6E5DBB75750C2E5E6E6E7E6E4E3E4E2E5E5E3E4E2E3E2E3E2E4E2E2E5E5E6E6E5E4E3E2E3E3E5E6E5E5E3C9E5E6E5E6E7E7E7E6E6E5E5E6E6E5E6E7E4E4E5E4E4E2E2E3E5E3E5E6E2E5E4E3E5E6E6E8E4E4E5E3E4E4E4E4E6E5E6E6E5E5E5E5E7E8E5E8E4E3E4E4E5E4E2E4E6E4E6E7A6E5E696E5E6E7E7E7E7E7E8E7E7E8E7E8E9E7E8E7E6E2E6E2E2E1DC20A8005BE0C9E3E1E39FE4E3E352D46D2641C59DB5E36A173C125B4C5DE0E4E5BEE1BE1041158EC0D8E3E0E19B2B0E000000ACE2E4E2BCDBAC83D4E2E3E3BEE3E4E1437AE4E400E0E1E4E3E4E5E5E2BC00415BDFE2E3E4E10024CBE5E4E4E4E2E4E40500006FE4E5E2E2E4E3E5E468E5E5C7E6E6E6E5C0B5E0E5E5E6E5E5E5E5E4E5E5E3E5E6E6E7E4E4E4E4E6E5E6E4E5E5E4E7E6E6E6E5E8E6E8E8E5E6E5E3E5E5E5E6E7E4E4E5E6E5E5E6E7E7E6E7E6E3E5E6E4E5E5E6E3E3E6E5E5E5E4E4E5E5E6E5E3E5E6E5E3E4E4E4E6E7E7E9E6E6E5E6E6E5E6E6E7E6E3E7E7E7E5E5BEE8E0E7E3E7E7E8E8E6E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000950000000001000001E5E7E7E2E7E8E4E7E8E8E7E8E7E7E8E7E3E2E3E26DDE246FE2DEE4E4AC2FE3E3E2E2C0C05F2DC971BEBEE4B58E4E2F991599E5E7E2E5804500057AB3E1E3E3E29BB1071B1B1568BAE6E3E3E2E12F33B5D0D2E4E5E3E02F10523C05E4E3E09DDEE8E5453619005BE4E2E5E4E1000019DEE4E3E5E5E4B500E500BCE5E6E4E4E5E4E3451049E4E4E6E4E4E5E6E6C9E5E5E6E6E6E6E7E6E7E7E6E3E6E6E5E6E6E5E5E4E5E5E5E5E4E6E7E7E6E5E6E6E5E5E5E6E7E6E6E5E6E5E5E6E6E6E6E3E4E5E5E5E6E6E6E4E5E5E5E6E5E5E5E7E2E7E8E6E5E8E6E6E7E6CDE6E7E5E6E2E4E3E3E7E6E6E7E3E4E4E4E6E6E0E7E6E7E7E8E7E5E6E5E6E4E8E77CE7E6E6E7E6E7E5E5E7E7E7E7E6E7E6E7E7E8E7E6E4E6E5E2DBE2E2E58B3301E0E0E5DC311290E3E6E5E3E38EB3999FDDE3E4E3434C473310A1E1E1E6D6E2B5009B4789DCE5E4E0E2C53A00000122CBE3E0E3E2BCA80C50B1B1D8E5E5E3D4DF57361DE3E3E496E3E5BC47E4010000E4E6E6E6DC00000000A4E4E4E5E4E4100000E1E5E5E5E5E5E4E33C0090E6E3E6E3E5E6E6E5C0E4E6E6E8E8E6E8E6E7E6E7E4E5E4E5E4E4E4E4B7E5E6E7E5E6E7E7E6E6E6E3E5E5E7E6E5E3E4E5E6E6E7E5E9E6E6E8E5E6E4E7E5E6E6E5E4E6E4E5E5E4E5E4E6E6E8E7E4E6E6E5E6E5E6E6E6E5E6E7E1E5E4E6E7E5E5E6E5E4E7E6E7E7E8E7E6E6E6E7E4CD6FE4E8C9E8E7E5E6E8E7E7E5E7E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000970000000001000001E4E6E6E6E6E6E7E6E8E9EAE8E3E6E6E7E3C7E2E3E3D8BE1703BAE1E238174EDEE3E5E4E3E04EE3E2E4E4E3E55BAA5F3E014968B7E2E1BA5F7C8022DC92E3E3E3E5E03C68000022AFE4E3E1E4E38E83B352E1D0E2E6E3E2C97CE2E4E4E27E8796E0E387E0003C0073E4E5E5E400004700E4E4E4E4E26803000052E4E3E5E5E5E4003C0003E6E8E9E7E3E5E4E2C752E4E5E6E5E5E4E5E5E5E4E6E5E6E7E3E5E4E4E6E5E3E4E3E4E5E6E7E7E5E6E6E5E5E4E6E6E6E5E6E7E5E5E6E4E4E4E2E6E5E5E6E5E4E4E4E5E5E5E4E6E5E6E4E0E4E4E7E6E6E7E5E4E3E5E5E4E6E4E4E4E3E6E6E3E6E5E7E6E6E6E5E4E2E4E6E5E7E6E4E4E4E6E5E3E6E7E8E6E7E7E6E550E3E7E8E2E8E7E8E7E8E1E7E8E6E7E6E8E4E1E0E2E1E2E178195094E3E5523AE1CBE0E3E2DF417343DCE2E3E1E3E273995D224EBCE0E4E5E6D0385B286AC794E0E2E290DCE13A0C78E1E4E5E5E3E462265D3AD6E2E1E3E4DF22A4E6E5E6E36D9FDFE5E6E4E2000000E3E6CDE4E4000C0524E6E3E4E6E4E4752B00DCE4E7E4E4E5E35207053AE4E7E5E6E8E6E7E6E4E5E5E6E4E5E6E5E5E5E7E7E6E5E5E5E6E5E3E5E6E5E4E7E5E4E7E6E9E8E8E8E6E3E5E6E7E7E7E5E7E6E6E6E5E4E4E4E5E5E6E6E5E3E5E5E5E5E6E7E7E5E4E5E5E6E6E5E6E8E6E7E4E7E5E6E8E7E5E6E4E1E1E3E7E8E7E6E6E5E6E6E6E2E6E6E8E7E6E7E5E6E7E7E7E8E6E8E7E8E8E8E6E5E7E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000990000000001000001E3E6E6E7E7E7E7E7E9E7E9E9E5E7E5E7E4E4E4E5E2BCE02200DCE3E4C0BEBA8ED6E3E3E1D89D73BAE1E4E0E3E5E1B73859526AA4ACE4E5E02D6A62B7DCE196E2E4A49BE1662F3EDCD8E5E4E1E468A8E0E0D85F90E3E4E4E092DFE2E3E1DF505BE5E5E590000000BEE5E6E5E3A4150024E3E5E6E6E6E443129BE4E6E5E6E5E4E5E4755B5422E4E6E7E6E5E6E5E4E4E4E4E7E7E8E7E7E6E6E5E4E4E6E6E4E6E5E4E2E3E5E4E6E6E6E8E6E5E4E5E6E5E6E6E4E4E3E1E5E4E4E4E8E5E6E6E6E4E3E4E8E7E5E5E4E6E6E7E3E5E4E5E6E5E6E6E6E7DBE4E6E7E6E7E6E1E5E5DCE0E3E4E5E4E5E6E5E5E6E6E7E6E6E4E5E6E6E6E4AAE5E3E6E5E5E5E6E6E5E5E7E5E4E6E7E7E8E7E7E6E6E6E8E7E7E7E5E6E6E8E3E4E3E2E600A1E10AE0E6E4B5D68389E4B5E5E4A1E0C75BE1E5E2E3DCE196963820192B50DFE5E3E06F2FC5E2DCE5E4E2E4DFE2310700DDE2E3E6BEE5E4ACBAE1D492C7E4D2E3E5DFE4E2E4DCE2C5C9E2E5E5E6E199E1E7E7E5E5E5E43600C2E4E5E5E4E2E31500E4E7E5E6E5E5E5E5E38EDD261DE5E7E7E6E4E5E6E4E3E4E5E8E7E7E7E8E8E6A8E5E6E6E7E5E3E6E2E8E7E8E4E3E6E6E7E7E5E6E6E7E3E7E7E2E5E5E3E9E6E7E6E5E4E5E5E7E7E8E7E7E6E7E7E5E5E6E5E8E7E8E6C9E6E6E6E7E6E6E6E8E8E8E8E6E6E6E6E7E5E6E7E3E4E5E5E7E8E5E4E7E7E6E6E8E7E7E7E5E6E7E792E6E6DDE8E7E9E7E6E4E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000009B0000000001000001E8E7E7E7E6E7E6E7E8E8E8B5E8E5E5E8E4E4E4E3E3E152C7DBA8E5E3C08EAAA6BEE4E4E4E138A6316DDBE3E3DFE7CB33072F33A1E5E6E6E79985A1E03E73E3E2E6E4E4E51B380103D6E1E5E6E5E4BEAFC9DCB1D6D0E3E4D2E5E5E5E5E4E5C5D2E2E4E5E3E522432BC7E5E4E5E5E04547E6E5E6E6E6D60000E6E7E7E7E6E6E5E5E633280028DCE5E5E7E7E6E6E5E7E3E6E7E6E8E7E5E6E6E6E6E5E4E5E5E4E4E4E6E7E6E6C5E6E6E6E8E7E7E7E7E5E7E6E5E6A4E6E5E6E6E6E7E6E4E5E7E8E7E7E5E5E5E6E7E8E7E7E4E2E4E5E6E5E6E5E6E7E7E6E8E7E5E7E6E7E7E5E5E5E3E3E6E4E3E6E6E6E7E6E7E7E6E6E9E8E8E7E7E7E7E4E9E8E7E7E7E7E7E6E6E5E7E7E7E6E6E7E7E6E6E6E8E8E8E8EAE8EAE8E5E6E5E3E4E5E4E4E0E3E1E5E28E8B0078E3E1E0E5AABE9DB3E3BEE4E2E0997ABE0543C5E2E5E5E5D83E59502407D8E1E4E4E4DEA4000510E0E5E4E5E4E5E0B7549F6FE5E1E6E5E3E4E4E4E5E3E4C987E3E3E6E59B1B413EBEE6E5E8E5E3E0E4E6E7E8E6E5E30050C7E5E6E8E7E6E6E4E7E65DE50CE3E5E6E4E6E6E7E7E7E7E8E7E6E6E7E6E5E5E6E6E7E5E5E4E5E5E6E5E5E6E5E8E1E6E8E8E7E9C0E7E5E7E7E6E6E5E6E5E7E7E7E6E5E6E7E5E5E5E7E6E6E5E7E8E6E7E7E4E7E7E7E7E5E5E6E7E5E6E7E6E5E6E6E6E7E6E8E4E5E5E5E7E6E5E6E7E7E8E7E6E6E7E6E9E8E8E8E8E8E5A6E6E7E7E6E8E7E8E8E6E4E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000009D0000000001000001E4E5E2E5E7E8E7E8E6E6E6E7E6E5E6E4E5E4E4E0E5E2E5E3DFE2E2E2C7D099544C7AE3DFE3D6AF454CC9E4E4E6E0D085506A925FE2E2E4E3E3471DE062ACDBE3E3E3E6E4E0994E59E0E4E0E4E3E3E29D80D296D6E2E5E5E5E6E6E6E6E3E231B1E5E5E4E2BA269B00E0E5E4E5E6E4E3E6E6E7E4E7E6E6E6E200E3E5E1E3E5E5E3E4E600E49BE1E6E6E8E7E8E7E5E5E5E5E6E6E7E8E6E5E4E6E3E5E5E4E7E7E6E6E6E7E7E7E6E5E5E3E3E3E4E4E5E6E5E6E6E5E3E3E6E7E6E7E7E6E7E7E6E5E6E6E5E3E5E4E5E6E6E7E3E2E4E6E3E6E5E3E3E1E4E3E7E5E7E6E5E3E4E5E6E6E6D0E4E6E4E7E6E5E5E6E4E2E4E6E7E7E6E6E77CE6E9E8E7E6E7BEE5E6E6E6E6E5E6E7E8E7E7E8E7E7E7E7E7E2E6E5E5E4E3E4E4E2E3E2E2E2E20000E2E3E2E4E2473EA4DEE4E5E4281D9DE2E3E2E4E3BC5F547A5492E4DFE2E3E3AC9289A4BEB5E3E2E5E4E3E2B35757DEE3E5E6E4E4E4E1E4B3E2E4E5E6E7E7E5E3E4E5E0B1B1BEE3E5E6E47C47201596E6E4E5E6E5C0E5E6E7E6E7E6E5E5E00EE2E3E5E5E5E5E6E7E6C52F01E4E6E6E6E6E6E5E5E6E6E6E5E5E4E5E6E4E4E4E5E3E5E5E4E5E6E6E5E6E7E7E7E6E7E7E5E4E6E6E5E5E6E7E5E4E6E5E5E4E6E4E5E5E5E6E6E6E6E6E6E7E9E8E6E4E6E6E5E6E6E7E6E7E6E5E6E7E5E6E8E8E7E7E5E6E6E6E7E6E7E5E4E4E5E4E6E7E7E7E6E6E8E8E8E7E8E7E6E7E7E7E6E7E6E6E6E8E7E8E5E6E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C02000000000000010000009F0000000001000001E6E5E6E6E7E7E7E8E7E7E7E6E6E6E6E5E1E2E2E2E2E1E312000057E3E3E0C99D5F00E4E3E2E575000075E1E3E1E06A4C179DBA4520E2E5E4E4D0E3E13EA4E4E1E2E2E4B5E1E3E2C9BAE4E3E0E7E2E5E4E215DB8EE4E4E5E5E5E4E4E6E32F0C71E7E4E6E5A119200043E6E7E5E3E292E3E3E3E5E4E4E4E5E4E4E5E1E5E3E1E2E5E7E6E3E5E5E4E5B7E8E7E7E7E7E5E5E7E4E7E6E7E5E7E6E4D0E5E4E4E5E5E4E6E5E4E6E5E8E6E2E6E5E5E5E4E7E6E7E7E2E5E4E5E6E5E6E6E7E7E6E6E5E5E5E5E6E4E5E5E6E4E5E6E6E4E5E6E8E6E6DFE8E5E5E8E6E8E6E7E5E3E6E4E7E5E5E5E3E5E6E4E6E7E9E8E8E7E8E7E6E7E7E2E6E6E6E7E5E7E7E5E6E6E7E5E9E8E7E7E6E6E7E7E8E6E8E8E7E7E7E6E2E4E2E3E6E4E4E4E2E3E4E00000BCE4E4E4E4E16FE2E2E3E3E2E3100043C7CBE6E5C98EB7E3BC0C28DBE2E3E4D4E250C741E1E2E5E5E6E7E6E5E6E5E4E0E2E3E6E5E2E3897E7800E2E6E5E5E6E7E6E5E410E433B7E4E5E6E2D400E000E6E6E6E5E4E4E2E6E6E7E7E5E5E3E4DFE4E2E3E507E5E3E5E5E5E6E7E2E6E7E7E7E7EAE6E6E4E4E7E7E5E5E7E6E6DFE6E5E8E7E7E6E6E5E5B1E5E5E6E7E6E2E4E4E4E4E7E6E6E8E4E5E5E5E5E7E6E6E6E6E7E7E6E4E3E6E5E5E5E4E7E6E5E6E7E6E8E7E8E7E6E8E5E2E3E5E7E6E6E5E7E6E6E6E4E5E3E4E6E6E4E6E3E7E6E6E7E7E6E6E6E6E7E5E6E7E7E7E9E7E7E7E7E7E7E7E8E7E7E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000A10000000001000001E7E7E8E8E8E8E8E8E87EE8E8E6E4E5E4E4E3E2E1E5E4E4E3DF47E0E4E1E4E4E2E5E3E1E3E3E2E2C0128BE1E0E4E36DE3D0E07154806FE4E2E2E5CB45C01D94E0E2E2E2E1E5E4BE5903E3E4E4E5E3E3E4E0100EAAE3E3E5E4E5E5E2E5E4E0AAE1E8E7E7E7E4E3660000C9E2E4E4E1E4E3E6E5E6E7E8E6E6E3E3E6E5E4E66F41E3E5E3E5E2E5E5E7E5E6E5E5E4E8E6E6E6E9E7E7E7E5E4E4E4E4E4E5E6E5E6E4E4E4E5E6E5E5E7E7E8E6E6E5E4E6E7E6E6E4E5E5E5E7E9E6E6E5E6E7E7E4E5E4E4E7E6E8E7E6E6E5E4E4E6E5E5E7E6E5E4E2E4E7E8E9E1E6E6E8E7E6E6E6E6E7E5E7E6E6E7E6E6E8E6E6E6E7E6E5E5E6E6E8E6E7E6E6E5E6E7E7E8E7E9E6E3E6E3E7E6E7E6E8E8E7E7E7E7E6E6E6E5E6E8E2E3E4E3E4E5E4E2E4E5E5E5DEE3E1E3E2E159E3E4E3CB0C17788E75E2E2E5E4E38E01B71D90E4E1E0E3E2E0BCCD47E3E4E5E7E5E6E6B112664EE5E4D8E5E4E4E55D0AB3E0E4E2E3E5E4E4E4E35D0010E4E6E4E4E5E4000000E2E2E3D4E4E3E3E4E6E7E7E5E6E3E5E6E4E6E4E4E226E3E6E5E1E3E3E3E2E1E6E5E5E4E5E6E7E4E6E7E7E5E6E6E6E7E2E5E5E5E4E5E4E3E6E6E5E6E9E7E7E5E4E5E4E4E5E4E5E6E5E4E5E5E5E5E5E5E8E7E8E8E5E5E4E5E7E7E7E7E6E5E5E6E5E6E6E6E8E7E8E8E6E6E6E6E8E7E7E6E6E6E6E8E5E5E5E4E7E6E8E7E4E7E4E6E8E7E6E7E7E8E7E8E8E8E8E5E7E8E6E6E7E7E6E6E7E6E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000A30000000001000001E6E6E6E6D2E6E7E7E9E8E9E9E7E7E7E4E3E3E2DBE3E3E4E5E1E3E3E3E4E0E2E3E4E2A8E5E3E2E5E09D4C3AE3E4E6E7E7E7E4D21928E000E6E3E5E5E587D4E2E3E5E3E4E3E6E62B1D0500C2E3E7E6E6E7E5E0E3E3E6E5E6E5E5E4E4DCE4B754009FE5E7E7E4E500A8E2E5E6E5E4E5E6E5E4E4E4E2E6E5E7E6E4E5E5D2E6E7E5E6E6E7E7E7E4E4E4E3E5E4E3E6E4E7E5E6E8E6E7E7E7E4E6E3E4E6E4E6E7E7E6E6E8E3E7E7E6E7E5E5E6E5E5E4E8E5E5E5E7E7E6E6E9E6E7E3E8E7E8E7E4E3E5E4E7E6E8E8E5E3E4E5E8E7E6E7E8E6E5E7E7E6E7E9E6E5E0E5E5E5E6E6E6E6E5DDE8E7E7E7E6E6E6C9E3E0E6E6E6E5E5E6E4E5E5E5E7E7E7E6E8E7E8E8E7E6E6E6E7E5E7E6E7E8E8E8E8E8E8E8E8E7E6E5E4E0E4E2E3E1A8E4E3E4DBE2E3E2E4E0E6E4E5E4E3E1E5E0E24C45E5E4E3E6E4E5E4E05000C7E1E4E5E4E6C0E1D8E2CDE2E7E5E626E5A6A60005E1E4E5E6E4E5E7E5E5E6E6E5E3E7E4E5E4E5E3B3E3AA59E3E6E3E6E50AB7E5E5E6E8E4E6E8E6E6E6E5E6E6E7E5E5E5E5E4E5E5E6E6E5E8E6BAE5E9E6E6E7E3E2E4E5E7E8E8E6E6E6E8E7E9E7E8E6E6E7E6E6E7E5E5E5E6E7E8E6E6E5E3E4E6E7E5E7E6E6E8E6E8E6E7E7E7E6E5E6E5E4E5E4E6E4E6E7E8E7E8E7E6E5E4E6E7E7E8E7E7E7E6E7E8E7E7E7E5E5E6E7E7E8E5E7E5E6E4E6E8E7E8E8E7E5A6E6E7E7E7E8E3E5E5E7E6E7E7E6E8E7E9E7E8E8E8E8E6E6E6E5000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000A50000000001000001E7E7E7E7E7E7E9E7E9E7E8E8E2E7E7E3E3E4A4E3E5E0E3D4A4E2E3E4E4E3E5E5E7E7E6E6E69FE0E7E420017CE1E1E5E3E4E4E13315A4A4E4E6E7E4E5E4E5E6E2E5E5E4E2E5E6E3CB158375E4E7E6E6E5E5E5E0E5E6E7E6E5E6E6E4E5E6E457332FE6E6E6E2E696E380E3E4E4E3E6E4E5E6E6E6E7E6E6E8E7E7E5E5E5E4E5E5E2E8E7E7E7E5E6E5E6E6E7E5E5E7E7E7E8E6E3E6E7E3E6E6E6E4E7E7E6E4E5E6E5E5E5E6E6E5E5E5E4E6E7E5E5E7E6E6E5E6E7E5E7E5E6E6E5E7E5E6E3E5E6E5E7E7E6E5E6E6E7E6E7E7E7E8E6E7E6E8E7E3E7E8E7E6E5E5E7E8E6E5E7E8E6E5E6E8E7E8E6E6E7E6E6E6E7E6E7E6E6E5E6E7E6E7E5E8E8E8E9E8E7E8E7E6E6E6E6E8E7E8E8E7E7E6E6EAE9E9EAE6E7E8E8E1ACE2E2E3E4E2E3E564E2E4E4CDE5B1E1BCE6E7E5E5E7E5E5E27AE4E5E4E5E6E2E5E473E2DCE4E5E2C9E5E4E2E2E4B7E3E5E4E4E2E5E4E2549675E5E5E5E3E6E4E5E3E5E4E5E4E2E6E3E3E3E5E5A800C2E5E5E5E6E5E4D4E5E6E6E5E5E5E4E5E4E5E4E4E4E4E4E6E6E4E4E6E6E7E5E4E4E5E6E5E7E8E6E6E6E6E5E6E6E4E6E5E7E9E7E5E7E6E5E7E7E7E6E6E5E5E4E4E4E5E6E5E6E5E5E6E6E5E5E4E6E5E6E6E5E8E6E7E4E4E4E5E6E9E8E8E4E5E5E8E8E7E6E5E6E7E7E8E6E6E6E7E7E8E5E6E6E7E8E7E8E9E8E7E6E6E6E6E6E6E7E7ACE7E7E6E5E6E6E7E8E7E5E7E3E7E8E8E7E7E8E6E7E9E8E8E8E7E6E7E6E7E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000A70000000001000001E7E7E7E7E7E9E9E9E8E8E8E8E7E8E9E8E3E4E5E4E0DFB7E4E7E6E7E6E04131E5E6E5E5E5E4E4E5E39D80E6E5E5E675E6E7E7E7C0C0E2E5E4E6E4E5E4E2E4E3E3E6E7E6E7E6E5E5E6E4E2E5E4E1E2E6E7E4E6E5E5E4E5E5E7E6E6C5E5E6E4E12BE2E7E6D8E5E6E2E2E4E4E5E5E4E4E6E7E8E6E6E7E6E6E6E6E6E5E7E7E5E5E2E6E4E4E5E4E8E7E6E7E1E5E5E6E7E8E8C5E6E6E7E5E5E6E6E3E6E5E7E7E6E6E6E6E7E8E7E7E4E6E5E6E5E6E6E5E5E5E6E5E6E7E5E5E6E5E3E8E8E8E6E8E5E7E5E7E7E7E8E8E6E7E5E8E7E8E6E7E5E6E6E6E7E2E7E7E8E7E5E8E8E7E6E7E6E5E3E5E4E0E6E7E7E8E9E7E9E7E7E7E8E7E8E7E8E8E8E8E6E6E5E5E9E8E9E8E7E6E7E7E8E7E7E7E7E5E7E7E7E7E7E7E7E8E8E9E3E2E3E2E6E6E4E6E4E4E4E5E3E5E5E4E7E580C9E4DDE5E5E3E5E7A8E6E5E6E6E3E5E5E3E5E5E3E5E6E5E4E4E4E5E4E6E5E5E4E4E5E492E3E6E6E6E6E4E4E4E5E6E7E7E7E5E6E6E6E6E4E5E4E5E4E3E3E5E5E5E7E8E7E6E8E8E9E8E9E6E4E5E7E6E7E6E6E480E5E5E6E7E8E7E4E6E4E4E7E5E6E6E8E9E8E6E6E8E8E6E6E5E6E7E8E7E8E7E4E6CDE6E6E7E6E6E5E4E4E5E6E6E7E6E6E4E5E6E5E5E4E4E6E6E7D2E7E8E8E9E8E7E8E8E9E7E5E6E4E6E5E5E8E5E7E6E4E5E7E7E6E8E7E6E9E8E7E8E8E6E8E7E7E7DEE7E6E6E6E7E8E7E7E3E7E8E7E8E6E6E6E7E7E8E7E7E6E6E7E7E6E7E7E7E8E7E7E8E7E8E7E8E7E5E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000A90000000001000001E8E8E8E9E5E6E6E6E7E6E6E7E2E2E3E1E3E3E2E3E6E5E5E4E4E5E3E4E5E3E2E6283AE4E5E4E119E57CE2E6E7E6E7E7E4E6E5E5E692E1E5E5E3E4E3E4E4E5E5E4E5E6E4E7E6A1E7E6E6E6E6E7E6E6E5E3E5E4E5E3E6E6E5E6E6E6E6E5E4E5E5E6E5E6E6E6E7E5E5E5E4E6E5E3E4E3E3E4E4E5E5E5E5BEE5E5E4E4E6E4E6E7E4E6E8E5E7E6E7E4E6E5E6E4C5E6E7E7E7E7E8E7E8E7E6E6E7E7E5E4E5E4E4E4E4E3E6E3E4E3E6E6E8E7E7E6E4E5E7E6E6E8E5E5E7E7E4E5E6E7E6E5E7E7E3E4E6E5E8E1E7E5E7E3E6E6E5E5E4E6E8E6E7E8E5E5E4E4E85DE7E8E5E6E8E7E8E7E6E7E6E6E6E6E5E3E7E7E8E8E7E7E9E8E8E9E9E9E8EAE2E8E7E7E6E6E6E7E6E7E6E7E8E8E8E8E8E8E6E3E9EAE7EAE1E3E4E3E5E4E4E4E373E2E2E5E4E4E4E5E3E4E6B3E0E5E5E6E5E4E5E5C0E5E7E2E6E5689B9FE5E4E3E0E4E7E4E5E4E3E3E3E4E4E3E4E3E3E4E5E5E5E4E1E3E5E7E6E5E6E5E6E6E6E5E5E6E6E5E6E6E5E5E5E2E4E3E0E4E5E4E5E4E5E5E6E4E4E2E5E0E5E3E5E6E6E4E5E3E5E5E5E6E5E2E3E3E2E6E6E7E7E6E6E5E4E5E5C0E5E5E5E5E6E6E6E7E6E6E7E6E5E6E6E6E7E5E5E3E4E4E5E5E1E5E2E6E6E8E7E6E5E6E6E5E7E5E5E5E6E3E6E5E7E8E6E7E7E7E7E7E8E5E1E5E5E7E5E7E7E6E7E4E5E0E7E7E6E5E6E3E5E7E9E7E8E8E7E7E8E8E7E7E7E6E6E8E6E6E6E7E6E6E7E7E6E8E8E6E8E8E8E7E6E7E7E7E7E7E7E8E7E7E6E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000AB0000000001000001E6E6E6E6E9E8E8E8E8E8E7E6E4E4E3E5E2E3E4E1E6E6E5E0E5E6E5E4E8D0E7E8E4A1DE96AAE2E5E6E5E2E5E2E6E6E02B2F414CE4DFE1E4E5E5E5E6E4E4E3E4E5E5E5E5E4C7E7E5E5E4E4E2E4E6E7E7E6C7E5E5E596E1CDE5E4E4E5E4E6E5E1E4E6E6E8E8E6E4E4E5E7E7E4E5E4E5E4CBE5E6E7A8E7E5E6E5E6E7E7E7E5E5E7E5E6A1E3E6E7E5E6E3E4E6BEE7E7E5E5E5E6E3E6E5E6E6E6E5E6E6E1E8CDE1E4E5E6E4E3E3E5E7E7E6E5E5E6E4E4E3E4E5E5E8E7E7E6E6E7E6E8E5E7E7E6E6E6E6E7E7E7E5E6E7E7E9E7E6E8E6E4E5E7E8E6DDE5E6E6E8E7E7E8E8E8E8E6E7E5E4E9E8E8E8E7E7E8E5E7E7E7E7E6E7E8E6E7E7E6E9E8E6E6E4E7E7E7E6E6E6E6E5E9E7E7E8E7E8E7E7E8E8E8E9E1E3E3E3E3E5E3E5E5E5E4E4E7E7E7E7E5E5E5E6E5E5E4E4E7E7E6E72F43E4E2E8B533E771262831BEE5E6E3E5E44EE5E2E3DFDDE5E5E6E6E6E6E5E6E6E7E5E7E6E4E5E6E4E1E5E6E6E5E6E5E6E3E4E6E6D6E6E6E7E6E6E7E6E5E4E3E4E7E3E5E5E0E4E46FE6E2E7E7E6E51DE7E5E6E5E6E5E4E4E5E6E6E5E7E7E7E6E6E6E8E6E6E7E7E7E6E8E7E7E4E4E2C2E6E6E2E5E3E5E5E7E6E5E5E6E7E7E8E7E7E7E5E5E5E6E7E6E6E5E5E5E6E7E9E1E7E6E7E7E7E6E5E7E7E7E7E8E6E5E5E7E6E6E5E7E8E9E7E8E7E7E7E6E8E7E6E8E6E6E8E6E7E6E7E6E7E7E6E7E8E8E7E6E8E8E9E9E8E8E6E7E8E7E7E7E8E7E4E7E8E8E9E9E6E5E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000AD0000000001000001E6E5E6E6E9E7E7E8E8EAE9EAE8E6E5E6E3E2E3E4E2E3E5E3E2E5E6E4E5E300E6E6E6E0E6E7E2E6E3E1E4E0BCE8E5DEE7DDE6D44EE1E0E596A4E649E6E6DDE3A1E6E6E6E738E296B324E4E3A65D7AC2E5E7E7E5E6E5E2E4E3E5E5E4E4E5C0E5E6E5E5E673E4E5E4E5A1E6E6E8E5E4E6E4E6D2C7E2E4E5E5E6E4E8E3CDE1E6E5E1E3E3E2E4E5E5E6E1E5E56FE6E6E6E6E5E7E4E7E8E6E8E6E6E5E5E6E4E6E5E6E7E8E5E5E7E6E8E7E7E7E6E5E7E7E6E6E7E8E4E6E6E5E5E7E5E8E8E8E7E7E5E7E6E6E6E8E7E7E6E7E6E8E5E0E8E9E7E8E7E6E6E5E6E7E7E6E6E6E7E8E6E7E7E7E8E387E8E8E7E8E7E7E6E5E5E5E7E7E76DE6E6E6E7E7E8E7E7E7E4E7E7E6E6E5E5E8E7E8E8E7E7E6E6E8E8E7ACE4E4E2E3E3E4E3E4E7E6E6E5E7E6E5E6E6E4E5E5E7E6E6E8E7E5E6E6E5E6E6E7E5E5E6E6E7E7E7E6E7E1E7E5E6E7E6E7E7E7E468CDE5E3E4E7E2A6E0E3E6E3E6E0CDE7E7E5E5E6E475CDE5E5E7E7E6E7E5E1E5E4E6E5E6E5E8E7E5E2E6DBE4E7E8E7E6E5E5E4E5E4E7E6E7E8E5E5E6E2E6E6E6E7E6E6E8E6AFE7E6E7E7E8E9E5E6E5E5E6E9E8E8E8E6E5E7E7E9E8E7E7E6E8E8E2E6E6E7E7E6E6E7E8E8E9E9E8E6E6E6E6E9E8E8E8E7E9E8E9E7E8E8E8E6E7EBE8E8E8E6E7E7E7E6E7E7E6E6E7E9E5E7E8E7E8E7E7E8E7E6E7E7E8E7E8E7E8E7E7E8E7E8E7E9E9E9E8E6E6E6E6E8E7E7E7E7E8E9E7E8E6E6E7E8E8E6E7E6E5E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000AF0000000001000001E7E7E6E7E9E8E9E9E0E8E7E8E6E9E9E8E5E4E5E6E4E6E6E6E7E6E6E7E6E4E5E5E6E7E5E5E6E6E5E7E6E6E7E7E8E7E7E7E7E6E6E7E6E6E6E5E5E6E6E6E6E6E6E6E7E8E6E6E8E6E8E8E7E7E7E8E6E6E7E6E6E7E6A6E4E5E5E6E7E7E8E8E6E5E4E4E6E7E6E7E7E7E7E6EAE7E7E7E6E7E6E7E6E8E9E8EAE8E8E8E6E7E9E7E8E6E7E7E6E5E7E7E7E8E4E7E9E8E8E8E7E4E1E8E6E8E7E7E7E7E8E7E8E5E6E6E8E7E8E8E8E8E9E9E9E9E8E9E8E8E7E8E7E6E7E7E8E7E6E8E7E7E6E8E9E9E7E9E8E8E3E6E8E8E7E8E8E8E9E7E8E8E8E8E9E9E9E7E7E6E7E8E8E8E8E8E7E7E8E7E7E7E8E6E8E8E9E8E7E7E6E6E8E8E7E8E8E8E6E8EAEAE9EAE7E7E9E8E6E7E8E8E6E6E6E6E8E8E8E7E7E8E8E7EAE7E9E8E8E6E6E7E5E6E5E5E6E5E6E5E5E6E5E5E6E7E6E7E6E6E6E5E8E5E6E8E4E5E4E5E7E6E7E7E7E7E8E7E6E6E4E6E7E4E6E7E7E5E5E5E6E5E7E6E8E7E8E8E7E6E6E6E7E7E6E8E5E5E6E7E7E585E7E8E7E8E9E6E6E7E6E7E7E6E6E8E6E6A6E7E6E6E6E8E8E8E7E7E8E8E7E7E7E5E6E2E7E8E7E6E5E6E4E7E9E7E8E7E7E7E7E8E8E7E8E785E8E8E8E0E8E9E8E8E7E8E6E7E6E7E8E8E8E7E8E8E9E8E7E7E8E8E8E7E9E6E6E6E7E7E9E8E8E9E8E6E7E7E6E5E6E6E8E6E7E8E7E7E6E7E9E8E8E9E6E6E6E7E6E6E6E6E8E8E8E8E8E8E7E8E7E7E8E8E6E6E8E7E6E6E7E6E8E8E8E6E6E7E7E8E9E7E7E7E9E8E7E8D4E6E8E6EAE8E8E8E6E6E6E6000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000001000000B10000000001000001E6E6E6E6E8E7E8E9E9E8E7E8E5E8E8E8E6E4E5E5E6E5E6E5E7E7E8E8E1E5E4E5E7E6E7E7E5E6E5E6E6E741E5E7E6E8E8E6E5E6E5E8E6E7E8E5E6E5E6E93CE5E7E6E5E4E6E6E7E6E5E7E5E7E5E5E5E6E6E6E6E7E6E5E6E7E7E6E7E6E6E6E6E5E5E6E7E6E7E6E5E6E6E6E8E7E7E7E7E7E8E8E8E7E8E8E6E7E7E6E6E6E6E6E5E6E6E8E6E7E8E8E8E7E8E9E9E9E7E8E6E8E8E6E4E7E7E8E7E7E7E7E5E6E6E7E7E7E7E7E6E8E8E6E7E6B5E7E7E7E7E7E6E7E7E8E7E7E7E9E8E8E8E7E7E7E7E7E7E7E9E6E8E7E7E7E6E6E6E7E8E8E8E8E7E7E7E8E8EAE8E7E8E8E8E8E8E7E8E8E6E6E6E6E6E5E6E8E8E7E7E6E7E5E6E8E6E7E7E7E7E7E7E6E5E6E6E7E7E6E7E6E6E6E6E8E8E7E8E7E7E8E8EAE9E8E6E8E7E9E7E3E3E6E6E6E6E7E6E7E7E6E7E6E6E6E4E6E5E6E6E6E5E5E5E7E7E8E7E8E8E8E8E5E6E6E6E8E7E7E7E6E5E4E5E6E6E8E7E1E8E8E7E9E8E9E8E8E7E8E7E7E7E7E6E6E7E7E7E6E7E8E8E6E7E7E8E7E7E8E6E8E8E7E8E7E7E7E7C9E6E9E7E7E7E7E7E8E9E1EAE8E8E6E8E8E7E8E7E6E6E7E7E7E2E7E7EAE9E8E8E6E9E3E8E7E8E8E7E6E6E6E6E7E7E8E6E6E6E6E7E7E6E8E6E7E6E7E7E8E8E7E7E8E5E8E7E6E8E7E8E7E7E7E6E7E9E8EAE7E8E9E8E7E6E8E8E7E8E9E8E7E7E7E6EAE8E8E7E7E7E8E7E6E7E9E9E8E8E6E7E6E7E7E8E7E7E8E7E8E7E7E7E8E8E8E6E7E6E7E7E8E8E7E9E6E6E7E7E8E2E8E7E6E8E8E8E6E6E6E7000000
USBDEVFS_REAPURBNDELAY 0 3 131 0 0 540 540 0 802100001C0200000000000000000000B30000000001000001E6E4E5E5E7E7E8E7E9E9E9E8E6E8E8E8E4E6E5B3E4E4E5E6E5E5E5E7E5E5E5E6E6E6E6E5E9E7E8E7E5E5E5E6E8E8E7E7E7E9E9E8E8E6E8E7E6E6E7E8E6E5E5E5E7E7E7E4E6E6E6E7E7E6E6E6E6E6E7E8E6E6E664E8E7E6E6E6E7E8D6E7E5E6E6E9E7E7E6E6E7E6E6E6DCE8E8E8E7E8E8E7E8E6E8E9E7E5E6E6E4E6E6E6E7E7E7E8E8E7E7E8E7E8E7EAE6E7E8E7E7E7E8E9EAE9E9E6E6E6E7E7E7EAE9E8E7E7E7E8E6E6E7E8E6E8E8E7E7E6E6E6E7E7E8E8E7E8E4E8E6E7E7E7E9E6E9E6E7E6E7E8E8E9E7E7E7E6E8E9E8E9E8E9E7E7E7E7E5E7E2E8E7E7E8E7E6E7E6E6E6E7E7E6E7E8E5E8E6E8E7E8E9E9E8E6E5E7E7E9E8E9E9E7E5E7E6E7E7E6E7E6E6E6E5E8E8E8E7E7E7E8E8EAEAEAEAE6E6E8E6E5E5E6E6E4E3E4E4E6E4E5E7E6E6E5E5E6E6E6E7E8E6E8E8E8E7E9E7E7E6E7E7E9E7E7E8E8E4E7E8E7E7E7E6E7E7E7E6E5E4E5E6E7E3E4E5E6E6E6E4E9E8E7E8E7E8E7E9E6E6E6E6E7E7E6E4E5E4E5E4E5E6E6E6E8E7E6E7E7E7E8E6E5E7E7E6E3E7E6E6E8E5E6E6E8E7E8E8E7E6E7E7E8E8E7E7E6E6E7E7E6E8E5E8E5E5E5E6E8E9EAE9E9E8E9E9E9E9E8E7E6E7E7E99BE5E6E6E8E8E0E7E9E9E8E8EAE7E9E9E9E8E8E8E7E7E5E8E9E7E6E8E6E7E7E8EAE9E7E8E9E9E9E8E7E7E6E7E8E8E6E7E7E7E7E7E6E7E7E7EAE6E6E8E6E6E6E5E8E8E8E8E7E8E7E7E5E6E7E6E8E8E6E7E5E6E6E5E8E8E7E9E8E8E8E8E6E6E5E6000000

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

File diff suppressed because one or more lines are too long

View File

@@ -4,16 +4,14 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 01
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 40 38 0 00009C37FE5C669C2D000A01014101C10000D11BB7134A090FA1000000000100000000000003
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE011100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE01130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE021100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE035400
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE025400
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -22,13 +20,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355010C
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255010C
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -37,19 +35,19 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550119
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550119
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -58,13 +56,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -73,13 +71,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550132
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550132
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -88,13 +86,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -103,13 +101,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -118,13 +116,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355014B
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255014B
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -133,7 +131,7 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -142,13 +140,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550157
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550157
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -157,21 +155,21 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550164
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550164
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE03591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE02591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE04752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE047600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE05651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE03752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE037600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE04651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046600
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -180,9 +178,9 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE05651E4650312D30303030303030302D302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0568214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE06811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE06831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE07A100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE07A200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0468214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE05811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE05831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE06A100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE06A200

View File

@@ -20,14 +20,11 @@ d.open_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
print('enroll progress: ' + str(args))
# List, enroll, list, verify, delete, list
print("enrolling")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
print("listing")
@@ -36,9 +33,7 @@ print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
assert verify_res == True

View File

@@ -34,11 +34,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0000
A: bmAttributes=a0
A: busnum=1\n
A: busnum=1
A: configuration=
H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004
A: dev=189:69
A: devnum=70\n
A: devnum=70
A: devpath=1
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=00bd

View File

@@ -279,6 +279,4 @@ fpi_device_fake_class_init (FpiDeviceFakeClass *klass)
dev_class->list = fpi_device_fake_list;
dev_class->delete = fpi_device_fake_delete;
dev_class->cancel = fpi_device_fake_cancel;
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -20,7 +20,6 @@
#include <libfprint/fprint.h>
#include "test-utils.h"
#include "fpi-device.h"
static void
test_context_new (void)
@@ -50,7 +49,7 @@ test_context_has_virtual_device (void)
GPtrArray *devices;
unsigned int i;
fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
fpt_setup_virtual_device_environment ();
context = fp_context_new ();
devices = fp_context_get_devices (context);
@@ -82,7 +81,7 @@ test_context_enumerates_new_devices (void)
context = fp_context_new ();
fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
fpt_setup_virtual_device_environment ();
fp_context_enumerate (context);
devices = fp_context_get_devices (context);
@@ -93,296 +92,6 @@ test_context_enumerates_new_devices (void)
fpt_teardown_virtual_device_environment ();
}
#define DEV_REMOVED_CB 1
#define CTX_DEVICE_REMOVED_CB 2
static void
device_removed_cb (FpDevice *device, FptContext *tctx)
{
g_assert_nonnull (device);
g_assert_true (device == tctx->device);
g_assert_null (tctx->user_data);
tctx->user_data = GINT_TO_POINTER (DEV_REMOVED_CB);
}
static void
context_device_removed_cb (FpContext *ctx, FpDevice *device, FptContext *tctx)
{
g_assert_nonnull (device);
g_assert_true (device == tctx->device);
/* "device-removed" on context is always after "removed" on device */
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
tctx->user_data = GINT_TO_POINTER (CTX_DEVICE_REMOVED_CB);
}
static void
test_context_remove_device_closed (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
gboolean removed;
tctx->user_data = NULL;
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
/* Triggering remove on closed device. */
fpi_device_remove (tctx->device);
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* device-removed is dispatched from idle. */
while (g_main_context_iteration (NULL, FALSE))
{
}
/* The device is now destroyed and device-removed was called. */
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
close_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
{
g_autoptr(FpPrint) print = NULL;
GError **error = user_data;
g_assert_nonnull (error);
g_assert_false (fp_device_close_finish (FP_DEVICE (device), res, error));
g_assert_null (print);
g_assert_nonnull (*error);
}
static void
test_context_remove_device_closing (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(GError) close_error = NULL;
g_autoptr(GError) error = NULL;
gboolean removed;
tctx->user_data = NULL;
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
/* Triggering remove on device that is being closed. */
fp_device_close (tctx->device, NULL, close_done_cb, &close_error);
fpi_device_remove (tctx->device);
/* Removed but not yet notified*/
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_null (tctx->user_data);
/* Running the mainloop now will cause the close to fail eventually. */
while (!close_error)
g_main_context_iteration (NULL, TRUE);
g_assert_error (close_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
/* Now the removed callback has been called already. */
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* While device-removed needs another idle iteration. */
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
test_context_remove_device_open (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(GError) error = NULL;
gboolean removed = FALSE;
tctx->user_data = NULL;
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
/* Triggering remove on open device. */
fpi_device_remove (tctx->device);
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* At this point, the "removed" cb on the device should have been called!
* Iterating the mainloop will not change anything.
*/
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* On close, the device will be removed from the context,
* but only a main loop iteration later. */
fp_device_close_sync (tctx->device, NULL, &error);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
open_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpPrint) print = NULL;
gboolean *data = user_data;
g_assert_true (fp_device_open_finish (FP_DEVICE (device), res, &error));
g_assert_null (print);
g_assert_null (error);
*data = TRUE;
}
static void
test_context_remove_device_opening (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(GError) close_error = NULL;
gboolean open_done = FALSE;
gboolean removed;
tctx->user_data = NULL;
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
fp_device_open (tctx->device, NULL, open_done_cb, &open_done);
g_assert_false (open_done);
fpi_device_remove (tctx->device);
/* Removed but not yet notified*/
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_null (tctx->user_data);
/* Running the mainloop now will cause the open to *succeed* despite removal! */
while (!open_done)
g_main_context_iteration (NULL, TRUE);
/* Now the removed callback has been called already. */
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
fp_device_close_sync (tctx->device, NULL, &close_error);
g_assert_error (close_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* The device-removed signal needs an idle iteration. */
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
enroll_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
{
g_autoptr(FpPrint) print = NULL;
GError **error = user_data;
g_assert_nonnull (error);
print = fp_device_enroll_finish (FP_DEVICE (device), res, error);
g_assert_null (print);
g_assert_nonnull (*error);
}
static void
test_context_remove_device_active (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(GError) error = NULL;
g_autoptr(GCancellable) cancellable = NULL;
g_autoptr(GError) enroll_error = NULL;
FpPrint *template;
gboolean removed = FALSE;
tctx->user_data = NULL;
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
/* Start an enroll that we can cancel/fail later.
* NOTE: We need to cancel explicitly as remove() does not trigger a failure!
*/
template = fp_print_new (tctx->device);
cancellable = g_cancellable_new ();
fp_device_enroll (tctx->device, template, cancellable, NULL, NULL, NULL, enroll_done_cb, &enroll_error);
/* Triggering remove on active device. */
fpi_device_remove (tctx->device);
/* The removed property has changed, but the cb has *not* been called yet. */
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_null (tctx->user_data);
/* Running the mainloop now will cause the operation to fail eventually. */
while (!enroll_error)
g_main_context_iteration (NULL, TRUE);
/* The virtual image device throws an PROTO error internally,
* but we should still receive a REMOVED error here. */
g_assert_error (enroll_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* Now we close the device, state remains unchanged mostly. */
fp_device_close_sync (tctx->device, NULL, &error);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* And "device-removed" is called */
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
int
main (int argc, char *argv[])
{
@@ -392,11 +101,6 @@ main (int argc, char *argv[])
g_test_add_func ("/context/no-devices", test_context_has_no_devices);
g_test_add_func ("/context/has-virtual-device", test_context_has_virtual_device);
g_test_add_func ("/context/enumerates-new-devices", test_context_enumerates_new_devices);
g_test_add_func ("/context/remove-device-closed", test_context_remove_device_closed);
g_test_add_func ("/context/remove-device-closing", test_context_remove_device_closing);
g_test_add_func ("/context/remove-device-open", test_context_remove_device_open);
g_test_add_func ("/context/remove-device-opening", test_context_remove_device_opening);
g_test_add_func ("/context/remove-device-active", test_context_remove_device_active);
return g_test_run ();
}

View File

@@ -36,7 +36,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx)
static void
test_device_open_async (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx);
@@ -59,7 +59,7 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, FptContext *tctx)
static void
test_device_close_async (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx);
while (!tctx->user_data)
@@ -76,7 +76,7 @@ static void
test_device_open_sync (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
@@ -97,7 +97,7 @@ static void
test_device_open_sync_notify (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx);
fp_device_open_sync (tctx->device, NULL, &error);
@@ -109,7 +109,7 @@ static void
test_device_close_sync (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
fp_device_close_sync (tctx->device, NULL, &error);
@@ -131,7 +131,7 @@ static void
test_device_close_sync_notify (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
@@ -144,7 +144,7 @@ test_device_close_sync_notify (void)
static void
test_device_get_driver (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image");
@@ -153,7 +153,7 @@ test_device_get_driver (void)
static void
test_device_get_device_id (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0");
@@ -162,7 +162,7 @@ test_device_get_device_id (void)
static void
test_device_get_name (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpstr (fp_device_get_name (tctx->device), ==,
@@ -172,25 +172,16 @@ test_device_get_name (void)
static void
test_device_get_scan_type (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE);
}
static void
test_device_get_finger_status (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpint (fp_device_get_finger_status (tctx->device), ==, FP_FINGER_STATUS_NONE);
}
static void
test_device_get_nr_enroll_stages (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5);
@@ -199,7 +190,7 @@ test_device_get_nr_enroll_stages (void)
static void
test_device_supports_identify (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_true (fp_device_supports_identify (tctx->device));
@@ -208,7 +199,7 @@ test_device_supports_identify (void)
static void
test_device_supports_capture (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_true (fp_device_supports_capture (tctx->device));
@@ -217,7 +208,7 @@ test_device_supports_capture (void)
static void
test_device_has_storage (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_false (fp_device_has_storage (tctx->device));
@@ -238,7 +229,6 @@ main (int argc, char *argv[])
g_test_add_func ("/device/sync/get_device_id", test_device_get_device_id);
g_test_add_func ("/device/sync/get_name", test_device_get_name);
g_test_add_func ("/device/sync/get_scan_type", test_device_get_scan_type);
g_test_add_func ("/device/sync/get_finger_status", test_device_get_finger_status);
g_test_add_func ("/device/sync/get_nr_enroll_stages", test_device_get_nr_enroll_stages);
g_test_add_func ("/device/sync/supports_identify", test_device_supports_identify);
g_test_add_func ("/device/sync/supports_capture", test_device_supports_capture);

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +0,0 @@
#!/usr/bin/env bash
set -e
[ -x "$UDEV_HWDB" ] || exit 1
if [ "$UDEV_HWDB_CHECK_CONTENTS" == 1 ]; then
generated_rules=$(mktemp "${TMPDIR:-/tmp}/libfprint-XXXXXX.hwdb")
else
generated_rules=/dev/null
fi
$UDEV_HWDB > "$generated_rules"
if [ "$UDEV_HWDB_CHECK_CONTENTS" != 1 ]; then
exit 77
fi
if ! diff -u "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then
echo "E: Autosuspend file needs to be re-generated!"
echo " ninja -C $MESON_BUILD_ROOT libfprint/sync-udev-hwdb"
exit 1
fi
rm "$generated_rules"

View File

@@ -22,31 +22,16 @@
#include "test-utils.h"
struct
{
const char *envvar;
const char *driver_id;
const char *device_id;
} devtype_vars[FPT_NUM_VIRTUAL_DEVICE_TYPES] = {
{ "FP_VIRTUAL_IMAGE", "virtual_image", "virtual_image" }, /* FPT_VIRTUAL_DEVICE_IMAGE */
{ "FP_VIRTUAL_DEVICE", "virtual_device", "virtual_device" }, /* FPT_VIRTUAL_DEVICE_NONIMAGE */
{ "FP_VIRTUAL_DEVICE_STORAGE", "virtual_device_storage", "virtual_device_storage" } /* FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE */
};
static FptVirtualDeviceType global_devtype;
void
fpt_teardown_virtual_device_environment (void)
{
const char *path;
path = g_getenv (devtype_vars[global_devtype].envvar);
const char *path = g_getenv ("FP_VIRTUAL_IMAGE");
if (path)
{
g_autofree char *temp_dir = g_path_get_dirname (path);
g_unsetenv (devtype_vars[global_devtype].envvar);
g_unsetenv ("FP_VIRTUAL_IMAGE");
g_unlink (path);
g_rmdir (temp_dir);
}
@@ -59,23 +44,19 @@ on_signal_event (int sig)
}
void
fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype)
fpt_setup_virtual_device_environment (void)
{
g_autoptr(GError) error = NULL;
g_autofree char *temp_dir = NULL;
g_autofree char *temp_path = NULL;
g_autofree char *filename = NULL;
g_assert_null (g_getenv (devtype_vars[devtype].envvar));
g_assert_null (g_getenv ("FP_VIRTUAL_IMAGE"));
temp_dir = g_dir_make_tmp ("libfprint-XXXXXX", &error);
g_assert_no_error (error);
filename = g_strdup_printf ("%s.socket", devtype_vars[devtype].device_id);
temp_path = g_build_filename (temp_dir, filename, NULL);
g_setenv (devtype_vars[devtype].envvar, temp_path, TRUE);
global_devtype = devtype;
temp_path = g_build_filename (temp_dir, "virtual-image.socket", NULL);
g_setenv ("FP_VIRTUAL_IMAGE", temp_path, TRUE);
signal (SIGKILL, on_signal_event);
signal (SIGABRT, on_signal_event);
@@ -97,16 +78,13 @@ fpt_context_new (void)
}
FptContext *
fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype)
fpt_context_new_with_virtual_imgdev (void)
{
FptContext *tctx;
GPtrArray *devices;
unsigned int i;
g_assert_true (devtype >= FPT_VIRTUAL_DEVICE_IMAGE &&
devtype < FPT_NUM_VIRTUAL_DEVICE_TYPES);
fpt_setup_virtual_device_environment (devtype);
fpt_setup_virtual_device_environment ();
tctx = fpt_context_new ();
devices = fp_context_get_devices (tctx->fp_context);
@@ -118,7 +96,7 @@ fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype)
{
FpDevice *device = devices->pdata[i];
if (g_strcmp0 (fp_device_get_driver (device), devtype_vars[devtype].driver_id) == 0)
if (g_strcmp0 (fp_device_get_driver (device), "virtual_image") == 0)
{
tctx->device = device;
break;

View File

@@ -19,14 +19,7 @@
#include <glib.h>
typedef enum {
FPT_VIRTUAL_DEVICE_IMAGE = 0,
FPT_VIRTUAL_DEVICE_NONIMAGE,
FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE,
FPT_NUM_VIRTUAL_DEVICE_TYPES
} FptVirtualDeviceType;
void fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype);
void fpt_setup_virtual_device_environment (void);
void fpt_teardown_virtual_device_environment (void);
typedef struct _FptContext
@@ -37,7 +30,7 @@ typedef struct _FptContext
} FptContext;
FptContext * fpt_context_new (void);
FptContext * fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype);
FptContext * fpt_context_new_with_virtual_imgdev (void);
void fpt_context_free (FptContext *test_context);

View File

@@ -87,12 +87,6 @@ try:
if os.path.exists(os.path.join(ddir, "custom.ioctl")):
custom()
except Exception as e:
# Store created output files for inspection (in the build directory)
outdir = os.path.join('errors', os.path.basename(ddir))
shutil.copytree(tmpdir, outdir, dirs_exist_ok=True)
raise e
finally:
shutil.rmtree(tmpdir)

Some files were not shown because too many files have changed in this diff Show More